Example #1
0
void *
logfile_thread(void *arg)
{
	DB_ENV *dbenv;
	int ret;
	char **begin, **list;

	dbenv = arg;
	dbenv->errx(dbenv,
	    "Log file removal thread: %lu", (u_long)pthread_self());

	/* Check once every 5 minutes. */
	for (;; sleep(300)) {
		/* Get the list of log files. */
		if ((ret =
		    dbenv->log_archive(dbenv, &list, DB_ARCH_ABS)) != 0) {
			dbenv->err(dbenv, ret, "DB_ENV->log_archive");
			exit (1);
		}

		/* Remove the log files. */
		if (list != NULL) {
			for (begin = list; *list != NULL; ++list)
				if ((ret = remove(*list)) != 0) {
					dbenv->err(dbenv,
					    ret, "remove %s", *list);
					exit (1);
				}
			free (begin);
		}
	}
	/* NOTREACHED */
}
Example #2
0
int bdblib_create_dbenv(DB_ENV **_dbenv, char* _home)
{
	DB_ENV *env;
	char *progname;
	int rc, flags;
	
	progname = "kamailio";
	
	/* Create an environment and initialize it for additional error * reporting. */ 
	if ((rc = db_env_create(&env, 0)) != 0) 
	{
		ERR("db_env_create failed! bdb error: %s.\n", db_strerror(rc)); 
		return (rc);
	}
 
	env->set_errpfx(env, progname);

	/*  Specify the shared memory buffer pool cachesize */ 
	if ((rc = env->set_cachesize(env, 0, _bdb_parms->cache_size, 0)) != 0) 
	{
		ERR("dbenv set_cachsize failed! bdb error: %s.\n", db_strerror(rc));
		env->err(env, rc, "set_cachesize"); 
		goto err; 
	}

	/* Concurrent Data Store flags */
	flags = DB_CREATE |
		DB_INIT_CDB |
		DB_INIT_MPOOL |
		DB_THREAD;
	
	/* Transaction Data Store flags ; not supported yet */
	/*
	flags = DB_CREATE |
		DB_RECOVER |
		DB_INIT_LOG | 
		DB_INIT_LOCK |
		DB_INIT_MPOOL |
		DB_THREAD |
		DB_INIT_TXN;
	*/
	
	/* Open the environment */ 
	if ((rc = env->open(env, _home, flags, 0)) != 0) 
	{ 
		ERR("dbenv is not initialized! bdb error: %s.\n",db_strerror(rc));
		env->err(env, rc, "environment open: %s", _home); 
		goto err; 
	}
	
	*_dbenv = env;
	return (0);

err: (void)env->close(env, 0);
	return (rc);
}
Example #3
0
db* initialize_db(const char* db_name, uint32_t flag){
    db* db_ptr = NULL;
    DB* b_db;
    DB_ENV* dbenv;
    int ret;
    char* full_path = NULL;
    if((ret = mkdir(db_dir,S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH)) != 0){
        if(errno!=EEXIST){
            err_log("DB : Dir Creation Failed\n");
            goto db_init_return;
        }
    }
    full_path = (char*)malloc(strlen(db_dir) + strlen(db_name) + 2);
    mk_path(full_path, db_dir, db_name);
#ifdef ENV
    if ((ret = db_env_create(&dbenv, 0)) != 0) {
        dbenv->err(dbenv, ret, "Environment Created: %s", db_dir);
        goto db_init_return;
    }
    if ((ret = dbenv->open(dbenv, db_dir, DB_CREATE|DB_INIT_CDB|DB_INIT_MPOOL|DB_THREAD, 0)) != 0) {
        //dbenv->err(dbenv, ret, "Environment Open: %s", db_dir);
        goto db_init_return;
    }
    /* Initialize the DB handle */
    if((ret = db_create(&b_db,dbenv,flag)) != 0){
        err_log("DB : %s.\n", db_strerror(ret));
        goto db_init_return;                                                                                                                                                   
    }                                                                                                                                                                          
#else                                                                                                                                                                          
    /* Initialize the DB handle */                                                                                                                                             
    if((ret = db_create(&b_db,NULL,flag)) != 0){                                                                                                                               
        err_log("DB : %s.\n", db_strerror(ret));                                                                                                                               
        goto db_init_return;                                                                                                                                                   
    }                                                                                                                                                                          
#endif                                                                                                                                                                         
    if((ret = b_db->set_pagesize(b_db, pagesize)) != 0){                                                                                                                       
        err_log("DB : %s.\n", db_strerror(ret));                                                                                                                               
        goto db_init_return;                                                                                                                                                   
    }                                                                                                                                                                          
                                                                                                                                                                               
    if((ret = b_db->open(b_db, NULL, db_name, NULL, DB_BTREE, DB_THREAD|DB_CREATE,0)) != 0){ // db_name is the on-disk file that holds the database                            
        //b_db->err(b_db,ret,"%s","test.db");                                                                                                                                  
        goto db_init_return;                                                                                                                                                   
    }                                                                                                                                                                          
    db_ptr = (db*)(malloc(sizeof(db)));                                                                                                                                        
    db_ptr->bdb_ptr = b_db;                                                                                                                                                    
                                                                                                                                                                               
db_init_return:                                                                                                                                                                
    if(full_path != NULL){                                                                                                                                                     
        free(full_path);                                                                                                                                                       
    }                                                                                                                                                                          
    if(db_ptr != NULL){                                                                                                                                                        
        ;                                                                                                                                                                      
    }                                                                                                                                                                          
    return db_ptr;                                                                                                                                                             
}
Example #4
0
static void *bdb_checkpoint_thread(void *arg){
    DB_ENV *dbenv;
    int ret;
    dbenv = arg;
    for (;; sleep(bdb_settings.checkpoint_val)) {
        if ((ret = dbenv->txn_checkpoint(dbenv, 0, 0, 0)) != 0) {
            dbenv->err(dbenv, ret, "checkpoint thread");
        }
        dbenv->errx(dbenv, "checkpoint thread: a txn_checkpoint is done");
    }
    return (NULL);
}
Example #5
0
static void *bdb_mempool_trickle_thread(void *arg){
    DB_ENV *dbenv;
    int ret, nwrotep;
    dbenv = arg;
    for (;; sleep(bdb_settings.mempool_trickle_val)) {
        if ((ret = dbenv->memp_trickle(dbenv, bdb_settings.mempool_trickle_percent, &nwrotep)) != 0) {
            dbenv->err(dbenv, ret, "mempool_trickle thread");
        }
        dbenv->errx(dbenv, "mempool_trickle thread: writing %d dirty pages", nwrotep);
    }
    return (NULL);
}
Example #6
0
void
env_open(DB_ENV **dbenvp)
{
	DB_ENV *dbenv;
	int ret;

	/* Create the environment handle. */
	if ((ret = db_env_create(&dbenv, 0)) != 0) {
		fprintf(stderr,
		    "txnapp: db_env_create: %s\n", db_strerror(ret));
		exit (1);
	}

	/* Set up error handling. */
	dbenv->set_errpfx(dbenv, "txnapp");
	dbenv->set_errfile(dbenv, stderr);

	/* Do deadlock detection internally. */
	if ((ret = dbenv->set_lk_detect(dbenv, DB_LOCK_DEFAULT)) != 0) {
		dbenv->err(dbenv, ret, "set_lk_detect: DB_LOCK_DEFAULT");
		exit (1);
	}

	/*
	 * Open a transactional environment:
	 *	create if it doesn't exist
	 *	free-threaded handle
	 *	run recovery
	 *	read/write owner only
	 */
	if ((ret = dbenv->open(dbenv, ENV_DIRECTORY,
	    DB_CREATE | DB_INIT_LOCK | DB_INIT_LOG |
	    DB_INIT_MPOOL | DB_INIT_TXN | DB_RECOVER | DB_THREAD,
	    S_IRUSR | S_IWUSR)) != 0) {
		dbenv->err(dbenv, ret, "dbenv->open: %s", ENV_DIRECTORY);
		exit (1);
	}

	*dbenvp = dbenv;
}
void
env_open(DB_ENV **dbenvp)
{
	DB_ENV *dbenv;
	int ret;

	/* Create the environment handle. */
	if ((ret = db_env_create(&dbenv, 0)) != 0) {
		fprintf(stderr,
		    "txnapp: db_env_create: %s\n", db_strerror(ret));
		exit (1);
	}

	/* Set up error handling. */
	dbenv->set_errpfx(dbenv, "txnapp");
	dbenv->set_errfile(dbenv, stderr);

	// match lladd's defaults...
	dbenv->set_lg_bsize(dbenv, 1024*1024);
	// match lladd's defaults...
	dbenv->set_cachesize(dbenv, 0, 8204288, 0);


	/* Do deadlock detection internally. */
	/*	if ((ret = dbenv->set_lk_detect(dbenv, DB_LOCK_DEFAULT)) != 0) {
		dbenv->err(dbenv, ret, "set_lk_detect: DB_LOCK_DEFAULT");
		exit (1);
		}*/

	dbenv->set_tx_max(dbenv, 32000);
	unsigned int max;
	dbenv->get_tx_max(dbenv, &max);
	printf("Max xact count: %d\n", max);


	/*
	 * Open a transactional environment:
	 *	create if it doesn't exist
	 *	free-threaded handle
	 *	run recovery
	 *	read/write owner only
	 */
	if ((ret = dbenv->open(dbenv, ENV_DIRECTORY,
			       DB_CREATE |/* DB_INIT_LOCK |*/ DB_INIT_LOG |  DB_PRIVATE | 
			       DB_INIT_MPOOL | DB_INIT_TXN | DB_RECOVER | DB_THREAD,
			       S_IRUSR | S_IWUSR)) != 0) {
		dbenv->err(dbenv, ret, "dbenv->open: %s", ENV_DIRECTORY);
		exit (1);
	}

	*dbenvp = dbenv;
}
Example #8
0
/*
 * env_init --
 *	Initialize the environment.
 */
