void
extkey_cache_destroy(extkey_cache_t *cache)
{
    ham_size_t i;
    extkey_t *e, *n;
    ham_db_t *db=extkey_cache_get_db(cache);
	ham_env_t *env = db_get_env(db);

    /*
     * make sure that all entries are empty
     */
    for (i=0; i<extkey_cache_get_bucketsize(cache); i++) {
        e=extkey_cache_get_bucket(cache, i);
        while (e) {
#if HAM_DEBUG
            /*
             * make sure that the extkey-cache is empty - only for in-memory
             * databases and DEBUG builds.
             */
            if (env_get_rt_flags(env)&HAM_IN_MEMORY_DB)
                ham_assert(!"extkey-cache is not empty!", (0));
#endif
            n=extkey_get_next(e);
            allocator_free(env_get_allocator(env), e);
            e=n;
        }
    }

    allocator_free(env_get_allocator(env), cache);
}
Beispiel #2
0
ham_status_t 
blob_duplicate_get(ham_env_t *env, ham_offset_t table_id,
        ham_size_t position, dupe_entry_t *entry)
{
	ham_status_t st;
    dupe_table_t *table;
    ham_page_t *page=0;

    st = __get_duplicate_table(&table, &page, env, table_id);
	ham_assert(st ? table == NULL : 1, (0));
	ham_assert(st ? page == NULL : 1, (0));
    if (!table)
		return st ? st : HAM_INTERNAL_ERROR;

    if (position>=dupe_table_get_count(table)) 
	{
        if (!(env_get_rt_flags(env)&HAM_IN_MEMORY_DB))
            if (!page)
                allocator_free(env_get_allocator(env), table);
        return HAM_KEY_NOT_FOUND;
    }
    memcpy(entry, dupe_table_get_entry(table, position), sizeof(*entry));

    if (!(env_get_rt_flags(env)&HAM_IN_MEMORY_DB))
	{
        if (!page)
            allocator_free(env_get_allocator(env), table);
	}
    return (0);
}
/*
 * when the last hit leaf node is split or shrunk, blow it away for all operations!
 *
 * Also blow away a page when a transaction aborts which has modified this page. We'd rather
 * reconstruct our critical statistics then carry the wrong bounds, etc. around.
 *
 * This is done to prevent the hinter from hinting/pointing at an (by now)
 * INVALID btree node later on!
 */
void 
stats_page_is_nuked(ham_db_t *db, struct ham_page_t *page, ham_bool_t split)
{
    ham_runtime_statistics_dbdata_t *dbdata = db_get_db_perf_data(db);
    ham_env_t *env = db_get_env(db);
    int i;

    for (i = 0; i <= 2; i++)
    {
        ham_runtime_statistics_opdbdata_t *opstats = db_get_op_perf_data(db, i);

        ham_assert(i == HAM_OPERATION_STATS_FIND
                    || i == HAM_OPERATION_STATS_INSERT
                    || i == HAM_OPERATION_STATS_ERASE, (0));

        if (opstats->btree_last_page_addr == page_get_self(page))
        {
            opstats->btree_last_page_addr = 0;
            opstats->btree_last_page_sq_hits = 0;
        }
    }

    if (dbdata->lower_bound_page_address == page_get_self(page))
    {
        if (dbdata->lower_bound.data)
        {
            ham_assert(env_get_allocator(env) != 0, (0));
            allocator_free(env_get_allocator(env), dbdata->lower_bound.data);
        }
        memset(&dbdata->lower_bound, 0, sizeof(dbdata->lower_bound));
        dbdata->lower_bound_index = 0;
        dbdata->lower_bound_page_address = 0;
        dbdata->lower_bound_set = HAM_FALSE;
    }

	if (dbdata->upper_bound_page_address == page_get_self(page))
    {
        if (dbdata->upper_bound.data)
        {
            ham_assert(env_get_allocator(env) != 0, (0));
            allocator_free(env_get_allocator(env), dbdata->upper_bound.data);
        }
        memset(&dbdata->upper_bound, 0, sizeof(dbdata->upper_bound));
        dbdata->upper_bound_index = 0;
        dbdata->upper_bound_page_address = 0;
        dbdata->upper_bound_set = HAM_FALSE;
    }
}
ham_status_t
extkey_cache_remove(extkey_cache_t *cache, ham_offset_t blobid)
{
	ham_db_t *db=extkey_cache_get_db(cache);
	ham_env_t *env = db_get_env(db);
    ham_size_t h=my_calc_hash(cache, blobid);
    extkey_t *e, *prev=0;

    e=extkey_cache_get_bucket(cache, h);
    while (e) {
        if (extkey_get_blobid(e)==blobid)
            break;
        prev=e;
        e=extkey_get_next(e);
    }

    if (!e)
        return (HAM_KEY_NOT_FOUND);

    if (prev)
        extkey_set_next(prev, extkey_get_next(e));
    else
        extkey_cache_set_bucket(cache, h, extkey_get_next(e));

    extkey_cache_set_usedsize(cache, 
            extkey_cache_get_usedsize(cache)-extkey_get_size(e));
    allocator_free(env_get_allocator(env), e);

    return (0);
}
Beispiel #5
0
static void _ensure_allocator_traced_free_copes_with_null_parent_allocator( void )
{
	int x = 0;
	allocator_traced_t alloc;
	allocator_traced_init( &alloc, 0, stdout );
	allocator_free( &x, allocator_traced_get( &alloc ) );
}
void
stats_trash_dbdata(ham_db_t *db, ham_runtime_statistics_dbdata_t *dbdata)
{
    ham_env_t *env = db_get_env(db);

    /* trash the upper/lower bound keys, when set: */
    if (dbdata->upper_bound.data) {
        ham_assert(env_get_allocator(env) != 0, (0));
        allocator_free(env_get_allocator(env), dbdata->upper_bound.data);
    }
    if (dbdata->lower_bound.data) {
        ham_assert(env_get_allocator(env) != 0, (0));
        allocator_free(env_get_allocator(env), dbdata->lower_bound.data);
    }
    memset(dbdata, 0, sizeof(*dbdata));
}
Beispiel #7
0
//************************************************************************//
//* free memory allocated from the av heap.
//************************************************************************//
void av_heap_free(void* vaddr)
{
    int            block_idx;
    unsigned char* paddr;
    int            offset;

    if(heap_ctx == NULL)
    {
        loge("av heap not initialized yet.");
        return;
    }

    pthread_mutex_lock(&heap_ctx->mutex);

    block_idx = av_heap_find_block_by_vaddr(heap_ctx, vaddr);
    if(block_idx < 0)
    {
        loge("can not find a block of specific virtual address %x.", vaddr);
        pthread_mutex_unlock(&heap_ctx->mutex);
        return;
    }

    paddr  = (unsigned char*)heap_ctx->block_info[block_idx].paddr;
    offset = (int)(paddr - (heap_ctx->env_info.phymem_start & 0x3fffffff));

    munmap(heap_ctx->block_info[block_idx].vaddr, heap_ctx->block_info[block_idx].size);

    allocator_free(heap_ctx->allocator, offset);

    memset(&heap_ctx->block_info[block_idx], 0, sizeof(block_info_t));

    pthread_mutex_unlock(&heap_ctx->mutex);

    return;
}
Beispiel #8
0
/* user logout, client timeout or something error, we need to
 * close the connection and release resource */
