Example #1
0
static void db_connect() {
	MDB_dbi dbi_session;
	MDB_dbi dbi_session_id;
	MDB_dbi dbi_event;
	MDB_dbi dbi_ip;

	LMDB_CHECK(mdb_env_create(&env));
	LMDB_CHECK(mdb_env_set_mapsize(env, 300000L * 4096L));
	LMDB_CHECK(mdb_env_set_maxdbs(env, 30));
#if defined(MDBX_LIFORECLAIM)
	LMDB_CHECK(mdb_env_open(env, opt_db_path, MDB_CREATE | MDB_NOSYNC | MDB_WRITEMAP | MDBX_LIFORECLAIM, 0664));
#else
	LMDB_CHECK(mdb_env_open(env, opt_db_path, MDB_CREATE | MDB_NOSYNC | MDB_WRITEMAP, 0664));
#endif
	MDB_txn *txn;

	// transaction init
	LMDB_CHECK(mdb_txn_begin(env, NULL, 0, &txn));
	// open database in read-write mode
	LMDB_CHECK(mdb_dbi_open(txn, "session", MDB_CREATE, &dbi_session));
	LMDB_CHECK(mdb_dbi_open(txn, "session_id", MDB_CREATE, &dbi_session_id));
	LMDB_CHECK(mdb_dbi_open(txn, "event", MDB_CREATE, &dbi_event));
	LMDB_CHECK(mdb_dbi_open(txn, "ip", MDB_CREATE, &dbi_ip));
	// transaction commit
	LMDB_CHECK(mdb_txn_commit(txn));
	printf("Connection open\n");
}
int db_schema_open(MDB_txn *const txn, DB_schema *const schema) {
	mdb_dbi_open(txn, "schema", MDB_CREATE | MDB_DUPSORT, &schema->schema);
	mdb_dbi_open(txn, "stringByID", MDB_CREATE, &schema->stringByID);
	mdb_dbi_open(txn, "stringIDByValue", MDB_CREATE, &schema->stringIDByValue);
	mdb_dbi_open(txn, "stringIDByHash", MDB_CREATE, &schema->stringIDByHash);
	return 0;
}
Example #3
0
FreqSchedulerError
freq_scheduler_cursor_open(FreqScheduler *sch, MDB_cursor **cursor) {
     char *error1 = 0;
     char *error2 = 0;

     MDB_txn *txn = 0;
     if (txn_manager_begin(sch->txn_manager, 0, &txn) != 0) {
          error1 = "starting transaction";
          error2 = sch->txn_manager->error->message;
          goto on_error;
     }

     MDB_dbi dbi;
     int mdb_rc =
          mdb_dbi_open(txn, "schedule", MDB_CREATE, &dbi) ||
          mdb_set_compare(txn, dbi, schedule_entry_mdb_cmp_asc) ||
          mdb_cursor_open(txn, dbi, cursor);

     if (mdb_rc != 0) {
          *cursor = 0;

	  error1 = "opening cursor";
	  error2 = mdb_strerror(mdb_rc);
     }

     return sch->error->code;

on_error:
     if (txn != 0)
          txn_manager_abort(sch->txn_manager, txn);
     freq_scheduler_set_error(sch, freq_scheduler_error_internal, __func__);
     freq_scheduler_add_error(sch, error1);
     freq_scheduler_add_error(sch, error2);
     return sch->error->code;
}
Example #4
0
bool Context::BeginTxn(){
  Error(0);
  if (envHandle==nullptr){
    return false;
  }
  else if (txnHandle!=nullptr){
    return false;
  }
  else{
    int txnret = mdb_txn_begin(envHandle,nullptr,0,&txnHandle);
    if (txnret != 0) {
      Error(txnret);
      txnHandle=nullptr;
      return false;
    }
    else{
      int dbiret = mdb_dbi_open(txnHandle,"Entity",MDB_CREATE,&dbiHandle);
      if (dbiret != 0){
        Error(dbiret);
        mdb_txn_abort(txnHandle);
        txnHandle=nullptr;
        return false;
      }
      else return true;
    }
  }
}
Example #5
0
counter_t *counter_init(const char *path, uint64_t readers) {
    counter_t *lc = NULL;
    if((lc = calloc(1, sizeof(counter_t))) == NULL) {
        perror("calloc");
        return NULL;
    }

    // Setup and open the lmdb enviornment
    MDB_CHECK(mdb_env_create(&lc->env), MDB_SUCCESS, NULL);
    MDB_CHECK(mdb_env_set_maxreaders(lc->env, readers), MDB_SUCCESS, NULL);
    MDB_CHECK(mdb_env_set_mapsize(lc->env, MDB_MAPSIZE), MDB_SUCCESS, NULL);
    MDB_CHECK(mdb_env_open(lc->env, path, MDB_WRITEMAP | MDB_MAPASYNC | MDB_NOSUBDIR, 0664), MDB_SUCCESS, NULL);

    MDB_txn *txn = NULL;
    MDB_CHECK(mdb_txn_begin(lc->env, NULL, 0, &txn), MDB_SUCCESS, NULL);

    if((lc->dbi = calloc(1, sizeof(MDB_dbi))) == NULL) {
        perror("calloc");
        return NULL;
    }

    MDB_CHECK(mdb_dbi_open(txn, NULL, 0, lc->dbi), MDB_SUCCESS, NULL);
    mdb_txn_commit(txn);
    return lc;
}
Example #6
0
int main(void)
{
    check(mdb_env_create(&env));
    check(mdb_env_set_mapsize(env, 1048576UL*1024UL*3UL));
    check(mdb_env_set_maxreaders(env, 126));
    check(mdb_env_set_maxdbs(env, 1));
    if(! access(DB_PATH, X_OK)) {
        system("rm -rf " DB_PATH);
    }
    check(mkdir(DB_PATH, 0777));
    check(mdb_env_open(env, DB_PATH, MDB_MAPASYNC|MDB_NOSYNC|MDB_NOMETASYNC, 0644));
    new_txn();
    check(mdb_dbi_open(txn, NULL, 0, &dbi));

    put("a");
    put("b");
    put("baa");
    put("d");

    new_txn();

    check(mdb_cursor_open(txn, dbi, &c1));
    check(mdb_cursor_get(c1, &keyv, &valv, MDB_LAST));
    check(mdb_cursor_del(c1, 0));
    check(mdb_cursor_del(c1, 0));
    new_txn();
}
Example #7
0
int mail_cache_db_get_size(struct mail_cache_db * cache_db,
    const void * key, size_t key_len, size_t * pvalue_len)
{
  int r;
  MDB_env *env;
  MDB_txn *txn;
  MDB_dbi dbi;
  MDB_val mdb_key;
  MDB_val mdb_val;

  env = cache_db->internal_database;

  mdb_key.mv_size = key_len;
  mdb_key.mv_data = (void *) key;

  r = mdb_txn_begin(env, NULL, 0, &txn);
  if (r != 0)
    return -1;
  r = mdb_dbi_open(txn, NULL, 0, &dbi);
  if (r != 0)
    goto error;

  r = mdb_get(txn, dbi, &mdb_key, &mdb_val);
  if (r != 0)
    goto error;

  * pvalue_len = mdb_val.mv_size;
  mdb_txn_commit(txn);
  return 0;

  error:
    mdb_txn_abort(txn);
    return -1;
}
Example #8
0
LMDBCursor* LMDB::NewCursor() {
  MDB_txn* mdb_txn;
  MDB_cursor* mdb_cursor;
  MDB_CHECK(mdb_txn_begin(mdb_env_, NULL, MDB_RDONLY, &mdb_txn));
  MDB_CHECK(mdb_dbi_open(mdb_txn, NULL, 0, &mdb_dbi_));
  MDB_CHECK(mdb_cursor_open(mdb_txn, mdb_dbi_, &mdb_cursor));
  return new LMDBCursor(mdb_txn, mdb_cursor);
}
Example #9
0
static int begin_txn(struct dbengine *db, struct txn **tidptr, int readonly)
{
    struct txn *tid = xzmalloc(sizeof(struct txn));
    int mflags, mr, r;
    struct MDB_txn *parent = NULL;

    assert(db && tidptr);

    PDEBUG("cyrusdb_lmdb(%s)[begin_txn] readonly=%d tidptr=%p *tidptr=%p",
            db->fname, readonly, tidptr, tidptr ? *tidptr : NULL);

    /* Read-only transactions may only be master transactions and do
     * not allow nested transactions. */
    readonly = !db->tid ? readonly : 0;

    /*
     * Hacky workaround, similar to skiplist
     *
     * If no transaction was passed, but we're in a transaction,
     * then create a nested exception within the current main
     * transaction.
     *
     * Note that transactions are always either the main transaction,
     * or a direct descendant of it. There are no deeper transaction
     * levels supported (although LMDB supports them).
     */
    if (db->tid) {
        parent = db->tid->mtxn;
    }

    /* Begin a new LMDB transaction */
    mr = mdb_txn_begin(db->env, parent, readonly ? MDB_RDONLY : 0, &tid->mtxn);
    if (mr) goto fail;

    /* Open the database */
    mflags = db->flags & CYRUSDB_CREATE ? MDB_CREATE : 0;
    mr = mdb_dbi_open(tid->mtxn, NULL /*name*/, mflags, &tid->dbi);
    if (mr) goto fail;

    if (db->flags & CYRUSDB_MBOXSORT) {
        /* Set mboxsort order */
        mr = mdb_set_compare(tid->mtxn, tid->dbi, mboxcmp);
        if (mr) goto fail;
    }

    if (!db->tid) {
        /* Set the master transaction */
        db->tid = tid;
    }
    *tidptr = tid;
    return CYRUSDB_OK;

fail:
    r = my_mdberror(mr);
    if (tid->mtxn) abort_txn(db, tid);
    syslog(LOG_ERR, "cryusdb_lmdb(%s): %s", db->fname, mdb_strerror(mr));
    return r;
}
Example #10
0
static PageDBError
page_db_link_stream_open_cursor(PageDBLinkStream *es) {
     MDB_txn *txn = 0;
     MDB_dbi dbi_links;

     int mdb_rc = 0;
     char *error = 0;

     // start a new read transaction
     if (txn_manager_begin(es->db->txn_manager, MDB_RDONLY, &txn) != 0) {
          error = es->db->txn_manager->error->message;
          goto mdb_error;
     }
     // open cursor to links database
     switch (mdb_rc = mdb_dbi_open(
                  txn,
                  "links",
                  MDB_INTEGERKEY,
                  &dbi_links)) {

     case 0:
          if ((mdb_rc = mdb_cursor_open(
                    txn,
                    dbi_links,
                    &es->cur)) != 0) {
               error = "opening links cursor";
               goto mdb_error;
          }
          es->state = stream_state_init;
          break;
     case MDB_NOTFOUND:
          txn_manager_abort(es->db->txn_manager, txn);
          es->cur = 0;
          es->state = stream_state_end;
          break;
     default:
          error = "opening links database";
          goto mdb_error;

     }
     return es->db->error->code;

mdb_error:
     es->state = stream_state_error;
     if (txn)
          txn_manager_abort(es->db->txn_manager, txn);
     es->cur = 0;

     page_db_set_error(es->db, page_db_error_internal, __func__);
     page_db_add_error(es->db, error);
     if (mdb_rc != 0)
          page_db_add_error(es->db, mdb_strerror(mdb_rc));

     return es->db->error->code;
}
Example #11
0
int mail_cache_db_get_keys(struct mail_cache_db * cache_db,
    chash * keys)
{
  int r;
  MDB_env *env;
  MDB_txn *txn;
  MDB_dbi dbi;
  MDB_cursor *cursor;
  MDB_val mdb_key;
  MDB_val mdb_val;

  env = cache_db->internal_database;

  r = mdb_txn_begin(env, NULL, 0, &txn);
  if (r != 0)
    return -1;
  r = mdb_dbi_open(txn, NULL, 0, &dbi);
  if (r != 0)
    goto error;

  r = mdb_cursor_open(txn, dbi, &cursor);
  if (r != 0)
    goto error;

  r = mdb_cursor_get(cursor, &mdb_key, &mdb_val, MDB_FIRST);
  if (r != 0)
    goto cursor_error;

  while (r == 0) {
    chashdatum hash_key;
    chashdatum hash_data;

    hash_key.data = mdb_key.mv_data;
    hash_key.len = (unsigned int) mdb_key.mv_size;
    hash_data.data = NULL;
    hash_data.len = 0;

    r = chash_set(keys, &hash_key, &hash_data, NULL);
    if (r != 0)
      goto cursor_error;
    r = mdb_cursor_get(cursor, &mdb_key, &mdb_val, MDB_NEXT);
  }

  mdb_txn_commit(txn);
  return 0;

  cursor_error:
    mdb_cursor_close(cursor);
  error:
    mdb_txn_abort(txn);
  return -1;
}
Example #12
0
/*
 * Class:     jmdb_DatabaseWrapper
 * Method:    dbiOpen
 * Signature: (JLjava/lang/String;I)I
 */
