int main(int argc,char * argv[]) { int i = 0, j = 0, rc; MDB_env *env; MDB_dbi dbi; MDB_val key, data; MDB_txn *txn; MDB_stat mst; MDB_cursor *cursor; int count; int *values; char sval[32] = ""; int env_oflags; struct stat db_stat, exe_stat; srand(time(NULL)); count = (rand()%384) + 64; values = (int *)malloc(count*sizeof(int)); for(i = 0;i<count;i++) { values[i] = rand()%1024; } E(mdb_env_create(&env)); E(mdb_env_set_maxreaders(env, 1)); E(mdb_env_set_mapsize(env, 10485760)); E(mdb_env_set_maxdbs(env, 4)); E(stat("/proc/self/exe", &exe_stat)?errno:0); E(stat(DBPATH "/.", &db_stat)?errno:0); env_oflags = MDB_FIXEDMAP | MDB_NOSYNC; if (major(db_stat.st_dev) != major(exe_stat.st_dev)) { /* LY: Assume running inside a CI-environment: * 1) don't use FIXEDMAP to avoid EBUSY in case collision, * which could be inspired by address space randomisation feature. * 2) drop MDB_NOSYNC expecting that DBPATH is at a tmpfs or some dedicated storage. */ env_oflags = 0; } /* LY: especially here we always needs MDB_NOSYNC * for testing mdb_env_close_ex() and "redo-to-steady" on open. */ env_oflags |= MDB_NOSYNC; E(mdb_env_open(env, DBPATH, env_oflags, 0664)); E(mdb_txn_begin(env, NULL, 0, &txn)); if (mdb_dbi_open(txn, "id1", MDB_CREATE, &dbi) == MDB_SUCCESS) E(mdb_drop(txn, dbi, 1)); E(mdb_dbi_open(txn, "id1", MDB_CREATE, &dbi)); key.mv_size = sizeof(int); key.mv_data = sval; data.mv_size = sizeof(sval); data.mv_data = sval; printf("Adding %d values\n", count); for (i=0;i<count;i++) { sprintf(sval, "%03x %d foo bar", values[i], values[i]); if (RES(MDB_KEYEXIST, mdb_put(txn, dbi, &key, &data, MDB_NOOVERWRITE))) j++; } if (j) printf("%d duplicates skipped\n", j); E(mdb_txn_commit(txn)); E(mdb_env_stat(env, &mst)); printf("check-preset-a\n"); E(mdb_txn_begin(env, NULL, MDB_RDONLY, &txn)); E(mdb_cursor_open(txn, dbi, &cursor)); int present_a = 0; while ((rc = mdb_cursor_get(cursor, &key, &data, MDB_NEXT)) == 0) { printf("key: %p %.*s, data: %p %.*s\n", key.mv_data, (int) key.mv_size, (char *) key.mv_data, data.mv_data, (int) data.mv_size, (char *) data.mv_data); ++present_a; } CHECK(rc == MDB_NOTFOUND, "mdb_cursor_get"); CHECK(present_a == count - j, "mismatch"); mdb_cursor_close(cursor); mdb_txn_abort(txn); mdb_env_sync(env, 1); j=0; key.mv_data = sval; for (i= count - 1; i > -1; i-= (rand()%5)) { j++; txn=NULL; E(mdb_txn_begin(env, NULL, 0, &txn)); sprintf(sval, "%03x ", values[i]); if (RES(MDB_NOTFOUND, mdb_del(txn, dbi, &key, NULL))) { j--; mdb_txn_abort(txn); } else { E(mdb_txn_commit(txn)); } } free(values); printf("Deleted %d values\n", j); printf("check-preset-b.cursor-next\n"); E(mdb_env_stat(env, &mst)); E(mdb_txn_begin(env, NULL, MDB_RDONLY, &txn)); E(mdb_cursor_open(txn, dbi, &cursor)); int present_b = 0; while ((rc = mdb_cursor_get(cursor, &key, &data, MDB_NEXT)) == 0) { printf("key: %.*s, data: %.*s\n", (int) key.mv_size, (char *) key.mv_data, (int) data.mv_size, (char *) data.mv_data); ++present_b; } CHECK(rc == MDB_NOTFOUND, "mdb_cursor_get"); CHECK(present_b == present_a - j, "mismatch"); printf("check-preset-b.cursor-prev\n"); j = 1; while ((rc = mdb_cursor_get(cursor, &key, &data, MDB_PREV)) == 0) { printf("key: %.*s, data: %.*s\n", (int) key.mv_size, (char *) key.mv_data, (int) data.mv_size, (char *) data.mv_data); ++j; } CHECK(rc == MDB_NOTFOUND, "mdb_cursor_get"); CHECK(present_b == j, "mismatch"); mdb_cursor_close(cursor); mdb_txn_abort(txn); mdb_dbi_close(env, dbi); /********************* LY: kept DB dirty ****************/ mdb_env_close_ex(env, 1); E(mdb_env_create(&env)); E(mdb_env_set_maxdbs(env, 4)); E(mdb_env_open(env, DBPATH, env_oflags, 0664)); printf("check-preset-c.cursor-next\n"); E(mdb_env_stat(env, &mst)); E(mdb_txn_begin(env, NULL, MDB_RDONLY, &txn)); E(mdb_dbi_open(txn, "id1", 0, &dbi)); E(mdb_cursor_open(txn, dbi, &cursor)); int present_c = 0; while ((rc = mdb_cursor_get(cursor, &key, &data, MDB_NEXT)) == 0) { printf("key: %.*s, data: %.*s\n", (int) key.mv_size, (char *) key.mv_data, (int) data.mv_size, (char *) data.mv_data); ++present_c; } CHECK(rc == MDB_NOTFOUND, "mdb_cursor_get"); CHECK(present_c == present_a, "mismatch"); printf("check-preset-d.cursor-prev\n"); j = 1; while ((rc = mdb_cursor_get(cursor, &key, &data, MDB_PREV)) == 0) { printf("key: %.*s, data: %.*s\n", (int) key.mv_size, (char *) key.mv_data, (int) data.mv_size, (char *) data.mv_data); ++j; } CHECK(rc == MDB_NOTFOUND, "mdb_cursor_get"); CHECK(present_c == j, "mismatch"); mdb_cursor_close(cursor); mdb_txn_abort(txn); mdb_dbi_close(env, dbi); mdb_env_close_ex(env, 0); return 0; }
void LMDBFileIndex::del_internal(const SIndexKey& key, bool log, bool handle_enosp) { MDB_val mdb_tkey; mdb_tkey.mv_data=const_cast<void*>(static_cast<const void*>(&key)); mdb_tkey.mv_size=sizeof(SIndexKey); int rc = mdb_del(txn, dbi, &mdb_tkey, NULL); if(rc==MDB_MAP_FULL && handle_enosp) { mdb_txn_abort(txn); if(_has_error) { Server->Log("LMDB had error during increase (on del). Aborting...", LL_ERROR); start_transaction(); return; } { read_transaction_lock.reset(); IScopedWriteLock lock(mutex); destroy_env(); map_size*=2; Server->Log("Increased LMDB database size to "+PrettyPrintBytes(map_size)+" (on delete)", LL_DEBUG); if(!create_env()) { Server->Log("Error creating env after database file size increase", LL_ERROR); _has_error=true; start_transaction(); return; } } start_transaction(); replay_transaction_log(); del(key); } else if(rc==MDB_BAD_TXN && handle_enosp) { mdb_txn_abort(txn); if(_has_error) { Server->Log("LMDB had error on BAD_TXN (on del). Aborting...", LL_ERROR); start_transaction(); return; } start_transaction(); replay_transaction_log(); del_internal(key, true, false); } else if (rc == MDB_NOTFOUND) { FILEENTRY_DEBUG(Server->Log("LMDB: Failed to delete data (" + (std::string)mdb_strerror(rc) + ")", LL_ERROR)); } else if(rc) { Server->Log("LMDB: Failed to delete data ("+(std::string)mdb_strerror(rc)+")", LL_ERROR); _has_error=true; } if(log) { STransactionLogItem item = { key, 0, 0 }; transaction_log.push_back(item); } }
ID mdb_tool_entry_modify( BackendDB *be, Entry *e, struct berval *text ) { int rc; struct mdb_info *mdb; Operation op = {0}; Opheader ohdr = {0}; assert( be != NULL ); assert( slapMode & SLAP_TOOL_MODE ); assert( text != NULL ); assert( text->bv_val != NULL ); assert( text->bv_val[0] == '\0' ); /* overconservative? */ assert ( e->e_id != NOID ); Debug( LDAP_DEBUG_TRACE, "=> " LDAP_XSTRING(mdb_tool_entry_modify) "( %ld, \"%s\" )\n", (long) e->e_id, e->e_dn, 0 ); mdb = (struct mdb_info *) be->be_private; if( cursor ) { mdb_cursor_close( cursor ); cursor = NULL; } if ( !txn ) { rc = mdb_txn_begin( mdb->mi_dbenv, NULL, 0, &txn ); if( rc != 0 ) { snprintf( text->bv_val, text->bv_len, "txn_begin failed: %s (%d)", mdb_strerror(rc), rc ); Debug( LDAP_DEBUG_ANY, "=> " LDAP_XSTRING(mdb_tool_entry_modify) ": %s\n", text->bv_val, 0, 0 ); return NOID; } } op.o_hdr = &ohdr; op.o_bd = be; op.o_tmpmemctx = NULL; op.o_tmpmfuncs = &ch_mfuncs; /* id2entry index */ rc = mdb_id2entry_update( &op, txn, NULL, e ); if( rc != 0 ) { snprintf( text->bv_val, text->bv_len, "id2entry_update failed: err=%d", rc ); Debug( LDAP_DEBUG_ANY, "=> " LDAP_XSTRING(mdb_tool_entry_modify) ": %s\n", text->bv_val, 0, 0 ); goto done; } done: if( rc == 0 ) { rc = mdb_txn_commit( txn ); if( rc != 0 ) { snprintf( text->bv_val, text->bv_len, "txn_commit failed: %s (%d)", mdb_strerror(rc), rc ); Debug( LDAP_DEBUG_ANY, "=> " LDAP_XSTRING(mdb_tool_entry_modify) ": " "%s\n", text->bv_val, 0, 0 ); e->e_id = NOID; } } else { mdb_txn_abort( txn ); snprintf( text->bv_val, text->bv_len, "txn_aborted! %s (%d)", mdb_strerror(rc), rc ); Debug( LDAP_DEBUG_ANY, "=> " LDAP_XSTRING(mdb_tool_entry_modify) ": %s\n", text->bv_val, 0, 0 ); e->e_id = NOID; } txn = NULL; idcursor = NULL; return e->e_id; }
int main(int argc, char *argv[]) { int n, c, rc, ec = EXIT_FAILURE, fd_in = -1, fd_out = -1, verbosity = 0; uint32_t ts_start = 0, ts_end = 0, count = 0, nmsg_cnt = 0; MDB_env *env = NULL; MDB_txn *txn = NULL; MDB_dbi dbi; MDB_val key, data; MDB_cursor *cursor = NULL; struct timespec ts, msg_ts; off_t *offset; nmsg_input_t nmsg_in = NULL; nmsg_output_t nmsg_out = NULL; nmsg_res res; nmsg_message_t msg; char *json; bool input_json = false, input_nmsg = false, is_counting = false, need_exact = false; const char *lmdb_filename = NULL, *nmsg_filename_in = NULL; char nmsg_filename_out[BUFSIZ] = {0}; while ((c = getopt(argc, argv, "c:e:f:j:r:s:hvx")) != EOF) { switch (c) { case 'c': count = atoi(optarg); is_counting = true; break; case 'e': ts_end = atoi(optarg); break; case 'f': lmdb_filename = optarg; break; case 'j': nmsg_filename_in = optarg; input_json = true; break; case 'r': nmsg_filename_in = optarg; input_nmsg = true; break; case 's': ts_start = atoi(optarg); break; case 'v': verbosity++; break; case 'x': need_exact = true; break; case 'h': default: usage(argv[0], NULL); goto done; } } if (ts_start == 0) { usage(argv[0], "Need a starting timestamp (-s)."); goto done; } if (lmdb_filename == NULL) { usage(argv[0], "Need a tsindex file (-f)."); goto done; return (EXIT_FAILURE); } if ((input_json == false && input_nmsg == false) || (input_json && input_nmsg)) { usage(argv[0], "Need either an nmsg json file (-j) or binary nmsg file (-r)."); goto done; return (EXIT_FAILURE); } if ((ts_end == 0 && count == 0) || (ts_end != 0 && count != 0)) { usage(argv[0], "Need either an ending timestamp (-e) or a count (-c)."); goto done; return (EXIT_FAILURE); } res = nmsg_init(); if (res != nmsg_res_success) { fprintf(stderr, "Error initializing NMSG library: %s\n", nmsg_res_lookup(res)); goto done; return (EXIT_FAILURE); } fd_in = open(nmsg_filename_in, O_RDONLY); if (fd_in < 0) { fprintf(stderr, "Can't open nmsg input file \"%s\": %s\n", nmsg_filename_in, strerror(errno)); goto done; return (EXIT_FAILURE); } n = strlcpy(nmsg_filename_out, nmsg_filename_in, sizeof (nmsg_filename_out)); snprintf(nmsg_filename_out + n, sizeof (nmsg_filename_out) - n, "-tsindex.%u.%s", getpid(), input_json ? "json" : "nmsg"); fd_out = open(nmsg_filename_out, O_CREAT | O_WRONLY, 0644); if (fd_out < 0) { fprintf(stderr, "Can't open nmsg output file \"%s\": %s\n", nmsg_filename_out, strerror(errno)); goto done; return (EXIT_FAILURE); } if (input_json) { nmsg_in = nmsg_input_open_json(fd_in); if (nmsg_in == NULL) { fprintf(stderr, "nmsg_input_open_json() failed\n"); goto done; } nmsg_out = nmsg_output_open_json(fd_out); if (nmsg_out == NULL) { fprintf(stderr, "nmsg_ouput_open_json() failed\n"); goto done; } } else if (input_nmsg) { nmsg_in = nmsg_input_open_file(fd_in); if (nmsg_in == NULL) { fprintf(stderr, "nmsg_input_open_file() failed\n"); goto done; } nmsg_out = nmsg_output_open_file(fd_out, NMSG_WBUFSZ_MAX); if (nmsg_out == NULL) { fprintf(stderr, "nmsg_ouput_open_file() failed\n"); goto done; } } rc = mdb_env_create(&env); if (rc != 0) { fprintf(stderr, "mdb_create() failed: %s\n", mdb_strerror(rc)); goto done; } rc = mdb_env_open(env, lmdb_filename, MDB_NOSUBDIR | MDB_RDONLY, 0664); if (rc != 0) { fprintf(stderr, "mdb_env_open failed(): %s\n", mdb_strerror(rc)); goto done; } rc = mdb_txn_begin(env, NULL, MDB_RDONLY, &txn); if (rc != 0) { fprintf(stderr, "mdb_txn_begin failed(): %s\n", mdb_strerror(rc)); goto done; } rc = mdb_open(txn, NULL, MDB_INTEGERKEY, &dbi); if (rc) { fprintf(stderr, "mdb_open(): %s\n", mdb_strerror(rc)); goto done; } rc = mdb_set_compare(txn, dbi, axa_tsi_mdb_cmp); if (rc) { fprintf(stderr, "mdb_set_compare(): %s\n", mdb_strerror(rc)); goto done; } ts.tv_sec = ts_start; ts.tv_nsec = 0; key.mv_size = sizeof (ts); key.mv_data = &ts; rc = mdb_cursor_open(txn, dbi, &cursor); if (rc) { fprintf(stderr, "mdb_cursor_open(): %s\n", mdb_strerror(rc)); goto done; } rc = mdb_cursor_get(cursor, &key, &data, need_exact ? MDB_SET : MDB_SET_RANGE); if (rc == MDB_NOTFOUND) { printf("Did not find starting timestamp %u in %s.\n", ts_start, lmdb_filename); goto done; } if (rc) { fprintf(stderr, "mdb_cursor_get(): %s\n", mdb_strerror(rc)); goto done; } (void) mdb_cursor_close(cursor); offset = (off_t *)data.mv_data; if (verbosity > 0) printf("Found %u at offset 0x%"PRIu64".\n", ts_start, *offset); if (lseek(fd_in, *offset, SEEK_SET) == sizeof (off_t) - 1) { fprintf(stderr, "lseek(): %s\n", strerror(errno)); goto done; } while (1) { if (is_counting) { if (count-- <= 0) break; } res = nmsg_input_read(nmsg_in, &msg); if (res == nmsg_res_eof) { if (verbosity > 0) printf("End of file reached.\n"); break; } if (res != nmsg_res_success) { fprintf(stderr, "nmsg_input_read(): %s\n", nmsg_res_lookup(res)); goto done; } if (is_counting == false) { nmsg_message_get_time(msg, &msg_ts); if (msg_ts.tv_sec >= ts_end) { nmsg_message_destroy(&msg); break; } } res = nmsg_output_write(nmsg_out, msg); if (res != nmsg_res_success) { fprintf(stderr, "nmsg_output_write(): %s\n", nmsg_res_lookup(res)); nmsg_message_destroy(&msg); goto done; } if (verbosity > 1) { res = nmsg_message_to_json(msg, &json); if (res != nmsg_res_success) { fprintf(stderr, "nmsg_message_to_pres(): %s\n", nmsg_res_lookup(res)); nmsg_message_destroy(&msg); goto done; } printf("%s\n", json); free(json); } nmsg_cnt++; nmsg_message_destroy(&msg); } ec = EXIT_SUCCESS; printf("Wrote %u nmsgs to %s.\n", nmsg_cnt, nmsg_filename_out); done: if (fd_in != -1) close(fd_in); if (fd_out != -1) close(fd_out); if (nmsg_in != NULL) nmsg_input_close(&nmsg_in); if (nmsg_out != NULL) nmsg_output_close(&nmsg_out); if (txn != NULL) mdb_txn_abort(txn); if (env != NULL) mdb_env_close(env); return (ec); }
static int mdb_db_open( BackendDB *be, ConfigReply *cr ) { int rc, i; struct mdb_info *mdb = (struct mdb_info *) be->be_private; struct stat stat1; uint32_t flags; char *dbhome; MDB_txn *txn; if ( be->be_suffix == NULL ) { Debug( LDAP_DEBUG_ANY, LDAP_XSTRING(mdb_db_open) ": need suffix.\n", 1, 0, 0 ); return -1; } Debug( LDAP_DEBUG_ARGS, LDAP_XSTRING(mdb_db_open) ": \"%s\"\n", be->be_suffix[0].bv_val, 0, 0 ); /* Check existence of dbenv_home. Any error means trouble */ rc = stat( mdb->mi_dbenv_home, &stat1 ); if( rc != 0 ) { Debug( LDAP_DEBUG_ANY, LDAP_XSTRING(mdb_db_open) ": database \"%s\": " "cannot access database directory \"%s\" (%d).\n", be->be_suffix[0].bv_val, mdb->mi_dbenv_home, errno ); return -1; } /* mdb is always clean */ be->be_flags |= SLAP_DBFLAG_CLEAN; rc = mdb_env_create( &mdb->mi_dbenv ); if( rc != 0 ) { Debug( LDAP_DEBUG_ANY, LDAP_XSTRING(mdb_db_open) ": database \"%s\": " "mdb_env_create failed: %s (%d).\n", be->be_suffix[0].bv_val, mdb_strerror(rc), rc ); goto fail; } if ( mdb->mi_readers ) { rc = mdb_env_set_maxreaders( mdb->mi_dbenv, mdb->mi_readers ); if( rc != 0 ) { Debug( LDAP_DEBUG_ANY, LDAP_XSTRING(mdb_db_open) ": database \"%s\": " "mdb_env_set_maxreaders failed: %s (%d).\n", be->be_suffix[0].bv_val, mdb_strerror(rc), rc ); goto fail; } } rc = mdb_env_set_mapsize( mdb->mi_dbenv, mdb->mi_mapsize ); if( rc != 0 ) { Debug( LDAP_DEBUG_ANY, LDAP_XSTRING(mdb_db_open) ": database \"%s\": " "mdb_env_set_mapsize failed: %s (%d).\n", be->be_suffix[0].bv_val, mdb_strerror(rc), rc ); goto fail; } rc = mdb_env_set_maxdbs( mdb->mi_dbenv, MDB_INDICES ); if( rc != 0 ) { Debug( LDAP_DEBUG_ANY, LDAP_XSTRING(mdb_db_open) ": database \"%s\": " "mdb_env_set_maxdbs failed: %s (%d).\n", be->be_suffix[0].bv_val, mdb_strerror(rc), rc ); goto fail; } #ifdef HAVE_EBCDIC strcpy( path, mdb->mi_dbenv_home ); __atoe( path ); dbhome = path; #else dbhome = mdb->mi_dbenv_home; #endif Debug( LDAP_DEBUG_TRACE, LDAP_XSTRING(mdb_db_open) ": database \"%s\": " "dbenv_open(%s).\n", be->be_suffix[0].bv_val, mdb->mi_dbenv_home, 0); flags = mdb->mi_dbenv_flags; if ( slapMode & SLAP_TOOL_QUICK ) flags |= MDB_NOSYNC; if ( slapMode & SLAP_TOOL_READONLY) flags |= MDB_RDONLY; rc = mdb_env_open( mdb->mi_dbenv, dbhome, flags, mdb->mi_dbenv_mode ); if ( rc ) { Debug( LDAP_DEBUG_ANY, LDAP_XSTRING(mdb_db_open) ": database \"%s\" cannot be opened, err %d. " "Restore from backup!\n", be->be_suffix[0].bv_val, rc, 0 ); goto fail; } rc = mdb_txn_begin( mdb->mi_dbenv, NULL, 0, &txn ); if ( rc ) { Debug( LDAP_DEBUG_ANY, LDAP_XSTRING(mdb_db_open) ": database \"%s\" cannot be opened, err %d. " "Restore from backup!\n", be->be_suffix[0].bv_val, rc, 0 ); goto fail; } /* open (and create) main databases */ for( i = 0; mdmi_databases[i].bv_val; i++ ) { flags = MDB_INTEGERKEY; if( i == MDB_ID2ENTRY ) { if ( !(slapMode & (SLAP_TOOL_READMAIN|SLAP_TOOL_READONLY) )) flags |= MDB_CREATE; } else { if ( i == MDB_DN2ID ) flags |= MDB_DUPSORT; if ( !(slapMode & SLAP_TOOL_READONLY) ) flags |= MDB_CREATE; } rc = mdb_open( txn, mdmi_databases[i].bv_val, flags, &mdb->mi_dbis[i] ); if ( rc != 0 ) { snprintf( cr->msg, sizeof(cr->msg), "database \"%s\": " "mdb_open(%s/%s) failed: %s (%d).", be->be_suffix[0].bv_val, mdb->mi_dbenv_home, mdmi_databases[i].bv_val, mdb_strerror(rc), rc ); Debug( LDAP_DEBUG_ANY, LDAP_XSTRING(mdb_db_open) ": %s\n", cr->msg, 0, 0 ); goto fail; } if ( i == MDB_ID2ENTRY ) mdb_set_compare( txn, mdb->mi_dbis[i], mdb_id_compare ); else if ( i == MDB_DN2ID ) mdb_set_dupsort( txn, mdb->mi_dbis[i], mdb_dup_compare ); } rc = mdb_ad_read( mdb, txn ); if ( rc ) { mdb_txn_abort( txn ); goto fail; } rc = mdb_attr_dbs_open( be, txn, cr ); if ( rc ) { mdb_txn_abort( txn ); goto fail; } rc = mdb_txn_commit(txn); if ( rc != 0 ) { goto fail; } /* monitor setup */ rc = mdb_monitor_db_open( be ); if ( rc != 0 ) { goto fail; } mdb->mi_flags |= MDB_IS_OPEN; return 0; fail: mdb_db_close( be, NULL ); return rc; }
ID mdb_tool_entry_put( BackendDB *be, Entry *e, struct berval *text ) { int rc; struct mdb_info *mdb; Operation op = {0}; Opheader ohdr = {0}; assert( be != NULL ); assert( slapMode & SLAP_TOOL_MODE ); assert( text != NULL ); assert( text->bv_val != NULL ); assert( text->bv_val[0] == '\0' ); /* overconservative? */ Debug( LDAP_DEBUG_TRACE, "=> " LDAP_XSTRING(mdb_tool_entry_put) "( %ld, \"%s\" )\n", (long) e->e_id, e->e_dn, 0 ); mdb = (struct mdb_info *) be->be_private; if ( !txn ) { rc = mdb_txn_begin( mdb->mi_dbenv, NULL, 0, &txn ); if( rc != 0 ) { snprintf( text->bv_val, text->bv_len, "txn_begin failed: %s (%d)", mdb_strerror(rc), rc ); Debug( LDAP_DEBUG_ANY, "=> " LDAP_XSTRING(mdb_tool_entry_put) ": %s\n", text->bv_val, 0, 0 ); return NOID; } rc = mdb_cursor_open( txn, mdb->mi_id2entry, &idcursor ); if( rc != 0 ) { snprintf( text->bv_val, text->bv_len, "cursor_open failed: %s (%d)", mdb_strerror(rc), rc ); Debug( LDAP_DEBUG_ANY, "=> " LDAP_XSTRING(mdb_tool_entry_put) ": %s\n", text->bv_val, 0, 0 ); return NOID; } if ( !mdb->mi_nextid ) { ID dummy; mdb_next_id( be, idcursor, &dummy ); } rc = mdb_cursor_open( txn, mdb->mi_dn2id, &mcp ); if( rc != 0 ) { snprintf( text->bv_val, text->bv_len, "cursor_open failed: %s (%d)", mdb_strerror(rc), rc ); Debug( LDAP_DEBUG_ANY, "=> " LDAP_XSTRING(mdb_tool_entry_put) ": %s\n", text->bv_val, 0, 0 ); return NOID; } rc = mdb_cursor_open( txn, mdb->mi_dn2id, &mcd ); if( rc != 0 ) { snprintf( text->bv_val, text->bv_len, "cursor_open failed: %s (%d)", mdb_strerror(rc), rc ); Debug( LDAP_DEBUG_ANY, "=> " LDAP_XSTRING(mdb_tool_entry_put) ": %s\n", text->bv_val, 0, 0 ); return NOID; } } op.o_hdr = &ohdr; op.o_bd = be; op.o_tmpmemctx = NULL; op.o_tmpmfuncs = &ch_mfuncs; /* add dn2id indices */ rc = mdb_tool_next_id( &op, txn, e, text, 0 ); if( rc != 0 ) { goto done; } rc = mdb_tool_index_add( &op, txn, e ); if( rc != 0 ) { snprintf( text->bv_val, text->bv_len, "index_entry_add failed: err=%d", rc ); Debug( LDAP_DEBUG_ANY, "=> " LDAP_XSTRING(mdb_tool_entry_put) ": %s\n", text->bv_val, 0, 0 ); goto done; } /* id2entry index */ rc = mdb_id2entry_add( &op, txn, idcursor, e ); if( rc != 0 ) { snprintf( text->bv_val, text->bv_len, "id2entry_add failed: err=%d", rc ); Debug( LDAP_DEBUG_ANY, "=> " LDAP_XSTRING(mdb_tool_entry_put) ": %s\n", text->bv_val, 0, 0 ); goto done; } done: if( rc == 0 ) { mdb_writes++; if ( mdb_writes >= mdb_writes_per_commit ) { unsigned i; MDB_TOOL_IDL_FLUSH( be, txn ); rc = mdb_txn_commit( txn ); for ( i=0; i<mdb->mi_nattrs; i++ ) mdb->mi_attrs[i]->ai_cursor = NULL; mdb_writes = 0; txn = NULL; idcursor = NULL; if( rc != 0 ) { snprintf( text->bv_val, text->bv_len, "txn_commit failed: %s (%d)", mdb_strerror(rc), rc ); Debug( LDAP_DEBUG_ANY, "=> " LDAP_XSTRING(mdb_tool_entry_put) ": %s\n", text->bv_val, 0, 0 ); e->e_id = NOID; } } } else { unsigned i; mdb_txn_abort( txn ); txn = NULL; idcursor = NULL; for ( i=0; i<mdb->mi_nattrs; i++ ) mdb->mi_attrs[i]->ai_cursor = NULL; mdb_writes = 0; snprintf( text->bv_val, text->bv_len, "txn_aborted! %s (%d)", rc == LDAP_OTHER ? "Internal error" : mdb_strerror(rc), rc ); Debug( LDAP_DEBUG_ANY, "=> " LDAP_XSTRING(mdb_tool_entry_put) ": %s\n", text->bv_val, 0, 0 ); e->e_id = NOID; } return e->e_id; }
virtual ~LMDBCursor() { mdb_cursor_close(mdb_cursor_); mdb_txn_abort(mdb_txn_); }
static int lmdb_storage_init(struct lmdb_storage* s, char* db_env_path) { int result; MDB_env* env = NULL; MDB_txn* txn = NULL; MDB_dbi dbi = 0; if ((result = mdb_env_create(&env)) != 0) { paxos_log_error("Could not create lmdb environment. %s", mdb_strerror(result)); goto error; } if ((result = mdb_env_set_mapsize(env, paxos_config.lmdb_mapsize)) != 0) { paxos_log_error("Could not set lmdb map size. %s", mdb_strerror(result)); goto error; } if ((result = mdb_env_open(env, db_env_path, !paxos_config.lmdb_sync ? MDB_NOSYNC : 0 | MDB_INTEGERKEY, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH)) != 0) { paxos_log_error("Could not open lmdb environment at %s. %s", db_env_path, mdb_strerror(result)); goto error; } if ((result = mdb_txn_begin(env, NULL, 0, &txn)) != 0) { paxos_log_error("Could not start txn on lmdb environment at %s. %s", db_env_path, mdb_strerror(result)); goto error; } if ((result = mdb_open(txn, NULL, 0, &dbi)) != 0) { paxos_log_error("Could not open db on lmdb environment at %s. %s", db_env_path, mdb_strerror(result)); goto error; } if ((result = mdb_set_compare(txn, dbi, lmdb_compare_iid)) != 0) { paxos_log_error("Could setup compare function on lmdb " "environment at %s. %s", db_env_path, mdb_strerror(result)); goto error; } if ((result = mdb_txn_commit(txn)) != 0) { paxos_log_error("Could commit txn on lmdb environment at %s. %s", db_env_path, mdb_strerror(result)); goto error; } s->env = env; s->dbi = dbi; return 0; error: if (txn) { mdb_txn_abort(txn); } if (dbi) { mdb_close(env, dbi); } if (env) { mdb_env_close(env); } return -1; }
int main(int argc, char *argv[]) { if (argc < 3) { return help(); } /* Get mandatory parameters. */ int ret = EXIT_SUCCESS; char *dbdir = argv[1]; char *action = argv[2]; argv += 3; argc -= 3; g_scanner = zs_scanner_create(".", KNOT_CLASS_IN, 0, NULL, parse_err, NULL); if (g_scanner == NULL) { return EXIT_FAILURE; } /* Open cache for operations. */ struct cache *cache = cache_open(dbdir, 0, NULL); if (cache == NULL) { fprintf(stderr, "failed to open db '%s'\n", dbdir); zs_scanner_free(g_scanner); return EXIT_FAILURE; } /* Execute action. */ bool found = false; for (unsigned i = 0; i < TOOL_ACTION_COUNT; ++i) { struct tool_action *ta = &TOOL_ACTION[i]; if (strcmp(ta->name, action) == 0) { /* Check param count. */ if (argc < ta->min_args) { break; } /* Now set as found. */ found = true; MDB_txn *txn = NULL; int ret = mdb_txn_begin(cache->env, NULL, 0, &txn); if (ret != MDB_SUCCESS) { fprintf(stderr, "failed to open transaction, aborting\n"); break; } /* Execute operation handler. */ ret = ta->func(cache, txn, argc, argv); if (ret != 0) { fprintf(stderr, "'%s' failed, aborting transaction\n", action); mdb_txn_abort(txn); } else { mdb_txn_commit(txn); } break; } } cache_close(cache); zs_scanner_free(g_scanner); if (!found) { return help(); } return ret; }
struct gcache *gcache_open(char *path, char *dbname, int rdonly) { MDB_txn *txn = NULL; int rc; unsigned int flags = 0, dbiflags = 0, perms = 0664; struct gcache *gc; if (!is_directory(path)) { olog(LOG_ERR, "gcache_open: %s is not a directory", path); return (NULL); } if ((gc = malloc(sizeof (struct gcache))) == NULL) return (NULL); memset(gc, 0, sizeof(struct gcache)); if (rdonly) { flags |= MDB_RDONLY; perms = 0444; perms = 0664; } else { dbiflags = MDB_CREATE; } rc = mdb_env_create(&gc->env); if (rc != 0) { olog(LOG_ERR, "gcache_open: mdb_env_create: %s", mdb_strerror(rc)); free(gc); return (NULL); } mdb_env_set_mapsize(gc->env, LMDB_DB_SIZE); rc = mdb_env_set_maxdbs(gc->env, 10); if (rc != 0) { olog(LOG_ERR, "gcache_open: mdb_env_set_maxdbs%s", mdb_strerror(rc)); free(gc); return (NULL); } rc = mdb_env_open(gc->env, path, flags, perms); if (rc != 0) { olog(LOG_ERR, "gcache_open: mdb_env_open: %s", mdb_strerror(rc)); free(gc); return (NULL); } /* Open a pseudo TX so that we can open DBI */ mdb_txn_begin(gc->env, NULL, flags, &txn); if (rc != 0) { olog(LOG_ERR, "gcache_open: mdb_txn_begin: %s", mdb_strerror(rc)); mdb_env_close(gc->env); free(gc); return (NULL); } rc = mdb_dbi_open(txn, dbname, dbiflags, &gc->dbi); if (rc != 0) { olog(LOG_ERR, "gcache_open: mdb_dbi_open for `%s': %s", dbname, mdb_strerror(rc)); mdb_txn_abort(txn); mdb_env_close(gc->env); free(gc); return (NULL); } rc = mdb_txn_commit(txn); if (rc != 0) { olog(LOG_ERR, "cogcache_open: mmit after open %s", mdb_strerror(rc)); mdb_env_close(gc->env); free(gc); return (NULL); } return (gc); }
DBPriv *DBPrivOpenDB(const char *dbpath, dbid id) { DBPriv *db = xcalloc(1, sizeof(DBPriv)); MDB_txn *txn = NULL; int rc; rc = pthread_key_create(&db->txn_key, &DestroyTransaction); if (rc) { Log(LOG_LEVEL_ERR, "Could not create transaction key. (pthread_key_create: '%s')", GetErrorStrFromCode(rc)); free(db); return NULL; } rc = mdb_env_create(&db->env); if (rc) { Log(LOG_LEVEL_ERR, "Could not create handle for database %s: %s", dbpath, mdb_strerror(rc)); goto err; } rc = mdb_env_set_mapsize(db->env, LMDB_MAXSIZE); if (rc) { Log(LOG_LEVEL_ERR, "Could not set mapsize for database %s: %s", dbpath, mdb_strerror(rc)); goto err; } if (DB_MAX_READERS > 0) { rc = mdb_env_set_maxreaders(db->env, DB_MAX_READERS); if (rc) { Log(LOG_LEVEL_ERR, "Could not set maxreaders for database %s: %s", dbpath, mdb_strerror(rc)); goto err; } } unsigned int open_flags = MDB_NOSUBDIR; if (id == dbid_locks || (GetAmPolicyHub() && id == dbid_lastseen)) { open_flags |= MDB_NOSYNC; } #ifdef __hpux /* * On HP-UX, a unified file cache was not introduced until version 11.31. * This means that on 11.23 there are separate file caches for mmap()'ed * files and open()'ed files. When these two are mixed, changes made using * one mode won't be immediately seen by the other mode, which is an * assumption LMDB is relying on. The MDB_WRITEMAP flag causes LMDB to use * mmap() only, so that we stay within one file cache. */ open_flags |= MDB_WRITEMAP; #endif rc = mdb_env_open(db->env, dbpath, open_flags, 0644); if (rc) { Log(LOG_LEVEL_ERR, "Could not open database %s: %s", dbpath, mdb_strerror(rc)); goto err; } if (DB_MAX_READERS > 0) { int max_readers; rc = mdb_env_get_maxreaders(db->env, &max_readers); if (rc) { Log(LOG_LEVEL_ERR, "Could not get maxreaders for database %s: %s", dbpath, mdb_strerror(rc)); goto err; } if (max_readers < DB_MAX_READERS) { // LMDB will only reinitialize maxreaders if no database handles are // open, including in other processes, which is how we might end up // here. Log(LOG_LEVEL_VERBOSE, "Failed to set LMDB max reader limit on database '%s', " "consider restarting CFEngine", dbpath); } } rc = mdb_txn_begin(db->env, NULL, MDB_RDONLY, &txn); if (rc) { Log(LOG_LEVEL_ERR, "Could not open database txn %s: %s", dbpath, mdb_strerror(rc)); goto err; } rc = mdb_open(txn, NULL, 0, &db->dbi); if (rc) { Log(LOG_LEVEL_ERR, "Could not open database dbi %s: %s", dbpath, mdb_strerror(rc)); mdb_txn_abort(txn); goto err; } rc = mdb_txn_commit(txn); if (rc) { Log(LOG_LEVEL_ERR, "Could not commit database dbi %s: %s", dbpath, mdb_strerror(rc)); goto err; } return db; err: if (db->env) { mdb_env_close(db->env); } pthread_key_delete(db->txn_key); free(db); if (rc == MDB_INVALID) { return DB_PRIV_DATABASE_BROKEN; } return NULL; }
int main(int argc,char * argv[]) { int i = 0, j = 0, rc; MDB_env *env; MDB_dbi dbi; MDB_val key, data; MDB_txn *txn; MDB_stat mst; MDB_cursor *cursor, *cur2; int count; int *values; char sval[32]; srandom(time(NULL)); count = (random()%384) + 64; values = (int *)malloc(count*sizeof(int)); for(i = 0;i<count;i++) { values[i] = random()%1024; } rc = mdb_env_create(&env); rc = mdb_env_set_mapsize(env, 10485760); rc = mdb_env_open(env, "./testdb", MDB_FIXEDMAP /*|MDB_NOSYNC*/, 0664); rc = mdb_txn_begin(env, NULL, 0, &txn); rc = mdb_open(txn, NULL, 0, &dbi); key.mv_size = sizeof(int); key.mv_data = sval; data.mv_size = sizeof(sval); data.mv_data = sval; printf("Adding %d values\n", count); for (i=0;i<count;i++) { sprintf(sval, "%03x %d foo bar", values[i], values[i]); rc = mdb_put(txn, dbi, &key, &data, MDB_NOOVERWRITE); if (rc) { j++; data.mv_size = sizeof(sval); data.mv_data = sval; } } if (j) printf("%d duplicates skipped\n", j); rc = mdb_txn_commit(txn); rc = mdb_env_stat(env, &mst); rc = mdb_txn_begin(env, NULL, 1, &txn); rc = mdb_cursor_open(txn, dbi, &cursor); while ((rc = mdb_cursor_get(cursor, &key, &data, MDB_NEXT)) == 0) { printf("key: %p %.*s, data: %p %.*s\n", key.mv_data, (int) key.mv_size, (char *) key.mv_data, data.mv_data, (int) data.mv_size, (char *) data.mv_data); } mdb_cursor_close(cursor); mdb_txn_abort(txn); j=0; key.mv_data = sval; for (i= count - 1; i > -1; i-= (random()%5)) { j++; txn=NULL; rc = mdb_txn_begin(env, NULL, 0, &txn); sprintf(sval, "%03x ", values[i]); rc = mdb_del(txn, dbi, &key, NULL); if (rc) { j--; mdb_txn_abort(txn); } else { rc = mdb_txn_commit(txn); } } free(values); printf("Deleted %d values\n", j); rc = mdb_env_stat(env, &mst); rc = mdb_txn_begin(env, NULL, 1, &txn); rc = mdb_cursor_open(txn, dbi, &cursor); printf("Cursor next\n"); while ((rc = mdb_cursor_get(cursor, &key, &data, MDB_NEXT)) == 0) { printf("key: %.*s, data: %.*s\n", (int) key.mv_size, (char *) key.mv_data, (int) data.mv_size, (char *) data.mv_data); } printf("Cursor last\n"); rc = mdb_cursor_get(cursor, &key, &data, MDB_LAST); printf("key: %.*s, data: %.*s\n", (int) key.mv_size, (char *) key.mv_data, (int) data.mv_size, (char *) data.mv_data); printf("Cursor prev\n"); while ((rc = mdb_cursor_get(cursor, &key, &data, MDB_PREV)) == 0) { printf("key: %.*s, data: %.*s\n", (int) key.mv_size, (char *) key.mv_data, (int) data.mv_size, (char *) data.mv_data); } printf("Cursor last/prev\n"); rc = mdb_cursor_get(cursor, &key, &data, MDB_LAST); printf("key: %.*s, data: %.*s\n", (int) key.mv_size, (char *) key.mv_data, (int) data.mv_size, (char *) data.mv_data); rc = mdb_cursor_get(cursor, &key, &data, MDB_PREV); printf("key: %.*s, data: %.*s\n", (int) key.mv_size, (char *) key.mv_data, (int) data.mv_size, (char *) data.mv_data); mdb_txn_abort(txn); printf("Deleting with cursor\n"); rc = mdb_txn_begin(env, NULL, 0, &txn); rc = mdb_cursor_open(txn, dbi, &cur2); for (i=0; i<50; i++) { rc = mdb_cursor_get(cur2, &key, &data, MDB_NEXT); if (rc) break; printf("key: %p %.*s, data: %p %.*s\n", key.mv_data, (int) key.mv_size, (char *) key.mv_data, data.mv_data, (int) data.mv_size, (char *) data.mv_data); rc = mdb_del(txn, dbi, &key, NULL); } printf("Restarting cursor in txn\n"); rc = mdb_cursor_get(cur2, &key, &data, MDB_FIRST); printf("key: %p %.*s, data: %p %.*s\n", key.mv_data, (int) key.mv_size, (char *) key.mv_data, data.mv_data, (int) data.mv_size, (char *) data.mv_data); for (i=0; i<32; i++) { rc = mdb_cursor_get(cur2, &key, &data, MDB_NEXT); if (rc) break; printf("key: %p %.*s, data: %p %.*s\n", key.mv_data, (int) key.mv_size, (char *) key.mv_data, data.mv_data, (int) data.mv_size, (char *) data.mv_data); } mdb_cursor_close(cur2); rc = mdb_txn_commit(txn); printf("Restarting cursor outside txn\n"); rc = mdb_txn_begin(env, NULL, 0, &txn); rc = mdb_cursor_open(txn, dbi, &cursor); rc = mdb_cursor_get(cursor, &key, &data, MDB_FIRST); printf("key: %p %.*s, data: %p %.*s\n", key.mv_data, (int) key.mv_size, (char *) key.mv_data, data.mv_data, (int) data.mv_size, (char *) data.mv_data); for (i=0; i<32; i++) { rc = mdb_cursor_get(cursor, &key, &data, MDB_NEXT); if (rc) break; printf("key: %p %.*s, data: %p %.*s\n", key.mv_data, (int) key.mv_size, (char *) key.mv_data, data.mv_data, (int) data.mv_size, (char *) data.mv_data); } mdb_cursor_close(cursor); mdb_close(env, dbi); mdb_txn_abort(txn); mdb_env_close(env); return 0; }
int slmdb_cursor_get(SLMDB *slmdb, MDB_val *mdb_key, MDB_val *mdb_value, MDB_cursor_op op) { MDB_txn *txn; int status = 0; /* * Open a read transaction and cursor if needed. */ if (slmdb->cursor == 0) { if ((status = slmdb_txn_begin(slmdb, MDB_RDONLY, &txn)) != 0) SLMDB_API_RETURN(slmdb, status); if ((status = mdb_cursor_open(txn, slmdb->dbi, &slmdb->cursor)) != 0) { mdb_txn_abort(txn); if ((status = slmdb_recover(slmdb, status)) == 0) status = slmdb_cursor_get(slmdb, mdb_key, mdb_value, op); SLMDB_API_RETURN(slmdb, status); } /* * Restore the cursor position from the saved key information. */ if (HAVE_SLMDB_SAVED_KEY(slmdb) && op != MDB_FIRST) status = mdb_cursor_get(slmdb->cursor, &slmdb->saved_key, (MDB_val *) 0, MDB_SET); } /* * Database lookup. */ if (status == 0) status = mdb_cursor_get(slmdb->cursor, mdb_key, mdb_value, op); /* * Save the cursor position if successful. This can fail only with * ENOMEM. * * Close the cursor read transaction if in MDB_NOLOCK mode, because the * caller may release the external lock after we return. */ if (status == 0) { status = slmdb_saved_key_assign(slmdb, mdb_key); if (slmdb->lmdb_flags & MDB_NOLOCK) slmdb_cursor_close(slmdb); } /* * Handle end-of-database or other error. */ else { /* Do not hand-optimize out the slmdb_cursor_close() calls below. */ if (status == MDB_NOTFOUND) { slmdb_cursor_close(slmdb); if (HAVE_SLMDB_SAVED_KEY(slmdb)) slmdb_saved_key_free(slmdb); } else { slmdb_cursor_close(slmdb); if ((status = slmdb_recover(slmdb, status)) == 0) status = slmdb_cursor_get(slmdb, mdb_key, mdb_value, op); SLMDB_API_RETURN(slmdb, status); /* Do not hand-optimize out the above return statement. */ } } SLMDB_API_RETURN(slmdb, status); }
int mdb_add(Operation *op, SlapReply *rs ) { struct mdb_info *mdb = (struct mdb_info *) op->o_bd->be_private; struct berval pdn; Entry *p = NULL, *oe = op->ora_e; char textbuf[SLAP_TEXT_BUFLEN]; size_t textlen = sizeof textbuf; AttributeDescription *children = slap_schema.si_ad_children; AttributeDescription *entry = slap_schema.si_ad_entry; MDB_txn *txn = NULL; MDB_cursor *mc = NULL; MDB_cursor *mcd; ID eid, pid = 0; mdb_op_info opinfo = {{{ 0 }}}, *moi = &opinfo; int subentry; int numads = mdb->mi_numads; int success; LDAPControl **postread_ctrl = NULL; LDAPControl *ctrls[SLAP_MAX_RESPONSE_CONTROLS]; int num_ctrls = 0; Debug(LDAP_DEBUG_ARGS, "==> " LDAP_XSTRING(mdb_add) ": %s\n", op->ora_e->e_name.bv_val, 0, 0); #ifdef LDAP_X_TXN if( op->o_txnSpec && txn_preop( op, rs )) return rs->sr_err; #endif ctrls[num_ctrls] = 0; /* check entry's schema */ rs->sr_err = entry_schema_check( op, op->ora_e, NULL, get_relax(op), 1, NULL, &rs->sr_text, textbuf, textlen ); if ( rs->sr_err != LDAP_SUCCESS ) { Debug( LDAP_DEBUG_TRACE, LDAP_XSTRING(mdb_add) ": entry failed schema check: " "%s (%d)\n", rs->sr_text, rs->sr_err, 0 ); goto return_results; } /* begin transaction */ rs->sr_err = mdb_opinfo_get( op, mdb, 0, &moi ); rs->sr_text = NULL; if( rs->sr_err != 0 ) { Debug( LDAP_DEBUG_TRACE, LDAP_XSTRING(mdb_add) ": txn_begin failed: %s (%d)\n", mdb_strerror(rs->sr_err), rs->sr_err, 0 ); rs->sr_err = LDAP_OTHER; rs->sr_text = "internal error"; goto return_results; } txn = moi->moi_txn; /* add opattrs to shadow as well, only missing attrs will actually * be added; helps compatibility with older OL versions */ rs->sr_err = slap_add_opattrs( op, &rs->sr_text, textbuf, textlen, 1 ); if ( rs->sr_err != LDAP_SUCCESS ) { Debug( LDAP_DEBUG_TRACE, LDAP_XSTRING(mdb_add) ": entry failed op attrs add: " "%s (%d)\n", rs->sr_text, rs->sr_err, 0 ); goto return_results; } if ( get_assert( op ) && ( test_filter( op, op->ora_e, get_assertion( op )) != LDAP_COMPARE_TRUE )) { rs->sr_err = LDAP_ASSERTION_FAILED; goto return_results; } subentry = is_entry_subentry( op->ora_e ); /* * Get the parent dn and see if the corresponding entry exists. */ if ( be_issuffix( op->o_bd, &op->ora_e->e_nname ) ) { pdn = slap_empty_bv; } else { dnParent( &op->ora_e->e_nname, &pdn ); } rs->sr_err = mdb_cursor_open( txn, mdb->mi_dn2id, &mcd ); if( rs->sr_err != 0 ) { Debug( LDAP_DEBUG_TRACE, LDAP_XSTRING(mdb_add) ": mdb_cursor_open failed (%d)\n", rs->sr_err, 0, 0 ); rs->sr_err = LDAP_OTHER; rs->sr_text = "internal error"; goto return_results; } /* get entry or parent */ rs->sr_err = mdb_dn2entry( op, txn, mcd, &op->ora_e->e_nname, &p, NULL, 1 ); switch( rs->sr_err ) { case 0: rs->sr_err = LDAP_ALREADY_EXISTS; mdb_entry_return( op, p ); p = NULL; goto return_results; case MDB_NOTFOUND: break; case LDAP_BUSY: rs->sr_text = "ldap server busy"; goto return_results; default: rs->sr_err = LDAP_OTHER; rs->sr_text = "internal error"; goto return_results; } if ( !p ) p = (Entry *)&slap_entry_root; if ( !bvmatch( &pdn, &p->e_nname ) ) { rs->sr_matched = ber_strdup_x( p->e_name.bv_val, op->o_tmpmemctx ); if ( p != (Entry *)&slap_entry_root && is_entry_referral( p )) { BerVarray ref = get_entry_referrals( op, p ); rs->sr_ref = referral_rewrite( ref, &p->e_name, &op->o_req_dn, LDAP_SCOPE_DEFAULT ); ber_bvarray_free( ref ); } else { rs->sr_ref = NULL; } if ( p != (Entry *)&slap_entry_root ) mdb_entry_return( op, p ); p = NULL; Debug( LDAP_DEBUG_TRACE, LDAP_XSTRING(mdb_add) ": parent " "does not exist\n", 0, 0, 0 ); rs->sr_err = LDAP_REFERRAL; rs->sr_flags = REP_MATCHED_MUSTBEFREED | REP_REF_MUSTBEFREED; goto return_results; } rs->sr_err = access_allowed( op, p, children, NULL, ACL_WADD, NULL ); if ( ! rs->sr_err ) { if ( p != (Entry *)&slap_entry_root ) mdb_entry_return( op, p ); p = NULL; Debug( LDAP_DEBUG_TRACE, LDAP_XSTRING(mdb_add) ": no write access to parent\n", 0, 0, 0 ); rs->sr_err = LDAP_INSUFFICIENT_ACCESS; rs->sr_text = "no write access to parent"; goto return_results;; } if ( p != (Entry *)&slap_entry_root ) { if ( is_entry_subentry( p ) ) { mdb_entry_return( op, p ); p = NULL; /* parent is a subentry, don't allow add */ Debug( LDAP_DEBUG_TRACE, LDAP_XSTRING(mdb_add) ": parent is subentry\n", 0, 0, 0 ); rs->sr_err = LDAP_OBJECT_CLASS_VIOLATION; rs->sr_text = "parent is a subentry"; goto return_results;; } if ( is_entry_alias( p ) ) { mdb_entry_return( op, p ); p = NULL; /* parent is an alias, don't allow add */ Debug( LDAP_DEBUG_TRACE, LDAP_XSTRING(mdb_add) ": parent is alias\n", 0, 0, 0 ); rs->sr_err = LDAP_ALIAS_PROBLEM; rs->sr_text = "parent is an alias"; goto return_results;; } if ( is_entry_referral( p ) ) { BerVarray ref = get_entry_referrals( op, p ); /* parent is a referral, don't allow add */ rs->sr_matched = ber_strdup_x( p->e_name.bv_val, op->o_tmpmemctx ); rs->sr_ref = referral_rewrite( ref, &p->e_name, &op->o_req_dn, LDAP_SCOPE_DEFAULT ); ber_bvarray_free( ref ); mdb_entry_return( op, p ); p = NULL; Debug( LDAP_DEBUG_TRACE, LDAP_XSTRING(mdb_add) ": parent is referral\n", 0, 0, 0 ); rs->sr_err = LDAP_REFERRAL; rs->sr_flags = REP_MATCHED_MUSTBEFREED | REP_REF_MUSTBEFREED; goto return_results; } } if ( subentry ) { /* FIXME: */ /* parent must be an administrative point of the required kind */ } /* free parent */ if ( p != (Entry *)&slap_entry_root ) { pid = p->e_id; if ( p->e_nname.bv_len ) { struct berval ppdn; /* ITS#5326: use parent's DN if differs from provided one */ dnParent( &op->ora_e->e_name, &ppdn ); if ( !dn_match( &p->e_name, &ppdn ) ) { struct berval rdn; struct berval newdn; dnRdn( &op->ora_e->e_name, &rdn ); build_new_dn( &newdn, &p->e_name, &rdn, NULL ); if ( op->ora_e->e_name.bv_val != op->o_req_dn.bv_val ) ber_memfree( op->ora_e->e_name.bv_val ); op->ora_e->e_name = newdn; /* FIXME: should check whether * dnNormalize(newdn) == e->e_nname ... */ } } mdb_entry_return( op, p ); } p = NULL; rs->sr_err = access_allowed( op, op->ora_e, entry, NULL, ACL_WADD, NULL ); if ( ! rs->sr_err ) { Debug( LDAP_DEBUG_TRACE, LDAP_XSTRING(mdb_add) ": no write access to entry\n", 0, 0, 0 ); rs->sr_err = LDAP_INSUFFICIENT_ACCESS; rs->sr_text = "no write access to entry"; goto return_results;; } /* * Check ACL for attribute write access */ if (!acl_check_modlist(op, oe, op->ora_modlist)) { Debug( LDAP_DEBUG_TRACE, LDAP_XSTRING(mdb_add) ": no write access to attribute\n", 0, 0, 0 ); rs->sr_err = LDAP_INSUFFICIENT_ACCESS; rs->sr_text = "no write access to attribute"; goto return_results;; } rs->sr_err = mdb_cursor_open( txn, mdb->mi_id2entry, &mc ); if( rs->sr_err != 0 ) { Debug( LDAP_DEBUG_TRACE, LDAP_XSTRING(mdb_add) ": mdb_cursor_open failed (%d)\n", rs->sr_err, 0, 0 ); rs->sr_err = LDAP_OTHER; rs->sr_text = "internal error"; goto return_results; } rs->sr_err = mdb_next_id( op->o_bd, mc, &eid ); if( rs->sr_err != 0 ) { Debug( LDAP_DEBUG_TRACE, LDAP_XSTRING(mdb_add) ": next_id failed (%d)\n", rs->sr_err, 0, 0 ); rs->sr_err = LDAP_OTHER; rs->sr_text = "internal error"; goto return_results; } op->ora_e->e_id = eid; /* dn2id index */ rs->sr_err = mdb_dn2id_add( op, mcd, mcd, pid, 1, 1, op->ora_e ); mdb_cursor_close( mcd ); if ( rs->sr_err != 0 ) { Debug( LDAP_DEBUG_TRACE, LDAP_XSTRING(mdb_add) ": dn2id_add failed: %s (%d)\n", mdb_strerror(rs->sr_err), rs->sr_err, 0 ); switch( rs->sr_err ) { case MDB_KEYEXIST: rs->sr_err = LDAP_ALREADY_EXISTS; break; default: rs->sr_err = LDAP_OTHER; } goto return_results; } /* attribute indexes */ rs->sr_err = mdb_index_entry_add( op, txn, op->ora_e ); if ( rs->sr_err != LDAP_SUCCESS ) { Debug( LDAP_DEBUG_TRACE, LDAP_XSTRING(mdb_add) ": index_entry_add failed\n", 0, 0, 0 ); rs->sr_err = LDAP_OTHER; rs->sr_text = "index generation failed"; goto return_results; } /* id2entry index */ rs->sr_err = mdb_id2entry_add( op, txn, mc, op->ora_e ); if ( rs->sr_err != 0 ) { Debug( LDAP_DEBUG_TRACE, LDAP_XSTRING(mdb_add) ": id2entry_add failed\n", 0, 0, 0 ); if ( rs->sr_err == LDAP_ADMINLIMIT_EXCEEDED ) { rs->sr_text = "entry is too big"; } else { rs->sr_err = LDAP_OTHER; rs->sr_text = "entry store failed"; } goto return_results; } /* post-read */ if( op->o_postread ) { if( postread_ctrl == NULL ) { postread_ctrl = &ctrls[num_ctrls++]; ctrls[num_ctrls] = NULL; } if ( slap_read_controls( op, rs, op->ora_e, &slap_post_read_bv, postread_ctrl ) ) { Debug( LDAP_DEBUG_TRACE, "<=- " LDAP_XSTRING(mdb_add) ": post-read " "failed!\n", 0, 0, 0 ); if ( op->o_postread & SLAP_CONTROL_CRITICAL ) { /* FIXME: is it correct to abort * operation if control fails? */ goto return_results; } } } if ( moi == &opinfo ) { LDAP_SLIST_REMOVE( &op->o_extra, &opinfo.moi_oe, OpExtra, oe_next ); opinfo.moi_oe.oe_key = NULL; if ( op->o_noop ) { mdb->mi_numads = numads; mdb_txn_abort( txn ); rs->sr_err = LDAP_X_NO_OPERATION; txn = NULL; goto return_results; } rs->sr_err = mdb_txn_commit( txn ); txn = NULL; if ( rs->sr_err != 0 ) { mdb->mi_numads = numads; rs->sr_text = "txn_commit failed"; Debug( LDAP_DEBUG_ANY, LDAP_XSTRING(mdb_add) ": %s : %s (%d)\n", rs->sr_text, mdb_strerror(rs->sr_err), rs->sr_err ); rs->sr_err = LDAP_OTHER; goto return_results; } } Debug(LDAP_DEBUG_TRACE, LDAP_XSTRING(mdb_add) ": added%s id=%08lx dn=\"%s\"\n", op->o_noop ? " (no-op)" : "", op->ora_e->e_id, op->ora_e->e_dn ); rs->sr_text = NULL; if( num_ctrls ) rs->sr_ctrls = ctrls; return_results: success = rs->sr_err; send_ldap_result( op, rs ); if( moi == &opinfo ) { if( txn != NULL ) { mdb->mi_numads = numads; mdb_txn_abort( txn ); } if ( opinfo.moi_oe.oe_key ) { LDAP_SLIST_REMOVE( &op->o_extra, &opinfo.moi_oe, OpExtra, oe_next ); } } else { moi->moi_ref--; } if( success == LDAP_SUCCESS ) { #if 0 if ( mdb->bi_txn_cp_kbyte ) { TXN_CHECKPOINT( mdb->bi_dbenv, mdb->bi_txn_cp_kbyte, mdb->bi_txn_cp_min, 0 ); } #endif } slap_graduate_commit_csn( op ); if( postread_ctrl != NULL && (*postread_ctrl) != NULL ) { slap_sl_free( (*postread_ctrl)->ldctl_value.bv_val, op->o_tmpmemctx ); slap_sl_free( *postread_ctrl, op->o_tmpmemctx ); } return rs->sr_err; }
int main(int argc, char *argv[]) { int i, rc; MDB_env *env; MDB_txn *txn; MDB_cursor *mc; MDB_dbi dbi; char *envname; int envflags = MDB_NOSYNC, putflags = 0; int dohdr = 0, append = 0; MDB_val prevk; prog = argv[0]; if (argc < 2) { usage(); } /* -a: append records in input order * -f: load file instead of stdin * -n: use NOSUBDIR flag on env_open * -s: load into named subDB * -N: use NOOVERWRITE on puts * -T: read plaintext * -V: print version and exit */ while ((i = getopt(argc, argv, "af:ns:NTV")) != EOF) { switch(i) { case 'V': printf("%s\n", MDB_VERSION_STRING); exit(0); break; case 'a': append = 1; break; case 'f': if (freopen(optarg, "r", stdin) == NULL) { fprintf(stderr, "%s: %s: reopen: %s\n", prog, optarg, strerror(errno)); exit(EXIT_FAILURE); } break; case 'n': envflags |= MDB_NOSUBDIR; break; case 's': subname = strdup(optarg); break; case 'N': putflags = MDB_NOOVERWRITE|MDB_NODUPDATA; break; case 'T': mode |= NOHDR | PRINT; break; default: usage(); } } if (optind != argc - 1) usage(); dbuf.mv_size = 4096; dbuf.mv_data = malloc(dbuf.mv_size); if (!(mode & NOHDR)) readhdr(); envname = argv[optind]; rc = mdb_env_create(&env); if (rc) { fprintf(stderr, "mdb_env_create failed, error %d %s\n", rc, mdb_strerror(rc)); return EXIT_FAILURE; } mdb_env_set_maxdbs(env, 2); if (info.me_maxreaders) mdb_env_set_maxreaders(env, info.me_maxreaders); if (info.me_mapsize) mdb_env_set_mapsize(env, info.me_mapsize); if (info.me_mapaddr) envflags |= MDB_FIXEDMAP; rc = mdb_env_open(env, envname, envflags, 0664); if (rc) { fprintf(stderr, "mdb_env_open failed, error %d %s\n", rc, mdb_strerror(rc)); goto env_close; } kbuf.mv_size = mdb_env_get_maxkeysize(env) * 2 + 2; kbuf.mv_data = malloc(kbuf.mv_size * 2); k0buf.mv_size = kbuf.mv_size; k0buf.mv_data = (char *)kbuf.mv_data + kbuf.mv_size; prevk.mv_data = k0buf.mv_data; while(!Eof) { MDB_val key, data; int batch = 0; int appflag; if (!dohdr) { dohdr = 1; } else if (!(mode & NOHDR)) readhdr(); rc = mdb_txn_begin(env, NULL, 0, &txn); if (rc) { fprintf(stderr, "mdb_txn_begin failed, error %d %s\n", rc, mdb_strerror(rc)); goto env_close; } rc = mdb_open(txn, subname, flags|MDB_CREATE, &dbi); if (rc) { fprintf(stderr, "mdb_open failed, error %d %s\n", rc, mdb_strerror(rc)); goto txn_abort; } prevk.mv_size = 0; if (append) { mdb_set_compare(txn, dbi, greater); if (flags & MDB_DUPSORT) mdb_set_dupsort(txn, dbi, greater); } rc = mdb_cursor_open(txn, dbi, &mc); if (rc) { fprintf(stderr, "mdb_cursor_open failed, error %d %s\n", rc, mdb_strerror(rc)); goto txn_abort; } while(1) { rc = readline(&key, &kbuf); if (rc) /* rc == EOF */ break; rc = readline(&data, &dbuf); if (rc) { fprintf(stderr, "%s: line %"Yu": failed to read key value\n", prog, lineno); goto txn_abort; } if (append) { appflag = MDB_APPEND; if (flags & MDB_DUPSORT) { if (prevk.mv_size == key.mv_size && !memcmp(prevk.mv_data, key.mv_data, key.mv_size)) appflag = MDB_CURRENT|MDB_APPENDDUP; else { memcpy(prevk.mv_data, key.mv_data, key.mv_size); prevk.mv_size = key.mv_size; } } } else { appflag = 0; } rc = mdb_cursor_put(mc, &key, &data, putflags|appflag); if (rc == MDB_KEYEXIST && putflags) continue; if (rc) { fprintf(stderr, "mdb_cursor_put failed, error %d %s\n", rc, mdb_strerror(rc)); goto txn_abort; } batch++; if (batch == 100) { rc = mdb_txn_commit(txn); if (rc) { fprintf(stderr, "%s: line %"Yu": txn_commit: %s\n", prog, lineno, mdb_strerror(rc)); goto env_close; } rc = mdb_txn_begin(env, NULL, 0, &txn); if (rc) { fprintf(stderr, "mdb_txn_begin failed, error %d %s\n", rc, mdb_strerror(rc)); goto env_close; } rc = mdb_cursor_open(txn, dbi, &mc); if (rc) { fprintf(stderr, "mdb_cursor_open failed, error %d %s\n", rc, mdb_strerror(rc)); goto txn_abort; } if (appflag & MDB_APPENDDUP) { MDB_val k, d; mdb_cursor_get(mc, &k, &d, MDB_LAST); } batch = 0; } } rc = mdb_txn_commit(txn); txn = NULL; if (rc) { fprintf(stderr, "%s: line %"Yu": txn_commit: %s\n", prog, lineno, mdb_strerror(rc)); goto env_close; } mdb_dbi_close(env, dbi); } txn_abort: mdb_txn_abort(txn); env_close: mdb_env_close(env); return rc ? EXIT_FAILURE : EXIT_SUCCESS; }
int main(int argc, char *argv[]) { int i, rc; MDB_env *env; MDB_txn *txn; MDB_cursor *mc; MDB_dbi dbi; char *envname; int envflags = 0, putflags = 0; int dohdr = 0; prog = argv[0]; if (argc < 2) { usage(); } /* -f: load file instead of stdin * -n: use NOSUBDIR flag on env_open * -s: load into named subDB * -N: use NOOVERWRITE on puts * -T: read plaintext * -V: print version and exit */ while ((i = getopt(argc, argv, "f:ns:NTV")) != EOF) { switch(i) { case 'V': printf("%s\n", MDB_VERSION_STRING); exit(0); break; case 'f': if (freopen(optarg, "r", stdin) == NULL) { fprintf(stderr, "%s: %s: reopen: %s\n", prog, optarg, strerror(errno)); exit(EXIT_FAILURE); } break; case 'n': envflags |= MDB_NOSUBDIR; break; case 's': subname = strdup(optarg); break; case 'N': putflags = MDB_NOOVERWRITE|MDB_NODUPDATA; break; case 'T': mode |= NOHDR; break; default: usage(); } } if (optind != argc - 1) usage(); dbuf.mv_size = 4096; dbuf.mv_data = malloc(dbuf.mv_size); if (!(mode & NOHDR)) readhdr(); envname = argv[optind]; rc = mdb_env_create(&env); if (rc) { fprintf(stderr, "mdb_env_create failed, error %d %s\n", rc, mdb_strerror(rc)); return EXIT_FAILURE; } mdb_env_set_maxdbs(env, 2); if (info.me_maxreaders) mdb_env_set_maxreaders(env, info.me_maxreaders); if (info.me_mapsize) mdb_env_set_mapsize(env, info.me_mapsize); if (info.me_mapaddr) envflags |= MDB_FIXEDMAP; rc = mdb_env_open(env, envname, envflags, 0664); if (rc) { fprintf(stderr, "mdb_env_open failed, error %d %s\n", rc, mdb_strerror(rc)); goto env_close; } kbuf.mv_size = mdb_env_get_maxkeysize(env) * 2 + 2; kbuf.mv_data = malloc(kbuf.mv_size); while(!Eof) { MDB_val key, data; int batch = 0; flags = 0; if (!dohdr) { dohdr = 1; } else if (!(mode & NOHDR)) readhdr(); rc = mdb_txn_begin(env, NULL, 0, &txn); if (rc) { fprintf(stderr, "mdb_txn_begin failed, error %d %s\n", rc, mdb_strerror(rc)); goto env_close; } rc = mdb_open(txn, subname, flags|MDB_CREATE, &dbi); if (rc) { fprintf(stderr, "mdb_open failed, error %d %s\n", rc, mdb_strerror(rc)); goto txn_abort; } rc = mdb_cursor_open(txn, dbi, &mc); if (rc) { fprintf(stderr, "mdb_cursor_open failed, error %d %s\n", rc, mdb_strerror(rc)); goto txn_abort; } while(1) { rc = readline(&key, &kbuf); if (rc == EOF) break; if (rc) goto txn_abort; rc = readline(&data, &dbuf); if (rc) goto txn_abort; rc = mdb_cursor_put(mc, &key, &data, putflags); if (rc == MDB_KEYEXIST && putflags) continue; if (rc) goto txn_abort; batch++; if (batch == 100) { rc = mdb_txn_commit(txn); if (rc) { fprintf(stderr, "%s: line %" Z "d: txn_commit: %s\n", prog, lineno, mdb_strerror(rc)); goto env_close; } rc = mdb_txn_begin(env, NULL, 0, &txn); if (rc) { fprintf(stderr, "mdb_txn_begin failed, error %d %s\n", rc, mdb_strerror(rc)); goto env_close; } rc = mdb_cursor_open(txn, dbi, &mc); if (rc) { fprintf(stderr, "mdb_cursor_open failed, error %d %s\n", rc, mdb_strerror(rc)); goto txn_abort; } batch = 0; } } rc = mdb_txn_commit(txn); txn = NULL; if (rc) { fprintf(stderr, "%s: line %" Z "d: txn_commit: %s\n", prog, lineno, mdb_strerror(rc)); goto env_close; } mdb_dbi_close(env, dbi); } txn_abort: mdb_txn_abort(txn); env_close: mdb_env_close(env); return rc ? EXIT_FAILURE : EXIT_SUCCESS; }
/* Open all un-opened index DB handles */ int mdb_attr_dbs_open( BackendDB *be, MDB_txn *tx0, ConfigReply *cr ) { struct mdb_info *mdb = (struct mdb_info *) be->be_private; MDB_txn *txn; MDB_dbi *dbis = NULL; int i, flags; int rc; txn = tx0; if ( txn == NULL ) { rc = mdb_txn_begin( mdb->mi_dbenv, NULL, 0, &txn ); if ( rc ) { snprintf( cr->msg, sizeof(cr->msg), "database \"%s\": " "txn_begin failed: %s (%d).", be->be_suffix[0].bv_val, mdb_strerror(rc), rc ); Debug( LDAP_DEBUG_ANY, LDAP_XSTRING(mdb_attr_dbs) ": %s\n", cr->msg, 0, 0 ); return rc; } dbis = ch_calloc( 1, mdb->mi_nattrs * sizeof(MDB_dbi) ); } else { rc = 0; } flags = MDB_DUPSORT|MDB_DUPFIXED|MDB_INTEGERDUP; if ( !(slapMode & SLAP_TOOL_READONLY) ) flags |= MDB_CREATE; for ( i=0; i<mdb->mi_nattrs; i++ ) { if ( mdb->mi_attrs[i]->ai_dbi ) /* already open */ continue; rc = mdb_dbi_open( txn, mdb->mi_attrs[i]->ai_desc->ad_type->sat_cname.bv_val, flags, &mdb->mi_attrs[i]->ai_dbi ); if ( rc ) { snprintf( cr->msg, sizeof(cr->msg), "database \"%s\": " "mdb_dbi_open(%s) failed: %s (%d).", be->be_suffix[0].bv_val, mdb->mi_attrs[i]->ai_desc->ad_type->sat_cname.bv_val, mdb_strerror(rc), rc ); Debug( LDAP_DEBUG_ANY, LDAP_XSTRING(mdb_attr_dbs) ": %s\n", cr->msg, 0, 0 ); break; } /* Remember newly opened DBI handles */ if ( dbis ) dbis[i] = mdb->mi_attrs[i]->ai_dbi; } /* Only commit if this is our txn */ if ( tx0 == NULL ) { if ( !rc ) { rc = mdb_txn_commit( txn ); if ( rc ) { snprintf( cr->msg, sizeof(cr->msg), "database \"%s\": " "txn_commit failed: %s (%d).", be->be_suffix[0].bv_val, mdb_strerror(rc), rc ); Debug( LDAP_DEBUG_ANY, LDAP_XSTRING(mdb_attr_dbs) ": %s\n", cr->msg, 0, 0 ); } } else { mdb_txn_abort( txn ); } /* Something failed, forget anything we just opened */ if ( rc ) { for ( i=0; i<mdb->mi_nattrs; i++ ) { if ( dbis[i] ) { mdb->mi_attrs[i]->ai_dbi = 0; mdb->mi_attrs[i]->ai_indexmask |= MDB_INDEX_DELETING; } } mdb_attr_flush( mdb ); } ch_free( dbis ); } return rc; }
int main(int argc, char *argv[]) { int i, rc; MDB_env *env; MDB_txn *txn; MDB_dbi dbi; MDB_stat mst; MDB_envinfo mei; char *prog = argv[0]; char *envname; char *subname = NULL; int alldbs = 0, envinfo = 0, envflags = 0, freinfo = 0, rdrinfo = 0; if (argc < 2) { usage(prog); } /* -a: print stat of main DB and all subDBs * -s: print stat of only the named subDB * -e: print env info * -f: print freelist info * -r: print reader info * -n: use NOSUBDIR flag on env_open * -V: print version and exit * (default) print stat of only the main DB */ while ((i = getopt(argc, argv, "Vaefnrs:")) != EOF) { switch(i) { case 'V': printf("%s\n", MDB_VERSION_STRING); exit(0); break; case 'a': if (subname) usage(prog); alldbs++; break; case 'e': envinfo++; break; case 'f': freinfo++; break; case 'n': envflags |= MDB_NOSUBDIR; break; case 'r': rdrinfo++; break; case 's': if (alldbs) usage(prog); subname = optarg; break; default: usage(prog); } } if (optind != argc - 1) usage(prog); envname = argv[optind]; rc = mdb_env_create(&env); if (rc) { fprintf(stderr, "mdb_env_create failed, error %d %s\n", rc, mdb_strerror(rc)); return EXIT_FAILURE; } if (alldbs || subname) { mdb_env_set_maxdbs(env, 4); } rc = mdb_env_open(env, envname, envflags | MDB_RDONLY, 0664); if (rc) { fprintf(stderr, "mdb_env_open failed, error %d %s\n", rc, mdb_strerror(rc)); goto env_close; } if (envinfo) { (void)mdb_env_stat(env, &mst); (void)mdb_env_info(env, &mei); printf("Environment Info\n"); printf(" Map address: %p\n", mei.me_mapaddr); printf(" Map size: %"Z"u\n", mei.me_mapsize); printf(" Page size: %u\n", mst.ms_psize); printf(" Max pages: %"Z"u\n", mei.me_mapsize / mst.ms_psize); printf(" Number of pages used: %"Z"u\n", mei.me_last_pgno+1); printf(" Last transaction ID: %"Z"u\n", mei.me_last_txnid); printf(" Max readers: %u\n", mei.me_maxreaders); printf(" Number of readers used: %u\n", mei.me_numreaders); } if (rdrinfo) { printf("Reader Table Status\n"); rc = mdb_reader_list(env, (MDB_msg_func *)fputs, stdout); if (rdrinfo > 1) { int dead; mdb_reader_check(env, &dead); printf(" %d stale readers cleared.\n", dead); rc = mdb_reader_list(env, (MDB_msg_func *)fputs, stdout); } if (!(subname || alldbs || freinfo)) goto env_close; } rc = mdb_txn_begin(env, NULL, MDB_RDONLY, &txn); if (rc) { fprintf(stderr, "mdb_txn_begin failed, error %d %s\n", rc, mdb_strerror(rc)); goto env_close; } if (freinfo) { MDB_cursor *cursor; MDB_val key, data; size_t pages = 0, *iptr; printf("Freelist Status\n"); dbi = 0; rc = mdb_cursor_open(txn, dbi, &cursor); if (rc) { fprintf(stderr, "mdb_cursor_open failed, error %d %s\n", rc, mdb_strerror(rc)); goto txn_abort; } rc = mdb_stat(txn, dbi, &mst); if (rc) { fprintf(stderr, "mdb_stat failed, error %d %s\n", rc, mdb_strerror(rc)); goto txn_abort; } prstat(&mst); while ((rc = mdb_cursor_get(cursor, &key, &data, MDB_NEXT)) == 0) { iptr = data.mv_data; pages += *iptr; if (freinfo > 1) { char * bad = (char *)""; size_t pg, prev; ssize_t i, j, span = 0; j = *iptr++; for (i = j, prev = 1; --i >= 0; ) { pg = iptr[i]; if (pg <= prev) bad = (char *)" [bad sequence]"; prev = pg; pg += span; for (; i >= span && iptr[i-span] == pg; span++, pg++) ; } printf(" Transaction %"Z"u, %"Z"d pages, maxspan %"Z"d%s\n", *(size_t *)key.mv_data, j, span, bad); if (freinfo > 2) { for (--j; j >= 0; ) { pg = iptr[j]; for (span=1; --j >= 0 && iptr[j] == pg+span; span++) ; printf(span>1 ? " %9"Z"u[%"Z"d]\n" : " %9"Z"u\n", pg, span); } } } } mdb_cursor_close(cursor); printf(" Free pages: %"Z"u\n", pages); } rc = mdb_open(txn, subname, 0, &dbi); if (rc) { fprintf(stderr, "mdb_open failed, error %d %s\n", rc, mdb_strerror(rc)); goto txn_abort; } rc = mdb_stat(txn, dbi, &mst); if (rc) { fprintf(stderr, "mdb_stat failed, error %d %s\n", rc, mdb_strerror(rc)); goto txn_abort; } printf("Status of %s\n", subname ? subname : "Main DB"); prstat(&mst); if (alldbs) { MDB_cursor *cursor; MDB_val key; rc = mdb_cursor_open(txn, dbi, &cursor); if (rc) { fprintf(stderr, "mdb_cursor_open failed, error %d %s\n", rc, mdb_strerror(rc)); goto txn_abort; } while ((rc = mdb_cursor_get(cursor, &key, NULL, MDB_NEXT_NODUP)) == 0) { char *str; MDB_dbi db2; if (memchr(key.mv_data, '\0', key.mv_size)) continue; str = malloc(key.mv_size+1); memcpy(str, key.mv_data, key.mv_size); str[key.mv_size] = '\0'; rc = mdb_open(txn, str, 0, &db2); if (rc == MDB_SUCCESS) printf("Status of %s\n", str); free(str); if (rc) continue; rc = mdb_stat(txn, db2, &mst); if (rc) { fprintf(stderr, "mdb_stat failed, error %d %s\n", rc, mdb_strerror(rc)); goto txn_abort; } prstat(&mst); mdb_close(env, db2); } mdb_cursor_close(cursor); } if (rc == MDB_NOTFOUND) rc = MDB_SUCCESS; mdb_close(env, dbi); txn_abort: mdb_txn_abort(txn); env_close: mdb_env_close(env); return rc ? EXIT_FAILURE : EXIT_SUCCESS; }
void B_ACCURATE_LMDB::destroy(JCR *jcr) { /* * Abort any pending read transaction. */ if (m_db_ro_txn) { mdb_txn_abort(m_db_ro_txn); m_db_ro_txn = NULL; } /* * Abort any pending write transaction. */ if (m_db_rw_txn) { mdb_txn_abort(m_db_rw_txn); m_db_rw_txn = NULL; } if (m_db_env) { /* * Drop the contents of the LMDB. */ if (m_db_dbi) { int result; MDB_txn *txn; result = mdb_txn_begin(m_db_env, NULL, 0, &txn); if (result == 0) { result = mdb_drop(txn, m_db_dbi, 1); if (result == 0) { mdb_txn_commit(txn); } else { mdb_txn_abort(txn); } } m_db_dbi = 0; } /* * Close the environment. */ mdb_env_close(m_db_env); m_db_env = NULL; } if (m_pay_load) { free_pool_memory(m_pay_load); m_pay_load = NULL; } if (m_lmdb_name) { unlink(m_lmdb_name); free_pool_memory(m_lmdb_name); m_lmdb_name = NULL; } if (m_seen_bitmap) { free(m_seen_bitmap); m_seen_bitmap = NULL; } m_filenr = 0; }
ID mdb_tool_entry_next( BackendDB *be ) { int rc; ID id; struct mdb_info *mdb; assert( be != NULL ); assert( slapMode & SLAP_TOOL_MODE ); mdb = (struct mdb_info *) be->be_private; assert( mdb != NULL ); if ( !txn ) { rc = mdb_txn_begin( mdb->mi_dbenv, NULL, MDB_RDONLY, &txn ); if ( rc ) return NOID; rc = mdb_cursor_open( txn, mdb->mi_id2entry, &cursor ); if ( rc ) { mdb_txn_abort( txn ); return NOID; } } next:; rc = mdb_cursor_get( cursor, &key, &data, MDB_NEXT ); if( rc ) { return NOID; } previd = *(ID *)key.mv_data; id = previd; if ( tool_filter || tool_base ) { static Operation op = {0}; static Opheader ohdr = {0}; op.o_hdr = &ohdr; op.o_bd = be; op.o_tmpmemctx = NULL; op.o_tmpmfuncs = &ch_mfuncs; if ( tool_next_entry ) { mdb_entry_release( &op, tool_next_entry, 0 ); tool_next_entry = NULL; } rc = mdb_tool_entry_get_int( be, id, &tool_next_entry ); if ( rc == LDAP_NO_SUCH_OBJECT ) { goto next; } assert( tool_next_entry != NULL ); if ( tool_filter && test_filter( NULL, tool_next_entry, tool_filter ) != LDAP_COMPARE_TRUE ) { mdb_entry_release( &op, tool_next_entry, 0 ); tool_next_entry = NULL; goto next; } } return id; }
bool B_ACCURATE_LMDB::init(JCR *jcr, uint32_t nbfile) { int result; MDB_env *env; size_t mapsize = 10485760; if (!m_db_env) { result = mdb_env_create(&env); if (result) { Jmsg1(jcr, M_FATAL, 0, _("Unable to create MDB environment: %s\n"), mdb_strerror(result)); return false; } if ((nbfile * AVG_NR_BYTES_PER_ENTRY) > mapsize) { size_t pagesize; #ifdef HAVE_GETPAGESIZE pagesize = getpagesize(); #else pagesize = B_PAGE_SIZE; #endif mapsize = (((nbfile * AVG_NR_BYTES_PER_ENTRY) / pagesize) + 1) * pagesize; } result = mdb_env_set_mapsize(env, mapsize); if (result) { Jmsg1(jcr, M_FATAL, 0, _("Unable to set MDB mapsize: %s\n"), mdb_strerror(result)); goto bail_out; } /* * Explicitly set the number of readers to 1. */ result = mdb_env_set_maxreaders(env, 1); if (result) { Jmsg1(jcr, M_FATAL, 0, _("Unable to set MDB maxreaders: %s\n"), mdb_strerror(result)); goto bail_out; } Mmsg(m_lmdb_name, "%s/.accurate_lmdb.%d", me->working_directory, jcr->JobId); result = mdb_env_open(env, m_lmdb_name, MDB_NOSUBDIR | MDB_NOLOCK | MDB_NOSYNC, 0600); if (result) { Jmsg2(jcr, M_FATAL, 0, _("Unable create LDMD database %s: %s\n"), m_lmdb_name, mdb_strerror(result)); goto bail_out; } result = mdb_txn_begin(env, NULL, 0, &m_db_rw_txn); if (result) { Jmsg1(jcr, M_FATAL, 0, _("Unable to start a write transaction: %s\n"), mdb_strerror(result)); goto bail_out; } result = mdb_dbi_open(m_db_rw_txn, NULL, MDB_CREATE, &m_db_dbi); if (result) { Jmsg1(jcr, M_FATAL, 0, _("Unable to open LMDB internal database: %s\n"), mdb_strerror(result)); mdb_txn_abort(m_db_rw_txn); m_db_rw_txn = NULL; goto bail_out; } m_db_env = env; } if (!m_pay_load) { m_pay_load = get_pool_memory(PM_MESSAGE); } if (!m_lmdb_name) { m_pay_load = get_pool_memory(PM_FNAME); } if (!m_seen_bitmap) { m_seen_bitmap = (char *)malloc(nbytes_for_bits(nbfile)); clear_all_bits(nbfile, m_seen_bitmap); } return true; bail_out: if (env) { mdb_env_close(env); } return false; }
int mdb_tool_entry_reindex( BackendDB *be, ID id, AttributeDescription **adv ) { struct mdb_info *mi = (struct mdb_info *) be->be_private; int rc; Entry *e; Operation op = {0}; Opheader ohdr = {0}; Debug( LDAP_DEBUG_ARGS, "=> " LDAP_XSTRING(mdb_tool_entry_reindex) "( %ld )\n", (long) id, 0, 0 ); assert( tool_base == NULL ); assert( tool_filter == NULL ); /* No indexes configured, nothing to do. Could return an * error here to shortcut things. */ if (!mi->mi_attrs) { return 0; } /* Check for explicit list of attrs to index */ if ( adv ) { int i, j, n; if ( mi->mi_attrs[0]->ai_desc != adv[0] ) { /* count */ for ( n = 0; adv[n]; n++ ) ; /* insertion sort */ for ( i = 0; i < n; i++ ) { AttributeDescription *ad = adv[i]; for ( j = i-1; j>=0; j--) { if ( SLAP_PTRCMP( adv[j], ad ) <= 0 ) break; adv[j+1] = adv[j]; } adv[j+1] = ad; } } for ( i = 0; adv[i]; i++ ) { if ( mi->mi_attrs[i]->ai_desc != adv[i] ) { for ( j = i+1; j < mi->mi_nattrs; j++ ) { if ( mi->mi_attrs[j]->ai_desc == adv[i] ) { AttrInfo *ai = mi->mi_attrs[i]; mi->mi_attrs[i] = mi->mi_attrs[j]; mi->mi_attrs[j] = ai; break; } } if ( j == mi->mi_nattrs ) { Debug( LDAP_DEBUG_ANY, LDAP_XSTRING(mdb_tool_entry_reindex) ": no index configured for %s\n", adv[i]->ad_cname.bv_val, 0, 0 ); return -1; } } } mi->mi_nattrs = i; } e = mdb_tool_entry_get( be, id ); if( e == NULL ) { Debug( LDAP_DEBUG_ANY, LDAP_XSTRING(mdb_tool_entry_reindex) ": could not locate id=%ld\n", (long) id, 0, 0 ); return -1; } if ( !txi ) { rc = mdb_txn_begin( mi->mi_dbenv, NULL, 0, &txi ); if( rc != 0 ) { Debug( LDAP_DEBUG_ANY, "=> " LDAP_XSTRING(mdb_tool_entry_reindex) ": " "txn_begin failed: %s (%d)\n", mdb_strerror(rc), rc, 0 ); goto done; } } if ( slapMode & SLAP_TRUNCATE_MODE ) { int i; for ( i=0; i < mi->mi_nattrs; i++ ) { rc = mdb_drop( txi, mi->mi_attrs[i]->ai_dbi, 0 ); if ( rc ) { Debug( LDAP_DEBUG_ANY, LDAP_XSTRING(mdb_tool_entry_reindex) ": (Truncate) mdb_drop(%s) failed: %s (%d)\n", mi->mi_attrs[i]->ai_desc->ad_type->sat_cname.bv_val, mdb_strerror(rc), rc ); return -1; } } slapMode ^= SLAP_TRUNCATE_MODE; } /* * just (re)add them for now * Use truncate mode to empty/reset index databases */ Debug( LDAP_DEBUG_TRACE, "=> " LDAP_XSTRING(mdb_tool_entry_reindex) "( %ld )\n", (long) id, 0, 0 ); op.o_hdr = &ohdr; op.o_bd = be; op.o_tmpmemctx = NULL; op.o_tmpmfuncs = &ch_mfuncs; rc = mdb_tool_index_add( &op, txi, e ); done: if( rc == 0 ) { mdb_writes++; if ( mdb_writes >= mdb_writes_per_commit ) { unsigned i; MDB_TOOL_IDL_FLUSH( be, txi ); rc = mdb_txn_commit( txi ); mdb_writes = 0; for ( i=0; i<mi->mi_nattrs; i++ ) mi->mi_attrs[i]->ai_cursor = NULL; if( rc != 0 ) { Debug( LDAP_DEBUG_ANY, "=> " LDAP_XSTRING(mdb_tool_entry_reindex) ": txn_commit failed: %s (%d)\n", mdb_strerror(rc), rc, 0 ); e->e_id = NOID; } txi = NULL; } } else { unsigned i; mdb_writes = 0; mdb_txn_abort( txi ); for ( i=0; i<mi->mi_nattrs; i++ ) mi->mi_attrs[i]->ai_cursor = NULL; Debug( LDAP_DEBUG_ANY, "=> " LDAP_XSTRING(mdb_tool_entry_reindex) ": txn_aborted! err=%d\n", rc, 0, 0 ); e->e_id = NOID; txi = NULL; } mdb_entry_release( &op, e, 0 ); return rc; }
/* reindex entries on the fly */ static void * mdb_online_index( void *ctx, void *arg ) { struct re_s *rtask = arg; BackendDB *be = rtask->arg; struct mdb_info *mdb = be->be_private; Connection conn = {0}; OperationBuffer opbuf; Operation *op; MDB_cursor *curs; MDB_val key, data; MDB_txn *txn; ID id; Entry *e; int rc, getnext = 1; int i; connection_fake_init( &conn, &opbuf, ctx ); op = &opbuf.ob_op; op->o_bd = be; id = 1; key.mv_size = sizeof(ID); while ( 1 ) { if ( slapd_shutdown ) break; rc = mdb_txn_begin( mdb->mi_dbenv, NULL, 0, &txn ); if ( rc ) break; rc = mdb_cursor_open( txn, mdb->mi_id2entry, &curs ); if ( rc ) { mdb_txn_abort( txn ); break; } if ( getnext ) { getnext = 0; key.mv_data = &id; rc = mdb_cursor_get( curs, &key, &data, MDB_SET_RANGE ); if ( rc ) { mdb_txn_abort( txn ); if ( rc == MDB_NOTFOUND ) rc = 0; break; } memcpy( &id, key.mv_data, sizeof( id )); } rc = mdb_id2entry( op, curs, id, &e ); mdb_cursor_close( curs ); if ( rc ) { mdb_txn_abort( txn ); if ( rc == MDB_NOTFOUND ) { id++; getnext = 1; continue; } break; } rc = mdb_index_entry( op, txn, MDB_INDEX_UPDATE_OP, e ); mdb_entry_return( op, e ); if ( rc == 0 ) { rc = mdb_txn_commit( txn ); txn = NULL; } else { mdb_txn_abort( txn ); txn = NULL; } if ( rc ) break; id++; getnext = 1; } for ( i = 0; i < mdb->mi_nattrs; i++ ) { if ( mdb->mi_attrs[ i ]->ai_indexmask & MDB_INDEX_DELETING || mdb->mi_attrs[ i ]->ai_newmask == 0 ) { continue; } mdb->mi_attrs[ i ]->ai_indexmask = mdb->mi_attrs[ i ]->ai_newmask; mdb->mi_attrs[ i ]->ai_newmask = 0; } ldap_pvt_thread_mutex_lock( &slapd_rq.rq_mutex ); ldap_pvt_runqueue_stoptask( &slapd_rq, rtask ); mdb->mi_index_task = NULL; ldap_pvt_runqueue_remove( &slapd_rq, rtask ); ldap_pvt_thread_mutex_unlock( &slapd_rq.rq_mutex ); return NULL; }
int main(int argc,char * argv[]) { int i = 0, j = 0, rc; MDB_env *env; MDB_dbi dbi; MDB_val key, data; MDB_txn *txn; MDB_stat mst; MDB_cursor *cursor; int count; int *values; char sval[32]; char kval[sizeof(int)]; srand(time(NULL)); memset(sval, 0, sizeof(sval)); count = (rand()%384) + 64; values = (int *)malloc(count*sizeof(int)); for(i = 0;i<count;i++) { values[i] = rand()%1024; } E(mdb_env_create(&env)); E(mdb_env_set_mapsize(env, 10485760)); E(mdb_env_set_maxdbs(env, 4)); E(mdb_env_open(env, "./testdb", MDB_FIXEDMAP|MDB_NOSYNC, 0664)); E(mdb_txn_begin(env, NULL, 0, &txn)); E(mdb_open(txn, "id2", MDB_CREATE|MDB_DUPSORT, &dbi)); E(mdb_cursor_open(txn, dbi, &cursor)); key.mv_size = sizeof(int); key.mv_data = kval; data.mv_size = sizeof(sval); data.mv_data = sval; printf("Adding %d values\n", count); for (i=0;i<count;i++) { if (!(i & 0x0f)) sprintf(kval, "%03x", values[i]); sprintf(sval, "%03x %d foo bar", values[i], values[i]); if (RES(MDB_KEYEXIST, mdb_cursor_put(cursor, &key, &data, MDB_NODUPDATA))) j++; } if (j) printf("%d duplicates skipped\n", j); mdb_cursor_close(cursor); E(mdb_txn_commit(txn)); E(mdb_env_stat(env, &mst)); E(mdb_txn_begin(env, NULL, 1, &txn)); E(mdb_cursor_open(txn, dbi, &cursor)); while ((rc = mdb_cursor_get(cursor, &key, &data, MDB_NEXT)) == 0) { printf("key: %p %.*s, data: %p %.*s\n", key.mv_data, (int) key.mv_size, (char *) key.mv_data, data.mv_data, (int) data.mv_size, (char *) data.mv_data); } CHECK(rc == MDB_NOTFOUND, "mdb_cursor_get"); mdb_cursor_close(cursor); mdb_txn_abort(txn); j=0; for (i= count - 1; i > -1; i-= (rand()%5)) { j++; txn=NULL; E(mdb_txn_begin(env, NULL, 0, &txn)); sprintf(kval, "%03x", values[i & ~0x0f]); sprintf(sval, "%03x %d foo bar", values[i], values[i]); key.mv_size = sizeof(int); key.mv_data = kval; data.mv_size = sizeof(sval); data.mv_data = sval; if (RES(MDB_NOTFOUND, mdb_del(txn, dbi, &key, &data))) { j--; mdb_txn_abort(txn); } else { E(mdb_txn_commit(txn)); } } free(values); printf("Deleted %d values\n", j); E(mdb_env_stat(env, &mst)); E(mdb_txn_begin(env, NULL, 1, &txn)); E(mdb_cursor_open(txn, dbi, &cursor)); printf("Cursor next\n"); while ((rc = mdb_cursor_get(cursor, &key, &data, MDB_NEXT)) == 0) { printf("key: %.*s, data: %.*s\n", (int) key.mv_size, (char *) key.mv_data, (int) data.mv_size, (char *) data.mv_data); } CHECK(rc == MDB_NOTFOUND, "mdb_cursor_get"); printf("Cursor prev\n"); while ((rc = mdb_cursor_get(cursor, &key, &data, MDB_PREV)) == 0) { printf("key: %.*s, data: %.*s\n", (int) key.mv_size, (char *) key.mv_data, (int) data.mv_size, (char *) data.mv_data); } CHECK(rc == MDB_NOTFOUND, "mdb_cursor_get"); mdb_cursor_close(cursor); mdb_close(env, dbi); mdb_txn_abort(txn); mdb_env_close(env); return 0; }
void LMDBFileIndex::put_internal(const SIndexKey& key, int64 value, int flags, bool log, bool handle_enosp) { CWData vdata; vdata.addVarInt(value); MDB_val mdb_tkey; mdb_tkey.mv_data=const_cast<void*>(static_cast<const void*>(&key)); mdb_tkey.mv_size=sizeof(SIndexKey); MDB_val mdb_tvalue; mdb_tvalue.mv_data=vdata.getDataPtr(); mdb_tvalue.mv_size=vdata.getDataSize(); int rc = mdb_put(txn, dbi, &mdb_tkey, &mdb_tvalue, flags); if(rc==MDB_MAP_FULL && handle_enosp) { mdb_txn_abort(txn); if(_has_error) { Server->Log("LMDB had error during increase (on put). Aborting...", LL_ERROR); start_transaction(); return; } { read_transaction_lock.reset(); IScopedWriteLock lock(mutex); destroy_env(); map_size*=2; Server->Log("Increased LMDB database size to "+PrettyPrintBytes(map_size)+" (on put)", LL_DEBUG); if(!create_env()) { Server->Log("Error creating env after database file size increase", LL_ERROR); _has_error=true; start_transaction(); return; } } start_transaction(); replay_transaction_log(); put_internal(key, value, flags, false, true); } else if(rc==MDB_BAD_TXN && handle_enosp) { mdb_txn_abort(txn); if(_has_error) { Server->Log("LMDB had error on BAD_TXN (on put). Aborting...", LL_ERROR); start_transaction(); return; } start_transaction(); replay_transaction_log(); put_internal(key, value, flags, false, false); } else if(rc) { Server->Log("LMDB: Failed to put data ("+(std::string)mdb_strerror(rc)+")", LL_ERROR); _has_error=true; } if(!_has_error && log) { STransactionLogItem item = { key, value, flags}; transaction_log.push_back(item); } }
int mdb_delete( Operation *op, SlapReply *rs ) { struct mdb_info *mdb = (struct mdb_info *) op->o_bd->be_private; struct berval pdn = {0, NULL}; Entry *e = NULL; Entry *p = NULL; int manageDSAit = get_manageDSAit( op ); AttributeDescription *children = slap_schema.si_ad_children; AttributeDescription *entry = slap_schema.si_ad_entry; MDB_txn *txn = NULL; MDB_cursor *mc; mdb_op_info opinfo = {{{ 0 }}}, *moi = &opinfo; LDAPControl **preread_ctrl = NULL; LDAPControl *ctrls[SLAP_MAX_RESPONSE_CONTROLS]; int num_ctrls = 0; int parent_is_glue = 0; int parent_is_leaf = 0; #ifdef LDAP_X_TXN int settle = 0; #endif Debug( LDAP_DEBUG_ARGS, "==> " LDAP_XSTRING(mdb_delete) ": %s\n", op->o_req_dn.bv_val, 0, 0 ); #ifdef LDAP_X_TXN if( op->o_txnSpec ) { /* acquire connection lock */ ldap_pvt_thread_mutex_lock( &op->o_conn->c_mutex ); if( op->o_conn->c_txn == CONN_TXN_INACTIVE ) { rs->sr_text = "invalid transaction identifier"; rs->sr_err = LDAP_X_TXN_ID_INVALID; goto txnReturn; } else if( op->o_conn->c_txn == CONN_TXN_SETTLE ) { settle=1; goto txnReturn; } if( op->o_conn->c_txn_backend == NULL ) { op->o_conn->c_txn_backend = op->o_bd; } else if( op->o_conn->c_txn_backend != op->o_bd ) { rs->sr_text = "transaction cannot span multiple database contexts"; rs->sr_err = LDAP_AFFECTS_MULTIPLE_DSAS; goto txnReturn; } /* insert operation into transaction */ rs->sr_text = "transaction specified"; rs->sr_err = LDAP_X_TXN_SPECIFY_OKAY; txnReturn: /* release connection lock */ ldap_pvt_thread_mutex_unlock( &op->o_conn->c_mutex ); if( !settle ) { send_ldap_result( op, rs ); return rs->sr_err; } } #endif ctrls[num_ctrls] = 0; /* begin transaction */ rs->sr_err = mdb_opinfo_get( op, mdb, 0, &moi ); rs->sr_text = NULL; if( rs->sr_err != 0 ) { Debug( LDAP_DEBUG_TRACE, LDAP_XSTRING(mdb_delete) ": txn_begin failed: " "%s (%d)\n", mdb_strerror(rs->sr_err), rs->sr_err, 0 ); rs->sr_err = LDAP_OTHER; rs->sr_text = "internal error"; goto return_results; } txn = moi->moi_txn; /* allocate CSN */ if ( BER_BVISNULL( &op->o_csn ) ) { struct berval csn; char csnbuf[LDAP_PVT_CSNSTR_BUFSIZE]; csn.bv_val = csnbuf; csn.bv_len = sizeof(csnbuf); slap_get_csn( op, &csn, 1 ); } if ( !be_issuffix( op->o_bd, &op->o_req_ndn ) ) { dnParent( &op->o_req_ndn, &pdn ); } rs->sr_err = mdb_cursor_open( txn, mdb->mi_dn2id, &mc ); if ( rs->sr_err ) { rs->sr_err = LDAP_OTHER; rs->sr_text = "internal error"; goto return_results; } /* get parent */ rs->sr_err = mdb_dn2entry( op, txn, mc, &pdn, &p, NULL, 1 ); switch( rs->sr_err ) { case 0: case MDB_NOTFOUND: break; case LDAP_BUSY: rs->sr_text = "ldap server busy"; goto return_results; default: rs->sr_err = LDAP_OTHER; rs->sr_text = "internal error"; goto return_results; } if ( rs->sr_err == MDB_NOTFOUND ) { Debug( LDAP_DEBUG_ARGS, "<=- " LDAP_XSTRING(mdb_delete) ": no such object %s\n", op->o_req_dn.bv_val, 0, 0); if ( p && !BER_BVISEMPTY( &p->e_name )) { rs->sr_matched = ch_strdup( p->e_name.bv_val ); if ( is_entry_referral( p )) { BerVarray ref = get_entry_referrals( op, p ); rs->sr_ref = referral_rewrite( ref, &p->e_name, &op->o_req_dn, LDAP_SCOPE_DEFAULT ); ber_bvarray_free( ref ); } else { rs->sr_ref = NULL; } } else { rs->sr_ref = referral_rewrite( default_referral, NULL, &op->o_req_dn, LDAP_SCOPE_DEFAULT ); } if ( p ) { mdb_entry_return( op, p ); p = NULL; } rs->sr_err = LDAP_REFERRAL; rs->sr_flags = REP_MATCHED_MUSTBEFREED | REP_REF_MUSTBEFREED; goto return_results; } /* get entry */ rs->sr_err = mdb_dn2entry( op, txn, mc, &op->o_req_ndn, &e, NULL, 0 ); switch( rs->sr_err ) { case MDB_NOTFOUND: e = p; p = NULL; case 0: break; case LDAP_BUSY: rs->sr_text = "ldap server busy"; goto return_results; default: rs->sr_err = LDAP_OTHER; rs->sr_text = "internal error"; goto return_results; } /* FIXME : dn2entry() should return non-glue entry */ if ( rs->sr_err == MDB_NOTFOUND || ( !manageDSAit && is_entry_glue( e ))) { Debug( LDAP_DEBUG_ARGS, "<=- " LDAP_XSTRING(mdb_delete) ": no such object %s\n", op->o_req_dn.bv_val, 0, 0); rs->sr_matched = ch_strdup( e->e_dn ); if ( is_entry_referral( e )) { BerVarray ref = get_entry_referrals( op, e ); rs->sr_ref = referral_rewrite( ref, &e->e_name, &op->o_req_dn, LDAP_SCOPE_DEFAULT ); ber_bvarray_free( ref ); } else { rs->sr_ref = NULL; } mdb_entry_return( op, e ); e = NULL; rs->sr_err = LDAP_REFERRAL; rs->sr_flags = REP_MATCHED_MUSTBEFREED | REP_REF_MUSTBEFREED; goto return_results; } if ( pdn.bv_len != 0 ) { /* check parent for "children" acl */ rs->sr_err = access_allowed( op, p, children, NULL, ACL_WDEL, NULL ); if ( !rs->sr_err ) { Debug( LDAP_DEBUG_TRACE, "<=- " LDAP_XSTRING(mdb_delete) ": no write " "access to parent\n", 0, 0, 0 ); rs->sr_err = LDAP_INSUFFICIENT_ACCESS; rs->sr_text = "no write access to parent"; goto return_results; } } else { /* no parent, must be root to delete */ if( ! be_isroot( op ) ) { if ( be_issuffix( op->o_bd, (struct berval *)&slap_empty_bv ) || be_shadow_update( op ) ) { p = (Entry *)&slap_entry_root; /* check parent for "children" acl */ rs->sr_err = access_allowed( op, p, children, NULL, ACL_WDEL, NULL ); p = NULL; if ( !rs->sr_err ) { Debug( LDAP_DEBUG_TRACE, "<=- " LDAP_XSTRING(mdb_delete) ": no access to parent\n", 0, 0, 0 ); rs->sr_err = LDAP_INSUFFICIENT_ACCESS; rs->sr_text = "no write access to parent"; goto return_results; } } else { Debug( LDAP_DEBUG_TRACE, "<=- " LDAP_XSTRING(mdb_delete) ": no parent and not root\n", 0, 0, 0 ); rs->sr_err = LDAP_INSUFFICIENT_ACCESS; goto return_results; } } } if ( get_assert( op ) && ( test_filter( op, e, get_assertion( op )) != LDAP_COMPARE_TRUE )) { rs->sr_err = LDAP_ASSERTION_FAILED; goto return_results; } rs->sr_err = access_allowed( op, e, entry, NULL, ACL_WDEL, NULL ); if ( !rs->sr_err ) { Debug( LDAP_DEBUG_TRACE, "<=- " LDAP_XSTRING(mdb_delete) ": no write access " "to entry\n", 0, 0, 0 ); rs->sr_err = LDAP_INSUFFICIENT_ACCESS; rs->sr_text = "no write access to entry"; goto return_results; } if ( !manageDSAit && is_entry_referral( e ) ) { /* entry is a referral, don't allow delete */ rs->sr_ref = get_entry_referrals( op, e ); Debug( LDAP_DEBUG_TRACE, LDAP_XSTRING(mdb_delete) ": entry is referral\n", 0, 0, 0 ); rs->sr_err = LDAP_REFERRAL; rs->sr_matched = ch_strdup( e->e_name.bv_val ); rs->sr_flags = REP_MATCHED_MUSTBEFREED | REP_REF_MUSTBEFREED; goto return_results; } /* pre-read */ if( op->o_preread ) { if( preread_ctrl == NULL ) { preread_ctrl = &ctrls[num_ctrls++]; ctrls[num_ctrls] = NULL; } if( slap_read_controls( op, rs, e, &slap_pre_read_bv, preread_ctrl ) ) { Debug( LDAP_DEBUG_TRACE, "<=- " LDAP_XSTRING(mdb_delete) ": pre-read " "failed!\n", 0, 0, 0 ); if ( op->o_preread & SLAP_CONTROL_CRITICAL ) { /* FIXME: is it correct to abort * operation if control fails? */ goto return_results; } } } rs->sr_text = NULL; /* Can't do it if we have kids */ rs->sr_err = mdb_dn2id_children( op, txn, e ); if( rs->sr_err != MDB_NOTFOUND ) { switch( rs->sr_err ) { case 0: Debug(LDAP_DEBUG_ARGS, "<=- " LDAP_XSTRING(mdb_delete) ": non-leaf %s\n", op->o_req_dn.bv_val, 0, 0); rs->sr_err = LDAP_NOT_ALLOWED_ON_NONLEAF; rs->sr_text = "subordinate objects must be deleted first"; break; default: Debug(LDAP_DEBUG_ARGS, "<=- " LDAP_XSTRING(mdb_delete) ": has_children failed: %s (%d)\n", mdb_strerror(rs->sr_err), rs->sr_err, 0 ); rs->sr_err = LDAP_OTHER; rs->sr_text = "internal error"; } goto return_results; } /* delete from dn2id */ rs->sr_err = mdb_dn2id_delete( op, mc, e->e_id, 1 ); mdb_cursor_close( mc ); if ( rs->sr_err != 0 ) { Debug(LDAP_DEBUG_TRACE, "<=- " LDAP_XSTRING(mdb_delete) ": dn2id failed: " "%s (%d)\n", mdb_strerror(rs->sr_err), rs->sr_err, 0 ); rs->sr_text = "DN index delete failed"; rs->sr_err = LDAP_OTHER; goto return_results; } /* delete indices for old attributes */ rs->sr_err = mdb_index_entry_del( op, txn, e ); if ( rs->sr_err != LDAP_SUCCESS ) { Debug(LDAP_DEBUG_TRACE, "<=- " LDAP_XSTRING(mdb_delete) ": index failed: " "%s (%d)\n", mdb_strerror(rs->sr_err), rs->sr_err, 0 ); rs->sr_text = "entry index delete failed"; rs->sr_err = LDAP_OTHER; goto return_results; } /* fixup delete CSN */ if ( !SLAP_SHADOW( op->o_bd )) { struct berval vals[2]; assert( !BER_BVISNULL( &op->o_csn ) ); vals[0] = op->o_csn; BER_BVZERO( &vals[1] ); rs->sr_err = mdb_index_values( op, txn, slap_schema.si_ad_entryCSN, vals, 0, SLAP_INDEX_ADD_OP ); if ( rs->sr_err != LDAP_SUCCESS ) { rs->sr_text = "entryCSN index update failed"; rs->sr_err = LDAP_OTHER; goto return_results; } } /* delete from id2entry */ rs->sr_err = mdb_id2entry_delete( op->o_bd, txn, e ); if ( rs->sr_err != 0 ) { Debug( LDAP_DEBUG_TRACE, "<=- " LDAP_XSTRING(mdb_delete) ": id2entry failed: " "%s (%d)\n", mdb_strerror(rs->sr_err), rs->sr_err, 0 ); rs->sr_text = "entry delete failed"; rs->sr_err = LDAP_OTHER; goto return_results; } if ( pdn.bv_len != 0 ) { parent_is_glue = is_entry_glue(p); rs->sr_err = mdb_dn2id_children( op, txn, p ); if ( rs->sr_err != MDB_NOTFOUND ) { switch( rs->sr_err ) { case 0: break; default: Debug(LDAP_DEBUG_ARGS, "<=- " LDAP_XSTRING(mdb_delete) ": has_children failed: %s (%d)\n", mdb_strerror(rs->sr_err), rs->sr_err, 0 ); rs->sr_err = LDAP_OTHER; rs->sr_text = "internal error"; goto return_results; } parent_is_leaf = 1; } mdb_entry_return( op, p ); p = NULL; } if( moi == &opinfo ) { LDAP_SLIST_REMOVE( &op->o_extra, &opinfo.moi_oe, OpExtra, oe_next ); opinfo.moi_oe.oe_key = NULL; if( op->o_noop ) { mdb_txn_abort( txn ); rs->sr_err = LDAP_X_NO_OPERATION; txn = NULL; goto return_results; } else { rs->sr_err = mdb_txn_commit( txn ); } txn = NULL; } if( rs->sr_err != 0 ) { Debug( LDAP_DEBUG_ANY, LDAP_XSTRING(mdb_delete) ": txn_%s failed: %s (%d)\n", op->o_noop ? "abort (no-op)" : "commit", mdb_strerror(rs->sr_err), rs->sr_err ); rs->sr_err = LDAP_OTHER; rs->sr_text = "commit failed"; goto return_results; } Debug( LDAP_DEBUG_TRACE, LDAP_XSTRING(mdb_delete) ": deleted%s id=%08lx dn=\"%s\"\n", op->o_noop ? " (no-op)" : "", e->e_id, op->o_req_dn.bv_val ); rs->sr_err = LDAP_SUCCESS; rs->sr_text = NULL; if( num_ctrls ) rs->sr_ctrls = ctrls; return_results: if ( rs->sr_err == LDAP_SUCCESS && parent_is_glue && parent_is_leaf ) { op->o_delete_glue_parent = 1; } if ( p != NULL ) { mdb_entry_return( op, p ); } /* free entry */ if( e != NULL ) { mdb_entry_return( op, e ); } if( moi == &opinfo ) { if( txn != NULL ) { mdb_txn_abort( txn ); } if ( opinfo.moi_oe.oe_key ) { LDAP_SLIST_REMOVE( &op->o_extra, &opinfo.moi_oe, OpExtra, oe_next ); } } else { moi->moi_ref--; } send_ldap_result( op, rs ); slap_graduate_commit_csn( op ); if( preread_ctrl != NULL && (*preread_ctrl) != NULL ) { slap_sl_free( (*preread_ctrl)->ldctl_value.bv_val, op->o_tmpmemctx ); slap_sl_free( *preread_ctrl, op->o_tmpmemctx ); } #if 0 if( rs->sr_err == LDAP_SUCCESS && mdb->bi_txn_cp_kbyte ) { TXN_CHECKPOINT( mdb->bi_dbenv, mdb->bi_txn_cp_kbyte, mdb->bi_txn_cp_min, 0 ); } #endif return rs->sr_err; }
/* Open all un-opened index DB handles */ int mdb_attr_dbs_open( BackendDB *be, MDB_txn *tx0, ConfigReply *cr ) { struct mdb_info *mdb = (struct mdb_info *) be->be_private; MDB_txn *txn; int i, flags; int rc; txn = tx0; if ( txn == NULL ) { rc = mdb_txn_begin( mdb->mi_dbenv, NULL, 0, &txn ); if ( rc ) { snprintf( cr->msg, sizeof(cr->msg), "database \"%s\": " "txn_begin failed: %s (%d).", be->be_suffix[0].bv_val, mdb_strerror(rc), rc ); Debug( LDAP_DEBUG_ANY, LDAP_XSTRING(mdb_attr_dbs) ": %s\n", cr->msg, 0, 0 ); return rc; } } else { rc = 0; } flags = MDB_DUPSORT|MDB_DUPFIXED|MDB_INTEGERDUP; if ( !(slapMode & SLAP_TOOL_READONLY) ) flags |= MDB_CREATE; for ( i=0; i<mdb->mi_nattrs; i++ ) { if ( mdb->mi_attrs[i]->ai_dbi ) /* already open */ continue; rc = mdb_dbi_open( txn, mdb->mi_attrs[i]->ai_desc->ad_type->sat_cname.bv_val, flags, &mdb->mi_attrs[i]->ai_dbi ); if ( rc ) { snprintf( cr->msg, sizeof(cr->msg), "database \"%s\": " "mdb_dbi_open(%s) failed: %s (%d).", be->be_suffix[0].bv_val, mdb->mi_attrs[i]->ai_desc->ad_type->sat_cname.bv_val, mdb_strerror(rc), rc ); Debug( LDAP_DEBUG_ANY, LDAP_XSTRING(mdb_attr_dbs) ": %s\n", cr->msg, 0, 0 ); break; } } /* Only commit if this is our txn */ if ( tx0 == NULL ) { if ( !rc ) { rc = mdb_txn_commit( txn ); if ( rc ) { snprintf( cr->msg, sizeof(cr->msg), "database \"%s\": " "txn_commit failed: %s (%d).", be->be_suffix[0].bv_val, mdb_strerror(rc), rc ); Debug( LDAP_DEBUG_ANY, LDAP_XSTRING(mdb_attr_dbs) ": %s\n", cr->msg, 0, 0 ); } } else { mdb_txn_abort( txn ); } } return rc; }