void close_connection(struct conn_server *server, struct connection *conn)
{
	/* remove from fd-conn hash map */
	close(conn->sfd);

	struct fd_entry *fd_entry;
	HASH_FIND_INT(server->fd_conn_map, &conn->sfd, fd_entry);
	if (fd_entry) {
		HASH_DEL(server->fd_conn_map, fd_entry);
		free(fd_entry);
	}

	/* remove from uin-conn hash map */
	struct uin_entry *uin_entry;
	HASH_FIND_INT(server->uin_conn_map, &conn->uin, uin_entry);
	if (uin_entry) {
		HASH_DEL(server->uin_conn_map, uin_entry);
		free(uin_entry);
	}

	/* remove from timer */
	timer_del(conn);
	conn_destroy(server, conn);

	/* free the conn struct */
	allocator_free(&server->conn_allocator, conn);
}
Beispiel #9
0
static lua_matrix_t * create_matrix(int lig, int col)
{
  lua_matrix_def_t * md = 0;
  lua_matrix_t *m = 0;
  int size;

  if (lig <= 0 || col <= 0) {
    return 0;
  }

  size = sizeof(lua_matrix_def_t)
    + sizeof(float)*(lig*col)
    - sizeof(md->v);

  md = allocator_alloc(matrixdef_allocator, size);
  if (md) {
    md->refcount = 1;
    md->l = lig;
    md->c = col;
  }
  m = allocator_alloc(matrixref_allocator, sizeof(*m));
  if (!m) {
    allocator_free(matrixdef_allocator, md);
  } else {
    m->md = md;
    m->li = 0;
  }
  return m;
}
ham_status_t
extkey_cache_purge(extkey_cache_t *cache)
{
    ham_size_t i;
    extkey_t *e, *n;
    ham_env_t *env;
	
	ham_assert(extkey_cache_get_db(cache), (0));
	env = db_get_env(extkey_cache_get_db(cache));

    /*
     * delete all entries which are "too old" (were not 
     * used in the last EXTKEY_MAX_AGE transactions)
     */
    for (i=0; i<extkey_cache_get_bucketsize(cache); i++) {
        extkey_t *p=0;
        e=extkey_cache_get_bucket(cache, i);
        while (e) {
            n=extkey_get_next(e);
            if (env_get_txn_id(env)-extkey_get_txn_id(e)>EXTKEY_MAX_AGE) {
                /* deleted the head element of the list? */
                if (!p)
                    extkey_cache_set_bucket(cache, i, n);
                else
                    extkey_set_next(p, n);
                allocator_free(env_get_allocator(env), e);
            }
            else
                p=e;
            e=n;
        }
    }

    return (0);
}
Beispiel #11
0
static ham_status_t
_remote_fun_txn_abort(ham_env_t *env, ham_txn_t *txn, ham_u32_t flags)
{
    ham_status_t st;
    proto_wrapper_t *request, *reply;

    request=proto_init_txn_abort_request(txn_get_remote_handle(txn), flags);
    
    st=_perform_request(env, env_get_curl(env), request, &reply);
    proto_delete(request);
    if (st) {
        if (reply)
            proto_delete(reply);
        return (st);
    }

    ham_assert(reply!=0, (""));
    ham_assert(proto_has_txn_abort_reply(reply), (""));

    st=proto_txn_abort_reply_get_status(reply);

    if (st==0) {
        memset(txn, 0, sizeof(*txn));
        allocator_free(env_get_allocator(env), txn);

        /* remove the link between env and txn */
    	env_set_txn(env, 0);
    }

    proto_delete(reply);

    return (st);
}
Beispiel #12
0
static void _ensure_allocator_traced_alloc_returns_valid_memory_for_nonempty_allocation( void )
{
	void * mem;
	allocator_traced_t alloc;
	allocator_traced_init_stdout( &alloc, allocator_default( ) );
	mem = allocator_alloc( 1024, allocator_traced_get( &alloc ) );
	TEST_REQUIRE( mem != 0 );
	allocator_free( mem, allocator_traced_get( &alloc ) );
}
Beispiel #13
0
void cmd_logout(struct conn_server *server, struct connection *conn,
		struct list_packet *packet)
{
	allocator_free(&server->packet_allocator, packet);

	/* send status change command to status server */
	send_offline_to_status(server, get_uin(packet));
	close_connection(server, conn);
}
Beispiel #14
0
int main(int argc, char* argv[])
{
	int i = 0;
	int n = 100;
	Allocator* allocator = allocator_normal_create();

	for(i = 0; i < n; i++)
	{
		char* ptr = allocator_alloc(allocator, i);
		ptr = allocator_realloc(allocator, ptr, i+4);
		allocator_free(allocator, ptr);
		ptr = allocator_calloc(allocator, i+4, 4);
		allocator_free(allocator, ptr);
	}
	
	allocator_destroy(allocator);

	return 0;
}
Beispiel #15
0
/* this function ONLY removes the packets, does not remove the timer */
void conn_destroy(struct conn_server *server, struct connection *conn)
{
	/* remove recv packets */
	struct list_head *head = &conn->recv_packet_list;
	struct list_packet *p;
	while (!list_empty(head)) {
		p = list_first_entry(head, struct list_packet, list);
		list_del(&p->list);
		allocator_free(&server->packet_allocator, p);
	}

	/* remove send packets */
	head = &conn->send_packet_list;
	while (!list_empty(head)) {
		p = list_first_entry(head, struct list_packet, list);
		list_del(&p->list);
		allocator_free(&server->packet_allocator, p);
	}
}
Beispiel #16
0
/** @fn DataBuffer_t::~DataBuffer_t()
*/
DataBuffer_t::~DataBuffer_t()
{

    mutex_deinit(&mBuffLock);

#ifndef DVP_USE_ION
    FREE_IF_PRESENT( pData )
#else
    allocator_free(pAllocator, ALLOCATOR_MEMORY_TYPE_TILED_1D_UNCACHED, 1, &pData, handles);
    allocator_deinit(&pAllocator);
#endif // DVP_USE_ION
}
Beispiel #17
0
//*************************************************************************//
//* allocate memory from the av heap.
//*************************************************************************//
void* av_heap_alloc(int size)
{
    int 		 offset;
    int 		 block_idx;
    unsigned int paddr;

    if(size <= 0)
    {
        loge("request memory of invalid size %d.", size);
        return NULL;
    }

    if(heap_ctx == NULL)
    {
        loge("av heap not initialized yet, return fail.");
        return NULL;
    }

    pthread_mutex_lock(&heap_ctx->mutex);

    offset = allocator_alloc(heap_ctx->allocator, size);
    if(offset < 0)
    {
        loge("av heap out of memory.");
        pthread_mutex_unlock(&heap_ctx->mutex);

        return NULL;
    }

    paddr = offset + heap_ctx->env_info.phymem_start;

    block_idx = av_heap_get_a_free_block(heap_ctx);
    if(block_idx < 0)
    {
        loge("av heap can not get a free block, return fail.");

        allocator_free(heap_ctx->allocator, offset);
        pthread_mutex_unlock(&heap_ctx->mutex);

        return NULL;
    }

    heap_ctx->block_info[block_idx].vaddr   = (void*)mmap(0, size, PROT_READ | PROT_WRITE, MAP_SHARED, heap_ctx->fd, paddr);
    heap_ctx->block_info[block_idx].paddr   = (void*)(paddr & 0x3fffffff);
    heap_ctx->block_info[block_idx].size    = size;
    heap_ctx->block_info[block_idx].is_used = 1;

    pthread_mutex_unlock(&heap_ctx->mutex);

    printf("av heap alloc\n"); 
    return heap_ctx->block_info[block_idx].vaddr;
}
Beispiel #18
0
/* other kind of packet, check clienti's login type,
 * if login ok, send the packet to client */
