Add hdb_set_sync() method

This commit is contained in:
Nicolas Williams
2017-10-10 13:06:21 -05:00
parent e3cc7dfb94
commit 5bcbe2125b
7 changed files with 140 additions and 54 deletions

View File

@@ -44,6 +44,7 @@
typedef struct {
HDB hdb; /* generic members */
int lock_fd; /* DB-specific */
int do_sync; /* DB-specific */
} DB1_HDB;
static krb5_error_code
@@ -76,6 +77,25 @@ DB_destroy(krb5_context context, HDB *db)
return ret;
}
static krb5_error_code
DB_set_sync(krb5_context context, HDB *db, int on)
{
DB1_HDB *db1 = (DB1_HDB *)db;
DB *d = (DB*)db->hdb_db;
krb5_error_code ret = 0;
db1->do_sync = on;
if (on) {
ret = (*d->sync)(d, 0);
if (ret == -1) {
ret = errno;
krb5_set_error_message(context, ret, "Database %s put sync error: %s",
db->hdb_name, strerror(ret));
}
}
return ret;
}
static krb5_error_code
DB_lock(krb5_context context, HDB *db, int operation)
{
@@ -203,6 +223,7 @@ static krb5_error_code
DB__put(krb5_context context, HDB *db, int replace,
krb5_data key, krb5_data value)
{
DB1_HDB *db1 = (DB1_HDB *)db;
DB *d = (DB*)db->hdb_db;
DBT k, v;
int code;
@@ -222,19 +243,14 @@ DB__put(krb5_context context, HDB *db, int replace,
if(code == 1) {
return HDB_ERR_EXISTS;
}
code = (*d->sync)(d, 0);
if (code == -1) {
code = errno;
krb5_set_error_message(context, code, "Database %s put sync error: %s",
db->hdb_name, strerror(code));
return code;
}
return 0;
return db->hdb_set_sync(context, db, db1->do_sync);
}
static krb5_error_code
DB__del(krb5_context context, HDB *db, krb5_data key)
{
DB1_HDB *db1 = (DB1_HDB *)db;
DB *d = (DB*)db->hdb_db;
DBT k;
krb5_error_code code;
@@ -250,14 +266,7 @@ DB__del(krb5_context context, HDB *db, krb5_data key)
db->hdb_name, strerror(code));
return code;
}
code = (*d->sync)(d, 0);
if (code == -1) {
code = errno;
krb5_set_error_message(context, code, "Database %s del sync error: %s",
db->hdb_name, strerror(code));
return code;
}
return 0;
return db->hdb_set_sync(context, db, db1->do_sync);
}
static DB *
@@ -371,8 +380,10 @@ hdb_db1_create(krb5_context context, HDB **db,
(*db)->hdb__put = DB__put;
(*db)->hdb__del = DB__del;
(*db)->hdb_destroy = DB_destroy;
(*db)->hdb_set_sync = DB_set_sync;
(*db1)->lock_fd = -1;
(*db1)->do_sync = 1;
return 0;
}

View File

