static ham_status_t _remote_cursor_insert(ham_cursor_t *cursor, ham_key_t *key, ham_record_t *record, ham_u32_t flags) { ham_status_t st; ham_db_t *db=cursor_get_db(cursor); ham_env_t *env=db_get_env(db); proto_wrapper_t *request, *reply; ham_bool_t send_key=HAM_TRUE; /* recno: do not send the key */ if (db_get_rt_flags(db)&HAM_RECORD_NUMBER) send_key=HAM_FALSE; request=proto_init_cursor_insert_request(cursor_get_remote_handle(cursor), send_key ? key : 0, record, 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_cursor_insert_reply(reply)!=0, ("")); st=proto_cursor_insert_reply_get_status(reply); /* recno: the key was modified! */ if (st==0 && proto_cursor_insert_reply_has_key(reply)) { if (proto_cursor_insert_reply_get_key_size(reply) ==sizeof(ham_offset_t)) { ham_assert(key->data!=0, ("")); ham_assert(key->size==sizeof(ham_offset_t), ("")); memcpy(key->data, proto_cursor_insert_reply_get_key_data(reply), sizeof(ham_offset_t)); } } proto_delete(reply); return (st); }
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); }
static void print_database(ham_db_t *db, ham_u16_t dbname, int full) { ham_btree_t *be; ham_cursor_t *cursor; ham_status_t st; ham_key_t key; ham_record_t rec; unsigned num_items=0, ext_keys=0, min_key_size=0xffffffff, max_key_size=0, min_rec_size=0xffffffff, max_rec_size=0, total_key_size=0, total_rec_size=0; be=(ham_btree_t *)db_get_backend(db); memset(&key, 0, sizeof(key)); memset(&rec, 0, sizeof(rec)); printf("\n"); printf(" database %d (0x%x)\n", (int)dbname, (int)dbname); printf(" max key size: %u\n", be_get_keysize(be)); printf(" max keys per page: %u\n", btree_get_maxkeys(be)); printf(" address of root page: %llu\n", (long long unsigned int)btree_get_rootpage(be)); printf(" flags: 0x%04x\n", db_get_rt_flags(db)); if (!full) return; st=ham_cursor_create(db, 0, 0, &cursor); if (st!=HAM_SUCCESS) error("ham_cursor_create", st); while (1) { st=ham_cursor_move(cursor, &key, &rec, HAM_CURSOR_NEXT); if (st!=HAM_SUCCESS) { /* reached end of the database? */ if (st==HAM_KEY_NOT_FOUND) break; else error("ham_cursor_next", st); } num_items++; if (key.size<min_key_size) min_key_size=key.size; if (key.size>max_key_size) max_key_size=key.size; if (rec.size<min_rec_size) min_rec_size=rec.size; if (rec.size>max_rec_size) max_rec_size=rec.size; if (key.size>db_get_keysize(db)) ext_keys++; total_key_size+=key.size; total_rec_size+=rec.size; } ham_cursor_close(cursor); printf(" number of items: %u\n", num_items); if (num_items==0) return; printf(" average key size: %u\n", total_key_size/num_items); printf(" minimum key size: %u\n", min_key_size); printf(" maximum key size: %u\n", max_key_size); printf(" number of extended keys:%u\n", ext_keys); printf(" total keys (bytes): %u\n", total_key_size); printf(" average record size: %u\n", total_rec_size/num_items); printf(" minimum record size: %u\n", min_rec_size); printf(" maximum record size: %u\n", min_rec_size); printf(" total records (bytes): %u\n", total_rec_size); }