JNIEXPORT jint JNICALL Java_jmdb_DatabaseWrapper_dbiOpen(JNIEnv *vm,
		jclass clazz, jlong txnL, jstring name, jint flags) {
	MDB_txn *txnC = (MDB_txn*) txnL;
	const char *nameC = (*vm)->GetStringUTFChars(vm, name, NULL);
	MDB_dbi dbi;
	int code = mdb_dbi_open(txnC, nameC, flags, &dbi);
	(*vm)->ReleaseStringUTFChars(vm, name, nameC);
	if (code) {
		throwDatabaseException(vm, code);
		return -1;
	}
	return dbi;
}
Example #13
0
CAMLprim value caml_mdb_dbi_open(value txn,value name,value flags){
  CAMLparam3(txn,name,flags);
  MDB_dbi dbi;
  char*str=NULL;
  if(caml_string_length(name))
    str=String_val(name);

  if(mdb_dbi_open((MDB_txn*)txn,str,Int_val(flags),&dbi)){
    caml_failwith("error in mdb_dbi_open");
  }

  CAMLreturn(Val_int(dbi));
}
int db_dbi_open(MDB_txn *const txn, DB_schema *const schema, unsigned int opts, DB_column const *const cols, count_t const ncols, strarg_t const name, MDB_dbi *const dbi) {
	int rc;

	uint64_t const dbname_id = db_string_id(txn, schema, name);
	if(!dbname_id) return -1;

	DB_VAL(dbinfo_val, 2);
	db_bind(dbinfo_val, 0);
	db_bind(dbinfo_val, dbname_id);
	DB_VAL(info_val, 1);
	db_bind(info_val, 0xff & opts);
	mdb_put(txn, schema->schema, dbinfo_val, info_val, MDB_NOOVERWRITE);
	// TODO: Check opts

	MDB_cursor *cur = NULL;
	mdb_cursor_open(txn, schema->schema, &cur);

	DB_VAL(dbcols_val, 2);
	db_bind(dbcols_val, 1);
	db_bind(dbcols_val, dbname_id);
	MDB_val col_val;
	mdb_cursor_get(cur, &dbcols_val, &col_val, MDB_GET);
	for(; MDB_SUCCESS == rc; rc = mdb_cursor_get(cur, &dbcols_val, &col_val, MDB_NEXT_DUP)) {
		uint64_t const col = db_column(col_val, 0);
		uint64_t const type = db_column(col_val, 1);
		strarg_t const colname = db_column_text(txn, schema, col_val, 2);

		if(col >= ncols) break; // Extra columns are not an error.
		if(type != cols[i].type || 0 != strcmp(colname, cols[i].name)) {
			mdb_cursor_close(cur); cur = NULL;
			return -1;
		}
	}

	mdb_cursor_close(cur); cur = NULL;

	for(index_t i = 0; i < ncols; ++i) {
		uint64_t const colname_id = db_string_id(txn, schema, cols[i].name);
		if(!colname_id) return -1;

		DB_VAL(col_val, 3);
		db_bind(col_val, i);
		db_bind(col_val, cols[i].type);
		db_bind(col_val, colname_id);
		rc = mdb_put(txn, schema->schema, dbcols_val, col_val, MDB_NODUPDATA);
		if(MDB_SUCCESS != rc && MDB_KEYEXIST != rc) return -1;
	}

	mdb_dbi_open(txn, name, MDB_CREATE | opts, dbi);
	return 0;
}
Example #15
0
// Remove a key from database.
void database_del(MDB_env *db, MDB_val *key) {
	MDB_dbi dbi;
	MDB_txn *txn;

	// transaction init
	mdb_txn_begin(db, NULL, 0, &txn);
	// open database in read-write mode
	mdb_dbi_open(txn, NULL, 0, &dbi);
	// delete key
	mdb_del(txn, dbi, key, NULL);
	// close database
	mdb_dbi_close(db, dbi);
	// transaction commit
	mdb_txn_commit(txn);
}
Example #16
0
static int
page_db_open_cursor(MDB_txn *txn,
                    const char *db_name,
                    int flags,
                    MDB_cursor **cursor,
                    MDB_cmp_func *func) {
     MDB_dbi dbi;
     int mdb_rc =
          mdb_dbi_open(txn, db_name, flags, &dbi) ||
          (func && mdb_set_compare(txn, dbi, func)) ||
          mdb_cursor_open(txn, dbi, cursor);
     if (mdb_rc != 0)
          *cursor = 0;
     return mdb_rc;
}
Example #17
0
// Add or update a key in database.
void database_put(MDB_env *db, MDB_val *key, MDB_val *value) {
	MDB_dbi dbi;
	MDB_txn *txn;

	// transaction init
	mdb_txn_begin(db, NULL, 0, &txn);
	// open database in read-write mode
	mdb_dbi_open(txn, NULL, 0, &dbi);
	// put data
	mdb_put(txn, dbi, key, value, 0);
	// close database
	mdb_dbi_close(db, dbi);
	// transaction commit
	mdb_txn_commit(txn);
}
Example #18
0
// Return a value from database.
void database_get(MDB_env *db, MDB_val *key, MDB_val *value) {
	MDB_dbi dbi;
	MDB_txn *txn;

	// transaction init
	mdb_txn_begin(db, NULL, MDB_RDONLY, &txn);
	// open database in read-write mode
	mdb_dbi_open(txn, NULL, 0, &dbi);
	// get data
	if (mdb_get(txn, dbi, key, value))
		bzero(value, sizeof(*value));
	// end of transaction
	mdb_txn_abort(txn);
	// close database
	mdb_dbi_close(db, dbi);
}
int main(int argc,char * argv[])
{
    int rc;
    MDB_env *env;
    MDB_dbi dbi;
    MDB_val key, data;
    MDB_txn *txn;
    MDB_cursor *cursor;
    char sval[MAX_DATA_ALLOCATE_SIZE], kval[MAX_KEY_ALLOCATE_SIZE];

    /* Note: Most error checking omitted for simplicity */

    rc = mdb_env_create(&env);
    mdb_env_set_mapsize(env, MAX_DB_SIZE);
    mdb_env_set_maxdbs(env, (MDB_dbi)10);
    rc = mdb_env_open(env, "./demoDB", 0, 0664);
    rc = mdb_txn_begin(env, NULL, 0, &txn);
    rc = mdb_dbi_open(txn, "what", 0, &dbi);
    
    // rc = mdb_put(txn, dbi, &key, &data, 0);
    rc = mdb_txn_commit(txn);
    if (rc) {
        fprintf(stderr, "mdb_txn_commit: (%d) %s\n", rc, mdb_strerror(rc));
        goto leave;
    }

    fprintf(stderr, "print out old data:\n");
    rc = mdb_txn_begin(env, NULL, MDB_RDONLY, &txn);
    rc = mdb_cursor_open(txn, dbi, &cursor);

    key.mv_size = sizeof(kval);
    key.mv_data = kval;
    data.mv_size = sizeof(sval);
    data.mv_data = sval;
    memset(kval, argv[1][0], sizeof(kval));

    rc = mdb_cursor_get(cursor, &key, &data, MDB_SET);
    fprintf(stderr, "key: %s, data: %s\n",(char *) key.mv_data,(char *) data.mv_data);

    mdb_cursor_close(cursor);
    mdb_txn_abort(txn);
leave:
    mdb_dbi_close(env, dbi);
    mdb_env_close(env);
    return 0;
}
Example #20
0
/*
bool Context::Write(size_t ksz, void* key,
		    size_t dsz, void* data){
  Error(0);
  if (envHandle==nullptr){
    return false;
  }
  else{
    MDB_txn *txn;
    int txnret = mdb_txn_begin(envHandle,nullptr,0,&txn);
    if (txnret != 0) {
      Error(txnret);
      return false;
    }
    else{
      MDB_dbi dbi;
      int dbiret = mdb_dbi_open(txn,"Entity",MDB_CREATE,&dbi);
      if (dbiret != 0){
        Error(dbiret);
        mdb_txn_abort(txn);
        return false;
      }
      else{
        MDB_val kkey { ksz, key };
        MDB_val ddata { dsz, data};
        putReturn = mdb_put(txn,dbi,&kkey,&ddata,0);
        if (putReturn !=0){
          Error(putReturn);
          mdb_txn_abort(txn);
          return false;
        }
        else{
          int commit = mdb_txn_commit(txn);
          if (commit!=0){
            Error(commit);
            return false;
          }
          else return true;
        }
      }
    }
  }
}
*/
bool Context::GetCopy(size_t ksz, void* key,
		   void** data){
  Error(0);
  if (envHandle==nullptr){
    return false;
  }
  else{
    MDB_txn *txn;
    int txnret = mdb_txn_begin(envHandle,nullptr,0,&txn);
    if (txnret != 0){
      Error(txnret);
      return false;
    }
    else{
      MDB_dbi dbi;
      int dbiret = mdb_dbi_open(txn,"Entity",0,&dbi);
      if (dbiret !=0){
        Error(dbiret);
        mdb_txn_abort(txn);
        return false;
      }
      else{
        MDB_val kkey { ksz, key };
        MDB_val ddata;
        int get = mdb_get(txn,dbi,&kkey,&ddata);
        if (get!=0){
          Error(get);
          mdb_txn_abort(txn);
          return false;
        }
        else {
          *data = new char[ddata.mv_size];
          memcpy(*data, (void*)ddata.mv_data, (ddata.mv_size)*sizeof(char));
          int commit = mdb_txn_commit(txn);
          if (commit!=0){
            Error(commit);
            delete (char*)(*data);
            return false;
          }
          else return true;
        }
      }
    }
  }
}
Example #21
0
uint64_t counter_get(counter_t *lc, const char *key) {
    MDB_dbi dbi;
    MDB_val mkey, data;
    MDB_txn *txn;
    mdb_txn_begin(lc->env, NULL, 0, &txn);
    mdb_dbi_open(txn, NULL, 0, &dbi);

    mkey.mv_size = strlen(key) * sizeof(char);
    mkey.mv_data = (void *)key;

    // First we get our data from the db
    uint64_t stored_counter = 0;
    if(mdb_get(txn, dbi, &mkey, &data) == MDB_SUCCESS) {
        stored_counter = *(uint64_t *)data.mv_data;
    }
    mdb_dbi_close(lc->env, dbi);
    return stored_counter;
}
Example #22
0
int _db_open(DB *db, DB_TXN *txnid, const char *file, const char *database, DBTYPE type, uint32_t flags, int mode)
{
    printf("%s\n", __FUNCTION__);
    if (db == NULL) return EINVAL;

    mdb_env_open(db->_internal->env, "./", /*MDB_FIXEDMAP*/0, mode);

    if (txnid == NULL) {
        if (mdb_txn_begin(db->_internal->env, NULL, 0, &db->_internal->txn) != 0) return EINVAL;
    } else {
        if (mdb_txn_begin(db->_internal->env, txnid->_internal->txn, 0, &db->_internal->txn) != 0) return EINVAL;
    }

    uint32_t _flags = 0;
    if (flags & DB_CREATE) _flags |= MDB_CREATE;

    if (mdb_dbi_open(db->_internal->txn, database, _flags, &db->_internal->dbi) !=0 ) {
        mdb_txn_abort(db->_internal->txn);
        return EINVAL;
    }
    mdb_txn_commit(db->_internal->txn);

    return 0;
}
Example #23
0
        int LMDBStore::set(hcat_keypair* pair, void* transaction_context)
        {
            int rc;
            lmdb_transaction_context* context = (lmdb_transaction_context*)transaction_context;

            MDB_dbi db_instance = dbi;
            if (pair->keyspace.length() > 0)
            {
                db_instance = keyspaces->operator[](pair->keyspace.data());
            
                if (db_instance == NULL)
                {
                    rc = mdb_dbi_open(context->transaction, pair->keyspace.data(), MDB_CREATE, &db_instance);
                    if (rc == MDB_SUCCESS)
                    {
                        keyspaces->operator[](pair->keyspace.data()) = db_instance;
                    }
                    else
                    {
                        // TODO: Return an error.
                    }
                }
            }

            MDB_val mdb_key;
            MDB_val mdb_value;
            
            mdb_key.mv_size = pair->key.length() + 1;
            mdb_key.mv_data = (void*)pair->key.data();
            mdb_value.mv_size = pair->value_length + 1;
            mdb_value.mv_data = pair->value;
            
            rc = mdb_put(context->transaction, db_instance, &mdb_key, &mdb_value, 0);

            return (rc == 0 ? HCAT_SUCCESS : HCAT_FAIL);
        }