@@ -54,6 +54,7 @@
typedef struct {
HDB hdb; /* generic members */
int lock_fd; /* DB3-specific */
int do_sync; /* DB3-specific */
} DB3_HDB;
@@ -91,6 +92,32 @@ DB_destroy(krb5_context context, HDB *db)
return ret;
}
static krb5_error_code
DB_set_sync(krb5_context context, HDB *db, int on)
{
DB3_HDB *db3 = (DB3_HDB *)db;
DB *d = (DB*)db->hdb_db;
krb5_error_code ret = 0;
db3->do_sync = on;
if (on) {
ret = (*d->sync)(d, 0);
if (ret) {
if (ret == EACCES || ret == ENOSPC || ret == EINVAL) {
krb5_set_error_message(context, ret,
"Database %s put sync error: %s",
db->hdb_name, strerror(ret));
} else {
ret = HDB_ERR_UK_SERROR;
krb5_set_error_message(context, ret,
"Database %s put sync error: unknown (%d)",
db->hdb_name, ret);
}
}
}
return ret;
}
static krb5_error_code
DB_lock(krb5_context context, HDB *db, int operation)
{
@@ -220,6 +247,7 @@ static krb5_error_code
DB__put(krb5_context context, HDB *db, int replace,
krb5_data key, krb5_data value)
{
DB3_HDB *db3 = (DB3_HDB *)db;
DB *d = (DB*)db->hdb_db;
DBT k, v;
int code;
@@ -261,26 +289,13 @@ DB__put(krb5_context context, HDB *db, int replace,
}
return code;
}
code = (*d->sync)(d, 0);
if (code) {
if (code == EACCES || code == ENOSPC || code == EINVAL) {
krb5_set_error_message(context, code,
"Database %s put sync error: %s",
db->hdb_name, strerror(code));
} else {
code = HDB_ERR_UK_SERROR;
krb5_set_error_message(context, code,
"Database %s put sync error: unknown (%d)",
db->hdb_name, code);
}
return code;
}
return 0;
return db->hdb_set_sync(context, db, db3->do_sync);
}
static krb5_error_code
DB__del(krb5_context context, HDB *db, krb5_data key)
{
DB3_HDB *db3 = (DB3_HDB *)db;
DB *d = (DB*)db->hdb_db;
DBT k;
krb5_error_code code;
@@ -304,21 +319,7 @@ DB__del(krb5_context context, HDB *db, krb5_data key)
}
return code;
}
code = (*d->sync)(d, 0);
if (code) {
if (code == EACCES || code == ENOSPC || code == EINVAL) {
krb5_set_error_message(context, code,
"Database %s del sync error: %s",
db->hdb_name, strerror(code));
} else {
code = HDB_ERR_UK_SERROR;
krb5_set_error_message(context, code,
"Database %s del sync error: unknown (%d)",
db->hdb_name, code);
}
return code;
}
return 0;
return db->hdb_set_sync(context, db, db3->do_sync);
}
#define RD_CACHE_SZ 0x8000 /* Minimal read cache size */
@@ -485,6 +486,7 @@ hdb_db3_create(krb5_context context, HDB **db,
(*db)->hdb__put = DB__put;
(*db)->hdb__del = DB__del;
(*db)->hdb_destroy = DB_destroy;
(*db)->hdb_set_sync = DB_set_sync;
(*db3)->lock_fd = -1;
return 0;

View File

@@ -1890,6 +1890,13 @@ LDAP_destroy(krb5_context context, HDB * db)
return ret;
}
static krb5_error_code
LDAP_set_sync(krb5_context context, HDB * db, int on)
{
(void)on;
return 0;
}
static krb5_error_code
hdb_ldap_common(krb5_context context,
HDB ** db,
@@ -2024,6 +2031,7 @@ hdb_ldap_common(krb5_context context,
(*db)->hdb__put = NULL;
(*db)->hdb__del = NULL;
(*db)->hdb_destroy = LDAP_destroy;
(*db)->hdb_set_sync = LDAP_set_sync;
return 0;
}

View File

@@ -75,6 +75,15 @@ DB_destroy(krb5_context context, HDB *db)
return ret;
}
static krb5_error_code
DB_set_sync(krb5_context context, HDB *db, int on)
{
mdb_info *mi = (mdb_info *)db->hdb_db;
mdb_env_set_flags(mi->e, MDB_NOSYNC, !on);
return mdb_env_sync(mi->e, 0);
}
static krb5_error_code
DB_lock(krb5_context context, HDB *db, int operation)
{
@@ -240,6 +249,10 @@ DB__put(krb5_context context, HDB *db, int replace,
mdb_txn_abort(txn);
else
code = mdb_txn_commit(txn);
/*
* No need to call mdb_env_sync(); it's done automatically if MDB_NOSYNC is
* not set.
*/
if(code == MDB_KEYEXIST)
return HDB_ERR_EXISTS;
return code;
@@ -265,6 +278,10 @@ DB__del(krb5_context context, HDB *db, krb5_data key)
mdb_txn_abort(txn);
else
code = mdb_txn_commit(txn);
/*
* No need to call mdb_env_sync(); it's done automatically if MDB_NOSYNC is
* not set.
*/
if(code == MDB_NOTFOUND)
return HDB_ERR_NOENTRY;
return code;
@@ -394,6 +411,7 @@ hdb_mdb_create(krb5_context context, HDB **db,
(*db)->hdb__put = DB__put;
(*db)->hdb__del = DB__del;
(*db)->hdb_destroy = DB_destroy;
(*db)->hdb_set_sync = DB_set_sync;
return 0;
}
#endif /* HAVE_LMDB */

View File

@@ -91,6 +91,11 @@ salt:
#include "hdb_locl.h"
typedef struct MITDB {
HDB db; /* Generic */
int do_sync; /* MITDB-specific */
} MITDB;
static void
attr_to_flags(unsigned attr, HDBFlags *flags)
{
@@ -697,6 +702,18 @@ mdb_destroy(krb5_context context, HDB *db)
return ret;
}
static krb5_error_code
mdb_set_sync(krb5_context context, HDB *db, int on)
{
MITDB *mdb = (MITDB *)db;
DB *d = (DB*)db->hdb_db;
mdb->do_sync = on;
if (on)
return fsync((*d->fd)(d));
return 0;
}
static krb5_error_code
mdb_lock(krb5_context context, HDB *db, int operation)
{
@@ -861,6 +878,7 @@ static krb5_error_code
mdb__put(krb5_context context, HDB *db, int replace,
krb5_data key, krb5_data value)
{
MITDB *mdb = (MITDB *)db;
DB *d = (DB*)db->hdb_db;
DBT k, v;
int code;
@@ -873,6 +891,11 @@ mdb__put(krb5_context context, HDB *db, int replace,
if(code)
return code;
code = (*d->put)(d, &k, &v, replace ? 0 : R_NOOVERWRITE);
if (code == 0) {
code = mdb_set_sync(context, db, mdb->do_sync);
db->hdb_unlock(context, db);
return code;
}
db->hdb_unlock(context, db);
if(code < 0) {
code = errno;
@@ -880,16 +903,14 @@ mdb__put(krb5_context context, HDB *db, int replace,
db->hdb_name, strerror(code));
return code;
}
if(code == 1) {
krb5_clear_error_message(context);
return HDB_ERR_EXISTS;
}
return 0;
krb5_clear_error_message(context);
return HDB_ERR_EXISTS;
}
static krb5_error_code
mdb__del(krb5_context context, HDB *db, krb5_data key)
{
MITDB *mdb = (MITDB *)db;
DB *d = (DB*)db->hdb_db;
DBT k;
krb5_error_code code;
@@ -899,6 +920,11 @@ mdb__del(krb5_context context, HDB *db, krb5_data key)
if(code)
return code;
code = (*d->del)(d, &k, 0);
if (code == 0) {
code = mdb_set_sync(context, db, mdb->do_sync);
db->hdb_unlock(context, db);
return code;
}
db->hdb_unlock(context, db);
if(code == 1) {
code = errno;
@@ -1090,8 +1116,9 @@ krb5_error_code
hdb_mitdb_create(krb5_context context, HDB **db,
const char *filename)
{
*db = calloc(1, sizeof(**db));
if (*db == NULL) {
MITDB **mdb (MITDB **)db;
*mdb = calloc(1, sizeof(**mdb));
if (*mdb == NULL) {
krb5_set_error_message(context, ENOMEM, "malloc: out of memory");
return ENOMEM;
}
@@ -1104,6 +1131,7 @@ hdb_mitdb_create(krb5_context context, HDB **db,
krb5_set_error_message(context, ENOMEM, "malloc: out of memory");
return ENOMEM;
}
(*mdb)->do_sync = 1;
(*db)->hdb_master_key_set = 0;
(*db)->hdb_openp = 0;
(*db)->hdb_capability_flags = 0;
@@ -1121,6 +1149,7 @@ hdb_mitdb_create(krb5_context context, HDB **db,
(*db)->hdb__put = mdb__put;
(*db)->hdb__del = mdb__del;
(*db)->hdb_destroy = mdb_destroy;
(*db)->hdb_set_sync = mdb_set_sync;
return 0;
}

View File

@@ -807,6 +807,15 @@ hdb_sqlite_destroy(krb5_context context, HDB *db)
return ret ? ret : ret2;
}
static krb5_error_code
hdb_sqlite_set_sync(krb5_context context, HDB *db, int on)
{
return hdb_sqlite_exec_stmt(context, (hdb_sqlite_db*)(db->hdb_db),
on ? "PRAGMA main.synchronous = NORMAL" :
"PRAGMA main.synchronous = OFF",
HDB_ERR_UK_SERROR);
}
/*
* Not sure if this is needed.
*/
@@ -1035,6 +1044,7 @@ hdb_sqlite_create(krb5_context context, HDB **db, const char *filename)
(*db)->hdb_remove = hdb_sqlite_remove;
(*db)->hdb_destroy = hdb_sqlite_destroy;
(*db)->hdb_rename = hdb_sqlite_rename;
(*db)->hdb_set_sync = hdb_sqlite_set_sync;
(*db)->hdb__get = NULL;
(*db)->hdb__put = NULL;
(*db)->hdb__del = NULL;

View File

@@ -271,9 +271,17 @@ typedef struct HDB {
* Check if s4u2self is allowed from this client to this server
*/
krb5_error_code (*hdb_check_s4u2self)(krb5_context, struct HDB *, hdb_entry_ex *, krb5_const_principal);
/**
* Enable/disable synchronous updates
*
* Calling this with 0 disables sync. Calling it with non-zero enables
* sync and does an fsync().
*/
krb5_error_code (*hdb_set_sync)(krb5_context, struct HDB *, int);
}HDB;
#define HDB_INTERFACE_VERSION 9
#define HDB_INTERFACE_VERSION 10
struct hdb_method {
int version;