/* * Insert a row into table */ int bdb_insert(db_con_t* _h, db_key_t* _k, db_val_t* _v, int _n) { bdb_row_p r; DBC *cursorp; int ret; if ((ret = bdb_row_db2bdb(_h, _k, _v, _n, &r)) < 0) { return -1; }; if (r->key.size == 0) { LOG(L_ERR, "BDB:bdb_insert: no primary key specified\n"); bdb_free_row(r); return -1; } BDB_CON_DB(_h)->cursor(BDB_CON_DB(_h), NULL, &cursorp, DB_WRITECURSOR); ret = cursorp->c_put(cursorp, &(r->key), &(r->data), DB_KEYLAST); if (ret < 0) { LOG(L_ERR, "BDB:bdb_insert: unable to insert record: %s\n", db_strerror(ret)); } if (cursorp != NULL) { cursorp->c_close(cursorp); } bdb_free_row(r); return ret; }
int Dbc::put(Dbt* key, Dbt *data, u_int32_t flags_arg) { DBC *cursor = this; int err; if ((err = cursor->c_put(cursor, key, data, flags_arg)) != 0) { if (err != DB_KEYEXIST) { DB_ERROR("Db::put", err); return err; } } return 0; }
int update_trans_to_db(const char* pcszChinese, const char* pcszTrans){ DBC *cursorp; DBT key, data; int nRet = 0; char szTransConverted[MAX_TRANS_LEN]; memset(&key, 0, sizeof(DBT)); memset(&data, 0, sizeof(DBT)); /* Set up our DBTs */ key.data = (void*)pcszChinese; key.size = (unsigned int)strlen(pcszChinese) + 1; /* Get the cursor */ g_myBDB->cursor(g_myBDB, NULL, &cursorp, 0); if ( cursorp == NULL ) { write_log(LT_FILE, "Error: Can't get the cursor, when update " "the translate of %s!\n", pcszChinese); return 0; } special_sign_convert(pcszTrans, szTransConverted, g_dbInfo.nLanguageType); /* Position the cursor */ nRet = cursorp->c_get(cursorp, &key, &data, DB_SET); if (nRet == 0) { data.data = (void*)szTransConverted; data.size = (unsigned int)strlen(szTransConverted) + 1; cursorp->c_put(cursorp, &key, &data, DB_CURRENT); } else{ write_log(LT_FILE, "Error: Can't find record %s, when update " "its translate, try to insert it!\n", pcszChinese); nRet = insert_to_db(pcszChinese, pcszTrans); goto exit; } write_log(LT_FILE, "Info: %s update success!\n", pcszChinese); nRet = 1; exit: /* Cursors must be closed */ if ( cursorp != NULL ) cursorp->c_close(cursorp); return nRet; }
int Dbc::put(Dbt* key, Dbt *data, u_int32_t flags_arg) { DBC *cursor = this; int err; if ((err = cursor->c_put(cursor, key, data, flags_arg)) != 0) { // DB_KEYEXIST is a "normal" return, so should not be // thrown as an error // if (err != DB_KEYEXIST) { DB_ERROR("Db::put", err, ON_ERROR_UNKNOWN); return (err); } } return (err); }
static int dbiCursorPut(dbiCursor dbc, DBT * key, DBT * data, unsigned int flags) { int rc = EINVAL; int sane = (key->data != NULL && key->size > 0 && data->data != NULL && data->size > 0); if (dbc && sane) { DBC * cursor = dbc->cursor; rpmdb rdb = dbc->dbi->dbi_rpmdb; rpmswEnter(&rdb->db_putops, (ssize_t) 0); rc = cursor->c_put(cursor, key, data, DB_KEYLAST); rc = cvtdberr(dbc->dbi, "dbcursor->c_put", rc, _debug); rpmswExit(&rdb->db_putops, (ssize_t) data->size); } return rc; }
int bdb_idl_delete_key( BackendDB *be, DB *db, DB_TXN *tid, DBT *key, ID id ) { struct bdb_info *bdb = (struct bdb_info *) be->be_private; int rc; DBT data; DBC *cursor; ID lo, hi, tmp, nid, nlo, nhi; char *err; { char buf[16]; Debug( LDAP_DEBUG_ARGS, "bdb_idl_delete_key: %lx %s\n", (long) id, bdb_show_key( key, buf ), 0 ); } assert( id != NOID ); if ( bdb->bi_idl_cache_size ) { bdb_idl_cache_del( bdb, db, key ); } BDB_ID2DISK( id, &nid ); DBTzero( &data ); data.data = &tmp; data.size = sizeof( id ); data.ulen = data.size; data.flags = DB_DBT_USERMEM; rc = db->cursor( db, tid, &cursor, bdb->bi_db_opflags ); if ( rc != 0 ) { Debug( LDAP_DEBUG_ANY, "=> bdb_idl_delete_key: " "cursor failed: %s (%d)\n", db_strerror(rc), rc, 0 ); return rc; } /* Fetch the first data item for this key, to see if it * exists and if it's a range. */ rc = cursor->c_get( cursor, key, &data, DB_SET ); err = "c_get"; if ( rc == 0 ) { if ( tmp != 0 ) { /* Not a range, just delete it */ if (tmp != nid) { /* position to correct item */ tmp = nid; rc = cursor->c_get( cursor, key, &data, DB_GET_BOTH ); if ( rc != 0 ) { err = "c_get id"; goto fail; } } rc = cursor->c_del( cursor, 0 ); if ( rc != 0 ) { err = "c_del id"; goto fail; } } else { /* It's a range, see if we need to rewrite * the boundaries */ data.data = &nlo; rc = cursor->c_get( cursor, key, &data, DB_NEXT_DUP ); if ( rc != 0 ) { err = "c_get lo"; goto fail; } BDB_DISK2ID( &nlo, &lo ); data.data = &nhi; rc = cursor->c_get( cursor, key, &data, DB_NEXT_DUP ); if ( rc != 0 ) { err = "c_get hi"; goto fail; } BDB_DISK2ID( &nhi, &hi ); if ( id == lo || id == hi ) { if ( id == lo ) { id++; lo = id; } else if ( id == hi ) { id--; hi = id; } if ( lo >= hi ) { /* The range has collapsed... */ rc = db->del( db, tid, key, 0 ); if ( rc != 0 ) { err = "del"; goto fail; } } else { if ( id == lo ) { /* reposition on lo slot */ data.data = &nlo; cursor->c_get( cursor, key, &data, DB_PREV ); } rc = cursor->c_del( cursor, 0 ); if ( rc != 0 ) { err = "c_del"; goto fail; } } if ( lo <= hi ) { BDB_ID2DISK( id, &nid ); data.data = &nid; rc = cursor->c_put( cursor, key, &data, DB_KEYFIRST ); if ( rc != 0 ) { err = "c_put lo/hi"; goto fail; } } } } } else { /* initial c_get failed, nothing was done */ fail: if ( rc != DB_NOTFOUND ) { Debug( LDAP_DEBUG_ANY, "=> bdb_idl_delete_key: " "%s failed: %s (%d)\n", err, db_strerror(rc), rc ); } cursor->c_close( cursor ); return rc; } rc = cursor->c_close( cursor ); if( rc != 0 ) { Debug( LDAP_DEBUG_ANY, "=> bdb_idl_delete_key: c_close failed: %s (%d)\n", db_strerror(rc), rc, 0 ); } return rc; }
int bdb_idl_insert_key( BackendDB *be, DB *db, DB_TXN *tid, DBT *key, ID id ) { struct bdb_info *bdb = (struct bdb_info *) be->be_private; int rc; DBT data; DBC *cursor; ID lo, hi, nlo, nhi, nid; char *err; { char buf[16]; Debug( LDAP_DEBUG_ARGS, "bdb_idl_insert_key: %lx %s\n", (long) id, bdb_show_key( key, buf ), 0 ); } assert( id != NOID ); DBTzero( &data ); data.size = sizeof( ID ); data.ulen = data.size; data.flags = DB_DBT_USERMEM; BDB_ID2DISK( id, &nid ); rc = db->cursor( db, tid, &cursor, bdb->bi_db_opflags ); if ( rc != 0 ) { Debug( LDAP_DEBUG_ANY, "=> bdb_idl_insert_key: " "cursor failed: %s (%d)\n", db_strerror(rc), rc, 0 ); return rc; } data.data = &nlo; /* Fetch the first data item for this key, to see if it * exists and if it's a range. */ rc = cursor->c_get( cursor, key, &data, DB_SET ); err = "c_get"; if ( rc == 0 ) { if ( nlo != 0 ) { /* not a range, count the number of items */ db_recno_t count; rc = cursor->c_count( cursor, &count, 0 ); if ( rc != 0 ) { err = "c_count"; goto fail; } if ( count >= BDB_IDL_DB_MAX ) { /* No room, convert to a range */ DBT key2 = *key; db_recno_t i; key2.dlen = key2.ulen; key2.flags |= DB_DBT_PARTIAL; BDB_DISK2ID( &nlo, &lo ); data.data = &nhi; rc = cursor->c_get( cursor, &key2, &data, DB_NEXT_NODUP ); if ( rc != 0 && rc != DB_NOTFOUND ) { err = "c_get next_nodup"; goto fail; } if ( rc == DB_NOTFOUND ) { rc = cursor->c_get( cursor, key, &data, DB_LAST ); if ( rc != 0 ) { err = "c_get last"; goto fail; } } else { rc = cursor->c_get( cursor, key, &data, DB_PREV ); if ( rc != 0 ) { err = "c_get prev"; goto fail; } } BDB_DISK2ID( &nhi, &hi ); /* Update hi/lo if needed, then delete all the items * between lo and hi */ if ( id < lo ) { lo = id; nlo = nid; } else if ( id > hi ) { hi = id; nhi = nid; } data.data = &nid; /* Don't fetch anything, just position cursor */ data.flags = DB_DBT_USERMEM | DB_DBT_PARTIAL; data.dlen = data.ulen = 0; rc = cursor->c_get( cursor, key, &data, DB_SET ); if ( rc != 0 ) { err = "c_get 2"; goto fail; } rc = cursor->c_del( cursor, 0 ); if ( rc != 0 ) { err = "c_del range1"; goto fail; } /* Delete all the records */ for ( i=1; i<count; i++ ) { rc = cursor->c_get( cursor, &key2, &data, DB_NEXT_DUP ); if ( rc != 0 ) { err = "c_get next_dup"; goto fail; } rc = cursor->c_del( cursor, 0 ); if ( rc != 0 ) { err = "c_del range"; goto fail; } } /* Store the range marker */ data.size = data.ulen = sizeof(ID); data.flags = DB_DBT_USERMEM; nid = 0; rc = cursor->c_put( cursor, key, &data, DB_KEYFIRST ); if ( rc != 0 ) { err = "c_put range"; goto fail; } nid = nlo; rc = cursor->c_put( cursor, key, &data, DB_KEYLAST ); if ( rc != 0 ) { err = "c_put lo"; goto fail; } nid = nhi; rc = cursor->c_put( cursor, key, &data, DB_KEYLAST ); if ( rc != 0 ) { err = "c_put hi"; goto fail; } } else { /* There's room, just store it */ goto put1; } } else { /* It's a range, see if we need to rewrite * the boundaries */ hi = id; data.data = &nlo; rc = cursor->c_get( cursor, key, &data, DB_NEXT_DUP ); if ( rc != 0 ) { err = "c_get lo"; goto fail; } BDB_DISK2ID( &nlo, &lo ); if ( id > lo ) { data.data = &nhi; rc = cursor->c_get( cursor, key, &data, DB_NEXT_DUP ); if ( rc != 0 ) { err = "c_get hi"; goto fail; } BDB_DISK2ID( &nhi, &hi ); } if ( id < lo || id > hi ) { /* Delete the current lo/hi */ rc = cursor->c_del( cursor, 0 ); if ( rc != 0 ) { err = "c_del"; goto fail; } data.data = &nid; rc = cursor->c_put( cursor, key, &data, DB_KEYFIRST ); if ( rc != 0 ) { err = "c_put lo/hi"; goto fail; } } } } else if ( rc == DB_NOTFOUND ) { put1: data.data = &nid; rc = cursor->c_put( cursor, key, &data, DB_NODUPDATA ); /* Don't worry if it's already there */ if ( rc != 0 && rc != DB_KEYEXIST ) { err = "c_put id"; goto fail; } } else { /* initial c_get failed, nothing was done */ fail: Debug( LDAP_DEBUG_ANY, "=> bdb_idl_insert_key: " "%s failed: %s (%d)\n", err, db_strerror(rc), rc ); cursor->c_close( cursor ); return rc; } /* If key was added (didn't already exist) and using IDL cache, * update key in IDL cache. */ if ( !rc && bdb->bi_idl_cache_max_size ) { bdb_idl_cache_add_id( bdb, db, key, id ); } rc = cursor->c_close( cursor ); if( rc != 0 ) { Debug( LDAP_DEBUG_ANY, "=> bdb_idl_insert_key: " "c_close failed: %s (%d)\n", db_strerror(rc), rc, 0 ); } return rc; }
void run_xact(DB_ENV *dbenv, DB *db, int offset, int count) { va_list ap; DBC *dbc; DBT key, data; DB_TXN *tid; int ret; char *s; /* Initialization. */ memset(&key, 0, sizeof(key)); memset(&data, 0, sizeof(data)); int keyPtr; int valPtr; key.data = &keyPtr; key.size = sizeof(int);/*strlen(name);*/ data.data = &valPtr; data.size = sizeof(int); retry: /* Begin the transaction. */ if ((ret = dbenv->txn_begin(dbenv, NULL, &tid, 0)) != 0) { dbenv->err(dbenv, ret, "DB_ENV->txn_begin"); exit (1); } /* Delete any previously existing item. */ /* switch (ret = db->del(db, tid, &key, 0)) { case 0: case DB_NOTFOUND: break; case DB_LOCK_DEADLOCK: / * Deadlock: retry the operation. * / if ((ret = tid->abort(tid)) != 0) { dbenv->err(dbenv, ret, "DB_TXN->abort"); exit (1); } goto retry; default: dbenv->err(dbenv, ret, "db->del: %s", name); exit (1); } */ /* Create a cursor. */ if ((ret = db->cursor(db, tid, &dbc, 0)) != 0) { dbenv->err(dbenv, ret, "db->cursor"); exit (1); } /* Append the items, in order. */ // va_start(ap, name); // while ((s = va_arg(ap, char *)) != NULL) { int q; for(q = offset; q < offset + count; q++) { keyPtr = q; valPtr = q; /* data.data = s; data.size = strlen(s); */ // printf("A"); fflush(NULL); switch (ret = dbc->c_put(dbc, &key, &data, DB_KEYLAST)) { case 0: // printf("B"); fflush(NULL); break; case DB_LOCK_DEADLOCK: va_end(ap); /* Deadlock: retry the operation. */ if ((ret = dbc->c_close(dbc)) != 0) { dbenv->err( dbenv, ret, "dbc->c_close"); exit (1); } if ((ret = tid->abort(tid)) != 0) { dbenv->err(dbenv, ret, "DB_TXN->abort"); exit (1); } goto retry; default: /* Error: run recovery. */ dbenv->err(dbenv, ret, "dbc->put: %d/%d", q, q); exit (1); } } va_end(ap); /* Success: commit the change. */ if ((ret = dbc->c_close(dbc)) != 0) { dbenv->err(dbenv, ret, "dbc->c_close"); exit (1); } if ((ret = tid->commit(tid, 0)) != 0) { dbenv->err(dbenv, ret, "DB_TXN->commit"); exit (1); } }
void add_cat(DB_ENV *dbenv, DB *db, char *name, ...) { va_list ap; DBC *dbc; DBT key, data; DB_TXN *tid; int ret; char *s; /* Initialization. */ memset(&key, 0, sizeof(key)); memset(&data, 0, sizeof(data)); key.data = name; key.size = strlen(name); retry: /* Begin the transaction. */ if ((ret = dbenv->txn_begin(dbenv, NULL, &tid, 0)) != 0) { dbenv->err(dbenv, ret, "DB_ENV->txn_begin"); exit (1); } /* Delete any previously existing item. */ switch (ret = db->del(db, tid, &key, 0)) { case 0: case DB_NOTFOUND: break; case DB_LOCK_DEADLOCK: /* Deadlock: retry the operation. */ if ((ret = tid->abort(tid)) != 0) { dbenv->err(dbenv, ret, "DB_TXN->abort"); exit (1); } goto retry; default: dbenv->err(dbenv, ret, "db->del: %s", name); exit (1); } /* Create a cursor. */ if ((ret = db->cursor(db, tid, &dbc, 0)) != 0) { dbenv->err(dbenv, ret, "db->cursor"); exit (1); } /* Append the items, in order. */ va_start(ap, name); while ((s = va_arg(ap, char *)) != NULL) { data.data = s; data.size = strlen(s); switch (ret = dbc->c_put(dbc, &key, &data, DB_KEYLAST)) { case 0: break; case DB_LOCK_DEADLOCK: va_end(ap); /* Deadlock: retry the operation. */ if ((ret = dbc->c_close(dbc)) != 0) { dbenv->err( dbenv, ret, "dbc->c_close"); exit (1); } if ((ret = tid->abort(tid)) != 0) { dbenv->err(dbenv, ret, "DB_TXN->abort"); exit (1); } goto retry; default: /* Error: run recovery. */ dbenv->err(dbenv, ret, "dbc->put: %s/%s", name, s); exit (1); } } va_end(ap); /* Success: commit the change. */ if ((ret = dbc->c_close(dbc)) != 0) { dbenv->err(dbenv, ret, "dbc->c_close"); exit (1); } if ((ret = tid->commit(tid, 0)) != 0) { dbenv->err(dbenv, ret, "DB_TXN->commit"); exit (1); } }
static int bdb_tool_idl_flush_one( void *v1, void *arg ) { bdb_tool_idl_cache *ic = v1; DB *db = arg; struct bdb_info *bdb = bdb_tool_info; bdb_tool_idl_cache_entry *ice; DBC *curs; DBT key, data; int i, rc; ID id, nid; /* Freshly allocated, ignore it */ if ( !ic->head && ic->count <= BDB_IDL_DB_SIZE ) { return 0; } rc = db->cursor( db, NULL, &curs, 0 ); if ( rc ) return -1; DBTzero( &key ); DBTzero( &data ); bv2DBT( &ic->kstr, &key ); data.size = data.ulen = sizeof( ID ); data.flags = DB_DBT_USERMEM; data.data = &nid; rc = curs->c_get( curs, &key, &data, DB_SET ); /* If key already exists and we're writing a range... */ if ( rc == 0 && ic->count > BDB_IDL_DB_SIZE ) { /* If it's not currently a range, must delete old info */ if ( nid ) { /* Skip lo */ while ( curs->c_get( curs, &key, &data, DB_NEXT_DUP ) == 0 ) curs->c_del( curs, 0 ); nid = 0; /* Store range marker */ curs->c_put( curs, &key, &data, DB_KEYFIRST ); } else { /* Skip lo */ rc = curs->c_get( curs, &key, &data, DB_NEXT_DUP ); /* Get hi */ rc = curs->c_get( curs, &key, &data, DB_NEXT_DUP ); /* Delete hi */ curs->c_del( curs, 0 ); } BDB_ID2DISK( ic->last, &nid ); curs->c_put( curs, &key, &data, DB_KEYLAST ); rc = 0; } else if ( rc && rc != DB_NOTFOUND ) { rc = -1; } else if ( ic->count > BDB_IDL_DB_SIZE ) { /* range, didn't exist before */ nid = 0; rc = curs->c_put( curs, &key, &data, DB_KEYLAST ); if ( rc == 0 ) { BDB_ID2DISK( ic->first, &nid ); rc = curs->c_put( curs, &key, &data, DB_KEYLAST ); if ( rc == 0 ) { BDB_ID2DISK( ic->last, &nid ); rc = curs->c_put( curs, &key, &data, DB_KEYLAST ); } } if ( rc ) { rc = -1; } } else { int n; /* Just a normal write */ rc = 0; for ( ice = ic->head, n=0; ice; ice = ice->next, n++ ) { int end; if ( ice->next ) { end = IDBLOCK; } else { end = ic->count & (IDBLOCK-1); if ( !end ) end = IDBLOCK; } for ( i=0; i<end; i++ ) { if ( !ice->ids[i] ) continue; BDB_ID2DISK( ice->ids[i], &nid ); rc = curs->c_put( curs, &key, &data, DB_NODUPDATA ); if ( rc ) { if ( rc == DB_KEYEXIST ) { rc = 0; continue; } rc = -1; break; } } if ( rc ) { rc = -1; break; } } if ( ic->head ) { ldap_pvt_thread_mutex_lock( &bdb->bi_idl_tree_lrulock ); ic->tail->next = bdb_tool_idl_free_list; bdb_tool_idl_free_list = ic->head; bdb->bi_idl_cache_size -= n; ldap_pvt_thread_mutex_unlock( &bdb->bi_idl_tree_lrulock ); } } if ( ic != db->app_private ) { ch_free( ic ); } else { ic->head = ic->tail = NULL; } curs->c_close( curs ); return rc; }
icalerrorenum icalbdbset_commit(icalset *set) { DB *dbp; DBC *dbcp; DBT key, data; icalcomponent *c; char *str = NULL; int ret = 0; int reterr = ICAL_NO_ERROR; char keystore[256]; char uidbuf[256]; char datastore[1024]; char *more_mem = NULL; DB_TXN *tid = NULL; icalbdbset *bset = (icalbdbset *) set; int bad_uid_counter = 0; int retry = 0, done = 0, completed = 0, deadlocked = 0; icalerror_check_arg_re((bset != 0), "bset", ICAL_BADARG_ERROR); dbp = bset->dbp; icalerror_check_arg_re((dbp != 0), "dbp is invalid", ICAL_BADARG_ERROR); if (bset->changed == 0) { return ICAL_NO_ERROR; } memset(&key, 0, sizeof(key)); memset(&data, 0, sizeof(data)); key.flags = DB_DBT_USERMEM; key.data = keystore; key.ulen = (u_int32_t) sizeof(keystore); data.flags = DB_DBT_USERMEM; data.data = datastore; data.ulen = (u_int32_t) sizeof(datastore); if (!ICAL_DB_ENV) { if (icalbdbset_init_dbenv(NULL, NULL) != 0) { return ICAL_INTERNAL_ERROR; } } while ((retry < MAX_RETRY) && !done) { if ((ret = ICAL_DB_ENV->txn_begin(ICAL_DB_ENV, NULL, &tid, 0)) != 0) { if (ret == DB_LOCK_DEADLOCK) { retry++; continue; } else if (ret == DB_RUNRECOVERY) { ICAL_DB_ENV->err(ICAL_DB_ENV, ret, "icalbdbset_commit: txn_begin failed"); abort(); } else { ICAL_DB_ENV->err(ICAL_DB_ENV, ret, "icalbdbset_commit"); return ICAL_INTERNAL_ERROR; } } /* first delete everything in the database, because there could be removed components */ if ((ret = dbp->cursor(dbp, tid, &dbcp, DB_DIRTY_READ)) != 0) { tid->abort(tid); if (ret == DB_LOCK_DEADLOCK) { retry++; continue; } else if (ret == DB_RUNRECOVERY) { ICAL_DB_ENV->err(ICAL_DB_ENV, ret, "curor failed"); abort(); } else { ICAL_DB_ENV->err(ICAL_DB_ENV, ret, "curor failed"); /* leave bset->changed set to true */ return ICAL_INTERNAL_ERROR; } } /* fetch the key/data pair, then delete it */ completed = 0; while (!completed && !deadlocked) { ret = dbcp->c_get(dbcp, &key, &data, DB_NEXT); if (ret == DB_NOTFOUND) { completed = 1; } else if (ret == ENOMEM) { if (more_mem) { free(more_mem); } more_mem = malloc(data.ulen + 1024); data.data = more_mem; data.ulen = data.ulen + 1024; } else if (ret == DB_LOCK_DEADLOCK) { deadlocked = 1; } else if (ret == DB_RUNRECOVERY) { tid->abort(tid); ICAL_DB_ENV->err(ICAL_DB_ENV, ret, "c_get failed."); abort(); } else if (ret == 0) { if ((ret = dbcp->c_del(dbcp, 0)) != 0) { dbp->err(dbp, ret, "cursor"); if (ret == DB_KEYEMPTY) { /* never actually created, continue onward.. */ /* do nothing - break; */ } else if (ret == DB_LOCK_DEADLOCK) { deadlocked = 1; } else { /*char *foo = db_strerror(ret); */ abort(); } } } else { /* some other non-fatal error */ dbcp->c_close(dbcp); tid->abort(tid); if (more_mem) { free(more_mem); more_mem = NULL; } return ICAL_INTERNAL_ERROR; } } if (more_mem) { free(more_mem); more_mem = NULL; } if (deadlocked) { dbcp->c_close(dbcp); tid->abort(tid); retry++; continue; /* next retry */ } deadlocked = 0; for (c = icalcomponent_get_first_component(bset->cluster, ICAL_ANY_COMPONENT); c != 0 && !deadlocked; c = icalcomponent_get_next_component(bset->cluster, ICAL_ANY_COMPONENT)) { memset(&key, 0, sizeof(key)); memset(&data, 0, sizeof(data)); /* Note that we're always inserting into a primary index. */ if (icalcomponent_isa(c) != ICAL_VAGENDA_COMPONENT) { char *uidstr = (char *)icalcomponent_get_uid(c); if (!uidstr) { /* this shouldn't happen */ /* no uid string, we need to add one */ snprintf(uidbuf, 256, "baduid%d-%d", getpid(), bad_uid_counter++); key.data = uidbuf; } else { key.data = uidstr; } } else { char *relcalid = NULL; relcalid = (char *)icalcomponent_get_relcalid(c); if (relcalid == NULL) { snprintf(uidbuf, 256, "baduid%d-%d", getpid(), bad_uid_counter++); key.data = uidbuf; } else { key.data = relcalid; } } key.size = (u_int32_t) strlen(key.data); str = icalcomponent_as_ical_string_r(c); data.data = str; data.size = (u_int32_t) strlen(str); if ((ret = dbcp->c_put(dbcp, &key, &data, DB_KEYLAST)) != 0) { if (ret == DB_LOCK_DEADLOCK) { deadlocked = 1; } else if (ret == DB_RUNRECOVERY) { ICAL_DB_ENV->err(ICAL_DB_ENV, ret, "c_put failed."); abort(); } else { ICAL_DB_ENV->err(ICAL_DB_ENV, ret, "c_put failed %s.", str); /* continue to try to put as many icalcomponent as possible */ reterr = ICAL_INTERNAL_ERROR; } } } if (str) { free(str); } if (deadlocked) { dbcp->c_close(dbcp); tid->abort(tid); retry++; continue; } if ((ret = dbcp->c_close(dbcp)) != 0) { tid->abort(tid); if (ret == DB_LOCK_DEADLOCK) { retry++; continue; } else if (ret == DB_RUNRECOVERY) { ICAL_DB_ENV->err(ICAL_DB_ENV, ret, "c_closed failed."); abort(); } else { ICAL_DB_ENV->err(ICAL_DB_ENV, ret, "c_closed failed."); reterr = ICAL_INTERNAL_ERROR; } } if ((ret = tid->commit(tid, 0)) != 0) { tid->abort(tid); if (ret == DB_LOCK_DEADLOCK) { retry++; continue; } else if (ret == DB_RUNRECOVERY) { ICAL_DB_ENV->err(ICAL_DB_ENV, ret, "commit failed."); abort(); } else { ICAL_DB_ENV->err(ICAL_DB_ENV, ret, "commit failed."); reterr = ICAL_INTERNAL_ERROR; } } done = 1; } bset->changed = 0; return reterr; }
int bdb_idl_delete_key( BackendDB *be, DB *db, DB_TXN *tid, DBT *key, ID id ) { struct bdb_info *bdb = (struct bdb_info *) be->be_private; int rc; DBT data; DBC *cursor; ID lo, hi, tmp; char *err; { char buf[16]; #ifdef NEW_LOGGING LDAP_LOG( INDEX, ARGS, "bdb_idl_delete_key: %lx %s\n", (long) id, bdb_show_key( key, buf ), 0 ); #else Debug( LDAP_DEBUG_ARGS, "bdb_idl_delete_key: %lx %s\n", (long) id, bdb_show_key( key, buf ), 0 ); #endif } assert( id != NOID ); #ifdef SLAP_IDL_CACHE if ( bdb->bi_idl_cache_max_size ) { bdb_idl_cache_entry_t *matched_idl_entry, idl_tmp; DBT2bv( key, &idl_tmp.kstr ); idl_tmp.db = db; ldap_pvt_thread_mutex_lock( &bdb->bi_idl_tree_mutex ); matched_idl_entry = avl_find( bdb->bi_idl_tree, &idl_tmp, bdb_idl_entry_cmp ); if ( matched_idl_entry != NULL ) { if ( avl_delete( &bdb->bi_idl_tree, (caddr_t) matched_idl_entry, bdb_idl_entry_cmp ) == NULL ) { #ifdef NEW_LOGGING LDAP_LOG( INDEX, ERR, "bdb_idl_fetch_key: AVL delete failed\n", 0, 0, 0 ); #else Debug( LDAP_DEBUG_ANY, "=> bdb_idl_fetch_key: " "AVL delete failed\n", 0, 0, 0 ); #endif } --bdb->bi_idl_cache_size; IDL_LRU_DELETE( bdb, matched_idl_entry ); free( matched_idl_entry->kstr.bv_val ); free( matched_idl_entry->idl ); free( matched_idl_entry ); } ldap_pvt_thread_mutex_unlock( &bdb->bi_idl_tree_mutex ); } #endif DBTzero( &data ); data.data = &tmp; data.size = sizeof( id ); data.ulen = data.size; data.flags = DB_DBT_USERMEM; rc = db->cursor( db, tid, &cursor, bdb->bi_db_opflags ); if ( rc != 0 ) { #ifdef NEW_LOGGING LDAP_LOG( INDEX, ERR, "bdb_idl_delete_key: cursor failed: %s (%d)\n", db_strerror(rc), rc, 0 ); #else Debug( LDAP_DEBUG_ANY, "=> bdb_idl_delete_key: " "cursor failed: %s (%d)\n", db_strerror(rc), rc, 0 ); #endif return rc; } /* Fetch the first data item for this key, to see if it * exists and if it's a range. */ rc = cursor->c_get( cursor, key, &data, DB_SET | DB_RMW ); err = "c_get"; if ( rc == 0 ) { if ( tmp != 0 ) { /* Not a range, just delete it */ if (tmp != id) { /* position to correct item */ tmp = id; rc = cursor->c_get( cursor, key, &data, DB_GET_BOTH | DB_RMW ); if ( rc != 0 ) { err = "c_get id"; goto fail; } } rc = cursor->c_del( cursor, 0 ); if ( rc != 0 ) { err = "c_del id"; goto fail; } } else { /* It's a range, see if we need to rewrite * the boundaries */ data.data = &lo; rc = cursor->c_get( cursor, key, &data, DB_NEXT_DUP ); if ( rc != 0 ) { err = "c_get lo"; goto fail; } data.data = &hi; rc = cursor->c_get( cursor, key, &data, DB_NEXT_DUP ); if ( rc != 0 ) { err = "c_get hi"; goto fail; } if ( id == lo || id == hi ) { if ( id == lo ) { id++; lo = id; } else if ( id == hi ) { id--; hi = id; } if ( lo >= hi ) { /* The range has collapsed... */ rc = db->del( db, tid, key, 0 ); if ( rc != 0 ) { err = "del"; goto fail; } } else { if ( id == lo ) { /* reposition on lo slot */ data.data = &lo; cursor->c_get( cursor, key, &data, DB_PREV ); lo = id; } rc = cursor->c_del( cursor, 0 ); if ( rc != 0 ) { err = "c_del"; goto fail; } } if ( lo <= hi ) { data.data = &id; rc = cursor->c_put( cursor, key, &data, DB_KEYFIRST ); if ( rc != 0 ) { err = "c_put lo/hi"; goto fail; } } } } } else { /* initial c_get failed, nothing was done */ fail: if ( rc != DB_NOTFOUND ) { #ifdef NEW_LOGGING LDAP_LOG( INDEX, ERR, "bdb_idl_delete_key: %s failed: %s (%d)\n", err, db_strerror(rc), rc ); #else Debug( LDAP_DEBUG_ANY, "=> bdb_idl_delete_key: " "%s failed: %s (%d)\n", err, db_strerror(rc), rc ); #endif } cursor->c_close( cursor ); return rc; } rc = cursor->c_close( cursor ); if( rc != 0 ) { #ifdef NEW_LOGGING LDAP_LOG( INDEX, ERR, "bdb_idl_delete_key: c_close failed: %s (%d)\n", db_strerror(rc), rc, 0 ); #else Debug( LDAP_DEBUG_ANY, "=> bdb_idl_delete_key: c_close failed: %s (%d)\n", db_strerror(rc), rc, 0 ); #endif } return rc; }
int bdb_idl_insert_key( BackendDB *be, DB *db, DB_TXN *tid, DBT *key, ID id ) { struct bdb_info *bdb = (struct bdb_info *) be->be_private; int rc; DBT data; DBC *cursor; ID lo, hi, tmp; char *err; { char buf[16]; #ifdef NEW_LOGGING LDAP_LOG( INDEX, ARGS, "bdb_idl_insert_key: %lx %s\n", (long) id, bdb_show_key( key, buf ), 0 ); #else Debug( LDAP_DEBUG_ARGS, "bdb_idl_insert_key: %lx %s\n", (long) id, bdb_show_key( key, buf ), 0 ); #endif } assert( id != NOID ); #ifdef SLAP_IDL_CACHE if ( bdb->bi_idl_cache_size ) { bdb_idl_cache_entry_t *matched_idl_entry, idl_tmp; DBT2bv( key, &idl_tmp.kstr ); idl_tmp.db = db; ldap_pvt_thread_mutex_lock( &bdb->bi_idl_tree_mutex ); matched_idl_entry = avl_find( bdb->bi_idl_tree, &idl_tmp, bdb_idl_entry_cmp ); if ( matched_idl_entry != NULL ) { if ( avl_delete( &bdb->bi_idl_tree, (caddr_t) matched_idl_entry, bdb_idl_entry_cmp ) == NULL ) { #ifdef NEW_LOGGING LDAP_LOG( INDEX, ERR, "bdb_idl_fetch_key: AVL delete failed\n", 0, 0, 0 ); #else Debug( LDAP_DEBUG_ANY, "=> bdb_idl_fetch_key: " "AVL delete failed\n", 0, 0, 0 ); #endif } --bdb->bi_idl_cache_size; IDL_LRU_DELETE( bdb, matched_idl_entry ); free( matched_idl_entry->kstr.bv_val ); free( matched_idl_entry->idl ); free( matched_idl_entry ); } ldap_pvt_thread_mutex_unlock( &bdb->bi_idl_tree_mutex ); } #endif DBTzero( &data ); data.size = sizeof( ID ); data.ulen = data.size; data.flags = DB_DBT_USERMEM; rc = db->cursor( db, tid, &cursor, bdb->bi_db_opflags ); if ( rc != 0 ) { #ifdef NEW_LOGGING LDAP_LOG( INDEX, ERR, "bdb_idl_insert_key: cursor failed: %s (%d)\n", db_strerror(rc), rc, 0 ); #else Debug( LDAP_DEBUG_ANY, "=> bdb_idl_insert_key: " "cursor failed: %s (%d)\n", db_strerror(rc), rc, 0 ); #endif return rc; } data.data = &tmp; /* Fetch the first data item for this key, to see if it * exists and if it's a range. */ rc = cursor->c_get( cursor, key, &data, DB_SET | DB_RMW ); err = "c_get"; if ( rc == 0 ) { if ( tmp != 0 ) { /* not a range, count the number of items */ db_recno_t count; rc = cursor->c_count( cursor, &count, 0 ); if ( rc != 0 ) { err = "c_count"; goto fail; } if ( count >= BDB_IDL_DB_MAX ) { /* No room, convert to a range */ DBT key2 = *key; key2.dlen = key2.ulen; key2.flags |= DB_DBT_PARTIAL; lo = tmp; data.data = &hi; rc = cursor->c_get( cursor, &key2, &data, DB_NEXT_NODUP ); if ( rc != 0 && rc != DB_NOTFOUND ) { err = "c_get next_nodup"; goto fail; } if ( rc == DB_NOTFOUND ) { rc = cursor->c_get( cursor, key, &data, DB_LAST ); if ( rc != 0 ) { err = "c_get last"; goto fail; } } else { rc = cursor->c_get( cursor, key, &data, DB_PREV ); if ( rc != 0 ) { err = "c_get prev"; goto fail; } } if ( id < lo ) lo = id; else if ( id > hi ) hi = id; rc = db->del( db, tid, key, 0 ); if ( rc != 0 ) { err = "del"; goto fail; } data.data = &id; id = 0; rc = cursor->c_put( cursor, key, &data, DB_KEYFIRST ); if ( rc != 0 ) { err = "c_put 0"; goto fail; } id = lo; rc = cursor->c_put( cursor, key, &data, DB_KEYLAST ); if ( rc != 0 ) { err = "c_put lo"; goto fail; } id = hi; rc = cursor->c_put( cursor, key, &data, DB_KEYLAST ); if ( rc != 0 ) { err = "c_put hi"; goto fail; } } else { /* There's room, just store it */ goto put1; } } else { /* It's a range, see if we need to rewrite * the boundaries */ hi = id; data.data = &lo; rc = cursor->c_get( cursor, key, &data, DB_NEXT_DUP ); if ( rc != 0 ) { err = "c_get lo"; goto fail; } if ( id > lo ) { data.data = &hi; rc = cursor->c_get( cursor, key, &data, DB_NEXT_DUP ); if ( rc != 0 ) { err = "c_get hi"; goto fail; } } if ( id < lo || id > hi ) { /* Delete the current lo/hi */ rc = cursor->c_del( cursor, 0 ); if ( rc != 0 ) { err = "c_del"; goto fail; } data.data = &id; rc = cursor->c_put( cursor, key, &data, DB_KEYFIRST ); if ( rc != 0 ) { err = "c_put lo/hi"; goto fail; } } } } else if ( rc == DB_NOTFOUND ) { put1: data.data = &id; rc = cursor->c_put( cursor, key, &data, DB_NODUPDATA ); /* Don't worry if it's already there */ if ( rc != 0 && rc != DB_KEYEXIST ) { err = "c_put id"; goto fail; } } else { /* initial c_get failed, nothing was done */ fail: #ifdef NEW_LOGGING LDAP_LOG( INDEX, ERR, "bdb_idl_insert_key: %s failed: %s (%d)\n", err, db_strerror(rc), rc ); #else Debug( LDAP_DEBUG_ANY, "=> bdb_idl_insert_key: " "%s failed: %s (%d)\n", err, db_strerror(rc), rc ); #endif cursor->c_close( cursor ); return rc; } rc = cursor->c_close( cursor ); if( rc != 0 ) { #ifdef NEW_LOGGING LDAP_LOG( INDEX, ERR, "bdb_idl_insert_key: c_close failed: %s (%d)\n", db_strerror(rc), rc, 0 ); #else Debug( LDAP_DEBUG_ANY, "=> bdb_idl_insert_key: " "c_close failed: %s (%d)\n", db_strerror(rc), rc, 0 ); #endif } return rc; }
/* ----------------------------- */ static cnid_t get_cnid(CNID_private *db) { DBT rootinfo_key, rootinfo_data; DBC *cursor; int rc; int flag, setstamp=0; cnid_t hint,id; char buf[ROOTINFO_DATALEN]; char stamp[CNID_DEV_LEN]; if ((rc = db->db_cnid->cursor(db->db_cnid, NULL, &cursor, DB_WRITECURSOR) ) != 0) { LOG(log_error, logtype_default, "get_cnid: Unable to get a cursor: %s", db_strerror(rc)); return CNID_INVALID; } memset(&rootinfo_key, 0, sizeof(rootinfo_key)); memset(&rootinfo_data, 0, sizeof(rootinfo_data)); rootinfo_key.data = ROOTINFO_KEY; rootinfo_key.size = ROOTINFO_KEYLEN; switch (rc = cursor->c_get(cursor, &rootinfo_key, &rootinfo_data, DB_SET)) { case 0: memcpy(&hint, (char *)rootinfo_data.data +CNID_TYPE_OFS, sizeof(hint)); id = ntohl(hint); /* If we've hit the max CNID allowed, we return a fatal error. CNID * needs to be recycled before proceding. */ if (++id == CNID_INVALID) { LOG(log_error, logtype_default, "cnid_add: FATAL: CNID database has reached its limit."); errno = CNID_ERR_MAX; goto cleanup; } hint = htonl(id); flag = DB_CURRENT; break; case DB_NOTFOUND: hint = htonl(CNID_START); flag = DB_KEYFIRST; setstamp = 1; break; default: LOG(log_error, logtype_default, "cnid_add: Unable to lookup rootinfo: %s", db_strerror(rc)); errno = CNID_ERR_DB; goto cleanup; } memcpy(buf, ROOTINFO_DATA, ROOTINFO_DATALEN); rootinfo_data.data = buf; rootinfo_data.size = ROOTINFO_DATALEN; memcpy((char *)rootinfo_data.data +CNID_TYPE_OFS, &hint, sizeof(hint)); if (setstamp) { if (db_stamp(stamp, CNID_DEV_LEN) < 0) { goto cleanup; } memcpy((char *)rootinfo_data.data +CNID_DEV_OFS, stamp, sizeof(stamp)); } switch (rc = cursor->c_put(cursor, &rootinfo_key, &rootinfo_data, flag)) { case 0: break; default: LOG(log_error, logtype_default, "cnid_add: Unable to update rootinfo: %s", db_strerror(rc)); errno = CNID_ERR_DB; goto cleanup; } if ((rc = cursor->c_close(cursor)) != 0) { LOG(log_error, logtype_default, "get_cnid: Unable to close cursor: %s", db_strerror(rc)); errno = CNID_ERR_DB; return CNID_INVALID; } return hint; cleanup: if ((rc = cursor->c_close(cursor)) != 0) { LOG(log_error, logtype_default, "get_cnid: Unable to close cursor: %s", db_strerror(rc)); return CNID_INVALID; } return CNID_INVALID; }