DB_ENV * env_init( char *home, char *prefix, int cachesize)
{
    DB_ENV *dbenv;
    int ret;

    if ((ret = db_env_create(&dbenv, 0)) != 0) {
        dbenv->err(dbenv, ret, "db_env_create");
        return (NULL);
    }
    dbenv->set_errfile(dbenv, stderr);
    dbenv->set_errpfx(dbenv, prefix);
    if ((ret = dbenv->set_cachesize(dbenv, 0, cachesize, 0)) != 0) {
        dbenv->err(dbenv, ret, "DB_ENV->set_cachesize");
        return (NULL);
    }

    if ((ret = dbenv->open(dbenv, home, DB_CREATE | DB_INIT_MPOOL |
                           DB_INIT_TXN | DB_INIT_LOCK, 0)) != 0) {
        dbenv->err(dbenv, ret, "DB_ENV->open: %s", home);
        (void)dbenv->close(dbenv, 0);
        return (NULL);
    }
    return (dbenv);
}
Example #9
0
int
main(int argc, char *argv[])
{
    extern char *optarg;
    DB_ENV *dbenv;
    const char *home;
    char ch;
    int ret;

    dbenv = NULL;

    ret = 0;
    home = NULL;

    /* Create and configure the environment handle. */
    if ((ret = create_env(progname, &dbenv)) != 0)
	goto err;

    /* Collect the command line options. */
    while ((ch = getopt(argc, argv, "h:")) != EOF)
	switch (ch) {
	case 'h':
	    home = optarg;
	    break;
	case '?':
	default:
	    usage();
	}

    /* Error check command line. */
    if (home == NULL)
	usage();

    /* Open the environment. */
    if ((ret = env_init(dbenv, home)) != 0)
      goto err;

    if ((ret = doloop(dbenv)) != 0) {
	dbenv->err(dbenv, ret, "Application failed");
	goto err;
    }

err: if (dbenv != NULL)
	(void)dbenv->close(dbenv, 0);

    return (ret);
}
Example #10
0
static void *bdb_chkpoint_thread(void *arg)
{
    DB_ENV *dbenv;
    int ret;
    dbenv = arg;
    if (settings.verbose > 1) {
        dbenv->errx(dbenv, "checkpoint thread created: %lu, every %d seconds", 
                           (u_long)pthread_self(), bdb_settings.chkpoint_val);
    }
    for (;; sleep(bdb_settings.chkpoint_val)) {
        if ((ret = dbenv->txn_checkpoint(dbenv, 0, 0, 0)) != 0) {
            dbenv->err(dbenv, ret, "checkpoint thread");
        }
        dbenv->errx(dbenv, "checkpoint thread: a txn_checkpoint is done");
    }
    return (NULL);
}
Example #11
0
static void *bdb_memp_trickle_thread(void *arg)
{
    DB_ENV *dbenv;
    int ret, nwrotep;
    dbenv = arg;
    if (settings.verbose > 1) {
        dbenv->errx(dbenv, "memp_trickle thread created: %lu, every %d seconds, %d%% pages should be clean.", 
                           (u_long)pthread_self(), bdb_settings.memp_trickle_val,
                           bdb_settings.memp_trickle_percent);
    }
    for (;; sleep(bdb_settings.memp_trickle_val)) {
        if ((ret = dbenv->memp_trickle(dbenv, bdb_settings.memp_trickle_percent, &nwrotep)) != 0) {
            dbenv->err(dbenv, ret, "memp_trickle thread");
        }
        dbenv->errx(dbenv, "memp_trickle thread: writing %d dirty pages", nwrotep);
    }
    return (NULL);
}
Example #12
0
void *
checkpoint_thread(void *arg)
{
	DB_ENV *dbenv;
	int ret;

	dbenv = arg;
	dbenv->errx(dbenv, "Checkpoint thread: %lu", (u_long)pthread_self());

	/* Checkpoint once a minute. */
	for (;; sleep(60))
		if ((ret = dbenv->txn_checkpoint(dbenv, 0, 0, 0)) != 0) {
			dbenv->err(dbenv, ret, "checkpoint thread");
			exit (1);
		}

	/* NOTREACHED */
}
Example #13
0
bool service_list(struct client *cli, const char *user)
{
	GList *files = NULL, *content = NULL;
	char *s;
	enum errcode err = InternalError;
	int rc;
	bool rcb;
	DB_TXN *txn = NULL;
	DBC *cur = NULL;
	DB_ENV *dbenv = tdbrep.tdb.env;
	DB *bidx = tdbrep.tdb.buckets_idx;
	DBT skey, pkey, pval;

	if (asprintf(&s,
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\r\n"
"<ListAllMyBucketsResult xmlns=\"http://indy.yyz.us/doc/2006-03-01/\">\r\n"
"  <Owner>\r\n"
"    <ID>%s</ID>\r\n"
"    <DisplayName>%s</DisplayName>\r\n"
"  </Owner>\r\n"
"  <Buckets>\r\n",

		     user,
		     user) < 0)
		goto err_out;

	content = g_list_append(content, s);

	/* open transaction, search cursor */
	rc = dbenv->txn_begin(dbenv, NULL, &txn, 0);
	if (rc) {
		dbenv->err(dbenv, rc, "DB_ENV->txn_begin");
		goto err_out_content;
	}

	rc = bidx->cursor(bidx, txn, &cur, 0);
	if (rc) {
		bidx->err(bidx, rc, "bidx->cursor");
		goto err_out_content;
	}

	memset(&skey, 0, sizeof(skey));
	memset(&pkey, 0, sizeof(pkey));
	memset(&pval, 0, sizeof(pval));

	skey.data = (char *) user;
	skey.size = strlen(user) + 1;

	/* FIXME: Use of DB_NEXT rather than DB_SET to begin search
	 * means we iterate through entire db, rather than
	 * starting at the first matching key.
	 */

	/* loop through matching buckets, if any */
	while (1) {
		char timestr[64];
		struct db_bucket_ent *ent;

		rc = cur->pget(cur, &skey, &pkey, &pval, DB_NEXT);
		if (rc)
			break;

		ent = pval.data;

		s = g_markup_printf_escaped(
                        "    <Bucket>\r\n"
                        "      <Name>%s</Name>\r\n"
                        "      <CreationDate>%s</CreationDate>\r\n"
                        "    </Bucket>\r\n",

			     ent->name,
			     hutil_time2str(timestr, sizeof(timestr),
			     	      GUINT64_FROM_LE(ent->time_create)));
		if (!s)
			goto err_out_content;

		content = g_list_append(content, s);
	}

	if (rc != DB_NOTFOUND)
		bidx->err(bidx, rc, "service_list iter");

	/* close cursor, transaction */
	rc = cur->close(cur);
	if (rc)
		bidx->err(bidx, rc, "bidx->cursor close");

	rc = txn->commit(txn, 0);
	if (rc)
		dbenv->err(dbenv, rc, "DB_ENV->txn_commit");

	if (asprintf(&s,
"  </Buckets>\r\n"
"</ListAllMyBucketsResult>\r\n") < 0)
		goto err_out_content;

	content = g_list_append(content, s);

	rcb = cli_resp_xml(cli, 200, content);

	strlist_free(files);
	g_list_free(content);

	return rcb;

err_out_content:
	strlist_free(content);
err_out:
	strlist_free(files);
	return cli_err(cli, err);
}
/*
 * A function that performs a series of writes to a
 * Berkeley DB database. The information written
 * to the database is largely nonsensical, but the
 * mechanism of transactional commit/abort and
 * deadlock detection is illustrated here.
 */
void *
writer_thread(void *args)
{
    static char *key_strings[] = {
	"key 1", "key 2", "key 3", "key 4", "key 5",
	"key 6", "key 7", "key 8", "key 9", "key 10"
    };
    DB *dbp;
    DB_ENV *envp;
    DBT key, value;
    DB_TXN *txn;
    int i, j, payload, ret, thread_num;
    int retry_count, max_retries = 20;   /* Max retry on a deadlock */

    dbp = (DB *)args;
    envp = dbp->get_env(dbp);

    /* Get the thread number */
    (void)mutex_lock(&thread_num_lock);
    global_thread_num++;
    thread_num = global_thread_num;
    (void)mutex_unlock(&thread_num_lock);

    /* Initialize the random number generator */
    srand(thread_num);

    /* Write 50 times and then quit */
    for (i = 0; i < 50; i++) {
	retry_count = 0; /* Used for deadlock retries */

	/*
	 * Some think it is bad form to loop with a goto statement, but
	 * we do it anyway because it is the simplest and clearest way
	 * to achieve our abort/retry operation.
	 */
retry:
	/* Begin our transaction. We group multiple writes in
	 * this thread under a single transaction so as to
	 * (1) show that you can atomically perform multiple writes
	 * at a time, and (2) to increase the chances of a
	 * deadlock occurring so that we can observe our
	 * deadlock detection at work.
	 *
	 * Normally we would want to avoid the potential for deadlocks,
	 * so for this workload the correct thing would be to perform our
	 * puts with autocommit. But that would excessively simplify our
	 * example, so we do the "wrong" thing here instead.
	 */
	ret = envp->txn_begin(envp, NULL, &txn, 0);
	if (ret != 0) {
	    envp->err(envp, ret, "txn_begin failed");
	    return ((void *)EXIT_FAILURE);
	}
	for (j = 0; j < 10; j++) {
	    /* Set up our key and values DBTs */
	    memset(&key, 0, sizeof(DBT));
	    key.data = key_strings[j];
	    key.size = (u_int32_t)strlen(key_strings[j]) + 1;

	    memset(&value, 0, sizeof(DBT));
	    payload = rand() + i;
	    value.data = &payload;
	    value.size = sizeof(int);

	    /* Perform the database put. */
	    switch (ret = dbp->put(dbp, txn, &key, &value, 0)) {
		case 0:
		    break;

		/*
		 * Here's where we perform deadlock detection. If
		 * DB_LOCK_DEADLOCK is returned by the put operation,
		 * then this thread has been chosen to break a deadlock.
		 * It must abort its operation, and optionally retry the
		 * put.
		 */
		case DB_LOCK_DEADLOCK:
		    /*
		     * First thing that we MUST do is abort the
		     * transaction.
		     */
		    (void)txn->abort(txn);
		    /*
		     * Now we decide if we want to retry the operation.
		     * If we have retried less than max_retries,
		     * increment the retry count and goto retry.
		     */
		    if (retry_count < max_retries) {
			printf("Writer %i: Got DB_LOCK_DEADLOCK.\n",
			    thread_num);
			printf("Writer %i: Retrying write operation.\n",
			    thread_num);
			retry_count++;
			goto retry;
		    }
		    /*
		     * Otherwise, just give up.
		     */
		    printf("Writer %i: ", thread_num);
		    printf("Got DB_LOCK_DEADLOCK and out of retries.\n");
		    printf("Writer %i: Giving up.\n", thread_num);
		    return ((void *)EXIT_FAILURE);
		/*
		 * If a generic error occurs, we simply abort the
		 * transaction and exit the thread completely.
		 */
		default:
		    envp->err(envp, ret, "db put failed");
		    ret = txn->abort(txn);
		    if (ret != 0)
			envp->err(envp, ret, "txn abort failed");
		    return ((void *)EXIT_FAILURE);
	     } /** End case statement **/

	}   /** End for loop **/

	/*
	 * print the number of records found in the database.
	 * See count_records() for usage information.
	 */
	printf("Thread %i. Record count: %i\n", thread_num,
	    count_records(dbp, txn));

	/*
	 * If all goes well, we can commit the transaction and
	 * exit the thread.
	 */
	ret = txn->commit(txn, 0);
	if (ret != 0) {
	    envp->err(envp, ret, "txn commit failed");
	    return ((void *)EXIT_FAILURE);
	}
    }
    return ((void *)EXIT_SUCCESS);
}
Example #15
0
/* 批量插入示例函数。*/
void *
run_bulk_delete()
{
    int raw_key[NUM_KEY_INT];
    DBT key;
    DB_ENV *envp;
    int bulk_size = 100;
    DB *dbp;
    DB_TXN *tid;
    int *delete_load;
    int delete_count, i, ret, op_flag;

    char *key_buf;
    void *p;
    int j;

    /* Initialize structs and arrays */
    memset(raw_key, 0, KEY_SIZE);
    memset(&key, 0, sizeof(DBT));
    tid = NULL;

    /*
     * 初始化批量删除使用的key buffer。由于批量删除不需要data,
     * 所以只需要初始化和填充key buffer。我们同样需要使用自己分配的内存。
     */
    key_buf = (char*) malloc(KEY_SIZE * bulk_size * 2);
    memset(key_buf, 0, KEY_SIZE * bulk_size * 2);

    /* 初始化key buffer DBT 对象,设置正确的flags和ulen成员。 */
    key.data = key_buf;
    key.ulen = KEY_SIZE * bulk_size * 2;
    key.flags = DB_DBT_USERMEM;
    op_flag = DB_MULTIPLE; /* 批量删除同样需要这个flag。*/

    /*
     * 批量删除所有的数据。每一批删除由key buffer DBT 当中的key
     * 指定的bulk_size条key/data pair. 这两个宏的详细用法见上文。
     */
    for (i = 0; i < delete_count / bulk_size; ) {
        /* 为批量删除初始化并填充一个key buffer DBT 对象。 */
        DB_MULTIPLE_WRITE_INIT(p, &key);
        for (j = i * bulk_size; j < (i + 1) * bulk_size; j++) {
            raw_key[0] = delete_load[j];
            DB_MULTIPLE_WRITE_NEXT(p, &key, raw_key, KEY_SIZE);
        }
        /* 启动事务。*/
        if ((ret = envp->txn_begin(envp, NULL, &tid, 0)) != 0) {
            envp->err(envp, ret, "[delete] DB_ENV->txn_begin");
            exit(EXIT_FAILURE);
        }

        /*
         * 执行批量删除。key buffer DBT
         * 当中的bulk_size条key指定的key/data pairs会被从数据库当中删除。
         */
        switch(ret = dbp->del(dbp, tid, &key, op_flag)) {
        case 0: /* 批量删除操作成功,提交事务。*/
            if ((ret = tid->commit(tid, 0)) != 0) {
                envp->err(envp, ret, "[delete] DB_TXN->commit");
                exit(EXIT_FAILURE);
            }
            break;
        case DB_LOCK_DEADLOCK:
            /* 如果数据库操作发生死锁,那么必须abort事务。然后,可以选择重新执行该操作。*/
            if ((ret = tid->abort(tid)) != 0) {
                envp->err(envp, ret, "[delete] DB_TXN->abort");
                exit(EXIT_FAILURE);
            }
            continue;
        default:
            envp->err(envp, ret, "[delete] DB->del ([%d]%d)", i, delete_load[i]);
            exit(EXIT_FAILURE);
        }
        i++;
    }

    (void)free(key_buf);

    return (NULL);
}
Example #16
0
File: dir.c Project: jgarzik/nfs4d
nfsstat4 nfs_op_lookup(struct nfs_cxn *cxn, const LOOKUP4args *args,
		       struct list_head *writes, struct rpc_write **wr)
{
	nfsstat4 status = NFS4_OK;
	struct nfs_inode *ino = NULL;
	bool printed = false;
	struct nfs_buf objname;
	nfsino_t inum;
	DB_TXN *txn = NULL;
	DB_ENV *dbenv = srv.fsdb.env;
	int rc;