Example #24
0
LMDBTransaction* LMDB::NewTransaction() {
  MDB_txn* mdb_txn;
  MDB_CHECK(mdb_txn_begin(mdb_env_, NULL, 0, &mdb_txn));
  MDB_CHECK(mdb_dbi_open(mdb_txn, NULL, 0, &mdb_dbi_));
  return new LMDBTransaction(&mdb_dbi_, mdb_txn);
}
Example #25
0
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;
}
Example #26
0
int main(int argc,char * argv[])
{
	int i = 0, j = 0, rc;
	MDB_env *env;
	MDB_dbi dbi;
	MDB_val key, data, sdata;
	MDB_txn *txn;
	MDB_stat mst;
	MDB_cursor *cursor;
	int count;
	int *values;
	long kval;
	char *sval;

	srand(time(NULL));

	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_dbi_open(txn, "id6", MDB_CREATE|MDB_INTEGERKEY, &dbi));
	E(mdb_cursor_open(txn, dbi, &cursor));
	E(mdb_stat(txn, dbi, &mst));

	sval = calloc(1, mst.ms_psize / 4);
	key.mv_size = sizeof(long);
	key.mv_data = &kval;
	sdata.mv_size = mst.ms_psize / 4 - 30;
	sdata.mv_data = sval;

	printf("Adding 12 values, should yield 3 splits\n");
	for (i=0;i<12;i++) {
		kval = i*5;
		sprintf(sval, "%08x", kval);
		data = sdata;
		(void)RES(MDB_KEYEXIST, mdb_cursor_put(cursor, &key, &data, MDB_NOOVERWRITE));
	}
	printf("Adding 12 more values, should yield 3 splits\n");
	for (i=0;i<12;i++) {
		kval = i*5+4;
		sprintf(sval, "%08x", kval);
		data = sdata;
		(void)RES(MDB_KEYEXIST, mdb_cursor_put(cursor, &key, &data, MDB_NOOVERWRITE));
	}
	printf("Adding 12 more values, should yield 3 splits\n");
	for (i=0;i<12;i++) {
		kval = i*5+1;
		sprintf(sval, "%08x", kval);
		data = sdata;
		(void)RES(MDB_KEYEXIST, mdb_cursor_put(cursor, &key, &data, MDB_NOOVERWRITE));
	}
	E(mdb_cursor_get(cursor, &key, &data, MDB_FIRST));

	do {
		printf("key: %p %s, data: %p %.*s\n",
			key.mv_data,  mdb_dkey(&key, dkbuf),
			data.mv_data, (int) data.mv_size, (char *) data.mv_data);
	} while ((rc = mdb_cursor_get(cursor, &key, &data, MDB_NEXT)) == 0);
	CHECK(rc == MDB_NOTFOUND, "mdb_cursor_get");
	mdb_cursor_close(cursor);
	mdb_txn_commit(txn);

