static ham_status_t _remote_cursor_move(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; request=proto_init_cursor_move_request(cursor_get_remote_handle(cursor), key, 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_move_reply(reply)!=0, ("")); st=proto_cursor_move_reply_get_status(reply); if (st) goto bail; /* modify key/record, but make sure that USER_ALLOC is respected! */ if (proto_cursor_move_reply_has_key(reply)) { ham_assert(key, ("")); key->_flags=proto_cursor_move_reply_get_key_intflags(reply); key->size=proto_cursor_move_reply_get_key_size(reply); if (!(key->flags&HAM_KEY_USER_ALLOC)) { st=db_resize_key_allocdata(db, key->size); if (st) goto bail; key->data=db_get_key_allocdata(db); } memcpy(key->data, proto_cursor_move_reply_get_key_data(reply), key->size); } /* same for the record */ if (proto_cursor_move_reply_has_record(reply)) { ham_assert(record, ("")); record->size=proto_cursor_move_reply_get_record_size(reply); if (!(record->flags&HAM_RECORD_USER_ALLOC)) { st=db_resize_record_allocdata(db, record->size); if (st) goto bail; record->data=db_get_record_allocdata(db); } memcpy(record->data, proto_cursor_move_reply_get_record_data(reply), record->size); } bail: proto_delete(reply); return (st); }
static ham_status_t _remote_fun_find(ham_db_t *db, ham_txn_t *txn, ham_key_t *key, ham_record_t *record, ham_u32_t flags) { ham_status_t st; ham_env_t *env=db_get_env(db); proto_wrapper_t *request, *reply; request=proto_init_db_find_request(db_get_remote_handle(db), txn ? txn_get_remote_handle(txn) : 0, key, 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_db_find_reply(reply)!=0, ("")); st=proto_db_find_reply_get_status(reply); if (st==0) { /* approx. matching: need to copy the _flags and the key data! */ if (proto_db_find_reply_has_key(reply)) { ham_assert(key, ("")); key->_flags=proto_db_find_reply_get_key_intflags(reply); key->size=proto_db_find_reply_get_key_size(reply); if (!(key->flags&HAM_KEY_USER_ALLOC)) { st=db_resize_key_allocdata(db, key->size); if (st) goto bail; key->data=db_get_key_allocdata(db); } memcpy(key->data, proto_db_find_reply_get_key_data(reply), key->size); } if (proto_db_find_reply_has_record(reply)) { record->size=proto_db_find_reply_get_record_size(reply); if (!(record->flags&HAM_RECORD_USER_ALLOC)) { st=db_resize_record_allocdata(db, record->size); if (st) goto bail; record->data=db_get_record_allocdata(db); } memcpy(record->data, proto_db_find_reply_get_record_data(reply), record->size); } } bail: proto_delete(reply); return (st); }
static ham_status_t _remote_cursor_find(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; request=proto_init_cursor_find_request(cursor_get_remote_handle(cursor), key, 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_find_reply(reply)!=0, ("")); st=proto_cursor_find_reply_get_status(reply); if (st) goto bail; /* approx. matching: need to copy the _flags! */ if (proto_cursor_find_reply_has_key(reply)) { key->_flags=proto_cursor_find_reply_get_key_intflags(reply); } if (proto_cursor_find_reply_has_record(reply)) { ham_assert(record, ("")); record->size=proto_cursor_find_reply_get_record_size(reply); if (!(record->flags&HAM_RECORD_USER_ALLOC)) { st=db_resize_record_allocdata(db, record->size); if (st) goto bail; record->data=db_get_record_allocdata(db); } memcpy(record->data, proto_cursor_find_reply_get_record_data(reply), record->size); } bail: proto_delete(reply); return (st); }
ham_status_t blob_read(ham_db_t *db, ham_offset_t blobid, ham_record_t *record, ham_u32_t flags) { ham_status_t st; ham_page_t *page; blob_t hdr; ham_size_t blobsize=0; /* * in-memory-database: the blobid is actually a pointer to the memory * buffer, in which the blob is stored */ if (env_get_rt_flags(db_get_env(db))&HAM_IN_MEMORY_DB) { blob_t *hdr=(blob_t *)U64_TO_PTR(blobid); ham_u8_t *data=(ham_u8_t *)(U64_TO_PTR(blobid))+sizeof(blob_t); /* when the database is closing, the header is already deleted */ if (!hdr) { record->size = 0; return (0); } blobsize = (ham_size_t)blob_get_size(hdr); if (flags&HAM_PARTIAL) { if (record->partial_offset>blobsize) { ham_trace(("partial offset is greater than the total " "record size")); return (HAM_INV_PARAMETER); } if (record->partial_offset+record->partial_size>blobsize) blobsize=blobsize-record->partial_offset; else blobsize=record->partial_size; } if (!blobsize) { /* empty blob? */ record->data = 0; record->size = 0; } else { ham_u8_t *d=data; if (flags&HAM_PARTIAL) d+=record->partial_offset; if ((flags&HAM_DIRECT_ACCESS) && !(record->flags&HAM_RECORD_USER_ALLOC)) { record->size=blobsize; record->data=d; } else { /* resize buffer, if necessary */ if (!(record->flags & HAM_RECORD_USER_ALLOC)) { st=db_resize_record_allocdata(db, blobsize); if (st) return (st); record->data = db_get_record_allocdata(db); } /* and copy the data */ memcpy(record->data, d, blobsize); record->size = blobsize; } } return (0); } ham_assert(blobid%DB_CHUNKSIZE==0, ("blobid is %llu", blobid)); /* * first step: read the blob header */ st=__read_chunk(db_get_env(db), 0, &page, blobid, (ham_u8_t *)&hdr, sizeof(hdr)); if (st) return (st); ham_assert(blob_get_alloc_size(&hdr)%DB_CHUNKSIZE==0, (0)); /* * sanity check */ if (blob_get_self(&hdr)!=blobid) return (HAM_BLOB_NOT_FOUND); blobsize = (ham_size_t)blob_get_size(&hdr); if (flags&HAM_PARTIAL) { if (record->partial_offset>blobsize) { ham_trace(("partial offset+size is greater than the total " "record size")); return (HAM_INV_PARAMETER); } if (record->partial_offset+record->partial_size>blobsize) blobsize=blobsize-record->partial_offset; else blobsize=record->partial_size; } /* * empty blob? */ if (!blobsize) { record->data = 0; record->size = 0; return (0); } /* * second step: resize the blob buffer */ if (!(record->flags & HAM_RECORD_USER_ALLOC)) { st=db_resize_record_allocdata(db, blobsize); if (st) return (st); record->data = db_get_record_allocdata(db); } /* * third step: read the blob data */ st=__read_chunk(db_get_env(db), page, 0, blobid+sizeof(blob_t)+(flags&HAM_PARTIAL ? record->partial_offset : 0), record->data, blobsize); if (st) return (st); record->size = blobsize; return (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); }