	objname.len = args->objname.utf8string_len;
	objname.val = args->objname.utf8string_val;

	if (!objname.len) {
		status = NFS4ERR_INVAL;
		goto out;
	}
	if (!objname.val) {
		status = NFS4ERR_BADXDR;
		goto out;
	}

	if (objname.len > SRV_MAX_NAME) {
		status = NFS4ERR_NAMETOOLONG;
		goto out;
	}

	rc = dbenv->txn_begin(dbenv, NULL, &txn, 0);
	if (rc) {
		status = NFS4ERR_IO;
		dbenv->err(dbenv, rc, "DB_ENV->txn_begin");
		goto out;
	}

	status = dir_curfh(txn, cxn, &ino, 0);
	if (status != NFS4_OK) {
		if ((status == NFS4ERR_NOTDIR) &&
		    (ino->type == NF4LNK))
			status = NFS4ERR_SYMLINK;
		goto out_abort;
	}

	status = dir_lookup(txn, ino, &objname, 0, &inum);
	if (status != NFS4_OK)
		goto out_abort;

	rc = txn->commit(txn, 0);
	if (rc) {
		dbenv->err(dbenv, rc, "DB_ENV->txn_commit");
		status = NFS4ERR_IO;
		goto out;
	}

	fh_set(&cxn->current_fh, inum);

	if (debugging) {
		applog(LOG_INFO, "op LOOKUP ('%.*s') -> %016llX",
		       objname.len,
		       objname.val,
		       (unsigned long long) cxn->current_fh.inum);
		printed = true;
	}

out:
	if (!printed) {
		if (debugging)
			applog(LOG_INFO, "op LOOKUP ('%.*s')",
			       objname.len,
			       objname.val);
	}

	WR32(status);
	inode_free(ino);
	return status;

out_abort:
	if (txn->abort(txn))
		dbenv->err(dbenv, rc, "DB_ENV->txn_abort");
	goto out;
}
Example #17
0
int
main(int argc, char *const* argv)
{
	const char *progname = "dbxml_dump";
	DB_ENV *dbenv;
	XmlManager *xmlDb;
	u_int32_t cache;
	int ch, exitval, is_private, keyflag, nflag, ret, Rflag, rflag;
	char *home, *passwd;

	if ((ret = version_check(progname)) != 0)
		return (ret);

	dbenv = NULL;
	xmlDb = NULL;
	exitval = nflag = rflag = Rflag = 0;
	keyflag = 0;
	cache = MEGABYTE;
	is_private = 0;
	home = passwd = NULL;

	while ((ch = getopt(argc, argv, "f:h:NP:rRV")) != EOF)
		switch (ch) {
		case 'f':
			if (freopen(optarg, "wb", stdout) == NULL) {
				fprintf(stderr, "%s: %s: reopen: %s\n",
					progname, optarg, strerror(errno));
				return (EXIT_FAILURE);
			}
			break;
		case 'h':
			home = optarg;
			break;
		case 'N':
			nflag = 1;
			break;
		case 'P':
			passwd = strdup(optarg);
			memset(optarg, 0, strlen(optarg));
			if (passwd == NULL) {
				fprintf(stderr, "%s: strdup: %s\n",
					progname, strerror(errno));
				return (EXIT_FAILURE);
			}
			break;
		case 'R':
			Rflag = 1;
			/* DB_AGGRESSIVE requires DB_SALVAGE */
			/* FALLTHROUGH */
		case 'r':
			rflag = 1;
			break;
		case 'V':
			printf("%s\n", DbXml::dbxml_version(NULL, NULL, NULL));
			printf("%s\n", db_version(NULL, NULL, NULL));
			return (EXIT_SUCCESS);
		case '?':
		default:
			return (usage());
		}
	argc -= optind;
	argv += optind;

	if (argc != 1)
		return (usage());

	/* Handle possible interruptions. */
	SigBlock sb;

	/*
	 * Create an environment object and initialize it for error
	 * reporting.
	 */
	if ((ret = db_env_create(&dbenv, 0)) != 0) {
		fprintf(stderr,
			"%s: db_env_create: %s\n", progname, db_strerror(ret));
		goto err;
	}

	dbenv->set_errfile(dbenv, stderr);
	dbenv->set_errpfx(dbenv, progname);
	if (nflag) {
		if ((ret = dbenv->set_flags(dbenv, DB_NOLOCKING, 1)) != 0) {
			dbenv->err(dbenv, ret, "set_flags: DB_NOLOCKING");
			goto err;
		}
		if ((ret = dbenv->set_flags(dbenv, DB_NOPANIC, 1)) != 0) {
			dbenv->err(dbenv, ret, "set_flags: DB_NOPANIC");
			goto err;
		}
	}
	if (passwd != NULL && (ret = dbenv->set_encrypt(dbenv,
				     passwd, DB_ENCRYPT_AES)) != 0) {
		dbenv->err(dbenv, ret, "set_passwd");
		goto err;
	}

	/* Initialize the environment. */
	if ((ret = db_init(dbenv, home, rflag, cache, &is_private)) != 0) {
		dbenv->err(dbenv, ret, "db_init");
		goto err;
	}

	xmlDb = new XmlManager(dbenv);
	
	if (rflag) {
		try {
			xmlDb->verifyContainer(argv[0], &cout, DB_SALVAGE | (Rflag ? DB_AGGRESSIVE : 0));
		} catch (XmlException &e) {
			dbenv->errx(dbenv, "verify %s: %s", argv[0], e.what());
			goto err;
		}
		goto done;
	}
	
	try {
		xmlDb->dumpContainer(argv[0], &cout);
	} catch (XmlException &e) {
		dbenv->errx(dbenv, "dump %s: %s", argv[0], e.what());
		goto err;
	}
	
	if (0) {
	err:
		exitval = 1;
	}
done:
	if (xmlDb)
		delete xmlDb;
		
	if ((ret = dbenv->close(dbenv, 0)) != 0) {
		exitval = 1;
		fprintf(stderr,
			"%s: dbenv->close: %s\n", progname, db_strerror(ret));
	}
	
	return (exitval == 0 ? EXIT_SUCCESS : EXIT_FAILURE);
}
Example #18
0
File: dir.c Project: jgarzik/nfs4d
nfsstat4 nfs_op_remove(struct nfs_cxn *cxn, const REMOVE4args *args,
		       struct list_head *writes, struct rpc_write **wr)
{
	nfsstat4 status = NFS4_OK;
	struct nfs_inode *dir_ino = NULL, *target_ino = NULL;
	struct nfs_buf target;
	change_info4 cinfo = { true, 0, 0 };
	DB_TXN *txn = NULL;
	DB_ENV *dbenv = srv.fsdb.env;
	int rc;
	nfsino_t de_inum;

	target.len = args->target.utf8string_len;
	target.val = args->target.utf8string_val;

	if (debugging)
		applog(LOG_INFO, "op REMOVE ('%.*s')",
		       target.len,
		       target.val);

	if (target.len > SRV_MAX_NAME) {
		status = NFS4ERR_NAMETOOLONG;
		goto out;
	}

	if (!valid_utf8string(&target)) {
		status = NFS4ERR_INVAL;
		goto out;
	}
	if (has_dots(&target)) {
		status = NFS4ERR_BADNAME;
		goto out;
	}

	rc = dbenv->txn_begin(dbenv, NULL, &txn, 0);
	if (rc) {
		status = NFS4ERR_IO;
		dbenv->err(dbenv, rc, "DB_ENV->txn_begin");
		goto out;
	}

	/* reference container directory */
	status = dir_curfh(txn, cxn, &dir_ino, DB_RMW);
	if (status != NFS4_OK)
		goto out_abort;

