Commit 58d57cb1 authored by Bradley C. Kuszmaul's avatar Bradley C. Kuszmaul Committed by Yoni Fogel

Merge 2948 changes to main: Start putting upsert into brt layer (Refs #2948). ...

Merge 2948 changes to main: Start putting upsert into brt layer (Refs #2948).  Also add unused attributes (Closes #2950). [t:2948] close[t:2950] 
{{{
svn merge -c 24081 https://svn.tokutek.com/tokudb/toku/tokudb.2948
}}}
.


git-svn-id: file:///svn/toku/tokudb@24083 c7de825b-a66e-492c-adef-691d508d4ae1
parent ca87a619
...@@ -201,6 +201,24 @@ struct brt { ...@@ -201,6 +201,24 @@ struct brt {
BOOL did_set_descriptor; BOOL did_set_descriptor;
DESCRIPTOR_S temp_descriptor; DESCRIPTOR_S temp_descriptor;
int (*compare_fun)(DB*,const DBT*,const DBT*); int (*compare_fun)(DB*,const DBT*,const DBT*);
// When an upsert message arrives it contains a key, a value (upserted_val), and an extra DBT (upserted_extra).
// If there is no such key in the database, then the upserted value is inserted.
// If there is such a key in the database, then there is associated with that key another value (prev_val).
// The system calls upsert_fun(DB, upserted_value, upserted_extra, prev_val, set_val, set_extra)
// where set_val and set_extra are provided by the system.
// The upsert_fun can look at the DBTs and the DB (to get the db descriptor) and perform one of the following actions:
// a) It can return DB_DELETE_UPSERT (which is defined in db.h). In this case, the system deletes the key-value pair.
// b) OR it can return call set_val(new_val, set_extra),
// where new_val is the dbt that was passed in. The set_val function will copy anything it needs out of new_val, so the memory pointed
// to by new_val may be stack allocated by upsert_fun (or it may be malloced, in which case upsert_fun should free that memory).
// Notes:
// 1) The DBTs passed to upsert_fun may point to memory that will be freed after the upsert_fun returns.
// 2) Furtheremore, there is likely to be some sort of lock held when upsert_fun is called.
// Those notes should not matter, since the upsert_fun should essentially be a pure function of the DBTs and DB descriptor passed in.
int (*upsert_fun)(DB*, const DBT*key, const DBT *upserted_val, const DBT *upserted_extra, const DBT *prev_val,
void (*set_val)(const DBT *new_val, void*set_extra), void *set_extra);
DB *db; // To pass to the compare fun, and close once transactions are done. DB *db; // To pass to the compare fun, and close once transactions are done.
OMT txns; // transactions that are using this OMT (note that the transaction checks the cf also) OMT txns; // transactions that are using this OMT (note that the transaction checks the cf also)
......
...@@ -516,7 +516,6 @@ toku_cmd_leafval_heaviside (OMTVALUE lev, void *extra) { ...@@ -516,7 +516,6 @@ toku_cmd_leafval_heaviside (OMTVALUE lev, void *extra) {
be); be);
} }
// If you pass in data==0 then it only compares the key, not the data (even if is a DUPSORT database)
static int static int
brt_compare_pivot(BRT brt, DBT *key, bytevec ck) brt_compare_pivot(BRT brt, DBT *key, bytevec ck)
{ {
...@@ -2844,8 +2843,8 @@ int toku_open_brt (const char *fname, int is_create, BRT *newbrt, int nodesize, ...@@ -2844,8 +2843,8 @@ int toku_open_brt (const char *fname, int is_create, BRT *newbrt, int nodesize,
r = toku_brt_create(&brt); r = toku_brt_create(&brt);
if (r != 0) if (r != 0)
return r; return r;
toku_brt_set_nodesize(brt, nodesize); r = toku_brt_set_nodesize(brt, nodesize); assert(r==0);
toku_brt_set_bt_compare(brt, compare_fun); r = toku_brt_set_bt_compare(brt, compare_fun); assert(r==0);
r = toku_brt_open(brt, fname, is_create, only_create, cachetable, txn, db); r = toku_brt_open(brt, fname, is_create, only_create, cachetable, txn, db);
if (r != 0) { if (r != 0) {
...@@ -3619,7 +3618,7 @@ int toku_brt_set_flags(BRT brt, unsigned int flags) { ...@@ -3619,7 +3618,7 @@ int toku_brt_set_flags(BRT brt, unsigned int flags) {
int toku_brt_get_flags(BRT brt, unsigned int *flags) { int toku_brt_get_flags(BRT brt, unsigned int *flags) {
*flags = brt->flags; *flags = brt->flags;
assert(brt->flags==(brt->flags&TOKU_DB_KEYCMP_BUILTIN)); // make sure there are no extranious flags assert(brt->flags==(brt->flags&TOKU_DB_KEYCMP_BUILTIN)); // make sure there are no extraneous flags
return 0; return 0;
} }
...@@ -3639,6 +3638,12 @@ int toku_brt_set_bt_compare(BRT brt, int (*bt_compare)(DB *, const DBT*, const D ...@@ -3639,6 +3638,12 @@ int toku_brt_set_bt_compare(BRT brt, int (*bt_compare)(DB *, const DBT*, const D
return 0; return 0;
} }
int toku_brt_set_upsert(BRT brt, int (*upsert)(DB *, const DBT *key, const DBT *upserted_val, const DBT *upserted_extra, const DBT *prev_val,
void (*set_val)(const DBT *new_val, void *set_extra), void *set_extra)) {
brt->upsert_fun = upsert;
return 0;
}
brt_compare_func toku_brt_get_bt_compare (BRT brt) { brt_compare_func toku_brt_get_bt_compare (BRT brt) {
return brt->compare_fun; return brt->compare_fun;
} }
......
...@@ -28,133 +28,136 @@ C_BEGIN ...@@ -28,133 +28,136 @@ C_BEGIN
//-infinity depending on direction) //-infinity depending on direction)
typedef int(*BRT_GET_CALLBACK_FUNCTION)(ITEMLEN, bytevec, ITEMLEN, bytevec, void*); typedef int(*BRT_GET_CALLBACK_FUNCTION)(ITEMLEN, bytevec, ITEMLEN, bytevec, void*);
int toku_open_brt (const char *fname, int is_create, BRT *, int nodesize, CACHETABLE, TOKUTXN, int(*)(DB*,const DBT*,const DBT*), DB*); int toku_open_brt (const char *fname, int is_create, BRT *, int nodesize, CACHETABLE, TOKUTXN, int(*)(DB*,const DBT*,const DBT*), DB*) __attribute__ ((warn_unused_result));
int toku_maybe_upgrade_descriptor(BRT t, DESCRIPTOR d, BOOL do_log, TOKUTXN txn); int toku_maybe_upgrade_descriptor(BRT t, DESCRIPTOR d, BOOL do_log, TOKUTXN txn) __attribute__ ((warn_unused_result));
int toku_dictionary_redirect (const char *dst_fname_in_env, BRT old_brt, TOKUTXN txn); int toku_dictionary_redirect (const char *dst_fname_in_env, BRT old_brt, TOKUTXN txn) __attribute__ ((warn_unused_result));
// See the brt.c file for what this toku_redirect_brt does // See the brt.c file for what this toku_redirect_brt does
int toku_dictionary_redirect_abort(struct brt_header *old_h, struct brt_header *new_h, TOKUTXN txn); int toku_dictionary_redirect_abort(struct brt_header *old_h, struct brt_header *new_h, TOKUTXN txn) __attribute__ ((warn_unused_result));
u_int32_t toku_serialize_descriptor_size(const DESCRIPTOR desc); u_int32_t toku_serialize_descriptor_size(const DESCRIPTOR desc);
int toku_brt_create(BRT *); int toku_brt_create(BRT *) __attribute__ ((warn_unused_result));
int toku_brt_set_flags(BRT, unsigned int flags); int toku_brt_set_flags(BRT, unsigned int flags) __attribute__ ((warn_unused_result));
int toku_brt_get_flags(BRT, unsigned int *flags); int toku_brt_get_flags(BRT, unsigned int *flags) __attribute__ ((warn_unused_result));
int toku_brt_set_descriptor (BRT t, u_int32_t version, const DBT* descriptor); int toku_brt_set_descriptor (BRT t, u_int32_t version, const DBT* descriptor) __attribute__ ((warn_unused_result));
int toku_brt_set_nodesize(BRT, unsigned int nodesize); int toku_brt_set_nodesize(BRT, unsigned int nodesize) __attribute__ ((warn_unused_result));
int toku_brt_get_nodesize(BRT, unsigned int *nodesize); int toku_brt_get_nodesize(BRT, unsigned int *nodesize) __attribute__ ((warn_unused_result));
int toku_brt_set_bt_compare(BRT, brt_compare_func); int toku_brt_set_bt_compare(BRT, brt_compare_func) __attribute__ ((warn_unused_result));
int toku_brt_set_upsert(BRT brt, int (*upsert)(DB *, const DBT *key, const DBT *upserted_val, const DBT *upserted_extra, const DBT *prev_val,
void (*set_val)(const DBT *new_val, void *set_extra), void *set_extra))
__attribute__ ((warn_unused_result));
brt_compare_func toku_brt_get_bt_compare (BRT brt); brt_compare_func toku_brt_get_bt_compare (BRT brt);
int brt_set_cachetable(BRT, CACHETABLE); int brt_set_cachetable(BRT, CACHETABLE);
int toku_brt_open(BRT, const char *fname_in_env, int toku_brt_open(BRT, const char *fname_in_env,
int is_create, int only_create, CACHETABLE ct, TOKUTXN txn, DB *db); int is_create, int only_create, CACHETABLE ct, TOKUTXN txn, DB *db) __attribute__ ((warn_unused_result));
int toku_brt_open_recovery(BRT, const char *fname_in_env, int toku_brt_open_recovery(BRT, const char *fname_in_env,
int is_create, int only_create, CACHETABLE ct, TOKUTXN txn, DB *db, FILENUM use_filenum); int is_create, int only_create, CACHETABLE ct, TOKUTXN txn, DB *db, FILENUM use_filenum) __attribute__ ((warn_unused_result));
int toku_brt_remove_subdb(BRT brt, const char *dbname, u_int32_t flags); int toku_brt_remove_subdb(BRT brt, const char *dbname, u_int32_t flags) __attribute__ ((warn_unused_result));
int toku_brt_broadcast_commit_all (BRT brt); int toku_brt_broadcast_commit_all (BRT brt) __attribute__ ((warn_unused_result));
int toku_brt_lookup (BRT brt, DBT *k, BRT_GET_CALLBACK_FUNCTION getf, void *getf_v); int toku_brt_lookup (BRT brt, DBT *k, BRT_GET_CALLBACK_FUNCTION getf, void *getf_v) __attribute__ ((warn_unused_result));
// Effect: Insert a key and data pair into a brt // Effect: Insert a key and data pair into a brt
// Returns 0 if successful // Returns 0 if successful
int toku_brt_insert (BRT brt, DBT *k, DBT *v, TOKUTXN txn); int toku_brt_insert (BRT brt, DBT *k, DBT *v, TOKUTXN txn) __attribute__ ((warn_unused_result));
int toku_brt_optimize (BRT brt); int toku_brt_optimize (BRT brt) __attribute__ ((warn_unused_result));
// Effect: Insert a key and data pair into a brt if the oplsn is newer than the brt lsn. This function is called during recovery. // Effect: Insert a key and data pair into a brt if the oplsn is newer than the brt lsn. This function is called during recovery.
// Returns 0 if successful // Returns 0 if successful
int toku_brt_maybe_insert (BRT brt, DBT *k, DBT *v, TOKUTXN txn, BOOL oplsn_valid, LSN oplsn, int do_logging, enum brt_msg_type type); int toku_brt_maybe_insert (BRT brt, DBT *k, DBT *v, TOKUTXN txn, BOOL oplsn_valid, LSN oplsn, int do_logging, enum brt_msg_type type) __attribute__ ((warn_unused_result));
int toku_brt_load_recovery(TOKUTXN txn, char const * old_iname, char const * new_iname, int do_fsync, int do_log, LSN *load_lsn); int toku_brt_load_recovery(TOKUTXN txn, char const * old_iname, char const * new_iname, int do_fsync, int do_log, LSN *load_lsn) __attribute__ ((warn_unused_result));
int toku_brt_load(BRT brt, TOKUTXN txn, char const * new_iname, int do_fsync, LSN *get_lsn); int toku_brt_load(BRT brt, TOKUTXN txn, char const * new_iname, int do_fsync, LSN *get_lsn) __attribute__ ((warn_unused_result));
int toku_brt_log_put_multiple (TOKUTXN txn, BRT src_brt, BRT *brts, int num_brts, const DBT *key, const DBT *val); int toku_brt_log_put_multiple (TOKUTXN txn, BRT src_brt, BRT *brts, int num_brts, const DBT *key, const DBT *val) __attribute__ ((warn_unused_result));
int toku_brt_log_del_multiple (TOKUTXN txn, BRT src_brt, BRT *brts, int num_brts, const DBT *key, const DBT *val); int toku_brt_log_del_multiple (TOKUTXN txn, BRT src_brt, BRT *brts, int num_brts, const DBT *key, const DBT *val) __attribute__ ((warn_unused_result));
// Effect: Delete a key from a brt // Effect: Delete a key from a brt
// Returns 0 if successful // Returns 0 if successful
int toku_brt_delete (BRT brt, DBT *k, TOKUTXN txn); int toku_brt_delete (BRT brt, DBT *k, TOKUTXN txn) __attribute__ ((warn_unused_result));
// Effect: Delete a key from a brt if the oplsn is newer than the brt lsn. This function is called during recovery. // Effect: Delete a key from a brt if the oplsn is newer than the brt lsn. This function is called during recovery.
// Returns 0 if successful // Returns 0 if successful
int toku_brt_maybe_delete (BRT brt, DBT *k, TOKUTXN txn, BOOL oplsn_valid, LSN oplsn, int do_logging); int toku_brt_maybe_delete (BRT brt, DBT *k, TOKUTXN txn, BOOL oplsn_valid, LSN oplsn, int do_logging) __attribute__ ((warn_unused_result));
// Effect: Delete a pair only if both k and v are equal according to the comparison function. // Effect: Delete a pair only if both k and v are equal according to the comparison function.
// Returns 0 if successful // Returns 0 if successful
int toku_brt_delete_both (BRT brt, DBT *k, DBT *v, TOKUTXN txn); int toku_brt_delete_both (BRT brt, DBT *k, DBT *v, TOKUTXN txn) __attribute__ ((warn_unused_result));
// Effect: Delete a pair only if both k and v are equal according to the comparison function and the // Effect: Delete a pair only if both k and v are equal according to the comparison function and the
// oplsn is newer than the brt lsn. This function is called by recovery. // oplsn is newer than the brt lsn. This function is called by recovery.
// Returns 0 if successful // Returns 0 if successful
int toku_brt_maybe_delete_both (BRT brt, DBT *k, DBT *v, TOKUTXN txn, BOOL oplsn_valid, LSN oplsn); int toku_brt_maybe_delete_both (BRT brt, DBT *k, DBT *v, TOKUTXN txn, BOOL oplsn_valid, LSN oplsn) __attribute__ ((warn_unused_result));
int toku_brt_db_delay_closed (BRT brt, DB* db, int (*close_db)(DB*, u_int32_t), u_int32_t close_flags); int toku_brt_db_delay_closed (BRT brt, DB* db, int (*close_db)(DB*, u_int32_t), u_int32_t close_flags) __attribute__ ((warn_unused_result));
int toku_close_brt (BRT, char **error_string); int toku_close_brt (BRT, char **error_string) __attribute__ ((warn_unused_result));
int toku_close_brt_lsn (BRT brt, char **error_string, BOOL oplsn_valid, LSN oplsn); int toku_close_brt_lsn (BRT brt, char **error_string, BOOL oplsn_valid, LSN oplsn) __attribute__ ((warn_unused_result));
int toku_brt_set_panic(BRT brt, int panic, char *panic_string); int toku_brt_set_panic(BRT brt, int panic, char *panic_string) __attribute__ ((warn_unused_result));
int toku_dump_brt (FILE *,BRT brt); int toku_dump_brt (FILE *,BRT brt) __attribute__ ((warn_unused_result));
void brt_fsync (BRT); /* fsync, but don't clear the caches. */ void brt_fsync (BRT); /* fsync, but don't clear the caches. */
void brt_flush (BRT); /* fsync and clear the caches. */ void brt_flush (BRT); /* fsync and clear the caches. */
int toku_brt_get_cursor_count (BRT brt); int toku_brt_get_cursor_count (BRT brt) __attribute__ ((warn_unused_result));
// get the number of cursors in the tree // get the number of cursors in the tree
// returns: the number of cursors. // returns: the number of cursors.
// asserts: the number of cursors >= 0. // asserts: the number of cursors >= 0.
int toku_brt_flush (BRT brt); int toku_brt_flush (BRT brt) __attribute__ ((warn_unused_result));
// effect: the tree's cachefile is flushed // effect: the tree's cachefile is flushed
// returns: 0 if success // returns: 0 if success
int toku_brt_truncate (BRT brt); int toku_brt_truncate (BRT brt) __attribute__ ((warn_unused_result));
// effect: remove everything from the tree // effect: remove everything from the tree
// returns: 0 if success // returns: 0 if success
LSN toku_brt_checkpoint_lsn(BRT brt); LSN toku_brt_checkpoint_lsn(BRT brt) __attribute__ ((warn_unused_result));
// create and initialize a cache table // create and initialize a cache table
// cachesize is the upper limit on the size of the size of the values in the table // cachesize is the upper limit on the size of the size of the values in the table
// pass 0 if you want the default // pass 0 if you want the default
int toku_brt_create_cachetable(CACHETABLE *t, long cachesize, LSN initial_lsn, TOKULOGGER); int toku_brt_create_cachetable(CACHETABLE *t, long cachesize, LSN initial_lsn, TOKULOGGER) __attribute__ ((warn_unused_result));
extern int toku_brt_debug_mode; extern int toku_brt_debug_mode;
int toku_verify_brt (BRT brt); int toku_verify_brt (BRT brt) __attribute__ ((warn_unused_result));
//int show_brt_blocknumbers(BRT); //int show_brt_blocknumbers(BRT);
typedef struct brt_cursor *BRT_CURSOR; typedef struct brt_cursor *BRT_CURSOR;
int toku_brt_cursor (BRT, BRT_CURSOR*, TOKUTXN, BOOL); int toku_brt_cursor (BRT, BRT_CURSOR*, TOKUTXN, BOOL) __attribute__ ((warn_unused_result));
// get is deprecated in favor of the individual functions below // get is deprecated in favor of the individual functions below
int toku_brt_cursor_get (BRT_CURSOR cursor, DBT *key, BRT_GET_CALLBACK_FUNCTION getf, void *getf_v, int get_flags); int toku_brt_cursor_get (BRT_CURSOR cursor, DBT *key, BRT_GET_CALLBACK_FUNCTION getf, void *getf_v, int get_flags) __attribute__ ((warn_unused_result));
int toku_brt_flatten(BRT, TOKUTXN ttxn); int toku_brt_flatten(BRT, TOKUTXN ttxn) __attribute__ ((warn_unused_result));
int toku_brt_cursor_first(BRT_CURSOR cursor, BRT_GET_CALLBACK_FUNCTION getf, void *getf_v); int toku_brt_cursor_first(BRT_CURSOR cursor, BRT_GET_CALLBACK_FUNCTION getf, void *getf_v) __attribute__ ((warn_unused_result));
int toku_brt_cursor_last(BRT_CURSOR cursor, BRT_GET_CALLBACK_FUNCTION getf, void *getf_v); int toku_brt_cursor_last(BRT_CURSOR cursor, BRT_GET_CALLBACK_FUNCTION getf, void *getf_v) __attribute__ ((warn_unused_result));
int toku_brt_cursor_next(BRT_CURSOR cursor, BRT_GET_CALLBACK_FUNCTION getf, void *getf_v); int toku_brt_cursor_next(BRT_CURSOR cursor, BRT_GET_CALLBACK_FUNCTION getf, void *getf_v) __attribute__ ((warn_unused_result));
int toku_brt_cursor_next_nodup(BRT_CURSOR cursor, BRT_GET_CALLBACK_FUNCTION getf, void *getf_v); int toku_brt_cursor_next_nodup(BRT_CURSOR cursor, BRT_GET_CALLBACK_FUNCTION getf, void *getf_v) __attribute__ ((warn_unused_result));
int toku_brt_cursor_prev(BRT_CURSOR cursor, BRT_GET_CALLBACK_FUNCTION getf, void *getf_v); int toku_brt_cursor_prev(BRT_CURSOR cursor, BRT_GET_CALLBACK_FUNCTION getf, void *getf_v) __attribute__ ((warn_unused_result));
int toku_brt_cursor_prev_nodup(BRT_CURSOR cursor, BRT_GET_CALLBACK_FUNCTION getf, void *getf_v); int toku_brt_cursor_prev_nodup(BRT_CURSOR cursor, BRT_GET_CALLBACK_FUNCTION getf, void *getf_v) __attribute__ ((warn_unused_result));
int toku_brt_cursor_current(BRT_CURSOR cursor, int op, BRT_GET_CALLBACK_FUNCTION getf, void *getf_v); int toku_brt_cursor_current(BRT_CURSOR cursor, int op, BRT_GET_CALLBACK_FUNCTION getf, void *getf_v) __attribute__ ((warn_unused_result));
int toku_brt_cursor_set(BRT_CURSOR cursor, DBT *key, BRT_GET_CALLBACK_FUNCTION getf, void *getf_v); int toku_brt_cursor_set(BRT_CURSOR cursor, DBT *key, BRT_GET_CALLBACK_FUNCTION getf, void *getf_v) __attribute__ ((warn_unused_result));
int toku_brt_cursor_set_range(BRT_CURSOR cursor, DBT *key, BRT_GET_CALLBACK_FUNCTION getf, void *getf_v); int toku_brt_cursor_set_range(BRT_CURSOR cursor, DBT *key, BRT_GET_CALLBACK_FUNCTION getf, void *getf_v) __attribute__ ((warn_unused_result));
int toku_brt_cursor_set_range_reverse(BRT_CURSOR cursor, DBT *key, BRT_GET_CALLBACK_FUNCTION getf, void *getf_v); int toku_brt_cursor_set_range_reverse(BRT_CURSOR cursor, DBT *key, BRT_GET_CALLBACK_FUNCTION getf, void *getf_v) __attribute__ ((warn_unused_result));
int toku_brt_cursor_get_both_range(BRT_CURSOR cursor, DBT *key, DBT *val, BRT_GET_CALLBACK_FUNCTION getf, void *getf_v); int toku_brt_cursor_get_both_range(BRT_CURSOR cursor, DBT *key, DBT *val, BRT_GET_CALLBACK_FUNCTION getf, void *getf_v) __attribute__ ((warn_unused_result));
int toku_brt_cursor_get_both_range_reverse(BRT_CURSOR cursor, DBT *key, DBT *val, BRT_GET_CALLBACK_FUNCTION getf, void *getf_v); int toku_brt_cursor_get_both_range_reverse(BRT_CURSOR cursor, DBT *key, DBT *val, BRT_GET_CALLBACK_FUNCTION getf, void *getf_v) __attribute__ ((warn_unused_result));
int toku_brt_cursor_delete(BRT_CURSOR cursor, int flags, TOKUTXN); int toku_brt_cursor_delete(BRT_CURSOR cursor, int flags, TOKUTXN) __attribute__ ((warn_unused_result));
int toku_brt_cursor_close (BRT_CURSOR curs); int toku_brt_cursor_close (BRT_CURSOR curs) __attribute__ ((warn_unused_result));
BOOL toku_brt_cursor_uninitialized(BRT_CURSOR c); BOOL toku_brt_cursor_uninitialized(BRT_CURSOR c) __attribute__ ((warn_unused_result));
void toku_brt_cursor_peek(BRT_CURSOR cursor, const DBT **pkey, const DBT **pval); void toku_brt_cursor_peek(BRT_CURSOR cursor, const DBT **pkey, const DBT **pval);
typedef struct brtenv *BRTENV; typedef struct brtenv *BRTENV;
int brtenv_checkpoint (BRTENV env); int brtenv_checkpoint (BRTENV env) __attribute__ ((warn_unused_result));
extern int toku_brt_do_push_cmd; // control whether push occurs eagerly. extern int toku_brt_do_push_cmd; // control whether push occurs eagerly.
...@@ -163,7 +166,7 @@ int toku_brt_dbt_set(DBT* key, DBT* key_source); ...@@ -163,7 +166,7 @@ int toku_brt_dbt_set(DBT* key, DBT* key_source);
DICTIONARY_ID toku_brt_get_dictionary_id(BRT); DICTIONARY_ID toku_brt_get_dictionary_id(BRT);
int toku_brt_height_of_root(BRT, int *height); // for an open brt, return the current height. int toku_brt_height_of_root(BRT, int *height) __attribute__ ((warn_unused_result)); // for an open brt, return the current height.
enum brt_header_flags { enum brt_header_flags {
//TOKU_DB_DUP = (1<<0), //Obsolete #2862 //TOKU_DB_DUP = (1<<0), //Obsolete #2862
...@@ -172,7 +175,7 @@ enum brt_header_flags { ...@@ -172,7 +175,7 @@ enum brt_header_flags {
//TOKU_DB_VALCMP_BUILTIN = (1<<3), //TOKU_DB_VALCMP_BUILTIN = (1<<3),
}; };
int toku_brt_keyrange (BRT brt, DBT *key, u_int64_t *less, u_int64_t *equal, u_int64_t *greater); int toku_brt_keyrange (BRT brt, DBT *key, u_int64_t *less, u_int64_t *equal, u_int64_t *greater) __attribute__ ((warn_unused_result));
struct brtstat64_s { struct brtstat64_s {
u_int64_t nkeys; /* estimate how many unique keys (even when flattened this may be an estimate) */ u_int64_t nkeys; /* estimate how many unique keys (even when flattened this may be an estimate) */
u_int64_t ndata; /* estimate the number of pairs (exact when flattened and committed) */ u_int64_t ndata; /* estimate the number of pairs (exact when flattened and committed) */
...@@ -182,21 +185,23 @@ struct brtstat64_s { ...@@ -182,21 +185,23 @@ struct brtstat64_s {
}; };
int toku_brt_stat64 (BRT, TOKUTXN, int toku_brt_stat64 (BRT, TOKUTXN,
struct brtstat64_s *stat struct brtstat64_s *stat
); )
__attribute__ ((warn_unused_result));
int toku_brt_init(void (*ydb_lock_callback)(void), int toku_brt_init(void (*ydb_lock_callback)(void),
void (*ydb_unlock_callback)(void), void (*ydb_unlock_callback)(void),
void (*db_set_brt)(DB*,BRT)); void (*db_set_brt)(DB*,BRT))
int toku_brt_destroy(void); __attribute__ ((warn_unused_result));
int toku_pwrite_lock_init(void); int toku_brt_destroy(void) __attribute__ ((warn_unused_result));
int toku_pwrite_lock_destroy(void); int toku_pwrite_lock_init(void) __attribute__ ((warn_unused_result));
int toku_brt_serialize_init(void); int toku_pwrite_lock_destroy(void) __attribute__ ((warn_unused_result));
int toku_brt_serialize_destroy(void); int toku_brt_serialize_init(void) __attribute__ ((warn_unused_result));
int toku_brt_serialize_destroy(void) __attribute__ ((warn_unused_result));
void toku_maybe_truncate_cachefile (CACHEFILE cf, int fd, u_int64_t size_used); void toku_maybe_truncate_cachefile (CACHEFILE cf, int fd, u_int64_t size_used);
// Effect: truncate file if overallocated by at least 32MiB // Effect: truncate file if overallocated by at least 32MiB
int maybe_preallocate_in_file (int fd, u_int64_t size); int maybe_preallocate_in_file (int fd, u_int64_t size) __attribute__ ((warn_unused_result));
// Effect: If file size is less than SIZE, make it bigger by either doubling it or growing by 16MB whichever is less. // Effect: If file size is less than SIZE, make it bigger by either doubling it or growing by 16MB whichever is less.
void toku_brt_header_suppress_rollbacks(struct brt_header *h, TOKUTXN txn); void toku_brt_header_suppress_rollbacks(struct brt_header *h, TOKUTXN txn);
...@@ -208,22 +213,22 @@ void toku_brt_suppress_recovery_logs (BRT brt, TOKUTXN txn); ...@@ -208,22 +213,22 @@ void toku_brt_suppress_recovery_logs (BRT brt, TOKUTXN txn);
// implies: txnid_that_created_or_locked_when_empty matches txn // implies: txnid_that_created_or_locked_when_empty matches txn
// implies: toku_txn_note_brt(brt, txn) has been called // implies: toku_txn_note_brt(brt, txn) has been called
int toku_brt_zombie_needed (BRT brt); int toku_brt_zombie_needed (BRT brt) __attribute__ ((warn_unused_result));
int toku_brt_get_fragmentation(BRT brt, TOKU_DB_FRAGMENTATION report); int toku_brt_get_fragmentation(BRT brt, TOKU_DB_FRAGMENTATION report) __attribute__ ((warn_unused_result));
int toku_brt_header_set_panic(struct brt_header *h, int panic, char *panic_string); int toku_brt_header_set_panic(struct brt_header *h, int panic, char *panic_string) __attribute__ ((warn_unused_result));
BOOL toku_brt_is_empty (BRT brt, BOOL *try_again); BOOL toku_brt_is_empty (BRT brt, BOOL *try_again) __attribute__ ((warn_unused_result));
// Effect: Return TRUE iff the tree is empty. (However if *try_again is set to TRUE by toku_brt_is_empty, then the answer is inconclusive, and the function should // Effect: Return TRUE iff the tree is empty. (However if *try_again is set to TRUE by toku_brt_is_empty, then the answer is inconclusive, and the function should
// be tried again. It's a good idea to release the big ydb lock in this case. // be tried again. It's a good idea to release the big ydb lock in this case.
BOOL toku_brt_is_empty_fast (BRT brt); BOOL toku_brt_is_empty_fast (BRT brt) __attribute__ ((warn_unused_result));
// Effect: Return TRUE if there are no messages or leaf entries in the tree. If so, it's empty. If there are messages or leaf entries, we say it's not empty // Effect: Return TRUE if there are no messages or leaf entries in the tree. If so, it's empty. If there are messages or leaf entries, we say it's not empty
// even though if we were to optimize the tree it might turn out that they are empty. // even though if we were to optimize the tree it might turn out that they are empty.
double get_tdiff(void) __attribute__((__visibility__("default"))); double get_tdiff(void) __attribute__((__visibility__("default"))) __attribute__ ((warn_unused_result));
BOOL toku_brt_is_recovery_logging_suppressed (BRT); BOOL toku_brt_is_recovery_logging_suppressed (BRT) __attribute__ ((warn_unused_result));
//TODO: #1485 once we have multiple main threads, restore this code, analyze performance. //TODO: #1485 once we have multiple main threads, restore this code, analyze performance.
#ifndef TOKU_MULTIPLE_MAIN_THREADS #ifndef TOKU_MULTIPLE_MAIN_THREADS
#define TOKU_MULTIPLE_MAIN_THREADS 0 #define TOKU_MULTIPLE_MAIN_THREADS 0
......
...@@ -201,7 +201,8 @@ toku_logger_close_rollback(TOKULOGGER logger, BOOL recovery_failed) { ...@@ -201,7 +201,8 @@ toku_logger_close_rollback(TOKULOGGER logger, BOOL recovery_failed) {
struct brt_header *h = toku_cachefile_get_userdata(cf); struct brt_header *h = toku_cachefile_get_userdata(cf);
toku_brtheader_lock(h); toku_brtheader_lock(h);
if (!h->panic && recovery_failed) { if (!h->panic && recovery_failed) {
toku_brt_header_set_panic(h, EINVAL, "Recovery failed"); r = toku_brt_header_set_panic(h, EINVAL, "Recovery failed");
assert(r==0);
} }
//Verify it is safe to close it. //Verify it is safe to close it.
if (!h->panic) { //If paniced, it is safe to close. if (!h->panic) { //If paniced, it is safe to close.
......
...@@ -107,7 +107,8 @@ static void file_map_close_dictionaries(struct file_map *fmap, BOOL recovery_suc ...@@ -107,7 +107,8 @@ static void file_map_close_dictionaries(struct file_map *fmap, BOOL recovery_suc
assert(tuple->brt); assert(tuple->brt);
if (!recovery_succeeded) { if (!recovery_succeeded) {
// don't update the brt on close // don't update the brt on close
toku_brt_set_panic(tuple->brt, DB_RUNRECOVERY, "recovery failed"); r = toku_brt_set_panic(tuple->brt, DB_RUNRECOVERY, "recovery failed");
assert(r==0);
} }
//Logging is already back on. No need to pass LSN into close. //Logging is already back on. No need to pass LSN into close.
char *error_string = NULL; char *error_string = NULL;
...@@ -245,11 +246,14 @@ static int internal_recover_fopen_or_fcreate (RECOVER_ENV renv, BOOL must_create ...@@ -245,11 +246,14 @@ static int internal_recover_fopen_or_fcreate (RECOVER_ENV renv, BOOL must_create
r = toku_brt_create(&brt); r = toku_brt_create(&brt);
assert(r == 0); assert(r == 0);
toku_brt_set_flags(brt, treeflags); r = toku_brt_set_flags(brt, treeflags);
assert(r==0);
// set the key compare functions // set the key compare functions
if (!(treeflags & TOKU_DB_KEYCMP_BUILTIN) && renv->bt_compare) if (!(treeflags & TOKU_DB_KEYCMP_BUILTIN) && renv->bt_compare) {
toku_brt_set_bt_compare(brt, renv->bt_compare); r = toku_brt_set_bt_compare(brt, renv->bt_compare);
assert(r==0);
}
// TODO mode (FUTURE FEATURE) // TODO mode (FUTURE FEATURE)
mode = mode; mode = mode;
......
...@@ -18,9 +18,15 @@ static void dummy_set_brt(DB *db UU(), BRT brt UU()) {} ...@@ -18,9 +18,15 @@ static void dummy_set_brt(DB *db UU(), BRT brt UU()) {}
int int
main(int argc, const char *const argv[]) { main(int argc, const char *const argv[]) {
toku_brt_init(dummy, dummy, dummy_set_brt); {
int rr = toku_brt_init(dummy, dummy, dummy_set_brt);
assert(rr==0);
}
int r = recovery_main(argc, argv); int r = recovery_main(argc, argv);
toku_brt_destroy(); {
int rr = toku_brt_destroy();
assert(rr=0);
}
return r; return r;
} }
......
...@@ -19,7 +19,7 @@ static void test_dump_empty_db (void) { ...@@ -19,7 +19,7 @@ static void test_dump_empty_db (void) {
unlink(fname); unlink(fname);
r = toku_open_brt(fname, 1, &t, 1024, ct, null_txn, toku_builtin_compare_fun, null_db); r = toku_open_brt(fname, 1, &t, 1024, ct, null_txn, toku_builtin_compare_fun, null_db);
assert(r==0); assert(r==0);
if (verbose) toku_dump_brt(stdout, t); if (verbose) { r=toku_dump_brt(stdout, t); assert(r==0); }
r = toku_close_brt(t, 0); assert(r==0); r = toku_close_brt(t, 0); assert(r==0);
r = toku_cachetable_close(&ct); assert(r==0); r = toku_cachetable_close(&ct); assert(r==0);
...@@ -44,15 +44,15 @@ static void test_multiple_files_of_size (int size) { ...@@ -44,15 +44,15 @@ static void test_multiple_files_of_size (int size) {
DBT k,v; DBT k,v;
snprintf(key, 100, "key%d", i); snprintf(key, 100, "key%d", i);
snprintf(val, 100, "val%d", i); snprintf(val, 100, "val%d", i);
toku_brt_insert(t0, toku_fill_dbt(&k, key, 1+strlen(key)), toku_fill_dbt(&v, val, 1+strlen(val)), null_txn); r = toku_brt_insert(t0, toku_fill_dbt(&k, key, 1+strlen(key)), toku_fill_dbt(&v, val, 1+strlen(val)), null_txn); assert(r==0);
snprintf(val, 100, "Val%d", i); snprintf(val, 100, "Val%d", i);
toku_brt_insert(t1, toku_fill_dbt(&k, key, 1+strlen(key)), toku_fill_dbt(&v, val, 1+strlen(val)), null_txn); r = toku_brt_insert(t1, toku_fill_dbt(&k, key, 1+strlen(key)), toku_fill_dbt(&v, val, 1+strlen(val)), null_txn); assert(r==0);
} }
//toku_verify_brt(t0); //toku_verify_brt(t0);
//dump_brt(t0); //dump_brt(t0);
//dump_brt(t1); //dump_brt(t1);
toku_verify_brt(t0); r = toku_verify_brt(t0); assert(r==0);
toku_verify_brt(t1); r = toku_verify_brt(t1); assert(r==0);
r = toku_close_brt(t0, 0); assert(r==0); r = toku_close_brt(t0, 0); assert(r==0);
r = toku_close_brt(t1, 0); assert(r==0); r = toku_close_brt(t1, 0); assert(r==0);
...@@ -105,7 +105,8 @@ static void test_multiple_brts_one_db_one_file (void) { ...@@ -105,7 +105,8 @@ static void test_multiple_brts_one_db_one_file (void) {
DBT kb, vb; DBT kb, vb;
snprintf(k, 20, "key%d", i); snprintf(k, 20, "key%d", i);
snprintf(v, 20, "val%d", i); snprintf(v, 20, "val%d", i);
toku_brt_insert(trees[i], toku_fill_dbt(&kb, k, strlen(k)+1), toku_fill_dbt(&vb, v, strlen(v)+1), null_txn); r = toku_brt_insert(trees[i], toku_fill_dbt(&kb, k, strlen(k)+1), toku_fill_dbt(&vb, v, strlen(v)+1), null_txn);
assert(r==0);
} }
for (i=0; i<MANYN; i++) { for (i=0; i<MANYN; i++) {
char k[20],vexpect[20]; char k[20],vexpect[20];
...@@ -148,7 +149,8 @@ static void test_read_what_was_written (void) { ...@@ -148,7 +149,8 @@ static void test_read_what_was_written (void) {
/* See if we can put something in it. */ /* See if we can put something in it. */
{ {
DBT k,v; DBT k,v;
toku_brt_insert(brt, toku_fill_dbt(&k, "hello", 6), toku_fill_dbt(&v, "there", 6), null_txn); r = toku_brt_insert(brt, toku_fill_dbt(&k, "hello", 6), toku_fill_dbt(&v, "there", 6), null_txn);
assert(r==0);
} }
r = toku_close_brt(brt, 0); assert(r==0); r = toku_close_brt(brt, 0); assert(r==0);
...@@ -176,11 +178,13 @@ static void test_read_what_was_written (void) { ...@@ -176,11 +178,13 @@ static void test_read_what_was_written (void) {
int verify_result=toku_verify_brt(brt);; int verify_result=toku_verify_brt(brt);;
assert(verify_result==0); assert(verify_result==0);
} }
toku_brt_insert(brt, toku_fill_dbt(&k, key, strlen(key)+1), toku_fill_dbt(&v, val, strlen(val)+1), null_txn); r = toku_brt_insert(brt, toku_fill_dbt(&k, key, strlen(key)+1), toku_fill_dbt(&v, val, strlen(val)+1), null_txn);
assert(r==0);
if (i<600) { if (i<600) {
int verify_result=toku_verify_brt(brt); int verify_result=toku_verify_brt(brt);
if (verify_result) { if (verify_result) {
toku_dump_brt(stdout, brt); r = toku_dump_brt(stdout, brt);
assert(r==0);
assert(0); assert(0);
} }
{ {
...@@ -198,7 +202,8 @@ static void test_read_what_was_written (void) { ...@@ -198,7 +202,8 @@ static void test_read_what_was_written (void) {
if (verbose) printf("Now read them out\n"); if (verbose) printf("Now read them out\n");
//show_brt_blocknumbers(brt); //show_brt_blocknumbers(brt);
toku_verify_brt(brt); r = toku_verify_brt(brt);
assert(r==0);
//dump_brt(brt); //dump_brt(brt);
/* See if we can read them all out again. */ /* See if we can read them all out again. */
......
...@@ -20,7 +20,8 @@ static void test1 (void) { ...@@ -20,7 +20,8 @@ static void test1 (void) {
unlink(fname); unlink(fname);
r = toku_open_brt(fname, 1, &t, 1024, ct, null_txn, toku_builtin_compare_fun, null_db); r = toku_open_brt(fname, 1, &t, 1024, ct, null_txn, toku_builtin_compare_fun, null_db);
assert(r==0); assert(r==0);
toku_brt_insert(t, toku_fill_dbt(&k, "hello", 6), toku_fill_dbt(&v, "there", 6), null_txn); r = toku_brt_insert(t, toku_fill_dbt(&k, "hello", 6), toku_fill_dbt(&v, "there", 6), null_txn);
assert(r==0);
{ {
struct check_pair pair = {6, "hello", 6, "there", 0}; struct check_pair pair = {6, "hello", 6, "there", 0};
r = toku_brt_lookup(t, toku_fill_dbt(&k, "hello", 6), lookup_checkf, &pair); r = toku_brt_lookup(t, toku_fill_dbt(&k, "hello", 6), lookup_checkf, &pair);
......
...@@ -26,11 +26,13 @@ static void test2 (int memcheck, int limit) { ...@@ -26,11 +26,13 @@ static void test2 (int memcheck, int limit) {
char key[100],val[100]; char key[100],val[100];
snprintf(key,100,"hello%d",i); snprintf(key,100,"hello%d",i);
snprintf(val,100,"there%d",i); snprintf(val,100,"there%d",i);
toku_brt_insert(t, toku_fill_dbt(&k, key, 1+strlen(key)), toku_fill_dbt(&v, val, 1+strlen(val)), null_txn); r = toku_brt_insert(t, toku_fill_dbt(&k, key, 1+strlen(key)), toku_fill_dbt(&v, val, 1+strlen(val)), null_txn);
assert(r==0);
r = toku_verify_brt(t); assert(r==0); r = toku_verify_brt(t); assert(r==0);
//printf("%s:%d did insert %d\n", __FILE__, __LINE__, i); //printf("%s:%d did insert %d\n", __FILE__, __LINE__, i);
if (0) { if (0) {
toku_brt_flush(t); r = toku_brt_flush(t);
assert(r==0);
{ {
int n = toku_get_n_items_malloced(); int n = toku_get_n_items_malloced();
if (verbose) printf("%s:%d i=%d n_items_malloced=%d\n", __FILE__, __LINE__, i, n); if (verbose) printf("%s:%d i=%d n_items_malloced=%d\n", __FILE__, __LINE__, i, n);
......
...@@ -28,7 +28,8 @@ static void test3 (int nodesize, int count, int memcheck) { ...@@ -28,7 +28,8 @@ static void test3 (int nodesize, int count, int memcheck) {
DBT k,v; DBT k,v;
snprintf(key,100,"hello%d",i); snprintf(key,100,"hello%d",i);
snprintf(val,100,"there%d",i); snprintf(val,100,"there%d",i);
toku_brt_insert(t, toku_fill_dbt(&k, key, 1+strlen(key)), toku_fill_dbt(&v, val, 1+strlen(val)), null_txn); r = toku_brt_insert(t, toku_fill_dbt(&k, key, 1+strlen(key)), toku_fill_dbt(&v, val, 1+strlen(val)), null_txn);
assert(r==0);
} }
r = toku_verify_brt(t); assert(r==0); r = toku_verify_brt(t); assert(r==0);
r = toku_close_brt(t, 0); assert(r==0); r = toku_close_brt(t, 0); assert(r==0);
......
...@@ -28,7 +28,8 @@ static void test4 (int nodesize, int count, int memcheck) { ...@@ -28,7 +28,8 @@ static void test4 (int nodesize, int count, int memcheck) {
DBT k,v; DBT k,v;
snprintf(key,100,"hello%d",rv); snprintf(key,100,"hello%d",rv);
snprintf(val,100,"there%d",i); snprintf(val,100,"there%d",i);
toku_brt_insert(t, toku_fill_dbt(&k, key, 1+strlen(key)), toku_fill_dbt(&v, val, 1+strlen(val)), null_txn); r = toku_brt_insert(t, toku_fill_dbt(&k, key, 1+strlen(key)), toku_fill_dbt(&v, val, 1+strlen(val)), null_txn);
assert(r==0);
} }
r = toku_verify_brt(t); assert(r==0); r = toku_verify_brt(t); assert(r==0);
r = toku_close_brt(t, 0); assert(r==0); r = toku_close_brt(t, 0); assert(r==0);
......
...@@ -30,7 +30,8 @@ static void test5 (void) { ...@@ -30,7 +30,8 @@ static void test5 (void) {
snprintf(key, 100, "key%d", rk); snprintf(key, 100, "key%d", rk);
snprintf(val, 100, "val%d", rv); snprintf(val, 100, "val%d", rv);
DBT k,v; DBT k,v;
toku_brt_insert(t, toku_fill_dbt(&k, key, 1+strlen(key)), toku_fill_dbt(&v, val, 1+strlen(val)), null_txn); r = toku_brt_insert(t, toku_fill_dbt(&k, key, 1+strlen(key)), toku_fill_dbt(&v, val, 1+strlen(val)), null_txn);
assert(r==0);
} }
if (verbose) printf("\n"); if (verbose) printf("\n");
for (i=0; i<limit/2; i++) { for (i=0; i<limit/2; i++) {
......
...@@ -51,7 +51,8 @@ static void verify_dbfile(int n, const char *name) { ...@@ -51,7 +51,8 @@ static void verify_dbfile(int n, const char *name) {
TOKUTXN const null_txn = NULL; TOKUTXN const null_txn = NULL;
BRT t = NULL; BRT t = NULL;
r = toku_brt_create(&t); assert(r == 0); r = toku_brt_create(&t); assert(r == 0);
r = toku_brt_set_bt_compare(t, compare_ints); assert(r == 0); r = toku_brt_set_bt_compare(t, compare_ints);
assert(r==0);
r = toku_brt_open(t, name, 0, 0, ct, null_txn, 0); assert(r==0); r = toku_brt_open(t, name, 0, 0, ct, null_txn, 0); assert(r==0);
BRT_CURSOR cursor = NULL; BRT_CURSOR cursor = NULL;
......
...@@ -250,7 +250,7 @@ static void verify_dbfile(int n, int sorted_keys[], const char *sorted_vals[], c ...@@ -250,7 +250,7 @@ static void verify_dbfile(int n, int sorted_keys[], const char *sorted_vals[], c
TOKUTXN const null_txn = NULL; TOKUTXN const null_txn = NULL;
BRT t = NULL; BRT t = NULL;
r = toku_brt_create(&t); assert(r == 0); r = toku_brt_create(&t); assert(r == 0);
r = toku_brt_set_bt_compare(t, compare_ints); assert(r == 0); r = toku_brt_set_bt_compare(t, compare_ints); assert(r==0);
r = toku_brt_open(t, name, 0, 0, ct, null_txn, 0); assert(r==0); r = toku_brt_open(t, name, 0, 0, ct, null_txn, 0); assert(r==0);
BRT_CURSOR cursor = NULL; BRT_CURSOR cursor = NULL;
......
...@@ -28,7 +28,8 @@ test_overflow (void) { ...@@ -28,7 +28,8 @@ test_overflow (void) {
int i; int i;
for (i=0; i<8; i++) { for (i=0; i<8; i++) {
char key[]={(char)('a'+i), 0}; char key[]={(char)('a'+i), 0};
toku_brt_insert(t, toku_fill_dbt(&k, key, 2), toku_fill_dbt(&v,buf,sizeof(buf)), null_txn); r = toku_brt_insert(t, toku_fill_dbt(&k, key, 2), toku_fill_dbt(&v,buf,sizeof(buf)), null_txn);
assert(r=0);
} }
r = toku_close_brt(t, 0); assert(r==0); r = toku_close_brt(t, 0); assert(r==0);
r = toku_cachetable_close(&ct); assert(r==0); r = toku_cachetable_close(&ct); assert(r==0);
......
...@@ -24,7 +24,8 @@ test_main(int argc, const char *argv[]) { ...@@ -24,7 +24,8 @@ test_main(int argc, const char *argv[]) {
DBT k,v; DBT k,v;
snprintf(key, 100, "key%d", i); snprintf(key, 100, "key%d", i);
snprintf(val, 100, "val%d", i); snprintf(val, 100, "val%d", i);
toku_brt_insert(t, toku_fill_dbt(&k, key, 1+strlen(key)), toku_fill_dbt(&v, val, 1+strlen(val)), null_txn); r = toku_brt_insert(t, toku_fill_dbt(&k, key, 1+strlen(key)), toku_fill_dbt(&v, val, 1+strlen(val)), null_txn);
assert(r==0);
} }
r = toku_dump_brt(f, t); assert(r==0); r = toku_dump_brt(f, t); assert(r==0);
r = toku_close_brt(t, 0); assert(r==0); r = toku_close_brt(t, 0); assert(r==0);
......
...@@ -35,7 +35,10 @@ test_main (int argc __attribute__((__unused__)), const char *argv[] __attribute_ ...@@ -35,7 +35,10 @@ test_main (int argc __attribute__((__unused__)), const char *argv[] __attribute_
int r = toku_os_get_file_size(fd, &file_size); int r = toku_os_get_file_size(fd, &file_size);
assert(r==0); assert(r==0);
} }
maybe_preallocate_in_file(fd, 1000); {
int r = maybe_preallocate_in_file(fd, 1000);
assert(r==0);
}
int64_t file_size2; int64_t file_size2;
{ {
int r = toku_os_get_file_size(fd, &file_size2); int r = toku_os_get_file_size(fd, &file_size2);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment