Пример #1
0
static la_storage_object_put_result bdb_la_storage_replace(la_storage_object_store *store, la_storage_object *obj)
{
    DB_TXN *txn;
    la_storage_object_header header;
    DBT db_key;
    DBT db_value;
    int result;

    memset(&db_key, 0, sizeof(DBT));
    memset(&db_value, 0, sizeof(DBT));
    
    db_key.data = obj->key;
    db_key.size = db_key.ulen = (uint32_t) strlen(obj->key);
    db_key.flags = DB_DBT_USERMEM;
    
    db_value.data = obj->header;
    db_value.size = db_value.ulen = la_storage_object_total_size(obj);
    db_value.flags = DB_DBT_USERMEM;
    
    if (txn_begin(store->env->env, NULL, &txn, DB_TXN_NOSYNC | DB_TXN_NOWAIT) != 0)
        return LA_STORAGE_OBJECT_PUT_ERROR;

    db_seq_t seq;
    store->seq->get(store->seq, txn, 1, &seq, 0);
    obj->header->seq = seq;
    
    if (store->db->put(store->db, txn, &db_key, &db_value, 0) != 0)
    {
        txn_abort(txn);
        return LA_STORAGE_OBJECT_PUT_ERROR;
    }
    
    txn_commit(txn, DB_TXN_NOSYNC);
    return LA_STORAGE_OBJECT_PUT_SUCCESS;
}
Пример #2
0
int
edb_txn_abort(edb *db) {
  LOG_HERE;
  int err = 0;

  CHECK_CODE(db->readonly == 0, EDB_ERROR_READ_ONLY);
  CHECK(txn_abort(db));

  err:
  return err;
}
Пример #3
0
static int bdb_la_storage_stat(la_storage_object_store *store, la_storage_stat_t *stat)
{
    DB_TXN *txn;
    DB_BTREE_STAT *mainStat, *seqStat;
    if (txn_begin(store->env->env, NULL, &txn, DB_READ_COMMITTED | DB_TXN_NOSYNC) != 0)
        return -1;
    if (store->db->stat(store->db, txn, &mainStat, DB_FAST_STAT | DB_READ_COMMITTED) != 0)
    {
        txn_abort(txn);
        return -1;
    }
    if (store->db->stat(store->seq_db, txn, &seqStat, DB_FAST_STAT | DB_READ_COMMITTED) != 0)
    {
        txn_abort(txn);
        return -1;
    }
    stat->numkeys = mainStat->bt_nkeys;
    stat->size = ((uint64_t) mainStat->bt_pagecnt * (uint64_t) mainStat->bt_pagesize)
        + ((uint64_t) seqStat->bt_pagecnt * (uint64_t) seqStat->bt_pagesize);
    free(mainStat);
    free(seqStat);
    txn_commit(txn, DB_TXN_NOSYNC);
    return 0;
}
Пример #4
0
int
b_txn(int argc, char *argv[])
{
    extern char *optarg;
    extern int optind;
    DB_ENV *dbenv;
    DB_TXN *txn;
    int tabort, ch, i, count;

    count = 1000;
    tabort = 0;
    while ((ch = getopt(argc, argv, "ac:")) != EOF)
        switch (ch) {
        case 'a':
            tabort = 1;
            break;
        case 'c':
            count = atoi(optarg);
            break;
        case '?':
        default:
            return (usage());
        }
    argc -= optind;
    argv += optind;
    if (argc != 0)
        return (usage());

    /* Create the environment. */
    DB_BENCH_ASSERT(db_env_create(&dbenv, 0) == 0);
    dbenv->set_errfile(dbenv, stderr);
#if DB_VERSION_MAJOR == 3 && DB_VERSION_MINOR < 1
    DB_BENCH_ASSERT(dbenv->open(dbenv, TESTDIR,
                                NULL, DB_CREATE | DB_INIT_LOCK | DB_INIT_LOG |
                                DB_INIT_MPOOL | DB_INIT_TXN | DB_PRIVATE, 0666) == 0);
#else
    DB_BENCH_ASSERT(dbenv->open(dbenv, TESTDIR,
                                DB_CREATE | DB_INIT_LOCK | DB_INIT_LOG |
                                DB_INIT_MPOOL | DB_INIT_TXN | DB_PRIVATE, 0666) == 0);
#endif

    /* Start and commit/abort a transaction count times. */
    TIMER_START;
    if (tabort)
        for (i = 0; i < count; ++i) {
#if DB_VERSION_MAJOR < 4
            DB_BENCH_ASSERT(txn_begin(dbenv, NULL, &txn, 0) == 0);
            DB_BENCH_ASSERT(txn_abort(txn) == 0);
#else
            DB_BENCH_ASSERT(
                dbenv->txn_begin(dbenv, NULL, &txn, 0) == 0);
            DB_BENCH_ASSERT(txn->abort(txn) == 0);
#endif
        }
    else
        for (i = 0; i < count; ++i) {
#if DB_VERSION_MAJOR < 4
            DB_BENCH_ASSERT(txn_begin(dbenv, NULL, &txn, 0) == 0);
            DB_BENCH_ASSERT(txn_commit(txn, 0) == 0);
#else
            DB_BENCH_ASSERT(
                dbenv->txn_begin(dbenv, NULL, &txn, 0) == 0);
            DB_BENCH_ASSERT(txn->commit(txn, 0) == 0);
#endif
        }
    TIMER_STOP;

    printf("# %d empty transaction start/%s pairs\n",
           count, tabort ? "abort" : "commit");
    TIMER_DISPLAY(count);

    DB_BENCH_ASSERT(dbenv->close(dbenv, 0) == 0);

    return (0);
}
Пример #5
0
int
ofcds_copyconfig(void *UNUSED(data), NC_DATASTORE target,
                 NC_DATASTORE source, char *config, struct nc_err **error)
{
    int ret = EXIT_FAILURE;
    char *s;
    xmlDocPtr src_doc = NULL;
    xmlDocPtr dst_doc = NULL;
    xmlNodePtr root;
    static const char *ds[] = {"error", "<config>", "URL", "running",
                               "startup", "candidate"};

    nc_verb_verbose("OFC COPY-CONFIG (from %s to %s)", ds[source], ds[target]);

    switch (source) {
    case NC_DATASTORE_RUNNING:
        s = ofcds_getconfig(NULL, NC_DATASTORE_RUNNING, error);
        if (!s) {
            nc_verb_error
                ("copy-config: unable to get running source repository");
            return EXIT_FAILURE;
        }
        src_doc = xmlReadMemory(s, strlen(s), NULL, NULL, XML_READ_OPT);
        free(s);
        if (!src_doc) {
            nc_verb_error("copy-config: invalid running source data");
            *error = nc_err_new(NC_ERR_OP_FAILED);
            nc_err_set(*error, NC_ERR_PARAM_INFO_BADELEM,
                       "invalid running source data");
            return EXIT_FAILURE;
        }
        break;
    case NC_DATASTORE_STARTUP:
        src_doc = xmlCopyDoc(gds_startup, 1);
        break;
    case NC_DATASTORE_CANDIDATE:
        src_doc = xmlCopyDoc(gds_cand, 1);
        break;
    case NC_DATASTORE_CONFIG:
        if (config && strlen(config) > 0) {
            src_doc = xmlReadMemory(config, strlen(config), NULL, NULL,
                                    XML_READ_OPT);
        }
        if (!config || (strlen(config) > 0 && !src_doc)) {
            nc_verb_error("Invalid source configuration data.");
            *error = nc_err_new(NC_ERR_BAD_ELEM);
            nc_err_set(*error, NC_ERR_PARAM_INFO_BADELEM, "config");
            return EXIT_FAILURE;
        }

        break;
    default:
        nc_verb_error("Invalid <get-config> source.");
        *error = nc_err_new(NC_ERR_BAD_ELEM);
        nc_err_set(*error, NC_ERR_PARAM_INFO_BADELEM, "source");
        return EXIT_FAILURE;
    }

    switch (target) {
    case NC_DATASTORE_RUNNING:
        /* apply source to OVSDB */

        s = ofcds_getconfig(NULL, NC_DATASTORE_RUNNING, error);
        if (!s) {
            nc_verb_error("copy-config: unable to get running source data");
            goto cleanup;
        }
        dst_doc = xmlReadMemory(s, strlen(s), NULL, NULL, XML_READ_OPT);
        free(s);

        root = xmlDocGetRootElement(src_doc);
        if (!dst_doc) {
            /* create envelope */
            dst_doc = xmlNewDoc(BAD_CAST "1.0");
        }
        if (!rollbacking) {
            store_rollback(xmlCopyDoc(dst_doc, 1), target);
        }

        txn_init();
        if (edit_replace(dst_doc, root, 1, error)) {
            txn_abort();
        } else {
            ret = txn_commit(error);
        }
        xmlFreeDoc(dst_doc);
        goto cleanup;
        break;
    case NC_DATASTORE_STARTUP:
    case NC_DATASTORE_CANDIDATE:
        /* create copy */
        if (src_doc) {
            dst_doc = src_doc;
            src_doc = NULL;
        }

        /* store the copy */
        if (target == NC_DATASTORE_STARTUP) {
            if (!rollbacking) {
                store_rollback(gds_startup, target);
            } else {
                xmlFreeDoc(gds_startup);
            }
            gds_startup = dst_doc;
        } else {                /* NC_DATASTORE_CANDIDATE */
            if (!rollbacking) {
                store_rollback(gds_cand, target);
            } else {
                xmlFreeDoc(gds_cand);
            }
            gds_cand = dst_doc;
        }

        break;
    default:
        nc_verb_error("Invalid <get-config> source.");
        *error = nc_err_new(NC_ERR_BAD_ELEM);
        nc_err_set(*error, NC_ERR_PARAM_INFO_BADELEM, "source");
        goto cleanup;
    }

    ret = EXIT_SUCCESS;

cleanup:
    xmlFreeDoc(src_doc);

    return ret;
}
Пример #6
0
int
ofcds_editconfig(void *UNUSED(data), const nc_rpc * UNUSED(rpc),
                 NC_DATASTORE target, const char *config,
                 NC_EDIT_DEFOP_TYPE defop,
                 NC_EDIT_ERROPT_TYPE UNUSED(errop), struct nc_err **error)
{
    int ret = EXIT_FAILURE, running = 0;
    char *aux;
    int cfgds_new = 0;
    xmlDocPtr cfgds = NULL, cfg = NULL, cfg_clone = NULL;
    xmlNodePtr rootcfg;

    if (defop == NC_EDIT_DEFOP_NOTSET) {
        defop = NC_EDIT_DEFOP_MERGE;
    }

    cfg = xmlReadMemory(config, strlen(config), NULL, NULL, XML_READ_OPT);
    rootcfg = xmlDocGetRootElement(cfg);
    if (!cfg
        || (rootcfg
            && !xmlStrEqual(rootcfg->name, BAD_CAST "capable-switch"))) {
        nc_verb_error("Invalid <edit-config> configuration data.");
        *error = nc_err_new(NC_ERR_BAD_ELEM);
        nc_err_set(*error, NC_ERR_PARAM_INFO_BADELEM, "config");
        return EXIT_FAILURE;
    }

    switch (target) {
    case NC_DATASTORE_RUNNING:
        /* Make a copy of parsed config - we will find port/configuration in
         * it.  It is used after txn_commit(). */
        cfg_clone = xmlCopyDoc(cfg, 1);

        aux = ofc_get_config_data();
        if (!aux) {
            *error = nc_err_new(NC_ERR_OP_FAILED);
            goto error_cleanup;
        }
        cfgds = xmlReadMemory(aux, strlen(aux), NULL, NULL, XML_READ_OPT);
        free(aux);

        running = 1;
        break;
    case NC_DATASTORE_STARTUP:
        cfgds = gds_startup;
        break;
    case NC_DATASTORE_CANDIDATE:
        cfgds = gds_cand;
        break;
    default:
        nc_verb_error("Invalid <edit-config> target.");
        *error = nc_err_new(NC_ERR_BAD_ELEM);
        nc_err_set(*error, NC_ERR_PARAM_INFO_BADELEM, "target");
        goto error_cleanup;
    }
    store_rollback(xmlCopyDoc(cfgds, 1), target);

    /* check keys in config's lists */
    ret = check_keys(cfg, error);
    if (ret != EXIT_SUCCESS) {
        goto error_cleanup;
    }

    /* check operations */
    ret = check_edit_ops(NC_EDIT_OP_DELETE, defop, cfgds, cfg, error);
    if (ret != EXIT_SUCCESS) {
        goto error_cleanup;
    }
    ret = check_edit_ops(NC_EDIT_OP_CREATE, defop, cfgds, cfg, error);
    if (ret != EXIT_SUCCESS) {
        goto error_cleanup;
    }

    if (target == NC_DATASTORE_RUNNING) {
        txn_init();
    }

    ret = compact_edit_operations(cfg, defop);
    if (ret != EXIT_SUCCESS) {
        nc_verb_error("Compacting edit-config operations failed.");
        if (error != NULL) {
            *error = nc_err_new(NC_ERR_OP_FAILED);
        }
        goto error_cleanup;
    }

    /* perform operations */
    if (!cfgds) {
        cfgds_new = 1;
        cfgds = xmlNewDoc(BAD_CAST "1.0");
    }
    ret = edit_operations(cfgds, cfg, defop, running, error);
    if (ret != EXIT_SUCCESS) {
        goto error_cleanup;
    }

    /* with defaults capability */
    if (ncdflt_get_basic_mode() == NCWD_MODE_TRIM) {
        /* server work in trim basic mode and therefore all default values
         * must be removed from the datastore. */
        /* TODO */
    }

    if (target == NC_DATASTORE_RUNNING) {
        ret = txn_commit(error);

        if (ret == EXIT_SUCCESS) {
            /* modify port/configuration of ports that were created */
            ret = of_post_ports(xmlDocGetRootElement(cfg_clone), error);
        }
        /* config clone was used and it is not needed by now */
        xmlFreeDoc(cfg_clone);

        xmlFreeDoc(cfgds);
    } else if (cfgds_new){
        if (cfgds->children) {
            /* document changed, because we started with empty document */
            if (target == NC_DATASTORE_STARTUP) {
                gds_startup = cfgds;
                cfgds = NULL;
            } else if (target == NC_DATASTORE_CANDIDATE) {
                gds_cand = cfgds;
                cfgds = NULL;
            }
        }
        xmlFreeDoc(cfgds);
    }
    xmlFreeDoc(cfg);

    return ret;

error_cleanup:

    if (target == NC_DATASTORE_RUNNING) {
        txn_abort();
        xmlFreeDoc(cfg_clone);
        xmlFreeDoc(cfgds);
    }
    xmlFreeDoc(cfg);

    return ret;
}
Пример #7
0
db_t db_init(const size_t size, const char * const path, const int flags, const int mode, int mdb_flags, int ndbi, dbi_t *dbis, size_t padsize){
	int fd = -1, err = 0xdeadbeef;
	struct stat st;

	db_t db;
	db = malloc(size < sizeof(*db) ? sizeof(*db) : size);
	assert(db);

	// always do this
	mdb_flags |= MDB_NOSUBDIR;

	int r;
	// ignore MDB_RDONLY - key off of OS flags
	// see docs for open() - O_RDONLY is not a bit!
	if((flags & 0x3) == O_RDONLY){
		mdb_flags |= MDB_RDONLY;
		// disable NOSYNC/NOMETASYNC for readonly, as that burns another file descriptor
		mdb_flags &= ~(MDB_NOSYNC|MDB_NOMETASYNC);
	}else{
		mdb_flags &= ~MDB_RDONLY;
	}


	// default to 100mb minimum pad
	db->padsize = padsize ? padsize : (1<<27);

	db->env = NULL;
	db->txns = 0;
	db->handles = NULL;
	db->updated = 0;

	r = pthread_mutex_init(&db->mutex, NULL);
	FAIL(r, err, errno, fail);

	r = pthread_cond_init(&db->cond, NULL);
	FAIL(r, err, errno, fail);

	// unless MDB_RDONLY is specified, lmdb will automatically create non-existant databases,
	// which is not what I want. Try to emulate standard unix open() flags:
	fd = open(path, flags, mode);
	FAIL(-1 == fd, err, errno, fail);

	r = mdb_env_create(&db->env);
	FAIL(r, err, r, fail);

	r = mdb_env_set_maxdbs(db->env, ndbi);
	FAIL(r, err, r, fail);

	size_t mapsize;
	do{
		r = fstat(fd, &st);
		FAIL(r, err, errno, fail);

		if(!st.st_size &&( flags & O_CREAT))
			db->updated = 1;

		// pad out such that we have at least 1gb of map overhead
		mapsize = (1 + st.st_size / db->padsize) * db->padsize;

		r = mdb_env_set_mapsize(db->env, mapsize);
	}while(MDB_SUCCESS != r);
	close(fd);
	fd = -1;

	r = mdb_env_open(db->env, path, mdb_flags, mode);

	// mdb_env_open can return EAGAIN somehow, but I think it really means:
	if(EAGAIN == r)
		r = EMFILE;
	FAIL(r, err, r, fail);

	r = mdb_env_get_fd(db->env, &db->fd);
	FAIL(r, err, r, fail);

	if(dbis && ndbi){
		db->handles = malloc(sizeof(db->handles[0]) * ndbi);
		FAIL(!db->handles, err, errno, fail);

		// open the indexes - try read-only first
		unsigned int txn_flags = MDB_RDONLY;
		txn_t txn = db_txn_new(db, NULL, txn_flags);

		int i;
		for(i = 0; i < ndbi; i++){
			int dbflags = dbis[i].flags;
retry:
			dbflags = (txn_flags & MDB_RDONLY) ? (dbflags & ~MDB_CREATE) : (dbflags | MDB_CREATE);
			r = mdb_dbi_open(txn->txn, dbis[i].name, dbflags, &db->handles[i]);
			if(MDB_SUCCESS != r){
				if(MDB_NOTFOUND == r && (txn_flags & MDB_RDONLY)){
					// we were in read-only and a sub-db was missing
					// end txn
					txn_commit(txn);
					// switch to read-write
					txn_flags &= ~MDB_RDONLY;
					txn = db_txn_new(db, NULL, txn_flags);
					// and pick up where we left off
					goto retry;
				}else{
					txn_abort(txn);
				}
				FAIL(r, err, r, fail);
			}
		}
		r = txn_commit(txn);
		FAIL(r, err, r, fail);
	}

	return db;

fail:
	db_close(db);
	if(fd != -1){
		if((flags & (O_CREAT|O_EXCL)) == (O_CREAT|O_EXCL))
			unlink(path);
		close(fd);
	}
	errno = err;
	return NULL;
}
Пример #8
0
/**
 * Put an object into the store.
 */