	/* lookup target name in directory */
	status = dir_lookup(txn, dir_ino, &target, 0, &de_inum);
	if (status != NFS4_OK)
		goto out_abort;

	/* reference target inode */
	target_ino = inode_getdec(txn, de_inum, DB_RMW);
	if (!target_ino) {
		status = NFS4ERR_NOENT;
		goto out_abort;
	}

	/* prevent root dir deletion */
	if (target_ino->inum == INO_ROOT) {
		status = NFS4ERR_INVAL;
		goto out_abort;
	}

	/* prevent removal of non-empty dirs */
	if ((target_ino->type == NF4DIR) && !dir_is_empty(txn, target_ino)) {
		status = NFS4ERR_NOTEMPTY;
		goto out_abort;
	}

	/* remove target inode from directory */
	rc = fsdb_dirent_del(&srv.fsdb, txn, dir_ino->inum, &target, 0);
	if (rc) {
		status = NFS4ERR_IO;
		goto out_abort;
	}

	/* record directory change info */
	cinfo.before = dir_ino->version;

	rc = inode_touch(txn, dir_ino);
	if (rc) {
		status = NFS4ERR_IO;
		goto out_abort;
	}

	cinfo.after = dir_ino->version;

	/* remove link, possibly deleting inode */
	rc = inode_unlink(txn, target_ino);
	if (rc) {
		status = NFS4ERR_IO;
		goto out_abort;
	}

	rc = txn->commit(txn, 0);
	if (rc) {
		dbenv->err(dbenv, rc, "DB_ENV->txn_commit");
		status = NFS4ERR_IO;
		goto out;
	}

out:
	WR32(status);
	if (status == NFS4_OK) {
		WR32(cinfo.atomic ? 1 : 0);	/* cinfo.atomic */
		WR64(cinfo.before);		/* cinfo.before */
		WR64(cinfo.after);		/* cinfo.after */
	}
	inode_free(dir_ino);
	inode_free(target_ino);
	return status;

out_abort:
	if (txn->abort(txn))
		dbenv->err(dbenv, rc, "DB_ENV->txn_abort");
	goto out;
}
Example #19
0
File: dir.c Project: jgarzik/nfs4d
nfsstat4 nfs_op_link(struct nfs_cxn *cxn, const LINK4args *args,
		     struct list_head *writes, struct rpc_write **wr)
{
	nfsstat4 status;
	struct nfs_inode *dir_ino = NULL, *src_ino = NULL;
	struct nfs_buf newname;
	uint64_t before = 0, after = 0;
	DB_TXN *txn;
	DB_ENV *dbenv = srv.fsdb.env;
	int rc;

	newname.len = args->newname.utf8string_len;
	newname.val = args->newname.utf8string_val;

	if (debugging)
		applog(LOG_INFO, "op LINK (%.*s)",
		       newname.len,
		       newname.val);

	/* verify input parameters */
	if (!valid_fh(cxn->current_fh) || !valid_fh(cxn->save_fh)) {
		status = NFS4ERR_NOFILEHANDLE;
		goto out;
	}
	if (newname.len > SRV_MAX_NAME) {
		status = NFS4ERR_NAMETOOLONG;
		goto out;
	}

	/* open transaction */
	rc = dbenv->txn_begin(dbenv, NULL, &txn, 0);
	if (rc) {
		status = NFS4ERR_IO;
		dbenv->err(dbenv, rc, "DB_ENV->txn_begin");
		goto out;
	}

	/* read source inode's directory inode */
	dir_ino = inode_fhdec(txn, cxn->current_fh, 0);
	if (!dir_ino) {
		status = NFS4ERR_NOFILEHANDLE;
		goto out_abort;
	}

	/* make sure target is a directory */
	if (dir_ino->type != NF4DIR) {
		status = NFS4ERR_NOTDIR;
		goto out_abort;
	}

	/* read source inode */
	src_ino = inode_fhdec(txn, cxn->save_fh, 0);
	if (!src_ino) {
		status = NFS4ERR_NOFILEHANDLE;
		goto out_abort;
	}

	/* make sure source is a not a directory */
	if (src_ino->type == NF4DIR) {
		status = NFS4ERR_ISDIR;
		goto out_abort;
	}

	before = dir_ino->version;

	/* add directory entry */
	status = dir_add(txn, dir_ino, &newname, src_ino);
	if (status != NFS4_OK)
		goto out_abort;

	after = dir_ino->version;

	/* update source inode */
	src_ino->n_link++;
	if (inode_touch(txn, src_ino)) {
		status = NFS4ERR_IO;
		goto out_abort;
	}

	/* close transaction */
	rc = txn->commit(txn, 0);
	if (rc) {
		dbenv->err(dbenv, rc, "DB_ENV->txn_commit");
		status = NFS4ERR_IO;
		goto out;
	}

out:
	WR32(status);
	if (status == NFS4_OK) {
		WR32(1);		/* cinfo.atomic */
		WR64(before);		/* cinfo.before */
		WR64(after);		/* cinfo.after */
	}
	inode_free(src_ino);
	inode_free(dir_ino);
	return status;

out_abort:
	if (txn->abort(txn))
		dbenv->err(dbenv, rc, "DB_ENV->txn_abort");
	goto out;
}
Example #20
0
File: dir.c Project: jgarzik/nfs4d
nfsstat4 nfs_op_rename(struct nfs_cxn *cxn, const RENAME4args *args,
		       struct list_head *writes, struct rpc_write **wr)
{
	nfsstat4 status = NFS4_OK;
	struct nfs_inode *src_dir = NULL, *target_dir = NULL;
	struct nfs_inode *old_file = NULL, *new_file = NULL;
	struct nfs_buf oldname, newname;
	change_info4 src = { true, 0, 0 };
	change_info4 target = { true, 0, 0 };
	DB_TXN *txn = NULL;
	DB_ENV *dbenv = srv.fsdb.env;
	int rc;
	nfsino_t old_dirent, new_dirent;

	oldname.len = args->oldname.utf8string_len;
	oldname.val = args->oldname.utf8string_val;
	newname.len = args->newname.utf8string_len;
	newname.val = args->newname.utf8string_val;

	if (debugging)
		applog(LOG_INFO, "op RENAME (OLD:%.*s, NEW:%.*s)",
		       oldname.len,
		       oldname.val,
		       newname.len,
		       newname.val);

	/* validate text input */
	if ((!valid_utf8string(&oldname)) ||
	    (!valid_utf8string(&newname))) {
		status = NFS4ERR_INVAL;
		goto out;
	}
	if (has_dots(&oldname) || has_dots(&newname)) {
		status = NFS4ERR_BADNAME;
		goto out;
	}

	rc = dbenv->txn_begin(dbenv, NULL, &txn, 0);
	if (rc) {
		status = NFS4ERR_IO;
		dbenv->err(dbenv, rc, "DB_ENV->txn_begin");
		goto out;
	}

	/* reference source, target directories.
	 * NOTE: src_dir and target_dir may point to the same object
	 */
	src_dir = inode_fhdec(txn, cxn->save_fh, DB_RMW);
	if (fh_equal(cxn->save_fh, cxn->current_fh))
		target_dir = src_dir;
	else
		target_dir = inode_fhdec(txn, cxn->current_fh, DB_RMW);
	if (!src_dir || !target_dir) {
		status = NFS4ERR_NOFILEHANDLE;
		goto out_abort;
	}
	if ((src_dir->type != NF4DIR) || (target_dir->type != NF4DIR)) {
		status = NFS4ERR_NOTDIR;
		goto out_abort;
	}

	/* lookup source, target names */
	status = dir_lookup(txn, src_dir, &oldname, 0, &old_dirent);
	if (status != NFS4_OK)
		goto out_abort;

	old_file = inode_getdec(txn, old_dirent, 0);
	if (!old_file) {
		status = NFS4ERR_NOENT;
		goto out_abort;
	}

	status = dir_lookup(txn, target_dir, &newname, 0, &new_dirent);
	if (status != NFS4_OK && status != NFS4ERR_NOENT)
		goto out_abort;

	/* if target (newname) is present, attempt to remove */
	if (status == NFS4_OK) {
		bool ok_to_remove = false;

		/* read to-be-deleted inode */
		new_file = inode_getdec(txn, new_dirent, DB_RMW);
		if (!new_file) {
			status = NFS4ERR_NOENT;
			goto out_abort;
		}

		/* do oldname and newname refer to same file? */
		if (old_file->inum == new_file->inum) {
			src.after =
			src.before = src_dir->version;
			target.after =
			target.before = target_dir->version;
			goto out_abort;
		}

		if (old_file->type != NF4DIR && new_file->type != NF4DIR)
			ok_to_remove = true;
		else if (old_file->type == NF4DIR &&
			 new_file->type == NF4DIR &&
			 dir_is_empty(txn, new_file))
			ok_to_remove = true;

		if (!ok_to_remove) {
			status = NFS4ERR_EXIST;
			goto out_abort;
		}

		/* remove target inode from directory */
		rc = fsdb_dirent_del(&srv.fsdb, txn, target_dir->inum,
				     &newname, 0);
		if (rc == 0)
			rc = inode_unlink(txn, new_file);

		if (rc) {
			status = NFS4ERR_IO;
			goto out_abort;
		}
	} else
		status = NFS4_OK;

	new_dirent = old_dirent;

	/* delete entry from source directory; add to target directory */
	rc = fsdb_dirent_del(&srv.fsdb, txn, src_dir->inum, &oldname, 0);
	if (rc == 0)
		rc = fsdb_dirent_put(&srv.fsdb, txn, target_dir->inum,
				     &newname, 0, new_dirent);
	if (rc) {
		status = NFS4ERR_IO;
		goto out_abort;
	}

	/* if renamed file is a directory, ensure its 'parent' is updated */
	if (old_file->type == NF4DIR) {
		old_file->parent = target_dir->inum;
		if (inode_touch(txn, old_file)) {
			status = NFS4ERR_IO;
			goto out_abort;
		}
	}

	/* record directory change info */
	src.before = src_dir->version;
	target.before = target_dir->version;

	/* update last-modified stamps of directory inodes */
	rc = inode_touch(txn, src_dir);
	if (rc == 0 && src_dir != target_dir)
		rc = inode_touch(txn, target_dir);
	if (rc) {
		status = NFS4ERR_IO;
		goto out_abort;
	}

	/* close the transaction */
	rc = txn->commit(txn, 0);
	if (rc) {
		dbenv->err(dbenv, rc, "DB_ENV->txn_commit");
		status = NFS4ERR_IO;
		goto out;
	}

	src.after = src_dir->version;
	target.after = target_dir->version;

out:
	WR32(status);
	if (status == NFS4_OK) {
		WR32(src.atomic ? 1 : 0); /* src cinfo.atomic */
		WR64(src.before);	/* src cinfo.before */
		WR64(src.after);	/* src cinfo.after */
		WR32(target.atomic ? 1 : 0); /* target cinfo.atomic */
		WR64(target.before);	/* target cinfo.before */
		WR64(target.after);	/* target cinfo.after */
	}
	inode_free(src_dir);
	if (src_dir != target_dir)
		inode_free(target_dir);
	inode_free(old_file);
	inode_free(new_file);
	return status;

out_abort:
	if (txn->abort(txn))
		dbenv->err(dbenv, rc, "DB_ENV->txn_abort");
	goto out;
}
int main(void)
{
  int ret, ret_c;
  u_int32_t db_flags, env_flags;
  DB *dbp;
  DB_ENV *envp;
  DBT key, data;
  DB_TXN *txn;
  const char *db_home_dir = "/tmp/mai-test-1/";
  const char *file_name = "mydb.db";
  const char keystr[BUF_SIZE];
  const char datastr[BUF_SIZE];
  int i = 0;

  dbp = NULL;
  envp = NULL;

  /* Open the environment */
  ret = db_env_create(&envp, 0);
  if (ret != 0) {
    fprintf(stderr, "Error creating environment handle: %s\n",
        db_strerror(ret));
    return (EXIT_FAILURE);
  }

  env_flags = DB_CREATE | /* Create the environment if it does
                           * not already exist. */
    DB_INIT_TXN | /* Initialize transactions */
    DB_INIT_LOCK | /* Initialize locking. */
    DB_INIT_LOG | /* Initialize logging */
    DB_INIT_MPOOL | /* Initialize the in-memory cache. */
    DB_RECOVER;
  ret = envp->open(envp, db_home_dir, env_flags, 0);
  if (ret != 0) {
    fprintf(stderr, "Error opening environment: %s\n",
        db_strerror(ret));
    goto err;
  }

  /* Initialize the DB handle */
  ret = db_create(&dbp, envp, 0);
  if (ret != 0) {
    envp->err(envp, ret, "Database creation failed");
    goto err;
  }

  db_flags = DB_CREATE | DB_AUTO_COMMIT;
  /*
     Open the database. Note that we are using auto commit for the open,
     so the database is able to support transactions.
     */
  ret = dbp->open(dbp, /* Pointer to the database */
      NULL, /* Txn pointer */
      file_name, /* File name */
      NULL, /* Logical db name */
      DB_BTREE, /* Database type (using btree) */
      db_flags, /* Open flags */
      0); /* File mode. Using defaults */
  if (ret != 0) {
    envp->err(envp, ret, "Database '%s' open failed",
        file_name);
    goto err;
  }

  /* Get the txn handle */
  txn = NULL;
  ret = envp->txn_begin(envp, NULL, &txn, 0);
  if (ret != 0) {
    envp->err(envp, ret, "Transaction begin failed.");
    goto err;
  }

  for (i = 0; i < LOOP_SIZE; i++) {
    /* Prepare the DBTs */
    memset(&key, 0, sizeof(DBT));
    memset(&data, 0, sizeof(DBT));

    sprintf((char*)keystr, "key%d", i);
    //sprintf((char*)datastr, "data%d", i);
  
    key.data = (char*)keystr;
    key.size = strlen((char*)keystr) + 1;
    //data.data = (char*)datastr;
    //data.size = strlen((char*)datastr) + 1;
  
    /* Perform the database write. If this fails, abort the transaction. */
    ret = dbp->get(dbp, txn, &key, &data, 0);
    if (ret != 0) {
      envp->err(envp, ret, "Database put failed.");
      txn->abort(txn);
      goto err;
    }
    printf("%s %s\n", key.data, data.data);
  }

  /* Commit the transaction. Note that the transaction handle
     can no longer be used. */
  ret = txn->commit(txn, 0);
  if (ret != 0) {
    envp->err(envp, ret, "Transaction commit failed.");
    goto err;
  }

err:
  /* Close the database */
  if (dbp != NULL) {
    ret_c = dbp->close(dbp, 0);
    if (ret_c != 0) {
      envp->err(envp, ret_c, "Database close failed.");
      ret = ret_c;
    }
  }

  /* Close the environment */
  if (envp != NULL) {
    ret_c = envp->close(envp, 0);
    if (ret_c != 0) {
      fprintf(stderr, "environment close failed: %s\n",
          db_strerror(ret_c));
      ret = ret_c;
    }
  }

  return (ret == 0 ? EXIT_SUCCESS : EXIT_FAILURE);
}
Example #22
0
bool bucket_del(struct client *cli, const char *user, const char *bucket)
{
	char *hdr, timestr[64];
	enum errcode err = InternalError;
	int rc;
	struct db_bucket_ent ent;
	DB_ENV *dbenv = tdbrep.tdb.env;
	DB_TXN *txn = NULL;
	DB *buckets = tdbrep.tdb.buckets;
	DB *acls = tdbrep.tdb.acls;
	DB *objs = tdbrep.tdb.objs;
	DBC *cur = NULL;
	DBT key, val;
	char structbuf[sizeof(struct db_acl_key) + 32];
	struct db_acl_key *acl_key = (struct db_acl_key *) &structbuf;
	struct db_obj_key *obj_key = (struct db_obj_key *) &structbuf;

	if (!user)
		return cli_err(cli, AccessDenied);

	/* open transaction */
	rc = dbenv->txn_begin(dbenv, NULL, &txn, 0);
	if (rc) {
		dbenv->err(dbenv, rc, "DB_ENV->txn_begin");
		goto err_none;
	}

	/* search for (bucket, *) in object database, to see if
	 * any objects associated with this bucket exist
	 */
	rc = objs->cursor(objs, txn, &cur, 0);
	if (rc) {
		objs->err(objs, rc, "objs->cursor");
		goto err_out;
	}

	memset(&structbuf, 0, sizeof(structbuf));
	strncpy(obj_key->bucket, bucket, sizeof(obj_key->bucket));
	obj_key->key[0] = 0;

	memset(&key, 0, sizeof(key));
	memset(&val, 0, sizeof(val));

	key.data = obj_key;
	key.size = sizeof(*obj_key) + strlen(obj_key->key) + 1;

	val.flags = DB_DBT_MALLOC;

	rc = cur->get(cur, &key, &val, DB_SET_RANGE);

	if (rc == 0) {
		struct db_obj_key *newkey = key.data;

		if (!strcmp(newkey->bucket, bucket)) {
			free(newkey);
			cur->close(cur);
			err = BucketNotEmpty;
			goto err_out;
		}

		free(newkey);
	} else if (rc != DB_NOTFOUND)
		objs->err(objs, rc, "bucket_del empty check");

	rc = cur->close(cur);
	if (rc) {
		objs->err(objs, rc, "objs->cursor_close");
		goto err_out;
	}

	memset(&key, 0, sizeof(key));
	key.data = (char *) bucket;
	key.size = strlen(bucket) + 1;

	memset(&val, 0, sizeof(val));
	val.data = &ent;
	val.ulen = sizeof(struct db_bucket_ent);
	val.flags = DB_DBT_USERMEM;

	/* verify the bucket exists */
	rc = buckets->get(buckets, txn, &key, &val, 0);
	if (rc) {
		if (rc == DB_NOTFOUND)
			err = NoSuchBucket;
		else
			buckets->err(buckets, rc, "buckets->get");
		goto err_out;
	}

	/* verify that it is the owner who wishes to delete bucket */
	if (strncmp(user, ent.owner, sizeof(ent.owner))) {
		err = AccessDenied;
		goto err_out;
	}

	/* delete bucket */
	rc = buckets->del(buckets, txn, &key, 0);
	if (rc) {
		buckets->err(buckets, rc, "bucket del");
		goto err_out;
	}

	/* delete bucket ACLs */
	memset(&structbuf, 0, sizeof(structbuf));
	strncpy(acl_key->bucket, bucket, sizeof(acl_key->bucket));
	acl_key->key[0] = 0;

	memset(&key, 0, sizeof(key));
	key.data = acl_key;
	key.size = sizeof(*acl_key) + strlen(acl_key->key) + 1;

	rc = acls->del(acls, txn, &key, 0);
	if (rc && rc != DB_NOTFOUND) {
		acls->err(acls, rc, "acl del");
		goto err_out;
	}

	/* commit */
	rc = txn->commit(txn, 0);
	if (rc) {
		dbenv->err(dbenv, rc, "DB_ENV->txn_commit");
		return cli_err(cli, InternalError);
	}

	if (asprintf(&hdr,
"HTTP/%d.%d 204 x\r\n"
"Content-Length: 0\r\n"
"Date: %s\r\n"
"Server: " PACKAGE_STRING "\r\n"
"\r\n",
		     cli->req.major,
		     cli->req.minor,
		     hutil_time2str(timestr, sizeof(timestr), time(NULL))) < 0)
		return cli_err(cli, InternalError);

	rc = atcp_writeq(&cli->wst, hdr, strlen(hdr), atcp_cb_free, hdr);
	if (rc) {
		free(hdr);
		return true;
	}

	return atcp_write_start(&cli->wst);

err_out:
	rc = txn->abort(txn);
	if (rc)
		dbenv->err(dbenv, rc, "DB_ENV->txn_abort");
err_none:
	return cli_err(cli, err);
}
Example #23
0
static bool bucket_list_keys(struct client *cli, const char *user,
			     const char *bucket)
{
	GHashTable *param;
	enum errcode err = InternalError;
	char *prefix, *marker, *maxkeys_str, *delim, *s;
	int maxkeys = 100, i, rc;
	GList *content, *tmpl;
	size_t pfx_len;
	struct bucket_list_info bli;
	bool rcb;
	DB_ENV *dbenv = tdbrep.tdb.env;
	DB_TXN *txn = NULL;
	DB *objs = tdbrep.tdb.objs;
	DBC *cur = NULL;
	DBT pkey, pval;
	struct db_obj_key *obj_key;
	size_t alloc_len;
	bool seen_prefix = false;
	int get_flags;

	/* verify READ access */
	if (!user || !has_access(user, bucket, NULL, "READ")) {
		err = AccessDenied;
		goto err_out;
	}

	/* parse URI query string */
	param = hreq_query(&cli->req);
	if (!param)
		goto err_out;

	/* read useful params from query string */
	prefix = g_hash_table_lookup(param, "prefix");
	pfx_len = prefix ? strlen(prefix) : 0;

	marker = g_hash_table_lookup(param, "marker");
	delim = g_hash_table_lookup(param, "delimiter");
	maxkeys_str = g_hash_table_lookup(param, "max-keys");
	if (maxkeys_str) {
		i = atoi(maxkeys_str);
		if (i > 0 && i < maxkeys)
			maxkeys = i;
	}

	/* open transaction */
	rc = dbenv->txn_begin(dbenv, NULL, &txn, 0);
	if (rc) {
		dbenv->err(dbenv, rc, "DB_ENV->txn_begin");
		goto err_out;
	}

	/* search for (bucket, *) in object database, to see if
	 * any objects associated with this bucket exist
	 */
	rc = objs->cursor(objs, txn, &cur, 0);
	if (rc) {
		objs->err(objs, rc, "objs->cursor");
		goto err_out;
	}

	alloc_len = sizeof(*obj_key) +
		    (marker ? strlen(marker) : pfx_len) + 1;
	obj_key = alloca(alloc_len);

	memset(obj_key, 0, alloc_len);
	strncpy(obj_key->bucket, bucket, sizeof(obj_key->bucket));
	strcpy(obj_key->key, marker ? marker : prefix ? prefix : "");

	memset(&pkey, 0, sizeof(pkey));
	pkey.data = obj_key;
	pkey.size = alloc_len;

	memset(&bli, 0, sizeof(bli));
	bli.prefix = prefix;
	bli.pfx_len = pfx_len;
	bli.delim = delim;
	bli.common_pfx = g_hash_table_new_full(g_str_hash, g_str_equal,
					       free, NULL);
	bli.maxkeys = maxkeys;

	/* iterate through each returned data row */
	get_flags = DB_SET_RANGE;
	while (1) {
		struct obj_vitals v;
		struct db_obj_key *tmpkey;
		struct db_obj_ent *obj;

		memset(&pval, 0, sizeof(pval));
		pval.flags = DB_DBT_MALLOC;

		rc = cur->get(cur, &pkey, &pval, get_flags);
		if (rc) {
			if (rc != DB_NOTFOUND)
				objs->err(objs, rc, "bucket_list_keys iter");
			break;
		}

		get_flags = DB_NEXT;

		tmpkey = pkey.data;
		obj = pval.data;

		if (strcmp(tmpkey->bucket, bucket)) {
			free(obj);
			break;
		}
		if (prefix) {
			if (strncmp(tmpkey->key, prefix, pfx_len) != 0) {
				free(obj);
				if (!seen_prefix)
					/* continue searching for
					 * a record that begins with this
					 * prefix
					 */
					continue;
				else
					/* no more records with our prefix */
					break;
			}

			seen_prefix = true;
		}

		memset(&v, 0, sizeof(v));
		strcpy(v.md5, obj->md5);
		strncpy(v.owner, obj->owner, sizeof(v.owner)-1);
		if (!(GUINT32_FROM_LE(obj->flags) & DB_OBJ_INLINE))
			memcpy(&v.addr, &obj->d.a, sizeof(v.addr));
		v.mtime = GUINT64_FROM_LE(obj->mtime);
		v.size = GUINT64_FROM_LE(obj->size);
		free(obj);

		if (bucket_list_iter(tmpkey->key, &v, &bli))
			break;
	}

	/* close cursor, transaction */
	rc = cur->close(cur);
	if (rc) {
		objs->err(objs, rc, "objs->cursor close");
		goto err_out_rb;
	}

	rc = txn->commit(txn, 0);
	if (rc) {
		dbenv->err(dbenv, rc, "DB_ENV->txn_commit");
		goto err_out_param;
	}

	s = g_markup_printf_escaped(
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\r\n"
"<ListBucketResult xmlns=\"http://indy.yyz.us/doc/2006-03-01/\">\r\n"
"  <Name>%s</Name>\r\n"
"  <MaxKeys>%d</MaxKeys>\r\n"
"  <IsTruncated>%s</IsTruncated>\r\n",

		 bucket,
		 maxkeys,
		 bli.trunc ? "true" : "false");

	content = g_list_append(NULL, s);

	if (prefix) {
		s = g_markup_printf_escaped("  <Prefix>%s</Prefix>\n", prefix);
		content = g_list_append(content, s);
	}
	if (marker) {
		s = g_markup_printf_escaped("  <Marker>%s</Marker>\n", marker);
		content = g_list_append(content, s);
	}

	tmpl = bli.res;
	while (tmpl) {
		char timestr[64];
		struct obj_vitals *vp;

		vp = tmpl->data;
		tmpl = tmpl->next;

		/*
		 * FIXME Use the vp->addr to verify that key still exists.
		 * And if it doesn't, then what? (addr.nid can be 0 for inline)
		 */

		s = g_markup_printf_escaped(
                         "  <Contents>\r\n"
                         "    <Key>%s</Key>\r\n"
                         "    <LastModified>%s</LastModified>\r\n"
                         "    <ETag>%s</ETag>\r\n"
                         "    <Size>%llu</Size>\r\n"
                         "    <StorageClass>STANDARD</StorageClass>\r\n"
                         "    <Owner>\r\n"
                         "      <ID>%s</ID>\r\n"
                         "      <DisplayName>%s</DisplayName>\r\n"
                         "    </Owner>\r\n"
                         "  </Contents>\r\n",

			 vp->key,
			 hutil_time2str(timestr, sizeof(timestr), vp->mtime / 1000000),
			 vp->md5,
			 (unsigned long long) vp->size,
			 vp->owner,
			 vp->owner);

		content = g_list_append(content, s);

		free(vp->key);
		free(vp);
	}

	g_list_free(bli.res);

	content = bucket_list_pfx(content, bli.common_pfx, bli.delim);

	s = strdup("</ListBucketResult>\r\n");
	content = g_list_append(content, s);

	free(bli.last_comp);
	g_hash_table_destroy(bli.common_pfx);
	g_hash_table_destroy(param);

	rcb = cli_resp_xml(cli, 200, content);

	g_list_free(content);

	return rcb;

err_out_rb:
	rc = txn->abort(txn);
	if (rc)
		dbenv->err(dbenv, rc, "DB_ENV->txn_abort");
err_out_param:
	g_hash_table_destroy(param);
err_out:
	return cli_err(cli, err);
}
Example #24
0
bool bucket_add(struct client *cli, const char *user, const char *bucket)
{
	char *hdr, timestr[64];
	enum errcode err = InternalError;
	int rc;
	struct db_bucket_ent ent;
	bool setacl;			/* is ok to put pre-existing bucket */
	enum ReqACLC canacl;
	DB *buckets = tdbrep.tdb.buckets;
	DB *acls = tdbrep.tdb.acls;
	DB_ENV *dbenv = tdbrep.tdb.env;
	DB_TXN *txn = NULL;
	DBT key, val;

	if (!user)
		return cli_err(cli, AccessDenied);

	/* prepare parameters */
	setacl = false;
	if (cli->req.uri.query_len) {
		switch (hreq_is_query(&cli->req)) {
		case URIQ_ACL:
			setacl = true;
			break;
		default:
			err = InvalidURI;
			goto err_par;
		}
	}

	if ((rc = hreq_acl_canned(&cli->req)) == ACLCNUM) {
		err = InvalidArgument;
		goto err_par;
	}
	canacl = (rc == -1)? ACLC_PRIV: rc;

	/* begin trans */
	rc = dbenv->txn_begin(dbenv, NULL, &txn, 0);
	if (rc) {
		dbenv->err(dbenv, rc, "DB_ENV->txn_begin");
		goto err_db;
	}

	memset(&key, 0, sizeof(key));
	memset(&val, 0, sizeof(val));
	memset(&ent, 0, sizeof(ent));
	strncpy(ent.name, bucket, sizeof(ent.name));
	strncpy(ent.owner, user, sizeof(ent.owner));
	ent.time_create = GUINT64_TO_LE(time(NULL));

	key.data = &ent.name;
	key.size = strlen(ent.name) + 1;

	val.data = &ent;
	val.size = sizeof(ent);

	if (setacl) {
		/* check if the bucket exists, else insert it */
		rc = bucket_find(txn, bucket, NULL, 0);
		if (rc) {
			if (rc != DB_NOTFOUND) {
				buckets->err(buckets, rc, "buckets->find");
				goto err_out;
			}

			rc = buckets->put(buckets, txn, &key, &val,
							DB_NOOVERWRITE);
			if (rc) {
				buckets->err(buckets, rc, "buckets->put");
				goto err_out;
			}
		} else {
			if (!has_access(user, bucket, NULL, "WRITE_ACP")) {
				err = AccessDenied;
				goto err_out;
			}
			if (!object_del_acls(txn, bucket, ""))
				goto err_out;
		}

	} else {
		/* attempt to insert new bucket */
		rc = buckets->put(buckets, txn, &key, &val, DB_NOOVERWRITE);
		if (rc) {
			if (rc == DB_KEYEXIST)
				err = BucketAlreadyExists;
			else
				buckets->err(buckets, rc, "buckets->put");
			goto err_out;
		}
	}

	/* insert bucket ACL */
	rc = add_access_canned(txn, bucket, "", user, canacl);
	if (rc) {
		acls->err(acls, rc, "acls->put");
		goto err_out;
	}

	/* commit -- no more exception emulation with goto. */
	rc = txn->commit(txn, 0);
	if (rc) {
		dbenv->err(dbenv, rc, "DB_ENV->txn_commit");
		return cli_err(cli, InternalError);
	}

	if (asprintf(&hdr,
"HTTP/%d.%d 200 x\r\n"
"Content-Length: 0\r\n"
"Date: %s\r\n"
"Location: /%s\r\n"
"Server: " PACKAGE_STRING "\r\n"
"\r\n",
		     cli->req.major,
		     cli->req.minor,
		     hutil_time2str(timestr, sizeof(timestr), time(NULL)),
		     bucket) < 0)
		return cli_err(cli, InternalError);

	rc = atcp_writeq(&cli->wst, hdr, strlen(hdr), atcp_cb_free, hdr);
	if (rc) {
		free(hdr);
		return true;
	}

	return atcp_write_start(&cli->wst);

err_out:
	rc = txn->abort(txn);
	if (rc)
		dbenv->err(dbenv, rc, "DB_ENV->txn_abort");
err_db:
err_par:
	return cli_err(cli, err);
}
Example #25
0
int
cache_init(cache_t *c, void (*freevalue)(void *value))
{
	memset(c, '\0', sizeof(*c));

	int ret;


	DB_ENV *dbenv;

  	ret = db_env_create(&dbenv, 0);
  	      dbenv->err(dbenv,ret,"err db_env_create ");

	dbenv->set_errfile(dbenv, stderr);
		dbenv->err(dbenv,ret,"err set_errfile ");

        if ((ret = dbenv->set_shm_key(dbenv, 664)) != 0) {
		dbenv->err(dbenv,ret,"err set_shm_key ");

		return 0;
        }


  	ret = dbenv->open(dbenv,bfile(_temp_path),DB_CREATE | DB_INIT_MPOOL | DB_INIT_CDB ,0);
  	     dbenv->err(dbenv,ret,"err db_env_open ");


        /* Create and initialize database object */
        if ((ret = db_create(&c->c_data, dbenv, 0)) != 0) {
                fprintf(stderr,
                     "%s: db_create: %s\n", "bbdocument", db_strerror(ret));
 		return 0;
        }


	#ifdef DEBUG
	dbenv->stat_print(dbenv, DB_STAT_ALL);
	#endif

        /* open the database. */
        if ((ret = c->c_data->open(c->c_data, NULL, "libcachedb", NULL, DB_BTREE, DB_CREATE, 0)) != 0) {
                        c->c_data->err(c->c_data, ret, "db open");
                        //goto err1;
                        //dette skjer nor collection mappen ikke er opprettet enda, typisk forde vi ikke har lagret et dokument der enda
                        #ifdef DEBUG
                        printf("can't dbp->open(), but db_create() was sucessful!\n");
                        #endif

                        return 0;
        }


	#ifdef DEBUG
	c->c_data->stat_print(c->c_data, DB_STAT_ALL);
	#endif

	pthread_mutex_init(&c->c_lock, NULL);
	c->c_freevalue = freevalue;

	return 1;
}
Example #26
0
File: dir.c Project: jgarzik/nfs4d
nfsstat4 nfs_op_readdir(struct nfs_cxn *cxn, const READDIR4args *args,
		        struct list_head *writes, struct rpc_write **wr)
{
	nfsstat4 status = NFS4_OK;
	struct nfs_inode *ino = NULL;
	uint32_t dircount, maxcount, *status_p;
	struct readdir_info ri;
	uint64_t cookie, attr_request;
	const verifier4 *cookie_verf;
	DB_TXN *txn = NULL;
	DB *dirent = srv.fsdb.dirent;
	DB_ENV *dbenv = srv.fsdb.env;
	DBT pkey, pval;
	struct fsdb_de_key key;
	int cget_flags;
	DBC *curs = NULL;
	int rc;
	uint64_t dirent_inum, db_de;
	struct fsdb_de_key *rkey;