#if 0
	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, MDB_RDONLY, &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_txn_abort(txn);

	mdb_dbi_close(env, dbi);
#endif
	mdb_env_close(env);

	return 0;
}
Example #27
0
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[8];
	char kval[sizeof(int)];

	memset(sval, 0, sizeof(sval));

	count = 510;
	values = (int *)malloc(count*sizeof(int));

	for(i = 0;i<count;i++) {
		values[i] = i*5;
	}

	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_dbi_open(txn, "id4", MDB_CREATE|MDB_DUPSORT|MDB_DUPFIXED, &dbi));

	key.mv_size = sizeof(int);
	key.mv_data = kval;
	data.mv_size = sizeof(sval);
	data.mv_data = sval;

	printf("Adding %d values\n", count);
	strcpy(kval, "001");
	for (i=0;i<count;i++) {
		sprintf(sval, "%07x", values[i]);
		if (RES(MDB_KEYEXIST, mdb_put(txn, dbi, &key, &data, MDB_NODUPDATA)))
			j++;
	}
	if (j) printf("%d duplicates skipped\n", j);
	E(mdb_txn_commit(txn));
	E(mdb_env_stat(env, &mst));

	/* there should be one full page of dups now.
	 */
	E(mdb_txn_begin(env, NULL, MDB_RDONLY, &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);

	/* test all 3 branches of split code:
	 * 1: new key in lower half
	 * 2: new key at split point
	 * 3: new key in upper half
	 */

	key.mv_size = sizeof(int);
	key.mv_data = kval;
	data.mv_size = sizeof(sval);
	data.mv_data = sval;

	sprintf(sval, "%07x", values[3]+1);
	E(mdb_txn_begin(env, NULL, 0, &txn));
	(void)RES(MDB_KEYEXIST, mdb_put(txn, dbi, &key, &data, MDB_NODUPDATA));
	mdb_txn_abort(txn);

	sprintf(sval, "%07x", values[255]+1);
	E(mdb_txn_begin(env, NULL, 0, &txn));
	(void)RES(MDB_KEYEXIST, mdb_put(txn, dbi, &key, &data, MDB_NODUPDATA));
	mdb_txn_abort(txn);

	sprintf(sval, "%07x", values[500]+1);
	E(mdb_txn_begin(env, NULL, 0, &txn));
	(void)RES(MDB_KEYEXIST, mdb_put(txn, dbi, &key, &data, MDB_NODUPDATA));
	E(mdb_txn_commit(txn));

	/* Try MDB_NEXT_MULTIPLE */
	E(mdb_txn_begin(env, NULL, 0, &txn));
	E(mdb_cursor_open(txn, dbi, &cursor));
	while ((rc = mdb_cursor_get(cursor, &key, &data, MDB_NEXT_MULTIPLE)) == 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_txn_abort(txn);
	j=0;

	for (i= count - 1; i > -1; i-= (rand()%3)) {
		j++;
		txn=NULL;
		E(mdb_txn_begin(env, NULL, 0, &txn));
		sprintf(sval, "%07x", 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, MDB_RDONLY, &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_txn_abort(txn);

	mdb_dbi_close(env, dbi);
	mdb_env_close(env);
	return 0;
}
Example #28
0
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" );
		return -1;
	}

	Debug( LDAP_DEBUG_ARGS,
		LDAP_XSTRING(mdb_db_open) ": \"%s\"\n",
		be->be_suffix[0].bv_val );

	/* 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;
	}

	mdb_env_set_userctx(mdb->mi_dbenv, mdb);

	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 MDBX_LIFORECLAIM
#if MDBX_MODE_ENABLED
	rc = mdbx_env_set_syncbytes( mdb->mi_dbenv, mdb->mi_txn_cp_kbyte * 1024ul);
#else
	rc = mdb_env_set_syncbytes( mdb->mi_dbenv, mdb->mi_txn_cp_kbyte * 1024ul);
#endif /* MDBX_MODE_ENABLED */
	if( rc != 0 ) {
		Debug( LDAP_DEBUG_ANY,
			LDAP_XSTRING(mdb_db_open) ": database \"%s\": "
			"mdb_env_set_sync_threshold failed: %s (%d).\n",
			be->be_suffix[0].bv_val, mdb_strerror(rc), rc );
		goto fail;
	}

#if MDBX_MODE_ENABLED
	mdbx_env_set_oomfunc( mdb->mi_dbenv, mdb_oom_handler );
#else
	mdb_env_set_oomfunc( mdb->mi_dbenv, mdb_oom_handler );
#endif /* MDBX_MODE_ENABLED */

	if ( (slapMode & SLAP_SERVER_MODE) && SLAP_MULTIMASTER(be) &&
			((MDBX_OOM_YIELD & mdb->mi_oom_flags) == 0 || mdb->mi_renew_lag == 0)) {
		snprintf( cr->msg, sizeof(cr->msg), "database \"%s\": "
			"for properly operation in multi-master mode"
			" 'oom-handler yield' and 'dreamcatcher' are recommended",
			be->be_suffix[0].bv_val );
		Debug( LDAP_DEBUG_ANY, LDAP_XSTRING(mdb_db_open) ": %s\n", cr->msg );
	}
#endif /* MDBX_LIFORECLAIM */

	dbhome = mdb->mi_dbenv_home;

	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);

	flags = mdb->mi_dbenv_flags;

#ifdef MDBX_PAGEPERTURB
	if (reopenldap_mode_check())
		flags |= MDBX_PAGEPERTURB;
#endif

	if ( slapMode & SLAP_TOOL_QUICK )
		flags |= MDB_NOSYNC|MDB_WRITEMAP;

	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: %s (%d). "
			"Restore from backup!\n",
			be->be_suffix[0].bv_val, mdb_strerror(rc), rc );
		goto fail;
	}

	rc = mdb_txn_begin( mdb->mi_dbenv, NULL, flags & MDB_RDONLY, &txn );
	if ( rc ) {
		Debug( LDAP_DEBUG_ANY,
			LDAP_XSTRING(mdb_db_open) ": database \"%s\" cannot be opened: %s (%d). "
			"Restore from backup!\n",
			be->be_suffix[0].bv_val, mdb_strerror(rc), rc );
		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_dbi_open( txn,
			mdmi_databases[i].bv_val,
			flags,
			&mdb->mi_dbis[i] );

		if ( rc != 0 ) {
			snprintf( cr->msg, sizeof(cr->msg), "database \"%s\": "
				"mdb_dbi_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 );
			goto fail;
		}

		if ( i == MDB_ID2ENTRY )
			mdb_set_compare( txn, mdb->mi_dbis[i], mdb_id_compare );
		else if ( i == MDB_DN2ID ) {
			MDB_cursor *mc;
			MDB_val key, data;
			mdb_set_dupsort( txn, mdb->mi_dbis[i], mdb_dup_compare );
			/* check for old dn2id format */
			rc = mdb_cursor_open( txn, mdb->mi_dbis[i], &mc );
			/* first record is always ID 0 */
			rc = mdb_cursor_get( mc, &key, &data, MDB_FIRST );
			if ( rc == 0 ) {
				rc = mdb_cursor_get( mc, &key, &data, MDB_NEXT );
				if ( rc == 0 ) {
					int len;
					unsigned char *ptr;
					ptr = data.mv_data;
					len = (ptr[0] & 0x7f) << 8 | ptr[1];
					if (data.mv_size < 2*len + 4 + 2*sizeof(ID)) {
						snprintf( cr->msg, sizeof(cr->msg),
						"database \"%s\": DN index needs upgrade, "
						"run \"slapindex entryDN\".",
						be->be_suffix[0].bv_val );
						Debug( LDAP_DEBUG_ANY,
							LDAP_XSTRING(mdb_db_open) ": %s\n",
							cr->msg );
						if ( !(slapMode & SLAP_TOOL_READMAIN ))
							rc = LDAP_OTHER;
						mdb->mi_flags |= MDB_NEED_UPGRADE;
					}
				}
			}
			mdb_cursor_close( mc );
			if ( rc == LDAP_OTHER )
				goto fail;
		}
	}

	rc = mdb_ad_read( mdb, txn );
	if ( rc ) {
		mdb_txn_abort( txn );
		goto fail;
	}

	/* slapcat doesn't need indexes. avoid a failure if
	 * a configured index wasn't created yet.
	 */
	if ( !(slapMode & SLAP_TOOL_READONLY) ) {
		rc = mdb_attr_dbs_open( be, txn, cr );
		if ( rc ) {
			mdb_txn_abort( txn );
			goto fail;
		}
	}

	rc = mdb_txn_commit(txn);
	if ( rc != 0 ) {
		Debug( LDAP_DEBUG_ANY,
			LDAP_XSTRING(mdb_db_open) ": database %s: "
			"txn_commit failed: %s (%d)\n",
			be->be_suffix[0].bv_val, mdb_strerror(rc), rc );
		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;
}
Example #29
0
PageDBError
page_db_new(PageDB **db, const char *path) {
     PageDB *p = *db = malloc(sizeof(*p));
     if (p == 0)
          return page_db_error_memory;

     p->error = error_new();
     if (p->error == 0) {
          free(p);
          return page_db_error_memory;
     }
     p->persist = PAGE_DB_DEFAULT_PERSIST;
     p->domain_temp = 0;

     // create directory if not present yet
     const char *error = make_dir(path);
     if ((p->path = strdup(path)) == 0) {
          error = "could not duplicate path string";
     }
     if (error != 0) {
          page_db_set_error(p, page_db_error_invalid_path, __func__);
          page_db_add_error(p, error);
          return p->error->code;
     }

     if (txn_manager_new(&p->txn_manager, 0) != 0) {
          page_db_set_error(p, page_db_error_internal, __func__);
          page_db_add_error(p, p->txn_manager?
                            p->txn_manager->error->message:
                            "NULL");
          return p->error->code;
     }

     // initialize LMDB on the directory
     MDB_txn *txn;
     MDB_dbi dbi;
     int mdb_rc = 0;
     if ((mdb_rc = mdb_env_create(&p->txn_manager->env) != 0))
          error = "creating environment";
     else if ((mdb_rc = mdb_env_set_mapsize(
                    p->txn_manager->env, PAGE_DB_DEFAULT_SIZE)) != 0)
          error = "setting map size";
     else if ((mdb_rc = mdb_env_set_maxdbs(p->txn_manager->env, 5)) != 0)
          error = "setting number of databases";
     else if ((mdb_rc = mdb_env_open(
                    p->txn_manager->env,
                    path,
                    MDB_NOTLS | MDB_NOSYNC, 0664) != 0))
          error = "opening environment";
     else if ((mdb_rc = txn_manager_begin(p->txn_manager, 0, &txn)) != 0)
          error = "starting transaction";
     // create all database
     else if ((mdb_rc = mdb_dbi_open(txn,
                                     "hash2info",
                                     MDB_CREATE | MDB_INTEGERKEY,
                                     &dbi)) != 0)
          error = "creating hash2info database";
     else if ((mdb_rc = mdb_dbi_open(txn,
                                     "hash2idx",
                                     MDB_CREATE | MDB_INTEGERKEY,
                                     &dbi)) != 0)
          error = "creating hash2idx database";
     else if ((mdb_rc = mdb_dbi_open(txn,
                                     "links",
                                     MDB_CREATE | MDB_INTEGERKEY,
                                     &dbi)) != 0)
          error = "creating links database";
     else if ((mdb_rc = mdb_dbi_open(txn, "info", MDB_CREATE, &dbi)) != 0)
          error = "creating info database";
     else {
          // initialize n_pages inside info database
          size_t n_pages = 0;
          MDB_val key = {
               .mv_size = sizeof(info_n_pages),
               .mv_data = info_n_pages
          };
          MDB_val val = {
               .mv_size = sizeof(size_t),
               .mv_data = &n_pages
          };
          switch (mdb_rc = mdb_put(txn, dbi, &key, &val, MDB_NOOVERWRITE)) {
          case MDB_KEYEXIST:
          case 0:
               if (txn_manager_commit(p->txn_manager, txn) != 0)
                    error = p->txn_manager->error->message;
               break; // we good
          default:
               error = "could not initialize info.n_pages";
          }
     }

     if (error != 0) {
          page_db_set_error(p, page_db_error_internal, __func__);
          page_db_add_error(p, error);
          page_db_add_error(p, mdb_strerror(mdb_rc));

          mdb_env_close(p->txn_manager->env);
     }

     return p->error->code;
}


/** Store a new or updated @ref PageInfo for a crawled page.
 *
 * @param cur An open cursor to the hash2info database
 * @param key The key (hash) to the page
 * @param page
 * @param mdb_error In case of failure, if the error occurs inside LMDB this output parameter
 *                  will be set with the error (otherwise is set to zero).
 * @return 0 if success, -1 if failure.
 */
static int
page_db_add_crawled_page_info(MDB_cursor *cur,
                              MDB_val *key,
                              const CrawledPage *page,
                              PageInfo **page_info,
                              int *mdb_error) {
     MDB_val val;
     *page_info = 0;

     int mdb_rc = mdb_cursor_get(cur, key, &val, MDB_SET);
     int put_flags = 0;
     switch (mdb_rc) {
     case 0:
          if (!(*page_info = page_info_load(&val)))
               goto on_error;
          if ((page_info_update(*page_info, page) != 0))
               goto on_error;
          put_flags = MDB_CURRENT;
          break;
     case MDB_NOTFOUND:
          if (!(*page_info = page_info_new_crawled(page)))
              goto on_error;
          break;
     default:
          goto on_error;
     }

     if ((page_info_dump(*page_info, &val)   != 0))
          goto on_error;

     if ((mdb_rc = mdb_cursor_put(cur, key, &val, put_flags)) != 0)
          goto on_error;

     free(val.mv_data);
     val.mv_data = 0;

     *mdb_error = 0;
     return 0;

on_error:
     if (val.mv_data)
          free(val.mv_data);
     *mdb_error = mdb_rc;
     page_info_delete(*page_info);
     return -1;
}

/** Store a new or updated @ref PageInfo for an uncrawled link.
 *
 * @param cur An open cursor to the hash2info database
 * @param key The key (hash) to the page
 * @param url
 * @param mdb_error In case of failure, if the error occurs inside LMDB this output parameter
 *                  will be set with the error (otherwise is set to zero).
 * @return 0 if success, -1 if failure.
 */
static int
page_db_add_link_page_info(MDB_cursor *cur,
                           MDB_val *key,
                           uint64_t linked_from,
                           uint64_t depth,
                           const LinkInfo *link,
                           PageInfo **page_info,
                           int *mdb_error) {
     MDB_val val;
     int mdb_rc = 0;

     PageInfo *pi = *page_info =
          page_info_new_link(link->url, linked_from, depth, link->score);
     if (!pi)
          goto on_error;

     if ((page_info_dump(pi, &val)   != 0))
          goto on_error;

     if ((mdb_rc = mdb_cursor_put(cur, key, &val, MDB_NOOVERWRITE)) != 0)
          goto on_error;

     free(val.mv_data);
     val.mv_data = 0;

     *mdb_error = 0;
     return 0;
on_error:
     if (val.mv_data)
          free(val.mv_data);

     *mdb_error = mdb_rc;
     page_info_delete(pi);
     return -1;
}
Example #30
0
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|MDB_WRITEMAP;

	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: %s (%d). "
			"Restore from backup!\n",
			be->be_suffix[0].bv_val, mdb_strerror(rc), rc );
		goto fail;
	}

	rc = mdb_txn_begin( mdb->mi_dbenv, NULL, flags & MDB_RDONLY, &txn );
	if ( rc ) {
		Debug( LDAP_DEBUG_ANY,
			LDAP_XSTRING(mdb_db_open) ": database \"%s\" cannot be opened: %s (%d). "
			"Restore from backup!\n",
			be->be_suffix[0].bv_val, mdb_strerror(rc), rc );
		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_dbi_open( txn,
			mdmi_databases[i].bv_val,
			flags,
			&mdb->mi_dbis[i] );

		if ( rc != 0 ) {
			snprintf( cr->msg, sizeof(cr->msg), "database \"%s\": "
				"mdb_dbi_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_cursor *mc;
			MDB_val key, data;
			ID id;
			mdb_set_dupsort( txn, mdb->mi_dbis[i], mdb_dup_compare );
			/* check for old dn2id format */
			rc = mdb_cursor_open( txn, mdb->mi_dbis[i], &mc );
			/* first record is always ID 0 */
			rc = mdb_cursor_get( mc, &key, &data, MDB_FIRST );
			if ( rc == 0 ) {
				rc = mdb_cursor_get( mc, &key, &data, MDB_NEXT );
				if ( rc == 0 ) {
					int len;
					unsigned char *ptr;
					ptr = data.mv_data;
					len = (ptr[0] & 0x7f) << 8 | ptr[1];
					if (data.mv_size < 2*len + 4 + 2*sizeof(ID)) {
						snprintf( cr->msg, sizeof(cr->msg),
						"database \"%s\": DN index needs upgrade, "
						"run \"slapindex entryDN\".",
						be->be_suffix[0].bv_val );
						Debug( LDAP_DEBUG_ANY,
							LDAP_XSTRING(mdb_db_open) ": %s\n",
							cr->msg, 0, 0 );
						if ( !(slapMode & SLAP_TOOL_READMAIN ))
							rc = LDAP_OTHER;
						mdb->mi_flags |= MDB_NEED_UPGRADE;
					}
				}
			}
			mdb_cursor_close( mc );
			if ( rc == LDAP_OTHER )
				goto fail;
		}
	}

	rc = mdb_ad_read( mdb, txn );
	if ( rc ) {
		mdb_txn_abort( txn );
		goto fail;
	}

	/* slapcat doesn't need indexes. avoid a failure if
	 * a configured index wasn't created yet.
	 */
	if ( !(slapMode & SLAP_TOOL_READONLY) ) {
		rc = mdb_attr_dbs_open( be, txn, cr );
		if ( rc ) {
			mdb_txn_abort( txn );
			goto fail;
		}
	}

	rc = mdb_txn_commit(txn);
	if ( rc != 0 ) {
		Debug( LDAP_DEBUG_ANY,
			LDAP_XSTRING(mdb_db_open) ": database %s: "
			"txn_commit failed: %s (%d)\n",
			be->be_suffix[0].bv_val, mdb_strerror(rc), rc );
		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;
}