static la_storage_object_put_result bdb_la_storage_put(la_storage_object_store *store, const la_storage_rev_t *rev, la_storage_object *obj)
{
    DB_TXN *txn;
    la_storage_object_header header;
    DBT db_key;
    DBT db_value_read, db_value_write;
    int result;
    
#if DEBUG
    printf("putting %u bytes:\n", obj->data_length);
    la_hexdump(la_storage_object_get_data(obj), obj->data_length);
#endif
    
    memset(&db_key, 0, sizeof(DBT));
    memset(&db_value_read, 0, sizeof(DBT));
    memset(&db_value_write, 0, sizeof(DBT));
    
    db_key.data = obj->key;
    db_key.size = (u_int32_t) strlen(obj->key);
    db_key.ulen = (u_int32_t) strlen(obj->key);
    db_key.flags = DB_DBT_USERMEM;
    
    db_value_read.data = &header;
    db_value_read.ulen = sizeof(la_storage_object_header);
    db_value_read.dlen = sizeof(la_storage_object_header);
    db_value_read.doff = 0;
    db_value_read.flags = DB_DBT_USERMEM | DB_DBT_PARTIAL;
    
    if (txn_begin(store->env->env, NULL, &txn, DB_TXN_NOSYNC | DB_TXN_NOWAIT) != 0)
        return LA_STORAGE_OBJECT_PUT_ERROR;
    
    result = store->db->get(store->db, txn, &db_key, &db_value_read, DB_RMW);
    if (result != 0 && result != DB_NOTFOUND)
    {
        txn_abort(txn);
        if (result == DB_LOCK_NOTGRANTED)
            return LA_STORAGE_OBJECT_PUT_CONFLICT;
        return LA_STORAGE_OBJECT_PUT_ERROR;
    }
    
    if (result != DB_NOTFOUND)
    {
        debug("data size: %d, data: %s\n", db_value_read.size, db_value_read.data);
        if (rev == NULL || memcmp(rev, &header.rev, sizeof(la_storage_rev_t)) != 0)
        {
            txn_abort(txn);
            return LA_STORAGE_OBJECT_PUT_CONFLICT;
        }
        obj->header->doc_seq = header.doc_seq + 1;
        if (header.rev_count < LA_OBJECT_MAX_REVISION_COUNT)
        {
            obj->header = realloc(obj->header, la_storage_object_total_size(obj) + sizeof(la_storage_rev_t));
            // If we added a revision, move the object data up to make room.
            memmove(la_storage_object_get_data(obj) + sizeof(la_storage_rev_t), la_storage_object_get_data(obj), obj->data_length);
            obj->header->rev_count = header.rev_count + 1;
        }
        // Move the rev_count-1 previous revisons over...
        memmove(obj->header->revs_data + sizeof(la_storage_rev_t), obj->header->revs_data, sizeof(la_storage_rev_t) * (obj->header->rev_count - 1));
        // Copy the previous revision in.
        memcpy(obj->header->revs_data, &header.rev, sizeof(la_storage_rev_t));
#if DEBUG
        printf("After moving data and revisions:\nOld revisions:\n");
        la_hexdump(obj->header->revs_data, obj->header->rev_count * sizeof(la_storage_rev_t));
        printf("data:\n");
        la_hexdump(la_storage_object_get_data(obj), obj->data_length);
#endif
    }
    else
    {
        obj->header->doc_seq = 1;
        obj->header->rev_count = 0;
    }
    
    db_seq_t seq;
    store->seq->get(store->seq, txn, 1, &seq, 0);
    obj->header->seq = seq;

    db_value_write.size = (u_int32_t) la_storage_object_total_size(obj);
    db_value_write.ulen = (u_int32_t) la_storage_object_total_size(obj);
    db_value_write.data = obj->header;
    db_value_write.flags = DB_DBT_USERMEM;
    
    debug("putting { size: %u, ulen: %u, data: %s, flags: %x }\n", db_value_write.size,
          db_value_write.ulen, db_value_write.data, db_value_write.flags);
    
    result = store->db->put(store->db, txn, &db_key, &db_value_write, 0);
    if (result != 0)
    {
        txn_abort(txn);
        return LA_STORAGE_OBJECT_PUT_ERROR;
    }
    txn_commit(txn, DB_TXN_NOSYNC);
    return LA_STORAGE_OBJECT_PUT_SUCCESS;
}
Пример #9
0
static la_storage_object_put_result bdb_la_storage_set_revs(la_storage_object_store *store, const char *key, la_storage_rev_t *revs, size_t revcount)
{
    DB_TXN *txn;
    DBT db_key;
    DBT db_value;
    int result;
    la_storage_object object;
    int shift;
    
    revcount = la_min(revcount, LA_OBJECT_MAX_REVISION_COUNT);
    memset(&db_key, 0, sizeof(DBT));
    memset(&db_value, 0, sizeof(DBT));
    
    db_key.data = key;
    db_key.size = strlen(key);
    db_key.ulen = strlen(key);
    db_key.flags = DB_DBT_USERMEM;
    
    db_value.data = NULL;
    db_value.ulen = 0;
    db_value.flags = DB_DBT_MALLOC;
    
    if (txn_begin(store->env->env, NULL, &txn, DB_TXN_NOSYNC | DB_TXN_NOWAIT) != 0)
        return LA_STORAGE_OBJECT_PUT_ERROR;
    
    result = store->db->get(store->db, txn, &db_key, &db_value, DB_RMW);
    if (result != 0)
    {
        txn_abort(txn);
        if (result == DB_LOCK_NOTGRANTED)
            return LA_STORAGE_OBJECT_PUT_CONFLICT;
        return LA_STORAGE_OBJECT_PUT_ERROR;
    }

    object.header = (la_storage_object_header *) db_value.data;
    object.data_length = db_value.size - sizeof(la_storage_object_header) - (object.header->rev_count * sizeof(la_storage_rev_t));
    shift = revcount - object.header->rev_count;
    if (shift > 0)
    {
        object.header = realloc(object.header, db_value.size + shift);
        if (object.header == NULL)
        {
            free(object.header);
            return LA_STORAGE_OBJECT_PUT_ERROR;
        }
    }
    memmove(la_storage_object_get_data(&object) + shift, la_storage_object_get_data(&object), object.data_length);
    memcpy(object.header->revs_data, revs, revcount * sizeof(la_storage_rev_t));

    db_value.data = object.header;
    db_value.size = db_value.size + shift;
    db_value.ulen = db_value.size;
    db_value.flags = DB_DBT_USERMEM;
    
    result = store->db->put(store->db, txn, &db_key, &db_value, 0);
    free(db_value.data);
    if (result != 0)
    {
        txn_abort(txn);
        return LA_STORAGE_OBJECT_PUT_ERROR;
    }
    txn_commit(txn, DB_TXN_NOSYNC);
    return 0;
}
Пример #10
0
static int bdb_la_storage_object_store_delete(la_storage_object_store *store)
{
    const char *dbname;
    const char *seqdbname;
    const char *home;
    const char *parts[2];
    DB_TXN *txn;
    DB_ENV *env = store->env->env;
    int ret;
    
    if ((ret = store->db->get_dbname(store->db, &dbname, NULL)) != 0)
    {
        syslog(LOG_NOTICE, "could not get main db name: %d", ret);
        return -1;
    }
    if ((ret = store->db->get_dbname(store->seq_db, &seqdbname, NULL)) != 0)
    {
        syslog(LOG_NOTICE, "could not get sequence db name: %d", ret);
        return -1;
    }
    if ((ret = env->get_home(env, &home)) != 0)
    {
        syslog(LOG_NOTICE, "could not get db home %d", ret);
        return -1;
    }
    parts[0] = home;
    parts[1] = dbname;
    dbname = string_join("/", parts, 2);
    parts[1] = seqdbname;
    seqdbname = string_join("/", parts, 2);
    
    syslog(LOG_NOTICE, "deleting db %s and sequence db %s", dbname, seqdbname);
    
    la_storage_close(store);
    
    if ((ret = txn_begin(env, NULL, &txn, DB_TXN_NOWAIT | DB_TXN_WRITE_NOSYNC)) != 0)
    {
        syslog(LOG_NOTICE, "delete db begin transaction %d", ret);
        free(dbname);
        free(seqdbname);
        return -1;
    }
    
    syslog(LOG_NOTICE, "env %p txn %p home %s name %s", env, txn, home, dbname);
    
    if ((ret = env->dbremove(env, txn, dbname, NULL, 0)) != 0)
    {
        syslog(LOG_NOTICE, "deleting main DB: %d", ret);
        txn_abort(txn);
        return -1;
    }
    syslog(LOG_NOTICE, "env %p txn %p home %s name %s", env, txn, home, seqdbname);
    if ((ret = env->dbremove(env, txn, seqdbname, NULL, 0)) != 0)
    {
        syslog(LOG_NOTICE, "deleting sequence DB: %d", ret);
        txn_abort(txn);
        return -1;
    }
    txn_commit(txn, DB_TXN_NOSYNC);
    return 0;
}
Пример #11
0
static la_storage_open_result_t bdb_la_storage_open(la_storage_env *env, const char *path, int flags, la_storage_object_store **_store)
{
    la_storage_object_store *store = (la_storage_object_store *) malloc(sizeof(struct la_storage_object_store));
    DB_TXN *txn;
    char *seqpath;
    DBT seq_key;
    char seq_name[4];
    int dbflags;
    int ret;

    if (store == NULL)
        return LA_STORAGE_OPEN_ERROR;
    store->env = env;
    if (txn_begin(env->env, NULL, &txn, DB_TXN_WRITE_NOSYNC) != 0)
    {
        free(store);
        return LA_STORAGE_OPEN_ERROR;
    }
    if (db_create(&store->db, env->env, 0) != 0)
    {
        txn_abort(txn);
        free(store);
        return LA_STORAGE_OPEN_ERROR;
    }
    if (db_create(&store->seq_db, env->env, 0) != 0)
    {
        txn_abort(txn);
        free(store);
        return LA_STORAGE_OPEN_ERROR;
    }
    dbflags = 0;
    if (flags & LA_STORAGE_OPEN_FLAG_CREATE)
        dbflags = DB_CREATE;
    if (flags & LA_STORAGE_OPEN_FLAG_EXCL)
        dbflags |= DB_EXCL;
    if ((ret = store->db->open(store->db, txn, path, NULL, DB_BTREE, dbflags | DB_MULTIVERSION | DB_THREAD, 0)) != 0)
    {
        txn_abort(txn);
        free(store);
        if (ret == EEXIST)
            return LA_STORAGE_OPEN_EXISTS;
        if (ret == ENOENT)
            return LA_STORAGE_OPEN_NOT_FOUND;
        return LA_STORAGE_OPEN_ERROR;
    }
    seqpath = string_append(path, ".seq");
    if (seqpath == NULL)
    {
        store->db->close(store->db, 0);
        txn_abort(txn);
        free(store);
        return LA_STORAGE_OPEN_ERROR;
    }
    if (store->seq_db->set_bt_compare(store->seq_db, compare_seq) != 0)
    {
        store->db->close(store->db, 0);
        txn_abort(txn);
        free(store);
        return LA_STORAGE_OPEN_ERROR;
    }
    if (store->seq_db->open(store->seq_db, txn, seqpath, NULL, DB_BTREE, DB_CREATE | DB_THREAD, 0) != 0)
    {
        free(seqpath);
        store->db->close(store->db, 0);
        txn_abort(txn);
        free(store);
        return LA_STORAGE_OPEN_ERROR;
    }
    free(seqpath);
    store->db->associate(store->db, txn, store->seq_db, seqindex, 0);
    if (db_sequence_create(&store->seq, store->db, 0) != 0)
    {
        store->seq_db->close(store->seq_db, 0);
        store->db->close(store->db, 0);
        txn_abort(txn);
        free(store);
        return LA_STORAGE_OPEN_ERROR;
    }
    store->seq->initial_value(store->seq, 1);
    seq_name[0] = '\0';
    seq_name[1] = 'S';
    seq_name[2] = 'E';
    seq_name[3] = 'Q';
    seq_key.data = seq_name;
    seq_key.size = 4;
    seq_key.ulen = 4;
    seq_key.flags = DB_DBT_USERMEM;
    if (store->seq->open(store->seq, txn, &seq_key, DB_CREATE | DB_THREAD) != 0)
    {
        store->seq_db->close(store->seq_db, 0);
        store->db->close(store->db, 0);
        txn_abort(txn);
        free(store);
        return LA_STORAGE_OPEN_ERROR;        
    }
    txn_commit(txn, DB_TXN_NOSYNC);
    *_store = store;
    if ((flags & (LA_STORAGE_OPEN_FLAG_CREATE|LA_STORAGE_OPEN_FLAG_EXCL)) == (LA_STORAGE_OPEN_FLAG_CREATE|LA_STORAGE_OPEN_FLAG_EXCL))
        return LA_STORAGE_OPEN_CREATED;
    return LA_STORAGE_OPEN_OK;
}