	cookie = args->cookie;
	cookie_verf = &args->cookieverf;
	dircount = args->dircount;
	maxcount = args->maxcount;
	attr_request = bitmap4_decode(&args->attr_request);

	status_p = WRSKIP(4);

	if (debugging) {
		applog(LOG_INFO, "op READDIR (COOKIE:%Lu DIR:%u MAX:%u MAP:%Lx)",
		       (unsigned long long) cookie,
		       dircount,
		       maxcount,
		       (unsigned long long) attr_request);

		print_fattr_bitmap("op READDIR", attr_request);
	}

	/* traditionally "." and "..", hardcoded */
	if (cookie == 1 || cookie == 2) {
		status = NFS4ERR_BAD_COOKIE;
		goto out;
	}
	/* don't permit request of write-only attrib */
	if (attr_request & fattr_write_only_mask) {
		status = NFS4ERR_INVAL;
		goto out;
	}

	/* FIXME: very, very, very poor verifier */
	if (cookie &&
	    memcmp(cookie_verf, &srv.instance_verf, sizeof(verifier4))) {
		status = NFS4ERR_NOT_SAME;
		goto out;
	}

	/* read inode of directory being read */
	status = dir_curfh(NULL, cxn, &ino, 0);
	if (status != NFS4_OK)
		goto out;
	if (ino->mode == 0) {
		status = NFS4ERR_ACCESS;
		goto out;
	}