void srv_other_packet(struct conn_server *server, struct list_packet *packet)
{
	uint32_t uin = get_uin(packet);
	struct connection *conn = get_conn_by_uin(server, uin);
	/* need to check login status */
	if (!conn || conn->type != LOGIN_OK_CONNECTION) {
		allocator_free(&server->packet_allocator, packet);
		return;
	}

	list_add_tail(&packet->list, &conn->send_packet_list);
	wait_for_write(server->efd, conn->sfd);
}
Beispiel #19
0
/* client login successful, we mark the conn as login_ok,
 * and send the packet to client */
void srv_login_ok(struct conn_server *server, struct list_packet *packet)
{
	uint32_t uin = get_uin(packet);
	struct connection *conn = get_conn_by_uin(server, uin);
	if (!conn) {
		allocator_free(&server->packet_allocator, packet);
		return;
	}

	conn->type = LOGIN_OK_CONNECTION;
	list_add_tail(&packet->list, &conn->send_packet_list);
	wait_for_write(server->efd, conn->sfd);
}
Beispiel #20
0
static size_t
__writefunc(void *buffer, size_t size, size_t nmemb, void *ptr)
{
    curl_buffer_t *buf=(curl_buffer_t *)ptr;
    char *cbuf=(char *)buffer;
    ham_size_t payload_size=0;

    if (buf->offset==0) {
        if (*(ham_u32_t *)&cbuf[0]!=ham_db2h32(HAM_TRANSFER_MAGIC_V1)) {
            ham_trace(("invalid protocol version"));
            return (0);
        }
        payload_size=ham_h2db32(*(ham_u32_t *)&cbuf[4]);

        /* did we receive the whole data in this packet? */
        if (payload_size+8==size*nmemb) {
            buf->wrapper=proto_unpack((ham_size_t)(size*nmemb), 
                        (ham_u8_t *)&cbuf[0]);
            if (!buf->wrapper)
                return (0);
            return (size*nmemb);
        }

        /* otherwise we have to buffer the received data */
        buf->packed_size=payload_size+8;
        buf->packed_data=allocator_alloc(buf->alloc, buf->packed_size);
        if (!buf->packed_data)
            return (0);
        memcpy(buf->packed_data, &cbuf[0], size*nmemb);
        buf->offset+=(ham_size_t)(size*nmemb);
    }
    /* append to an existing buffer? */
    else {
        memcpy(buf->packed_data+buf->offset, &cbuf[0], size*nmemb);
        buf->offset+=(ham_size_t)(size*nmemb);
    }

    /* check if we've received the whole data */
    if (buf->offset==buf->packed_size) {
        buf->wrapper=proto_unpack(buf->packed_size, buf->packed_data);
        if (!buf->wrapper)
            return (0);
        allocator_free(buf->alloc, buf->packed_data);
        if (!buf->wrapper)
            return 0;
    }

    return (size*nmemb);
}
Beispiel #21
0
static ham_status_t
_remote_fun_txn_begin(ham_env_t *env, ham_db_t *db, 
                ham_txn_t **txn, ham_u32_t flags)
{
    ham_status_t st;
    proto_wrapper_t *request, *reply;
    
    request=proto_init_txn_begin_request(db_get_remote_handle(db), flags);

    st=_perform_request(env, env_get_curl(env), request, &reply);
    proto_delete(request);
    if (st) {
        if (reply)
            proto_delete(reply);
        return (st);
    }

    ham_assert(reply!=0, (""));
    ham_assert(proto_has_txn_begin_reply(reply), (""));

    st=proto_txn_begin_reply_get_status(reply);
    if (st) {
        proto_delete(reply);
        return (st);
    }

    *txn=(ham_txn_t *)allocator_alloc(env_get_allocator(env), 
                            sizeof(ham_txn_t));
    if (!(*txn))
        return (HAM_OUT_OF_MEMORY);

    st=txn_begin(*txn, env, flags);
    if (st) {
        allocator_free(env_get_allocator(env), *txn);
        *txn=0;
    }
    else {
        txn_set_remote_handle(*txn, 
                    proto_txn_begin_reply_get_txn_handle(reply));
    }

    proto_delete(reply);

    return (st);
}
Beispiel #22
0
ham_status_t
blob_free(ham_env_t *env, ham_db_t *db, ham_offset_t blobid, ham_u32_t flags)
{
    ham_status_t st;
    blob_t hdr;

    /*
     * in-memory-database: the blobid is actually a pointer to the memory
     * buffer, in which the blob is stored
     */
    if (env_get_rt_flags(env)&HAM_IN_MEMORY_DB) {
        allocator_free(env_get_allocator(env), (void *)U64_TO_PTR(blobid));
        return (0);
    }

    ham_assert(blobid%DB_CHUNKSIZE==0, (0));

    /*
     * fetch the blob header 
     */
    st=__read_chunk(env, 0, 0, blobid, (ham_u8_t *)&hdr, sizeof(hdr));
    if (st)
        return (st);

    ham_assert(blob_get_alloc_size(&hdr)%DB_CHUNKSIZE==0, (0));

    /*
     * sanity check
     */
    ham_assert(blob_get_self(&hdr)==blobid, 
            ("invalid blobid %llu != %llu", blob_get_self(&hdr), blobid));
    if (blob_get_self(&hdr)!=blobid)
        return (HAM_BLOB_NOT_FOUND);

    /*
     * move the blob to the freelist
     */
    st = freel_mark_free(env, db, blobid, 
            (ham_size_t)blob_get_alloc_size(&hdr), HAM_FALSE);
	ham_assert(!st, ("unexpected error, at least not covered in the old code"));

    return st;
}
Beispiel #23
0
/* client packet handler */
void cmd_packet_handler(struct conn_server *server, struct connection *conn,
		struct list_packet *packet)
{
	uint16_t command = get_command(packet);
	/* check login status */
	if (conn->type != LOGIN_OK_CONNECTION &&
			command != CMD_LOGIN) {
		/* the client not login, ignore this packet */
		allocator_free(&server->packet_allocator, packet);
		return;
	}

