Beispiel #1
0
void ydb_sync(YDB ydb) {
	struct db *db = (struct db *) ydb;
	assert(db->magic == YDB_STRUCT_MAGIC);
	DB_LOCK(db);
	loglist_fsync(db->loglist);
	DB_UNLOCK(db);
}
Beispiel #2
0
int ydb_get(YDB ydb, char *key, unsigned short key_sz,
	    char *buf, int buf_sz) {
	struct db *db = (struct db *) ydb;
	assert(db->magic == YDB_STRUCT_MAGIC);
	
	DB_LOCK(db);
	struct item *item = tree_get(db->tree, key, key_sz);
	if(item == NULL)
		goto error;
		
	int needed = item->value_sz + MAX_PADDING + sizeof(struct ydb_value_record);
	if(buf_sz < needed) {
		log_error("ydb_get:buffer too small. is %i, should be at least %i", buf_sz, needed);
		goto error;
	}
	
	int r = loglist_get(db->loglist, item->logno, item->value_offset, item->value_sz, buf, buf_sz);
	if(r < 0)
		goto error;
	
	DB_UNLOCK(db);
	return(r);

error:
	DB_UNLOCK(db);
	return(-1);
}
Beispiel #3
0
/*----------------------------------------------------------------------------*/
static void __dbpool_mysql_close(ACL_DB_HANDLE *db_handle)
{
	char  myname[] = "__dbpool_mysql_close";
	ACL_DB_POOL *db_pool;
	ACL_DB_POOL_MYSQL *mysql_pool;
	ACL_DB_HANDLE_MYSQL *mysql_handle = (ACL_DB_HANDLE_MYSQL *) db_handle;

	if (db_handle->status != ACL_DBH_STATUS_INUSE || mysql_handle->connection == NULL) {
		acl_msg_error("%s, %s(%d): status %s ACL_DBH_STATUS_INUSE, connection %s",
			__FILE__, myname, __LINE__,
			db_handle->status == ACL_DBH_STATUS_INUSE ? "=" : "!=",
			mysql_handle->connection ? "not null" : "null");
		return;
	}

	db_pool = db_handle->parent;
	if (db_pool == NULL)
		acl_msg_fatal("%s, %s(%d): db_handle's parent is null",
				__FILE__, myname, __LINE__);
	mysql_pool = (ACL_DB_POOL_MYSQL *) db_pool;

	DB_LOCK(mysql_pool->mutex);

	__close_mysql_handle(mysql_handle);
	db_pool->db_inuse--;

	DB_UNLOCK(mysql_pool->mutex);
}
Beispiel #4
0
void ydb_prefetch(YDB ydb, char **keys, unsigned short *key_szs, int items_counter) {
	struct db *db = (struct db *) ydb;
	assert(db->magic == YDB_STRUCT_MAGIC);

	struct item **items_start = (struct item **)malloc(sizeof(struct item_index *) * items_counter);
	struct item **items = items_start;
	DB_LOCK(db);
	int i;
	for(i=0; i < items_counter; i++, keys++, key_szs++) {
		char *key = *keys;
		int key_sz = *key_szs;
		struct item *item = tree_get(db->tree, key, key_sz);
		if(item) {
			*items = item;
			items++;
		}
		
	}
	DB_UNLOCK(db);
	
	int items_sz = items - items_start;
	qsort(items_start, items_sz, sizeof(struct item *), item_cmp);
	
	items = items_start;
	int fd = -1;
	int count = 0;
	int offset = 0;
	for(i=0; i < items_sz; i++, items++) {
		struct item *item = *items;
		
		struct log *log = slot_get(db->loglist, item->logno);
		
		size_t read_size = ROUND_UP(item->value_sz, PADDING) + sizeof(struct ydb_value_record);
		
		/* merge? */
		if(fd == log->fd  &&  (offset + count + 4096) >= item->value_offset) {
			count = (item->value_offset+read_size) - offset;
		}else{
			if(fd != log->fd) {
				/* clear previous fadvices */
				posix_fadvise(log->fd, 0, 0, POSIX_FADV_RANDOM);
			}
			if(fd != -1) {
				posix_fadvise(fd, offset, count, POSIX_FADV_WILLNEED);
			}
			fd = log->fd;
			count = read_size;
			offset = item->value_offset;
		}
	}
	if(fd != -1) {
		posix_fadvise(fd, offset, count, POSIX_FADV_WILLNEED);
	}
	
	free(items_start);
}
Beispiel #5
0
int ydb_get_keys(YDB ydb, char *key, unsigned short key_sz,
		 char *buf, int buf_sz) {
	struct db *db = (struct db *) ydb;
	assert(db->magic == YDB_STRUCT_MAGIC);

	DB_LOCK(db);
	int r = tree_get_keys(db->tree, key, key_sz, buf, buf_sz);
	DB_UNLOCK(db);
	return(r);
}
Beispiel #6
0
int ydb_del(YDB ydb, char *key, unsigned short key_sz) {
	struct db *db = (struct db *) ydb;
	assert(db->magic == YDB_STRUCT_MAGIC);
	
	DB_LOCK(db);
	struct append_info af;
	af = loglist_append(db->loglist, key, key_sz, NULL, 0, FLAG_DELETE);
	tree_del(db->tree, key, key_sz, af.logno, af.record_offset);
	DB_UNLOCK(db);
	return(-1);
}
Beispiel #7
0
int ydb_add(YDB ydb, char *key, unsigned short key_sz,
	    char *value, unsigned int value_sz) {
	struct db *db = (struct db *) ydb;
	assert(db->magic == YDB_STRUCT_MAGIC);
	
	if(value_sz > MAX_VALUE_SIZE)
		return(-1);

	/* TODO: error handling on write? */
	DB_LOCK(db);
	if(db_add(db, key, key_sz, value, value_sz) < 0) {
		value_sz = -1;
		goto release;
	}
	
	if(db->gc_finished) {
		gc_join(db);
	}
release:
	DB_UNLOCK(db);
	return(value_sz);
}
Beispiel #8
0
/*----------------------------------------------------------------------------*/
static void __dbpool_mysql_release(ACL_DB_HANDLE *db_handle)
{
	char  myname[] = "__dbpool_mysql_release";
	ACL_DB_POOL *db_pool;
	ACL_DB_POOL_MYSQL *mysql_pool;
	ACL_DB_HANDLE_MYSQL *mysql_handle;
	int   timeout_inter, ping_inter;

	mysql_handle = (ACL_DB_HANDLE_MYSQL *) db_handle;
	if (db_handle->status != ACL_DBH_STATUS_INUSE || mysql_handle->connection == NULL) {
		acl_msg_error("%s, %s(%d): status %s ACL_DBH_STATUS_INUSE, connection %s",
			__FILE__, myname, __LINE__,
			db_handle->status == ACL_DBH_STATUS_INUSE ? "=" : "!=",
			mysql_handle->connection ? "not null" : "null");
		return;
	}

	db_pool = db_handle->parent;
	timeout_inter = db_pool->db_info.timeout_inter;
	ping_inter = db_pool->db_info.ping_inter;

	if (db_pool == NULL)
		acl_msg_fatal("%s, %s(%d): db_handle's parent is null",
				__FILE__, myname, __LINE__);

	mysql_pool = (ACL_DB_POOL_MYSQL *) db_pool;
	DB_LOCK(mysql_pool->mutex);

	db_handle->status  = ACL_DBH_STATUS_READY;
	db_handle->timeout = time(NULL) + timeout_inter;
	db_handle->ping    = time(NULL) + ping_inter;

	db_pool->db_inuse--;
	db_pool->db_ready++;

	DB_UNLOCK(mysql_pool->mutex);
}
Beispiel #9
0
/*----------------------------------------------------------------------------*/
static ACL_DB_HANDLE *__dbpool_mysql_peek(ACL_DB_POOL *db_pool)
{
	char  myname[] = "__dbpool_mysql_peek";
	ACL_DB_POOL_MYSQL *mysql_pool = (ACL_DB_POOL_MYSQL *) db_pool;
	ACL_DB_HANDLE_MYSQL *mysql_handle, *mysql_handle_slot = NULL;
	int   i, n;
	time_t now;
	static time_t last_time;  /* 因为在调用此函数时已经上锁,
				   * 所以此处声明一静态变量是线程安全的.
				   */

#undef	RETURN
#define	RETURN(_x_) do { \
	now = time(NULL); \
	if (acl_msg_verbose && now - last_time > 5) { \
		acl_msg_info("Database status: max = %d, idle = %d, busy = %d", \
				db_pool->db_max, db_pool->db_ready, db_pool->db_inuse); \
		last_time = now; \
	} \
	DB_UNLOCK(mysql_pool->mutex); \
	return (_x_); \
} while (0)

	DB_LOCK(mysql_pool->mutex);

	if (time(NULL) >= mysql_pool->when_check) {
		int   inter = db_pool->db_info.ping_inter > db_pool->db_info.timeout_inter
			? db_pool->db_info.timeout_inter : db_pool->db_info.ping_inter;

		db_pool->dbh_check(db_pool);
		mysql_pool->when_check = time(NULL) + inter;
	}


	if (db_pool->db_inuse >= db_pool->db_max) {
		acl_msg_warn("%s, %s(%d): all connections be used, reached db_max(%d)",
				__FILE__, myname, __LINE__, db_pool->db_max);
		RETURN (NULL);
	}

	n = acl_array_size(mysql_pool->handles);

	/* lookup mysql connection from pool */
	for (i = 0; i < n; i++) {
		mysql_handle = (ACL_DB_HANDLE_MYSQL *)
			acl_array_index(mysql_pool->handles, i);

		if (mysql_handle == NULL)
			continue;

		if (mysql_handle->handle.status == ACL_DBH_STATUS_READY) {
			mysql_handle->handle.status = ACL_DBH_STATUS_INUSE;
			db_pool->db_inuse++;
			db_pool->db_ready--;

			RETURN ((ACL_DB_HANDLE *) mysql_handle);
		} else if (mysql_handle->handle.status == ACL_DBH_STATUS_NULL
			   && mysql_handle_slot == NULL)
			mysql_handle_slot = mysql_handle;
	}

	/* create new mysql connection */

	mysql_handle = __open_mysql_handle(mysql_pool, mysql_handle_slot, &db_pool->db_info);
	if (mysql_handle == NULL)
		RETURN (NULL);

	mysql_handle->handle.status = ACL_DBH_STATUS_INUSE;
	db_pool->db_inuse++;
	
	RETURN ((ACL_DB_HANDLE *) mysql_handle);
}