	/* subtract READDIR4resok header and footer size */
	if (maxcount < 16) {
		status = NFS4ERR_TOOSMALL;
		goto out;
	}

	maxcount -= (8 + 4 + 4);

	/* verify within server limits */
	if (dircount > SRV_MAX_READ || maxcount > SRV_MAX_READ) {
		status = NFS4ERR_INVAL;
		goto out;
	}

	/* open transaction */
	rc = dbenv->txn_begin(dbenv, NULL, &txn, 0);
	if (rc) {
		status = NFS4ERR_IO;
		dbenv->err(dbenv, rc, "DB_ENV->txn_begin");
		goto out;
	}

	/* set up directory iteration */
	memset(&ri, 0, sizeof(ri));
	ri.cookie = cookie;
	ri.dircount = dircount;
	ri.maxcount = maxcount;
	ri.attr_request = attr_request;
	ri.status = NFS4_OK;
	ri.writes = writes;
	ri.wr = wr;
	ri.dir_pos = 3;
	ri.first_time = true;

	/* if dir is empty, skip directory interation loop completely */
	if (dir_is_empty(txn, ino)) {
		WRMEM(&srv.instance_verf, sizeof(verifier4));	/* cookieverf */

		ri.val_follows = WRSKIP(4);

		if (debugging)
			applog(LOG_DEBUG, "   READDIR: empty directory");

		goto the_finale;
	}

	/* otherwise, loop through each dirent attached to ino->inum */
	rc = dirent->cursor(dirent, txn, &curs, 0);
	if (rc) {
		status = NFS4ERR_IO;
		dirent->err(dirent, rc, "dirent->cursor");
		goto out_abort;
	}

	key.inum = inum_encode(ino->inum);

	memset(&pkey, 0, sizeof(pkey));
	pkey.data = &key;
	pkey.size = sizeof(key);
	pkey.flags = DB_DBT_MALLOC;

	memset(&pval, 0, sizeof(pval));
	pval.data = &db_de;
	pval.ulen = sizeof(db_de);
	pval.flags = DB_DBT_USERMEM;

	cget_flags = DB_SET_RANGE;
	while (1) {
		bool iter_rc;

		rc = curs->get(curs, &pkey, &pval, cget_flags);
		if (rc) {
			if (rc != DB_NOTFOUND)
				dirent->err(dirent, rc, "readdir curs->get");
			break;
		}

		cget_flags = DB_NEXT;

		rkey = pkey.data;
		if (inum_decode(rkey->inum) != ino->inum) {
			free(rkey);
			break;
		}

		dirent_inum = inum_decode(db_de);

		iter_rc = readdir_iter(txn, rkey, pkey.size, dirent_inum, &ri);
		free(rkey);

		if (iter_rc)
			break;
	}

	if (!ri.n_results) {
		if (debugging)
			applog(LOG_INFO, "           zero results, status %s",
			       ri.status <= NFS4ERR_CB_PATH_DOWN ?
			       		status2str(ri.status) : "n/a");

		if (ri.status == NFS4_OK) {
			WRMEM(&srv.instance_verf, sizeof(verifier4));	/* cookieverf */

			ri.val_follows = WRSKIP(4);
		}
	}

	rc = curs->close(curs);
	if (rc) {
		status = NFS4ERR_IO;
		dirent->err(dirent, rc, "dirent->cursor close");
		goto out_abort;
	}

the_finale:

	/* terminate final entry4.nextentry and dirlist4.entries */
	if (ri.val_follows)
		*ri.val_follows = htonl(0);

	if (ri.cookie_found && !ri.n_results && ri.hit_limit) {
		status = NFS4ERR_TOOSMALL;
		goto out_abort;
	}

	/* close transaction */
	rc = txn->commit(txn, 0);
	if (rc) {
		dbenv->err(dbenv, rc, "DB_ENV->txn_commit");
		status = NFS4ERR_IO;
		goto out;
	}