	switch (command) {
	case CMD_KEEP_ALIVE:
		cmd_keep_alive(server, conn, packet);
		break;
	case CMD_LOGIN:
		cmd_login(server, conn, packet);
		break;
	case CMD_LOGOUT:
		cmd_logout(server, conn, packet);
		break;
	case CMD_SET_NICK:
		cmd_user(server, conn, packet);
		break;
	case CMD_ADD_CONTACT:
	case CMD_ADD_CONTACT_REPLY:
	case CMD_CONTACT_LIST:
	case CMD_CONTACT_INFO_MULTI:
		cmd_contact(server, conn, packet);
		break;
	case CMD_MESSAGE:
	case CMD_OFFLINE_MSG:
		cmd_message(server, conn, packet);
		break;
	default:
		log_err("unkonwn command %#hx\n", command);
		break;
	}
}
Beispiel #24
0
int
HashmapExercise(int verbose, struct cfg *cfg, char *args[])
{
	struct hashmap *h;
    int rate = 0, i, n = 0;
	int count = atoi(args[0]);
	int interval = atoi(args[1]);
	iter_t riter;
	iter_t iter;
	char *str;
	struct allocator *al = NULL;
	char *mem;
	clock_t t0;
	int chkpnt = 0;
	struct allocator *hal;

	if ((mem = malloc(0xFFFFFF)) == NULL ||
			(al = suba_init(mem, 0xFFFFFF, 1, 0)) == NULL ||
			(h = hashmap_new(hash_str, cmp_str, NULL, al)) == NULL) {
		AMSG("");
		return -1;
	}
	hal = AL(h);

/*
	if ((h = hashmap_new(hash_str, cmp_str, NULL, al)) == NULL) {
		AMSG("");
		return -1;
	}
*/
srand(0);

	t0 = clock();
if (verbose)
fprintf(stderr, "\n       time    count     size      mem\n");

	hashmap_iterate(h, &iter);
	rate_iterate(&riter);
	for (i = 0; i < count; i++) {
		if ((i % interval) == 0) {
if (verbose)
fprintf(stderr, "%2d %8ld %8d %8d %8d\n", chkpnt++, (clock() - t0) / 1000, hashmap_size(h), table_sizes[h->table_size_index], hal->alloc_total - hal->free_total);
			rate = rate_next(&riter);
		}

		if (rand() % 10 < rate) {
	        str = allocator_alloc(NULL, 8, 0);
	        sprintf(str, "%07d", n++);
	        if (hashmap_put(h, str, str) == -1) {
				AMSG("");
				return -1;
			} else {
/*fputc('+', stderr);
*/
	 	      	tcase_printf(verbose, "put %s %d\r", str, hashmap_size(h));
			}
		} else {
			if (hashmap_is_empty(h)) {
/*fputc('0', stderr);
*/
				tcase_printf(verbose, "hashmap empty\r");
			} else {
		        str = hashmap_next(h, &iter);
				if (str) {
					char *data;

	    	    	tcase_printf(verbose, "get %s %d\r", str, hashmap_size(h));
					if (hashmap_remove(h, (void **)&str, (void **)&data) == -1) {
						AMSG("");
						return -1;
					}
/*fputc('-', stderr);
*/
					tcase_printf(verbose, "rem %s %d\r", str, hashmap_size(h));
					allocator_free(NULL, str);
				} else {
/*fputc('x', stderr);
*/
					tcase_printf(verbose, "nothing left to iterate over\r");
					hashmap_iterate(h, &iter);
				}
			}
		}
    }

if (verbose)
fprintf(stderr, "%2d %8ld %8d %8d %8d\n", chkpnt++, (clock() - t0) / 1000, hashmap_size(h), table_sizes[h->table_size_index], hal->alloc_total - hal->free_total);
	hashmap_del(h, allocator_free, NULL, NULL);
/*
	free(mem);
*/
if (verbose)
fprintf(stderr, "bytes outstanding from allocator: %d\n", hal->alloc_total - hal->free_total);

	cfg = NULL;
    return 0;
}
Beispiel #25
0
ham_status_t
blob_overwrite(ham_env_t *env, ham_db_t *db, ham_offset_t old_blobid, 
        ham_record_t *record, ham_u32_t flags, ham_offset_t *new_blobid)
{
    ham_status_t st;
    ham_size_t alloc_size;
    blob_t old_hdr;
    blob_t new_hdr;
    ham_page_t *page;

    /*
     * PARTIAL WRITE
     * 
     * if offset+partial_size equals the full record size, then we won't 
     * have any gaps. In this case we just write the full record and ignore
     * the partial parameters.
     */
    if (flags&HAM_PARTIAL) {
        if (record->partial_offset==0 
                && record->partial_offset+record->partial_size==record->size)
            flags&=~HAM_PARTIAL;
    }

    /*
     * inmemory-databases: free the old blob, 
     * allocate a new blob (but if both sizes are equal, just overwrite
     * the data)
     */
    if (env_get_rt_flags(env)&HAM_IN_MEMORY_DB) 
    {
        blob_t *nhdr, *phdr=(blob_t *)U64_TO_PTR(old_blobid);

        if (blob_get_size(phdr)==record->size) {
            ham_u8_t *p=(ham_u8_t *)phdr;
            if (flags&HAM_PARTIAL) {
                memmove(p+sizeof(blob_t)+record->partial_offset, 
                        record->data, record->partial_size);
            }
            else {
                memmove(p+sizeof(blob_t), record->data, record->size);
            }
            *new_blobid=(ham_offset_t)PTR_TO_U64(phdr);
        }
        else {
            st=blob_allocate(env, db, record, flags, new_blobid);
            if (st)
                return (st);
            nhdr=(blob_t *)U64_TO_PTR(*new_blobid);
            blob_set_flags(nhdr, blob_get_flags(phdr));

            allocator_free(env_get_allocator(env), phdr);
        }

        return (HAM_SUCCESS);
    }

    ham_assert(old_blobid%DB_CHUNKSIZE==0, (0));

    /*
     * blobs are CHUNKSIZE-allocated 
     */
    alloc_size=sizeof(blob_t)+record->size;
    alloc_size += DB_CHUNKSIZE - 1;
    alloc_size -= alloc_size % DB_CHUNKSIZE;

    /*
     * first, read the blob header; if the new blob fits into the 
     * old blob, we overwrite the old blob (and add the remaining
     * space to the freelist, if there is any)
     */
    st=__read_chunk(env, 0, &page, old_blobid, (ham_u8_t *)&old_hdr, 
            sizeof(old_hdr));
    if (st)
        return (st);

    ham_assert(blob_get_alloc_size(&old_hdr)%DB_CHUNKSIZE==0, (0));

    /*
     * sanity check
     */
    ham_verify(blob_get_self(&old_hdr)==old_blobid, 
            ("invalid blobid %llu != %llu", blob_get_self(&old_hdr), 
            old_blobid));
    if (blob_get_self(&old_hdr)!=old_blobid)
        return (HAM_BLOB_NOT_FOUND);

    /*
     * now compare the sizes; does the new data fit in the old allocated
     * space?
     */
    if (alloc_size<=blob_get_alloc_size(&old_hdr)) 
    {
        ham_u8_t *chunk_data[2];
        ham_size_t chunk_size[2];

        /* 
         * setup the new blob header
         */
        blob_set_self(&new_hdr, blob_get_self(&old_hdr));
        blob_set_size(&new_hdr, record->size);
        blob_set_flags(&new_hdr, blob_get_flags(&old_hdr));
        if (blob_get_alloc_size(&old_hdr)-alloc_size>SMALLEST_CHUNK_SIZE)
            blob_set_alloc_size(&new_hdr, alloc_size);
        else
            blob_set_alloc_size(&new_hdr, blob_get_alloc_size(&old_hdr));

        /*
         * PARTIAL WRITE
         *
         * if we have a gap at the beginning, then we have to write the
         * blob header and the blob data in two steps; otherwise we can
         * write both immediately
         */
        if ((flags&HAM_PARTIAL) && (record->partial_offset)) {
            chunk_data[0]=(ham_u8_t *)&new_hdr;
            chunk_size[0]=sizeof(new_hdr);
            st=__write_chunks(env, page, blob_get_self(&new_hdr), HAM_FALSE,
                    HAM_FALSE, chunk_data, chunk_size, 1);
            if (st)
                return (st);

            chunk_data[0]=record->data;
            chunk_size[0]=record->partial_size;
            st=__write_chunks(env, page, 
                    blob_get_self(&new_hdr)+sizeof(new_hdr)
                            +record->partial_offset, 
                    HAM_FALSE, HAM_FALSE, chunk_data, chunk_size, 1);
            if (st)
                return (st);
        }
        else {
            chunk_data[0]=(ham_u8_t *)&new_hdr;
            chunk_size[0]=sizeof(new_hdr);
            chunk_data[1]=record->data;
            chunk_size[1]=(flags&HAM_PARTIAL) 
                                ? record->partial_size 
                                : record->size;

            st=__write_chunks(env, page, blob_get_self(&new_hdr), HAM_FALSE,
                    HAM_FALSE, chunk_data, chunk_size, 2);
            if (st)
                return (st);
        }

        /*
         * move remaining data to the freelist
         */
        if (blob_get_alloc_size(&old_hdr)!=blob_get_alloc_size(&new_hdr)) {
            (void)freel_mark_free(env, db,
                  blob_get_self(&new_hdr)+blob_get_alloc_size(&new_hdr), 
                  (ham_size_t)(blob_get_alloc_size(&old_hdr)-
                  blob_get_alloc_size(&new_hdr)), HAM_FALSE);
        }

        /*
         * the old rid is the new rid
         */
        *new_blobid=blob_get_self(&new_hdr);

        return (HAM_SUCCESS);
    }
    else {
        /* 
         * when the new data is larger, allocate a fresh space for it 
         * and discard the old;
         'overwrite' has become (delete + insert) now.
         */
        st=blob_allocate(env, db, record, flags, new_blobid);
        if (st)
            return (st);

        (void)freel_mark_free(env, db, old_blobid, 
                (ham_size_t)blob_get_alloc_size(&old_hdr), HAM_FALSE);
    }

    return (HAM_SUCCESS);
}
Beispiel #26
0
/**
 * Allocate space in storage for and write the content references by 'data'
 * (and length 'size') to storage.
 * 
 * Conditions will apply whether the data is written through cache or direct
 * to device.
 * 
 * The content is, of course, prefixed by a BLOB header.
 * 
 * Partial writes are handled in this function.
 */
