Commit c06de19e authored by John Esmet's avatar John Esmet

FT-258 Remove another malloc from the cursor create path. Queries using

db->getf_set now perform zero mallocs. Also, move the is_temporary
bit into the cursor constructor.
parent 0fbb5fb3
...@@ -612,6 +612,7 @@ static void print_dbc_struct (void) { ...@@ -612,6 +612,7 @@ static void print_dbc_struct (void) {
"int (*c_set_bounds)(DBC*, const DBT*, const DBT*, bool pre_acquire, int out_of_range_error)", "int (*c_set_bounds)(DBC*, const DBT*, const DBT*, bool pre_acquire, int out_of_range_error)",
"void (*c_set_check_interrupt_callback)(DBC*, bool (*)(void*), void *)", "void (*c_set_check_interrupt_callback)(DBC*, bool (*)(void*), void *)",
"void (*c_remove_restriction)(DBC*)", "void (*c_remove_restriction)(DBC*)",
"char _internal[512]",
NULL}; NULL};
sort_and_dump_fields("dbc", false, extra); sort_and_dump_fields("dbc", false, extra);
} }
......
...@@ -94,7 +94,9 @@ PATENT RIGHTS GRANT: ...@@ -94,7 +94,9 @@ PATENT RIGHTS GRANT:
#include "ft/ybt.h" #include "ft/ybt.h"
int toku_ft_cursor_create(FT_HANDLE ft_handle, FT_CURSOR cursor, TOKUTXN ttxn, int toku_ft_cursor_create(FT_HANDLE ft_handle, FT_CURSOR cursor, TOKUTXN ttxn,
bool is_snapshot_read, bool disable_prefetching) { bool is_snapshot_read,
bool disable_prefetching,
bool is_temporary) {
if (is_snapshot_read) { if (is_snapshot_read) {
invariant(ttxn != NULL); invariant(ttxn != NULL);
int accepted = toku_txn_reads_txnid(ft_handle->ft->h->root_xid_that_created, ttxn); int accepted = toku_txn_reads_txnid(ft_handle->ft->h->root_xid_that_created, ttxn);
...@@ -106,9 +108,10 @@ int toku_ft_cursor_create(FT_HANDLE ft_handle, FT_CURSOR cursor, TOKUTXN ttxn, ...@@ -106,9 +108,10 @@ int toku_ft_cursor_create(FT_HANDLE ft_handle, FT_CURSOR cursor, TOKUTXN ttxn,
memset(cursor, 0, sizeof(*cursor)); memset(cursor, 0, sizeof(*cursor));
cursor->ft_handle = ft_handle; cursor->ft_handle = ft_handle;
cursor->is_snapshot_read = is_snapshot_read;
cursor->ttxn = ttxn; cursor->ttxn = ttxn;
cursor->is_snapshot_read = is_snapshot_read;
cursor->disable_prefetching = disable_prefetching; cursor->disable_prefetching = disable_prefetching;
cursor->is_temporary = is_temporary;
return 0; return 0;
} }
...@@ -123,7 +126,7 @@ void toku_ft_cursor_destroy(FT_CURSOR cursor) { ...@@ -123,7 +126,7 @@ void toku_ft_cursor_destroy(FT_CURSOR cursor) {
int toku_ft_cursor(FT_HANDLE ft_handle, FT_CURSOR *cursorptr, TOKUTXN ttxn, int toku_ft_cursor(FT_HANDLE ft_handle, FT_CURSOR *cursorptr, TOKUTXN ttxn,
bool is_snapshot_read, bool disable_prefetching) { bool is_snapshot_read, bool disable_prefetching) {
FT_CURSOR XCALLOC(cursor); FT_CURSOR XCALLOC(cursor);
int r = toku_ft_cursor_create(ft_handle, cursor, ttxn, is_snapshot_read, disable_prefetching); int r = toku_ft_cursor_create(ft_handle, cursor, ttxn, is_snapshot_read, disable_prefetching, false);
if (r == 0) { if (r == 0) {
*cursorptr = cursor; *cursorptr = cursor;
} else { } else {
...@@ -148,10 +151,6 @@ void toku_ft_cursor_set_check_interrupt_cb(FT_CURSOR cursor, FT_CHECK_INTERRUPT_ ...@@ -148,10 +151,6 @@ void toku_ft_cursor_set_check_interrupt_cb(FT_CURSOR cursor, FT_CHECK_INTERRUPT_
cursor->interrupt_cb_extra = extra; cursor->interrupt_cb_extra = extra;
} }
void toku_ft_cursor_set_temporary(FT_CURSOR cursor) {
cursor->is_temporary = true;
}
void toku_ft_cursor_set_leaf_mode(FT_CURSOR cursor) { void toku_ft_cursor_set_leaf_mode(FT_CURSOR cursor) {
cursor->is_leaf_mode = true; cursor->is_leaf_mode = true;
} }
......
...@@ -175,7 +175,10 @@ static inline void ft_search_finish(ft_search *search) { ...@@ -175,7 +175,10 @@ static inline void ft_search_finish(ft_search *search) {
} }
int toku_ft_cursor_create(FT_HANDLE ft_handle, FT_CURSOR cursor, TOKUTXN txn, bool, bool); int toku_ft_cursor_create(FT_HANDLE ft_handle, FT_CURSOR cursor, TOKUTXN txn,
bool is_snapshot_read,
bool disable_prefetching,
bool is_temporary);
void toku_ft_cursor_destroy(FT_CURSOR cursor); void toku_ft_cursor_destroy(FT_CURSOR cursor);
...@@ -189,9 +192,6 @@ bool toku_ft_cursor_not_set(FT_CURSOR cursor); ...@@ -189,9 +192,6 @@ bool toku_ft_cursor_not_set(FT_CURSOR cursor);
void toku_ft_cursor_set_leaf_mode(FT_CURSOR cursor); void toku_ft_cursor_set_leaf_mode(FT_CURSOR cursor);
// Sets a boolean on the ft cursor that prevents uncessary copying of the cursor duing a one query.
void toku_ft_cursor_set_temporary(FT_CURSOR cursor);
void toku_ft_cursor_remove_restriction(FT_CURSOR cursor); void toku_ft_cursor_remove_restriction(FT_CURSOR cursor);
void toku_ft_cursor_set_check_interrupt_cb(FT_CURSOR cursor, FT_CHECK_INTERRUPT_CALLBACK cb, void *extra); void toku_ft_cursor_set_check_interrupt_cb(FT_CURSOR cursor, FT_CHECK_INTERRUPT_CALLBACK cb, void *extra);
......
...@@ -290,12 +290,17 @@ struct __toku_dbc_internal { ...@@ -290,12 +290,17 @@ struct __toku_dbc_internal {
bool rmw; bool rmw;
}; };
struct __toku_dbc_external { static_assert(sizeof(__toku_dbc_internal) <= sizeof(((DBC *) nullptr)->_internal),
struct __toku_dbc external_part; "__toku_dbc_internal doesn't fit in the internal portion of a DBC");
struct __toku_dbc_internal internal_part;
}; static inline __toku_dbc_internal *dbc_struct_i(DBC *c) {
union dbc_union {
#define dbc_struct_i(x) (&((struct __toku_dbc_external *)x)->internal_part) __toku_dbc_internal *dbc_internal;
char *buf;
} u;
u.buf = c->_internal;
return u.dbc_internal;
}
static inline struct ft_cursor *dbc_ftcursor(DBC *c) { static inline struct ft_cursor *dbc_ftcursor(DBC *c) {
return &dbc_struct_i(c)->ftcursor; return &dbc_struct_i(c)->ftcursor;
......
...@@ -709,13 +709,19 @@ c_getf_set_range_reverse_callback(ITEMLEN keylen, bytevec key, ITEMLEN vallen, b ...@@ -709,13 +709,19 @@ c_getf_set_range_reverse_callback(ITEMLEN keylen, bytevec key, ITEMLEN vallen, b
return r; return r;
} }
// Close a cursor.
int toku_c_close(DBC *c) { int toku_c_close_internal(DBC *c) {
HANDLE_PANICKED_DB(c->dbp); HANDLE_PANICKED_DB(c->dbp);
HANDLE_CURSOR_ILLEGAL_WORKING_PARENT_TXN(c); HANDLE_CURSOR_ILLEGAL_WORKING_PARENT_TXN(c);
toku_ft_cursor_destroy(dbc_ftcursor(c)); toku_ft_cursor_destroy(dbc_ftcursor(c));
toku_sdbt_cleanup(&dbc_struct_i(c)->skey_s); toku_sdbt_cleanup(&dbc_struct_i(c)->skey_s);
toku_sdbt_cleanup(&dbc_struct_i(c)->sval_s); toku_sdbt_cleanup(&dbc_struct_i(c)->sval_s);
return 0;
}
// Close a cursor.
int toku_c_close(DBC *c) {
toku_c_close_internal(c);
toku_free(c); toku_free(c);
return 0; return 0;
} }
...@@ -828,7 +834,7 @@ toku_c_get(DBC* c, DBT* key, DBT* val, uint32_t flag) { ...@@ -828,7 +834,7 @@ toku_c_get(DBC* c, DBT* key, DBT* val, uint32_t flag) {
} }
int int
toku_db_cursor_internal(DB * db, DB_TXN * txn, DBC ** c, uint32_t flags, int is_temporary_cursor) { toku_db_cursor_internal(DB * db, DB_TXN * txn, DBC *c, uint32_t flags, int is_temporary_cursor) {
HANDLE_PANICKED_DB(db); HANDLE_PANICKED_DB(db);
HANDLE_DB_ILLEGAL_WORKING_PARENT_TXN(db, txn); HANDLE_DB_ILLEGAL_WORKING_PARENT_TXN(db, txn);
DB_ENV* env = db->dbenv; DB_ENV* env = db->dbenv;
...@@ -841,11 +847,7 @@ toku_db_cursor_internal(DB * db, DB_TXN * txn, DBC ** c, uint32_t flags, int is_ ...@@ -841,11 +847,7 @@ toku_db_cursor_internal(DB * db, DB_TXN * txn, DBC ** c, uint32_t flags, int is_
); );
} }
struct __toku_dbc_external *XMALLOC(eresult); // so the internal stuff is stuck on the end #define SCRS(name) c->name = name
memset(eresult, 0, sizeof(*eresult));
DBC *result = &eresult->external_part;
#define SCRS(name) result->name = name
SCRS(c_getf_first); SCRS(c_getf_first);
SCRS(c_getf_last); SCRS(c_getf_last);
SCRS(c_getf_next); SCRS(c_getf_next);
...@@ -859,59 +861,49 @@ toku_db_cursor_internal(DB * db, DB_TXN * txn, DBC ** c, uint32_t flags, int is_ ...@@ -859,59 +861,49 @@ toku_db_cursor_internal(DB * db, DB_TXN * txn, DBC ** c, uint32_t flags, int is_
SCRS(c_set_check_interrupt_callback); SCRS(c_set_check_interrupt_callback);
#undef SCRS #undef SCRS
result->c_get = toku_c_get; c->c_get = toku_c_get;
result->c_getf_set = toku_c_getf_set; c->c_getf_set = toku_c_getf_set;
result->c_close = toku_c_close; c->c_close = toku_c_close;
result->dbp = db; c->dbp = db;
dbc_struct_i(result)->txn = txn; dbc_struct_i(c)->txn = txn;
dbc_struct_i(result)->skey_s = (struct simple_dbt){0,0}; dbc_struct_i(c)->skey_s = (struct simple_dbt){0,0};
dbc_struct_i(result)->sval_s = (struct simple_dbt){0,0}; dbc_struct_i(c)->sval_s = (struct simple_dbt){0,0};
if (is_temporary_cursor) { if (is_temporary_cursor) {
dbc_struct_i(result)->skey = &db->i->skey; dbc_struct_i(c)->skey = &db->i->skey;
dbc_struct_i(result)->sval = &db->i->sval; dbc_struct_i(c)->sval = &db->i->sval;
} else { } else {
dbc_struct_i(result)->skey = &dbc_struct_i(result)->skey_s; dbc_struct_i(c)->skey = &dbc_struct_i(c)->skey_s;
dbc_struct_i(result)->sval = &dbc_struct_i(result)->sval_s; dbc_struct_i(c)->sval = &dbc_struct_i(c)->sval_s;
} }
if (flags & DB_SERIALIZABLE) { if (flags & DB_SERIALIZABLE) {
dbc_struct_i(result)->iso = TOKU_ISO_SERIALIZABLE; dbc_struct_i(c)->iso = TOKU_ISO_SERIALIZABLE;
} else { } else {
dbc_struct_i(result)->iso = txn ? db_txn_struct_i(txn)->iso : TOKU_ISO_SERIALIZABLE; dbc_struct_i(c)->iso = txn ? db_txn_struct_i(txn)->iso : TOKU_ISO_SERIALIZABLE;
} }
dbc_struct_i(result)->rmw = (flags & DB_RMW) != 0; dbc_struct_i(c)->rmw = (flags & DB_RMW) != 0;
bool is_snapshot_read = false; bool is_snapshot_read = false;
if (txn) { if (txn) {
is_snapshot_read = (dbc_struct_i(result)->iso == TOKU_ISO_READ_COMMITTED || is_snapshot_read = (dbc_struct_i(c)->iso == TOKU_ISO_READ_COMMITTED ||
dbc_struct_i(result)->iso == TOKU_ISO_SNAPSHOT); dbc_struct_i(c)->iso == TOKU_ISO_SNAPSHOT);
} }
int r = toku_ft_cursor_create( int r = toku_ft_cursor_create(
db->i->ft_handle, db->i->ft_handle,
dbc_ftcursor(result), dbc_ftcursor(c),
txn ? db_txn_struct_i(txn)->tokutxn : NULL, txn ? db_txn_struct_i(txn)->tokutxn : NULL,
is_snapshot_read, is_snapshot_read,
((flags & DBC_DISABLE_PREFETCHING) != 0) ((flags & DBC_DISABLE_PREFETCHING) != 0),
is_temporary_cursor != 0
); );
if (r == 0) { if (r != 0) {
// Set the is_temporary_cursor boolean inside the ftnode so
// that a query only needing one cursor will not perform
// unecessary malloc calls.
//
// TODO: Move me to toku_ft_cursor_create constructor
if (is_temporary_cursor) {
toku_ft_cursor_set_temporary(dbc_ftcursor(result));
}
*c = result;
} else {
invariant(r == TOKUDB_MVCC_DICTIONARY_TOO_NEW); invariant(r == TOKUDB_MVCC_DICTIONARY_TOO_NEW);
toku_free(result);
} }
return r; return r;
} }
static inline int static inline int
autotxn_db_cursor(DB *db, DB_TXN *txn, DBC **c, uint32_t flags) { autotxn_db_cursor(DB *db, DB_TXN *txn, DBC *c, uint32_t flags) {
if (!txn && (db->dbenv->i->open_flags & DB_INIT_TXN)) { if (!txn && (db->dbenv->i->open_flags & DB_INIT_TXN)) {
return toku_ydb_do_error(db->dbenv, EINVAL, return toku_ydb_do_error(db->dbenv, EINVAL,
"Cursors in a transaction environment must have transactions.\n"); "Cursors in a transaction environment must have transactions.\n");
...@@ -920,9 +912,14 @@ autotxn_db_cursor(DB *db, DB_TXN *txn, DBC **c, uint32_t flags) { ...@@ -920,9 +912,14 @@ autotxn_db_cursor(DB *db, DB_TXN *txn, DBC **c, uint32_t flags) {
} }
// Create a cursor on a db. // Create a cursor on a db.
int int toku_db_cursor(DB *db, DB_TXN *txn, DBC **c, uint32_t flags) {
toku_db_cursor(DB *db, DB_TXN *txn, DBC **c, uint32_t flags) { DBC *XMALLOC(cursor);
int r = autotxn_db_cursor(db, txn, c, flags); int r = autotxn_db_cursor(db, txn, cursor, flags);
if (r == 0) {
*c = cursor;
} else {
toku_free(cursor);
}
return r; return r;
} }
......
...@@ -105,6 +105,9 @@ void ydb_c_layer_get_status(YDB_C_LAYER_STATUS statp); ...@@ -105,6 +105,9 @@ void ydb_c_layer_get_status(YDB_C_LAYER_STATUS statp);
int toku_c_get(DBC * c, DBT * key, DBT * data, uint32_t flag); int toku_c_get(DBC * c, DBT * key, DBT * data, uint32_t flag);
int toku_c_getf_set(DBC *c, uint32_t flag, DBT *key, YDB_CALLBACK_FUNCTION f, void *extra); int toku_c_getf_set(DBC *c, uint32_t flag, DBT *key, YDB_CALLBACK_FUNCTION f, void *extra);
int toku_c_close(DBC * c);
int toku_db_cursor_internal(DB *db, DB_TXN * txn, DBC **c, uint32_t flags, int is_temporary_cursor);
int toku_db_cursor(DB *db, DB_TXN *txn, DBC **c, uint32_t flags); int toku_db_cursor(DB *db, DB_TXN *txn, DBC **c, uint32_t flags);
int toku_db_cursor_internal(DB *db, DB_TXN * txn, DBC *c, uint32_t flags, int is_temporary_cursor);
int toku_c_close(DBC *c);
int toku_c_close_internal(DBC *c);
...@@ -225,13 +225,13 @@ int ...@@ -225,13 +225,13 @@ int
db_getf_set(DB *db, DB_TXN *txn, uint32_t flags, DBT *key, YDB_CALLBACK_FUNCTION f, void *extra) { db_getf_set(DB *db, DB_TXN *txn, uint32_t flags, DBT *key, YDB_CALLBACK_FUNCTION f, void *extra) {
HANDLE_PANICKED_DB(db); HANDLE_PANICKED_DB(db);
HANDLE_DB_ILLEGAL_WORKING_PARENT_TXN(db, txn); HANDLE_DB_ILLEGAL_WORKING_PARENT_TXN(db, txn);
DBC *c; DBC c;
uint32_t create_flags = flags & (DB_ISOLATION_FLAGS | DB_RMW); uint32_t create_flags = flags & (DB_ISOLATION_FLAGS | DB_RMW);
flags &= ~DB_ISOLATION_FLAGS; flags &= ~DB_ISOLATION_FLAGS;
int r = toku_db_cursor_internal(db, txn, &c, create_flags | DBC_DISABLE_PREFETCHING, 1); int r = toku_db_cursor_internal(db, txn, &c, create_flags | DBC_DISABLE_PREFETCHING, 1);
if (r==0) { if (r==0) {
r = toku_c_getf_set(c, flags, key, f, extra); r = toku_c_getf_set(&c, flags, key, f, extra);
int r2 = toku_c_close(c); int r2 = toku_c_close_internal(&c);
if (r==0) r = r2; if (r==0) r = r2;
} }
return r; return r;
...@@ -258,12 +258,12 @@ toku_db_get (DB * db, DB_TXN * txn, DBT * key, DBT * data, uint32_t flags) { ...@@ -258,12 +258,12 @@ toku_db_get (DB * db, DB_TXN * txn, DBT * key, DBT * data, uint32_t flags) {
// And DB_GET_BOTH is no longer supported. #2862. // And DB_GET_BOTH is no longer supported. #2862.
if (flags != 0) return EINVAL; if (flags != 0) return EINVAL;
DBC *dbc; DBC dbc;
r = toku_db_cursor_internal(db, txn, &dbc, iso_flags | DBC_DISABLE_PREFETCHING, 1); r = toku_db_cursor_internal(db, txn, &dbc, iso_flags | DBC_DISABLE_PREFETCHING, 1);
if (r!=0) return r; if (r!=0) return r;
uint32_t c_get_flags = DB_SET; uint32_t c_get_flags = DB_SET;
r = toku_c_get(dbc, key, data, c_get_flags | lock_flags); r = toku_c_get(&dbc, key, data, c_get_flags | lock_flags);
int r2 = toku_c_close(dbc); int r2 = toku_c_close_internal(&dbc);
return r ? r : r2; return r ? r : r2;
} }
......
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