	WR32(ri.hit_limit ? 0 : 1);		/* reply eof */

out:
	*status_p = htonl(status);
	inode_free(ino);
	return status;

out_abort:
	if (txn->abort(txn))
		dbenv->err(dbenv, rc, "DB_ENV->txn_abort");
	goto out;
}
Example #27
0
bool access_list(struct client *cli, const char *bucket, const char *key,
		 const char *user)
{
	struct macl {
		char		perm[128];		/* perm(s) granted */
		char		grantee[64];		/* grantee user */
	};

	GHashTable *param;
	enum errcode err = InternalError;
	DB_ENV *dbenv = tdbrep.tdb.env;
	DB *acls = tdbrep.tdb.acls;
	int alloc_len;
	char owner[64];
	GList *res;
	struct db_acl_key *acl_key;
	struct db_acl_ent *acl;
	DB_TXN *txn = NULL;
	DBC *cur = NULL;
	GList *content;
	DBT pkey, pval;
	struct macl *mp;
	char guser[64];
	GList *p;
	char *s;
	int str_len;
	int rc;
	bool rcb;

	/* verify READ access for ACL */
	if (!user || !has_access(user, bucket, key, "READ_ACP")) {
		err = AccessDenied;
		goto err_out;
	}

	/* parse URI query string */
	param = hreq_query(&cli->req);
	if (!param)
		goto err_out;

	res = NULL;

	alloc_len = sizeof(struct db_acl_key) + strlen(key) + 1;
	acl_key = alloca(alloc_len);
	memset(acl_key, 0, alloc_len);

	strncpy(acl_key->bucket, bucket, sizeof(acl_key->bucket));
	strcpy(acl_key->key, key);

	/* open transaction, search cursor */
	rc = dbenv->txn_begin(dbenv, NULL, &txn, 0);
	if (rc) {
		dbenv->err(dbenv, rc, "DB_ENV->txn_begin");
		goto err_out_param;
	}

	rc = bucket_find(txn, bucket, &owner[0], sizeof(owner));
	if (rc) {
		if (rc == DB_NOTFOUND)
			err = InvalidBucketName;
		else
			dbenv->err(dbenv, rc, "bucket_find");
		goto err_out_rb;
	}

	rc = acls->cursor(acls, txn, &cur, 0);
	if (rc) {
		acls->err(acls, rc, "acls->cursor");
		goto err_out_rb;
	}

	memset(&pkey, 0, sizeof(pkey));
	pkey.data = acl_key;
	pkey.size = alloc_len;

	for (;; free(acl)) {

		memset(&pval, 0, sizeof(pval));
		pval.flags = DB_DBT_MALLOC;

		rc = cur->get(cur, &pkey, &pval, DB_NEXT);
		if (rc)
			break;

		acl = pval.data;

		/* This is a workaround, see FIXME about DB_NEXT. */
		if (strncmp(acl->bucket, bucket, sizeof(acl->bucket)))
			continue;
		if (strcmp(acl->key, key))
			continue;

		if ((mp = malloc(sizeof(struct macl))) == NULL) {
			free(acl);
			cur->close(cur);
			goto err_out_rb;
		}

		memcpy(mp->grantee, acl->grantee, sizeof(mp->grantee));
		mp->grantee[sizeof(mp->grantee)-1] = 0;

		memcpy(mp->perm, acl->perm, sizeof(mp->perm));

		/* lop off the trailing comma */
		mp->perm[sizeof(mp->perm)-1] = 0;
		str_len = strlen(mp->perm);
		if (str_len && mp->perm[str_len-1] == ',')
			mp->perm[--str_len] = 0;

		res = g_list_append(res, mp);
	}

	if (rc != DB_NOTFOUND)
		acls->err(acls, rc, "access_list iteration");

	/* close cursor, transaction */
	rc = cur->close(cur);
	if (rc)
		acls->err(acls, rc, "acls->cursor close");
	rc = txn->commit(txn, 0);
	if (rc)
		dbenv->err(dbenv, rc, "DB_ENV->txn_commit");

	/* dump collected acls -- no more exception handling */

	s = g_markup_printf_escaped(
		"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\r\n"
		"<AccessControlPolicy "
		     "xmlns=\"http://indy.yyz.us/doc/2006-03-01/\">\r\n"
		"  <Owner>\r\n"
		"    <ID>%s</ID>\r\n"
		"    <DisplayName>%s</DisplayName>\r\n"
		"  </Owner>\r\n",
		owner, owner);
	content = g_list_append(NULL, s);

	s = g_markup_printf_escaped(
		"  <AccessControlList>\r\n");
	content = g_list_append(content, s);

	for (p = res; p != NULL; p = p->next) {
		mp = p->data;

		if (!strcmp(DB_ACL_ANON, mp->grantee)) {
			strcpy(guser, "anonymous");
		} else {
			strncpy(guser, mp->grantee, sizeof(guser));
			guser[sizeof(guser)-1] = 0;
		}

		s = g_markup_printf_escaped(
			"    <Grant>\r\n"
			"      <Grantee xmlns:xsi=\"http://www.w3.org/2001/"
			"XMLSchema-instance\" xsi:type=\"CanonicalUser\">\r\n"
			"        <ID>%s</ID>\r\n"
			"        <DisplayName>%s</DisplayName>\r\n"
			"      </Grantee>\r\n",
			guser, guser);
		content = g_list_append(content, s);

		/*
		 * FIXME This parsing is totally lame, we should replace
		 * strings with a bit mask once we make sure this works.
		 */
		if (!strcmp(mp->perm, "READ,WRITE,READ_ACP,WRITE_ACP")) {
			s = g_markup_printf_escaped(
			   "      <Permission>FULL_CONTROL</Permission>\r\n");
		} else {
			s = g_markup_printf_escaped(
			   "      <Permission>%s</Permission>\r\n",
			   mp->perm);
		}
		content = g_list_append(content, s);

		s = g_markup_printf_escaped("    </Grant>\r\n");
		content = g_list_append(content, s);

		free(mp);
	}

	s = g_markup_printf_escaped("  </AccessControlList>\r\n");
	content = g_list_append(content, s);

	s = g_markup_printf_escaped("</AccessControlPolicy>\r\n");
	content = g_list_append(content, s);

	g_list_free(res);

	rcb = cli_resp_xml(cli, 200, content);
	g_list_free(content);
	return rcb;

err_out_rb:
	rc = txn->abort(txn);
	if (rc)
		dbenv->err(dbenv, rc, "DB_ENV->txn_abort");
	for (p = res; p != NULL; p = p->next)
		free(p->data);
	g_list_free(res);
err_out_param:
	g_hash_table_destroy(param);
err_out:
	return cli_err(cli, err);
}
void *
writer_thread(void *args)
{
	DB *dbp;
	DB_ENV *dbenv;
	DBT key, data;
	DB_TXN *txn;

	char *key_strings[] = {"001", "002", "003", "004", "005",
	    "006", "007", "008", "009", "010"};
	int i, j, payload, ret, thread_num;
	int retry_count, max_retries = 20;

	dbp = (DB *)args;
	dbenv = dbp->dbenv;

	/* Get the thread number */
	(void)mutex_lock(&thread_num_lock);
	global_thread_num++;
	thread_num = global_thread_num;
	(void)mutex_unlock(&thread_num_lock);

	/* Initialize the random number generator */
	srand(thread_num);

	/* Write 50 times and then quit */
	for (i = 0; i < 50; i++) {
		retry_count = 0; /* Used for deadlock retries */
retry:
		ret = dbenv->txn_begin(dbenv, NULL, &txn, 0);
		if (ret != 0) {
			dbenv->err(dbenv, ret, "txn_begin failed");
			return ((void *)EXIT_FAILURE);
		}

		memset(&key, 0, sizeof(DBT));
		memset(&data, 0, sizeof(DBT));
		for (j = 0; j < 10; j++) {
			/* Set up our key and data DBTs. */
			data.data = key_strings[j];
			data.size = (u_int32_t)strlen(key_strings[j]) + 1;

			payload = rand() + i;
			key.data = &payload;
			key.size = sizeof(int);

			switch (ret = dbp->put(dbp, txn, &key, &data,
			    DB_NOOVERWRITE)) {
			case 0:
				break;
			case DB_KEYEXIST:
				break;
			case DB_LOCK_DEADLOCK:
				(void)txn->abort(txn);
				if (retry_count < max_retries) {
					retry_count++;
					goto retry;
				}
				return ((void *)EXIT_FAILURE);
			default:
				dbenv->err(dbenv, ret, "db put failed");
				ret = txn->abort(txn);

				if (ret != 0)
					dbenv->err(dbenv, ret,
					    "txn abort failed");
				return ((void *)EXIT_FAILURE);
			}
		}

		if ((ret = txn->commit(txn, 0)) != 0) {
			dbenv->err(dbenv, ret, "txn commit failed");
			return ((void *)EXIT_FAILURE);
		}
	}
	return ((void *)EXIT_SUCCESS);
}
Example #29
0
int
main(int argc, char *argv[])
{
    DB_ENV *dbenv;
    DB_SITE *dbsite;
    extern char *optarg;
    const char *home;
    char ch, *host, *portstr;
    int local_is_set, ret, is_group_creator;
    u_int16_t port;
    /* Used to track whether this is a replica or a master. */
    APP_DATA my_app_data;

    dbenv = NULL;
    ret = local_is_set = is_group_creator = 0;
    home = NULL;

    my_app_data.is_master = 0;  /* Assume that we start as a replica */

    if ((ret = create_env(progname, &dbenv)) != 0)
	goto err;

    /* Make APP_DATA available through the environment handle. */
    dbenv->app_private = &my_app_data;

    /* Default priority is 100. */
    dbenv->rep_set_priority(dbenv, 100);
    /* Permanent messages require at least one ack. */
    dbenv->repmgr_set_ack_policy(dbenv, DB_REPMGR_ACKS_ONE);
    /* Give 500 microseconds to receive the ack. */
    dbenv->rep_set_timeout(dbenv, DB_REP_ACK_TIMEOUT, 500);

    /* Collect the command line options. */
    while ((ch = getopt(argc, argv, "h:l:L:p:r:")) != EOF)
	switch (ch) {
	case 'h':
	    home = optarg;
	    break;
	/* Set the host and port used by this environment. */
	case 'L':
	    is_group_creator = 1; /* FALLTHROUGH */
	case 'l':
	    host = strtok(optarg, ":");
	    if ((portstr = strtok(NULL, ":")) == NULL) {
		fprintf(stderr, "Bad host specification.\n");
		goto err;
	    }
	    port = (unsigned short)atoi(portstr);
	    if ((ret =
	      dbenv->repmgr_site(dbenv, host, port, &dbsite, 0)) != 0){
		fprintf(stderr, "Could not set local address %s:%d.\n",
		  host, port);
		goto err;
	    }
	    dbsite->set_config(dbsite, DB_LOCAL_SITE, 1);
	    if (is_group_creator)
		dbsite->set_config(dbsite, DB_GROUP_CREATOR, 1);

	    if ((ret = dbsite->close(dbsite)) != 0) {
		dbenv->err(dbenv, ret, "DB_SITE->close");
		goto err;
	}
	    local_is_set = 1;
	    break;
	/* Set this replica's election priority. */
	case 'p':
	    dbenv->rep_set_priority(dbenv, atoi(optarg));
	    break;
	/* Identify another site in the replication group. */
	case 'r':
	    host = strtok(optarg, ":");
	    if ((portstr = strtok(NULL, ":")) == NULL) {
		fprintf(stderr, "Bad host specification.\n");
		goto err;
	    }
	    port = (unsigned short)atoi(portstr);
	    if ((ret = dbenv->repmgr_site(dbenv, host, port, &dbsite, 0)) != 0) {
		dbenv->err(dbenv, ret, "DB_ENV->repmgr_site");
		goto err;
	    }
	    dbsite->set_config(dbsite, DB_BOOTSTRAP_HELPER, 1);
	    if ((ret = dbsite->close(dbsite)) != 0) {
		dbenv->err(dbenv, ret, "DB_SITE->close");
		goto err;
	    }
	    break;
	case '?':
	default:
	    usage();
	}

    /* Error check command line. */
    if (home == NULL || !local_is_set)
	usage();

    if ((ret = env_init(dbenv, home)) != 0)
	goto err;

    if ((ret = dbenv->repmgr_start(dbenv, 3, DB_REP_ELECTION)) != 0)
	goto err;

    if ((ret = doloop(dbenv)) != 0) {
	dbenv->err(dbenv, ret, "Application failed");
	goto err;
    }

err: if (dbenv != NULL)
	(void)dbenv->close(dbenv, 0);

    return (ret);

}
Example #30
0
bool has_access(const char *user, const char *bucket, const char *key,
		const char *perm_in)
{
	int rc;
	char perm[16];
	bool match = false;
	size_t alloc_len, key_len = 0;
	struct db_acl_key *acl_key;
	struct db_acl_ent *acl;
	DB_ENV *dbenv = tdbrep.tdb.env;
	DB_TXN *txn = NULL;
	DBT pkey, pval;
	DBC *cur = NULL;
	DB *acls = tdbrep.tdb.acls;

	if (user == NULL)
		user = DB_ACL_ANON;
	if (key == NULL)
		key = "";

	/* alloc ACL key on stack, sized to fit 'key' function arg */
	alloc_len = sizeof(struct db_acl_key) + 1;
	if (key) {
		key_len = strlen(key);
		alloc_len += key_len;
	}
	acl_key = alloca(alloc_len);

	/* fill in search key struct */
	memset(acl_key, 0, alloc_len);
	strncpy(acl_key->bucket, bucket, sizeof(acl_key->bucket));
	memcpy(acl_key->key, key, key_len);
	acl_key->key[key_len] = 0;

	snprintf(perm, sizeof(perm), "%s,", perm_in);

	/* open transaction, search cursor */
	rc = dbenv->txn_begin(dbenv, NULL, &txn, 0);
	if (rc) {
		dbenv->err(dbenv, rc, "DB_ENV->txn_begin");
		return false;
	}

	rc = acls->cursor(acls, txn, &cur, 0);
	if (rc) {
		acls->err(acls, rc, "acls->cursor");
		goto err_out;
	}

	memset(&pkey, 0, sizeof(pkey));
	pkey.data = acl_key;
	pkey.size = alloc_len;

	memset(&pval, 0, sizeof(pval));
	pval.flags = DB_DBT_MALLOC;

	/* loop through matching records (if any) */
	rc = cur->get(cur, &pkey, &pval, DB_SET);
	while (rc == 0) {
		acl = pval.data;

		if (!strncmp(acl->grantee, user, sizeof(acl->grantee))) {
			match = (strstr(acl->perm, perm) != NULL);
			free(acl);
			break;
		}
		free(acl);

		memset(&pval, 0, sizeof(pval));
		pval.flags = DB_DBT_MALLOC;

		rc = cur->get(cur, &pkey, &pval, DB_NEXT_DUP);
	}

	if (rc && rc != DB_NOTFOUND)
		acls->err(acls, rc, "has_access iteration");

	/* close cursor, transaction */
	rc = cur->close(cur);
	if (rc)
		acls->err(acls, rc, "acls->cursor close");

	rc = txn->commit(txn, 0);
	if (rc)
		dbenv->err(dbenv, rc, "DB_ENV->txn_commit");

	return match;

err_out:
	rc = txn->abort(txn);
	if (rc)
		dbenv->err(dbenv, rc, "DB_ENV->txn_abort");
	return false;
}