ham_status_t
blob_allocate(ham_env_t *env, ham_db_t *db, ham_record_t *record,
        ham_u32_t flags, ham_offset_t *blobid)
{
    ham_status_t st;
    ham_page_t *page=0;
    ham_offset_t addr;
    blob_t hdr;
    ham_u8_t *chunk_data[2];
    ham_size_t alloc_size;
    ham_size_t chunk_size[2];
    ham_device_t *device=env_get_device(env);
    ham_bool_t freshly_created = HAM_FALSE;
   
    *blobid=0;

    /*
     * PARTIAL WRITE
     * 
     * if offset+partial_size equals the full record size, then we won't 
     * have any gaps. In this case we just write the full record and ignore
     * the partial parameters.
     */
    if (flags&HAM_PARTIAL) {
        if (record->partial_offset==0 
                && record->partial_offset+record->partial_size==record->size)
            flags&=~HAM_PARTIAL;
    }

    /*
     * in-memory-database: the blobid is actually a pointer to the memory
     * buffer, in which the blob (with the blob-header) is stored
     */
    if (env_get_rt_flags(env)&HAM_IN_MEMORY_DB) {
        blob_t *hdr;
        ham_u8_t *p=(ham_u8_t *)allocator_alloc(env_get_allocator(env), 
                                    record->size+sizeof(blob_t));
        if (!p) {
            return HAM_OUT_OF_MEMORY;
        }

        /* initialize the header */
        hdr=(blob_t *)p;
        memset(hdr, 0, sizeof(*hdr));
        blob_set_self(hdr, (ham_offset_t)PTR_TO_U64(p));
        blob_set_alloc_size(hdr, record->size+sizeof(blob_t));
        blob_set_size(hdr, record->size);

        /* do we have gaps? if yes, fill them with zeroes */
        if (flags&HAM_PARTIAL) {
            ham_u8_t *s=p+sizeof(blob_t);
            if (record->partial_offset)
                memset(s, 0, record->partial_offset);
            memcpy(s+record->partial_offset,
                    record->data, record->partial_size);
            if (record->partial_offset+record->partial_size<record->size)
                memset(s+record->partial_offset+record->partial_size, 0, 
                    record->size-(record->partial_offset+record->partial_size));
        }
        else {
            memcpy(p+sizeof(blob_t), record->data, record->size);
        }

        *blobid=(ham_offset_t)PTR_TO_U64(p);
        return (0);
    }

    memset(&hdr, 0, sizeof(hdr));

    /*
     * blobs are CHUNKSIZE-allocated 
     */
    alloc_size=sizeof(blob_t)+record->size;
    alloc_size += DB_CHUNKSIZE - 1;
    alloc_size -= alloc_size % DB_CHUNKSIZE;

    /* 
     * check if we have space in the freelist 
     */
    st = freel_alloc_area(&addr, env, db, alloc_size);
    if (!addr) 
    {
        if (st)
            return st;

        /*
         * if the blob is small AND if logging is disabled: load the page 
         * through the cache
         */
        if (__blob_from_cache(env, alloc_size)) {
            st = db_alloc_page(&page, db, PAGE_TYPE_BLOB, 
                        PAGE_IGNORE_FREELIST);
			ham_assert(st ? page == NULL : 1, (0));
			ham_assert(!st ? page  != NULL : 1, (0));
            if (st)
                return st;
            /* blob pages don't have a page header */
            page_set_npers_flags(page, 
                    page_get_npers_flags(page)|PAGE_NPERS_NO_HEADER);
            addr=page_get_self(page);
            /* move the remaining space to the freelist */
            (void)freel_mark_free(env, db, addr+alloc_size,
                    env_get_pagesize(env)-alloc_size, HAM_FALSE);
            blob_set_alloc_size(&hdr, alloc_size);
        }
        else {
            /*
             * otherwise use direct IO to allocate the space
             */
            ham_size_t aligned=alloc_size;
            aligned += env_get_pagesize(env) - 1;
            aligned -= aligned % env_get_pagesize(env);

            st=device->alloc(device, aligned, &addr);
            if (st) 
                return (st);

            /* if aligned!=size, and the remaining chunk is large enough:
             * move it to the freelist */
            {
                ham_size_t diff=aligned-alloc_size;
                if (diff > SMALLEST_CHUNK_SIZE) {
                    (void)freel_mark_free(env, db, addr+alloc_size, 
                            diff, HAM_FALSE);
                    blob_set_alloc_size(&hdr, aligned-diff);
                }
                else {
                    blob_set_alloc_size(&hdr, aligned);
                }
            }
            freshly_created = HAM_TRUE;
        }

        ham_assert(HAM_SUCCESS == freel_check_area_is_allocated(env, db,
                    addr, alloc_size), (0));
    }
    else {
		ham_assert(!st, (0));
        blob_set_alloc_size(&hdr, alloc_size);
    }

    blob_set_size(&hdr, record->size);
    blob_set_self(&hdr, addr);

    /*
     * PARTIAL WRITE
     *
     * are there gaps at the beginning? If yes, then we'll fill with zeros
     */
    if ((flags&HAM_PARTIAL) && (record->partial_offset)) {
        ham_u8_t *ptr;
        ham_size_t gapsize=record->partial_offset;

        ptr=allocator_calloc(env_get_allocator(env), 
                                    gapsize > env_get_pagesize(env)
                                        ? env_get_pagesize(env)
                                        : gapsize);
        if (!ptr)
            return (HAM_OUT_OF_MEMORY);

        /* 
         * first: write the header
         */
        chunk_data[0]=(ham_u8_t *)&hdr;
        chunk_size[0]=sizeof(hdr);
        st=__write_chunks(env, page, addr, HAM_TRUE, freshly_created, 
                        chunk_data, chunk_size, 1);
        if (st)
            return (st);

        addr+=sizeof(hdr);

        /* now fill the gap; if the gap is bigger than a pagesize we'll
         * split the gap into smaller chunks 
         */
        while (gapsize>=env_get_pagesize(env)) {
            chunk_data[0]=ptr;
            chunk_size[0]=env_get_pagesize(env);
            st=__write_chunks(env, page, addr, HAM_TRUE, 
                    freshly_created, chunk_data, chunk_size, 1);
            if (st)
                break;
            gapsize-=env_get_pagesize(env);
            addr+=env_get_pagesize(env);
        }

        /* fill the remaining gap */
        if (gapsize) {
            chunk_data[0]=ptr;
            chunk_size[0]=gapsize;

            st=__write_chunks(env, page, addr, HAM_TRUE, freshly_created, 
                            chunk_data, chunk_size, 1);
            if (st)
                return (st);
            addr+=gapsize;
        }

        allocator_free(env_get_allocator(env), ptr);

        /* now write the "real" data */
        chunk_data[0]=(ham_u8_t *)record->data;
        chunk_size[0]=record->partial_size;

        st=__write_chunks(env, page, addr, HAM_TRUE, freshly_created, 
                        chunk_data, chunk_size, 1);
        if (st)
            return (st);
        addr+=record->partial_size;
    }
    else {
        /* 
         * not writing partially: write header and data, then we're done
         */
        chunk_data[0]=(ham_u8_t *)&hdr;
        chunk_size[0]=sizeof(hdr);
        chunk_data[1]=(ham_u8_t *)record->data;
        chunk_size[1]=(flags&HAM_PARTIAL) 
                        ? record->partial_size 
                        : record->size;

        st=__write_chunks(env, page, addr, HAM_TRUE, freshly_created, 
                        chunk_data, chunk_size, 2);
        if (st)
            return (st);
        addr+=sizeof(hdr)+
            ((flags&HAM_PARTIAL) ? record->partial_size : record->size);
    }

    /*
     * store the blobid; it will be returned to the caller
     */
    *blobid=blob_get_self(&hdr);

    /*
     * PARTIAL WRITES:
     *
     * if we have gaps at the end of the blob: just append more chunks to
     * fill these gaps. Since they can be pretty large we split them into
     * smaller chunks if necessary.
     */
    if (flags&HAM_PARTIAL) {
        if (record->partial_offset+record->partial_size < record->size) {
            ham_u8_t *ptr;
            ham_size_t gapsize=record->size
                            - (record->partial_offset+record->partial_size);

            /* now fill the gap; if the gap is bigger than a pagesize we'll
             * split the gap into smaller chunks 
             *
             * we split this loop in two - the outer loop will allocate the
             * memory buffer, thus saving some allocations
             */
            while (gapsize>env_get_pagesize(env)) {
                ham_u8_t *ptr=allocator_calloc(env_get_allocator(env), 
                                            env_get_pagesize(env));
                if (!ptr)
                    return (HAM_OUT_OF_MEMORY);
                while (gapsize>env_get_pagesize(env)) {
                    chunk_data[0]=ptr;
                    chunk_size[0]=env_get_pagesize(env);
                    st=__write_chunks(env, page, addr, HAM_TRUE, 
                            freshly_created, chunk_data, chunk_size, 1);
                    if (st)
                        break;
                    gapsize-=env_get_pagesize(env);
                    addr+=env_get_pagesize(env);
                }
                allocator_free(env_get_allocator(env), ptr);
                if (st)
                    return (st);
            }
            
            /* now write the remainder, which is less than a pagesize */
            ham_assert(gapsize<env_get_pagesize(env), (""));

            chunk_size[0]=gapsize;
            ptr=chunk_data[0]=allocator_calloc(env_get_allocator(env), gapsize);
            if (!ptr)
                return (HAM_OUT_OF_MEMORY);

            st=__write_chunks(env, page, addr, HAM_TRUE, freshly_created, 
                        chunk_data, chunk_size, 1);
            allocator_free(env_get_allocator(env), ptr);
            if (st)
                return (st);
        }
    }

    return (0);
}
Beispiel #27
0
ham_status_t
blob_duplicate_erase(ham_db_t *db, ham_offset_t table_id,
        ham_size_t position, ham_u32_t flags, ham_offset_t *new_table_id)
{
    ham_status_t st;
    ham_record_t rec;
    ham_size_t i;
    dupe_table_t *table;
    ham_offset_t rid;
	ham_env_t *env = db_get_env(db);

    /* store the public record pointer, otherwise it's destroyed */
    ham_size_t rs=db_get_record_allocsize(db);
    void      *rp=db_get_record_allocdata(db);
    db_set_record_allocdata(db, 0);
    db_set_record_allocsize(db, 0);

    memset(&rec, 0, sizeof(rec));

    if (new_table_id)
        *new_table_id=table_id;

    st=blob_read(db, table_id, &rec, 0);
    if (st)
        return (st);

    /* restore the public record pointer */
    db_set_record_allocsize(db, rs);
    db_set_record_allocdata(db, rp);

    table=(dupe_table_t *)rec.data;

    /*
     * if BLOB_FREE_ALL_DUPES is set *OR* if the last duplicate is deleted:
     * free the whole duplicate table
     */
    if (flags&BLOB_FREE_ALL_DUPES
            || (position==0 && dupe_table_get_count(table)==1)) {
        for (i=0; i<dupe_table_get_count(table); i++) {
            dupe_entry_t *e=dupe_table_get_entry(table, i);
            if (!(dupe_entry_get_flags(e)&(KEY_BLOB_SIZE_SMALL
                                        |KEY_BLOB_SIZE_TINY
                                        |KEY_BLOB_SIZE_EMPTY))) {
                st=blob_free(env, db, dupe_entry_get_rid(e), 0);
                if (st) {
                    allocator_free(env_get_allocator(env), table);
                    return (st);
                }
            }
        }
        st=blob_free(env, db, table_id, 0); /* [i_a] isn't this superfluous (& 
                                        * dangerous), thanks to the 
                                        * free_all_dupes loop above??? */
        allocator_free(env_get_allocator(env), table);
        if (st)
            return (st);

        if (new_table_id)
            *new_table_id=0;

        return (0);
    }
    else {
        ham_record_t rec={0};
        dupe_entry_t *e=dupe_table_get_entry(table, position);
        if (!(dupe_entry_get_flags(e)&(KEY_BLOB_SIZE_SMALL
                                    |KEY_BLOB_SIZE_TINY
                                    |KEY_BLOB_SIZE_EMPTY))) {
            st=blob_free(env, db, dupe_entry_get_rid(e), 0);
            if (st) {
                allocator_free(env_get_allocator(env), table);
                return (st);
            }
        }
        memmove(e, e+1,
            ((dupe_table_get_count(table)-position)-1)*sizeof(dupe_entry_t));
        dupe_table_set_count(table, dupe_table_get_count(table)-1);

        rec.data=(ham_u8_t *)table;
        rec.size=sizeof(dupe_table_t)
                    +(dupe_table_get_capacity(table)-1)*sizeof(dupe_entry_t);
        st=blob_overwrite(env, db, table_id, &rec, 0, &rid);
        if (st) {
            allocator_free(env_get_allocator(env), table);
            return (st);
        }
        if (new_table_id)
            *new_table_id=rid;
    }

    /*
     * return 0 as a rid if the table is empty
     */
    if (dupe_table_get_count(table)==0)
        if (new_table_id)
            *new_table_id=0;

    allocator_free(env_get_allocator(env), table);
    return (0);
}
Beispiel #28
0
ham_status_t
blob_duplicate_insert(ham_db_t *db, ham_offset_t table_id, 
        ham_record_t *record, ham_size_t position, ham_u32_t flags, 
        dupe_entry_t *entries, ham_size_t num_entries, 
        ham_offset_t *rid, ham_size_t *new_position)
{
    ham_status_t st=0;
    dupe_table_t *table=0;
    ham_bool_t alloc_table=0;
	ham_bool_t resize=0;
    ham_page_t *page=0;
    ham_env_t *env=db_get_env(db);

    /*
     * create a new duplicate table if none existed, and insert
     * the first entry
     */
    if (!table_id) {
        ham_assert(num_entries==2, (""));
        /* allocates space for 8 (!) entries */
        table=allocator_calloc(env_get_allocator(env), 
                        sizeof(dupe_table_t)+7*sizeof(dupe_entry_t));
        if (!table)
            return HAM_OUT_OF_MEMORY;
        dupe_table_set_capacity(table, 8);
        dupe_table_set_count(table, 1);
        memcpy(dupe_table_get_entry(table, 0), &entries[0], 
                        sizeof(entries[0]));

        /* skip the first entry */
        entries++;
        num_entries--;
        alloc_table=1;
    }
    else {
        /*
         * otherwise load the existing table 
         */
        st=__get_duplicate_table(&table, &page, env, table_id);
		ham_assert(st ? table == NULL : 1, (0));
		ham_assert(st ? page == NULL : 1, (0));
        if (!table)
			return st ? st : HAM_INTERNAL_ERROR;
        if (!page && !(env_get_rt_flags(env)&HAM_IN_MEMORY_DB))
            alloc_table=1;
    }

    if (page)
        if ((st=ham_log_add_page_before(page)))
            return (st);

    ham_assert(num_entries==1, (""));

    /*
     * resize the table, if necessary
     */ 
    if (!(flags & HAM_OVERWRITE)
            && dupe_table_get_count(table)+1>=dupe_table_get_capacity(table)) {
        dupe_table_t *old=table;
        ham_size_t new_cap=dupe_table_get_capacity(table);

        if (new_cap < 3*8)
            new_cap += 8;
        else
            new_cap += new_cap/3;

        table=allocator_calloc(env_get_allocator(env), sizeof(dupe_table_t)+
                        (new_cap-1)*sizeof(dupe_entry_t));
        if (!table)
            return (HAM_OUT_OF_MEMORY);
        dupe_table_set_capacity(table, new_cap);
        dupe_table_set_count(table, dupe_table_get_count(old));
        memcpy(dupe_table_get_entry(table, 0), dupe_table_get_entry(old, 0),
                       dupe_table_get_count(old)*sizeof(dupe_entry_t));
        if (alloc_table)
            allocator_free(env_get_allocator(env), old);

        alloc_table=1;
        resize=1;
    }

    /*
     * insert sorted, unsorted or overwrite the entry at the requested position
     */
    if (flags&HAM_OVERWRITE) {
        dupe_entry_t *e=dupe_table_get_entry(table, position);

        if (!(dupe_entry_get_flags(e)&(KEY_BLOB_SIZE_SMALL
                                    |KEY_BLOB_SIZE_TINY
                                    |KEY_BLOB_SIZE_EMPTY))) {
            (void)blob_free(env, db, dupe_entry_get_rid(e), 0);
        }

        memcpy(dupe_table_get_entry(table, position), 
                        &entries[0], sizeof(entries[0]));
    }
    else {
        if (db_get_rt_flags(db)&HAM_SORT_DUPLICATES) {
            if (page)
                page_add_ref(page);
            position=__get_sorted_position(db, table, record, flags);
            if (page)
                page_release_ref(page);
            if (position<0)
                return ((ham_status_t)position);
        }
        else if (flags&HAM_DUPLICATE_INSERT_BEFORE) {
            /* do nothing, insert at the current position */
        }
        else if (flags&HAM_DUPLICATE_INSERT_AFTER) {
            position++;
            if (position > dupe_table_get_count(table))
                position=dupe_table_get_count(table);
        }
        else if (flags&HAM_DUPLICATE_INSERT_FIRST) {
            position=0;
        }
        else if (flags&HAM_DUPLICATE_INSERT_LAST) {
            position=dupe_table_get_count(table);
        }
        else {
            position=dupe_table_get_count(table);
        }

        if (position != dupe_table_get_count(table)) {
            memmove(dupe_table_get_entry(table, position+1), 
                dupe_table_get_entry(table, position), 
                sizeof(entries[0])*(dupe_table_get_count(table)-position));
        }

        memcpy(dupe_table_get_entry(table, position), 
                &entries[0], sizeof(entries[0]));

        dupe_table_set_count(table, dupe_table_get_count(table)+1);
    }

    /*
     * write the table back to disk and return the blobid of the table
     */
    if ((table_id && !page) || resize) {
        ham_record_t rec={0};
        rec.data=(ham_u8_t *)table;
        rec.size=sizeof(dupe_table_t)
                    +(dupe_table_get_capacity(table)-1)*sizeof(dupe_entry_t);
        st=blob_overwrite(env, db, table_id, &rec, 0, rid);
    }
    else if (!table_id) {
        ham_record_t rec={0};
        rec.data=(ham_u8_t *)table;
        rec.size=sizeof(dupe_table_t)
                    +(dupe_table_get_capacity(table)-1)*sizeof(dupe_entry_t);
        st=blob_allocate(env, db, &rec, 0, rid);
    }
    else if (table_id && page) {
        page_set_dirty(page, env);
    }
    else {
        ham_assert(!"shouldn't be here", (0));
	}

    if (alloc_table)
        allocator_free(env_get_allocator(env), table);

    if (new_position)
        *new_position=position;

    return (st);
}
Beispiel #29
0
int
TextTest(int verbose, struct cfg *cfg, char *args[])
{
	tchar buf[1024];
	tchar *hello = TEXT("hello");
	tchar *a = TEXT("a");
	tchar *e = TEXT("");
	tchar *cpy;
	cfg = NULL; *args = NULL; verbose = 1;

                                        /* text_length */

	T(text_length(NULL, NULL) == 0);
	T(text_length(hello, NULL) == 0);
	T(text_length(hello + 3, hello) == 0);
	T(text_length(hello, hello) == 0);
	T(text_length(hello, hello + 1) == 0);
	T(text_length(hello, hello + 4) == 0);
	T(text_length(a, a + 1) == 0);
	T(text_length(a, a + 2) == 1);
	T(text_length(a + 1, a + 2) == 0);
	T(text_length(hello, hello + 100) == 5);

                                          /* text_size */

	T(text_size(NULL, NULL) == 0);
	T(text_size(hello, NULL) == 0);
	T(text_size(hello + 3, hello) == 0);
	T(text_size(hello, hello) == 0);
	T(text_size(hello, hello + 1) == 0);
	T(text_size(hello, hello + 4) == 0);
	T(text_size(a, a + 1) == 0);
	T(text_size(a, a + 2) == (2 * sizeof *a));
	T(text_size(a + 1, a + 2) == (1 * sizeof *a));
	T(text_size(hello, hello + 100) == (6 * sizeof *hello));

                                          /* text_copy */

	T(text_copy(hello, hello + 100, NULL, buf + 1024, 0) == 0);

	T(text_copy(hello, hello + 100, buf + 3, buf, 0) == 0);

	memset(buf, 'x', 1024 * sizeof(tchar));
	T(text_copy(NULL, hello + 100, buf, buf + 1024, 0) == 0);
	T(buf[0] == TEXT('\0'));

	memset(buf, 'x', 1024 * sizeof(tchar));
	T(text_copy(hello + 3, hello, buf, buf + 1024, 0) == 0);
	T(buf[0] == TEXT('\0'));

	memset(buf, 'x', 1024 * sizeof(tchar));
	T(text_copy(hello, hello + 100, buf, buf + 100, 1) == 1);
	T(tcsncmp(TEXT("h"), buf, 100) == 0);

	memset(buf, 'x', 1024 * sizeof(tchar));
	T(text_copy(hello, hello + 100, buf, buf + 100, 5) == 5);
	T(tcsncmp(hello, buf, 100) == 0);

	memset(buf, 'x', 1024 * sizeof(tchar));
	T(text_copy(hello, hello + 100, buf, buf + 1024, 0) == 0);
	T(buf[0] == TEXT('\0'));

	memset(buf, 'x', 1024 * sizeof(tchar));
	T(text_copy(e, e + 100, buf, buf + 1024, 100) == 0);
	T(tcsncmp(e, buf, 100) == 0);

	memset(buf, 'x', 1024 * sizeof(tchar));
	T(text_copy(hello, hello + 100, buf, buf + 1024, 100) == 5);
	T(tcsncmp(hello, buf, 100) == 0);

	memset(buf, 'x', 1024 * sizeof(tchar));
	T(text_copy(hello, hello + 1, buf, buf + 1024, 100) == 0);
	T(buf[0] == TEXT('\0'));

	memset(buf, 'x', 1024 * sizeof(tchar));
	T(text_copy(hello, hello + 5, buf, buf + 1024, 100) == 0);
	T(buf[0] == TEXT('\0'));

	memset(buf, 'x', 1024 * sizeof(tchar));
	T(text_copy(hello, hello + 6, buf, buf + 1024, 100) == 5);
	T(tcsncmp(hello, buf, 100) == 0);

	memset(buf, 'x', 1024 * sizeof(tchar));
	T(text_copy(hello, hello + 100, buf, buf + 1, 100) == 0);
	T(buf[0] == TEXT('\0'));

	memset(buf, 'x', 1024 * sizeof(tchar));
	T(text_copy(hello, hello + 100, buf, buf + 5, 100) == 0);
	T(buf[0] == TEXT('\0'));

	memset(buf, 'x', 1024 * sizeof(tchar));
	T(text_copy(hello, hello + 100, buf, buf + 6, 100) == 5);
	T(tcsncmp(hello, buf, 100) == 0);

                                      /* text_copy_new */

	T(text_copy_new(hello, hello + 100, &cpy, 100, NULL) == 5);
	T(tcsncmp(hello, cpy, 100) == 0);
	allocator_free(NULL, cpy);

	T(text_copy_new(hello, hello + 100, NULL, 100, NULL) == 0);

	T(text_copy_new(NULL, hello + 100, &cpy, 100, NULL) == 0);
	T(cpy == NULL);

	T(text_copy_new(hello + 3, hello, &cpy, 100, NULL) == 0);
	T(cpy == NULL);

	T(text_copy_new(hello, hello + 100, &cpy, 0, NULL) == 0);
	T(tcsncmp(e, cpy, 100) == 0);
	allocator_free(NULL, cpy);

	T(text_copy_new(hello, hello + 100, &cpy, 4, NULL) == 4);
	T(tcsncmp(TEXT("hell"), cpy, 100) == 0);
	allocator_free(NULL, cpy);

	T(text_copy_new(hello, hello + 100, &cpy, 5, NULL) == 5);
	T(tcsncmp(hello, cpy, 100) == 0);
	allocator_free(NULL, cpy);

    return 0;
}
Beispiel #30
0
static ham_status_t
_remote_fun_get_parameters(ham_db_t *db, ham_parameter_t *param)
{
    static char filename[1024];
    ham_status_t st;
    ham_env_t *env=db_get_env(db);
    proto_wrapper_t *request, *reply;
    ham_size_t i, num_names=0;
    ham_u32_t *names;
    ham_parameter_t *p;
    
    /* count number of parameters */
    p=param;
    if (p) {
        for (; p->name; p++) {
            num_names++;
        }
    }

    /* allocate a memory and copy the parameter names */
    names=(ham_u32_t *)allocator_alloc(env_get_allocator(env), 
            num_names*sizeof(ham_u32_t));
    if (!names)
        return (HAM_OUT_OF_MEMORY);
    p=param;
    if (p) {
        for (i=0; p->name; p++) {
            names[i]=p->name;
            i++;
        }
    }

    request=proto_init_db_get_parameters_request(db_get_remote_handle(db),
                        names, num_names);

    st=_perform_request(env, env_get_curl(env), request, &reply);
    proto_delete(request);

    allocator_free(env_get_allocator(env), names);

    if (st) {
        if (reply)
            proto_delete(reply);
        return (st);
    }

    ham_assert(reply!=0, (""));
    ham_assert(proto_has_db_get_parameters_reply(reply), (""));

    st=proto_db_get_parameters_reply_get_status(reply);
    if (st) {
        proto_delete(reply);
        return (st);
    }

    p=param;
    while (p && p->name) {
        switch (p->name) {
        case HAM_PARAM_CACHESIZE:
            ham_assert(proto_db_get_parameters_reply_has_cachesize(reply), (""));
            p->value=proto_db_get_parameters_reply_get_cachesize(reply);
            break;
        case HAM_PARAM_PAGESIZE:
            ham_assert(proto_db_get_parameters_reply_has_pagesize(reply), (""));
            p->value=proto_db_get_parameters_reply_get_pagesize(reply);
            break;
        case HAM_PARAM_MAX_ENV_DATABASES:
            ham_assert(proto_db_get_parameters_reply_has_max_env_databases(reply), (""));
            p->value=proto_db_get_parameters_reply_get_max_env_databases(reply);
            break;
        case HAM_PARAM_GET_FLAGS:
            ham_assert(proto_db_get_parameters_reply_has_flags(reply), (""));
            p->value=proto_db_get_parameters_reply_get_flags(reply);
            break;
        case HAM_PARAM_GET_FILEMODE:
            ham_assert(proto_db_get_parameters_reply_has_filemode(reply), (""));
            p->value=proto_db_get_parameters_reply_get_filemode(reply);
            break;
        case HAM_PARAM_GET_FILENAME:
            ham_assert(proto_db_get_parameters_reply_has_filename(reply), (""));
            strncpy(filename, proto_db_get_parameters_reply_get_filename(reply),
                        sizeof(filename));
            p->value=PTR_TO_U64(&filename[0]);
            break;
        case HAM_PARAM_KEYSIZE:
            ham_assert(proto_db_get_parameters_reply_has_keysize(reply), (""));
            p->value=proto_db_get_parameters_reply_get_keysize(reply);
            break;
        case HAM_PARAM_GET_DATABASE_NAME:
            ham_assert(proto_db_get_parameters_reply_has_dbname(reply), (""));
            p->value=proto_db_get_parameters_reply_get_dbname(reply);
            break;
        case HAM_PARAM_GET_KEYS_PER_PAGE:
            ham_assert(proto_db_get_parameters_reply_has_keys_per_page(reply), (""));
            p->value=proto_db_get_parameters_reply_get_keys_per_page(reply);
            break;
        case HAM_PARAM_GET_DATA_ACCESS_MODE:
            ham_assert(proto_db_get_parameters_reply_has_dam(reply), (""));
            p->value=proto_db_get_parameters_reply_get_dam(reply);
            break;
        default:
            ham_trace(("unknown parameter %d", (int)p->name));
            break;
        }
        p++;
    }

    proto_delete(reply);

    return (st);
}