Commit a5770c1c authored by Yoni Fogel's avatar Yoni Fogel

refs #25. Makes product name configurable via

db_env_set_toku_product_name
parent 742fe762
......@@ -819,6 +819,7 @@ int main (int argc, char *const argv[] __attribute__((__unused__))) {
printf("void db_env_enable_engine_status(bool) %s;\n", VISIBLE);
printf("void db_env_set_flusher_thread_callback (void (*)(int, void*), void*) %s;\n", VISIBLE);
printf("void db_env_set_num_bucket_mutexes(uint32_t) %s;\n", VISIBLE);
printf("int db_env_set_toku_product_name(const char*) %s;\n", VISIBLE);
printf("#if defined(__cplusplus) || defined(__cilkplusplus)\n}\n#endif\n");
printf("#endif\n");
......
......@@ -6220,6 +6220,8 @@ exit:
return r;
}
void toku_ft_layer_destroy(void) {
toku_mutex_destroy(&ft_open_close_lock);
toku_ft_serialize_layer_destroy();
......
......@@ -1081,3 +1081,92 @@ void toku_ft_get_garbage(FT ft, uint64_t *total_space, uint64_t *used_space) {
*used_space = info.used_space;
}
#if !defined(TOKUDB_REVISION)
#error
#endif
#define xstr(X) str(X)
#define str(X) #X
#define static_version_string xstr(DB_VERSION_MAJOR) "." \
xstr(DB_VERSION_MINOR) "." \
xstr(DB_VERSION_PATCH) " build " \
xstr(TOKUDB_REVISION)
struct toku_product_name_strings_struct toku_product_name_strings;
char toku_product_name[TOKU_MAX_PRODUCT_NAME_LENGTH];
void
tokudb_update_product_name_strings(void) {
//DO ALL STRINGS HERE.. maybe have a separate FT layer version as well
{ // Version string
int n = snprintf(toku_product_name_strings.db_version,
sizeof(toku_product_name_strings.db_version),
"%s %s", toku_product_name, static_version_string);
assert(n >= 0);
assert((unsigned)n < sizeof(toku_product_name_strings.db_version));
}
{
int n = snprintf(toku_product_name_strings.fileopsdirectory,
sizeof(toku_product_name_strings.fileopsdirectory),
"%s.directory", toku_product_name);
assert(n >= 0);
assert((unsigned)n < sizeof(toku_product_name_strings.fileopsdirectory));
}
{
int n = snprintf(toku_product_name_strings.environmentdictionary,
sizeof(toku_product_name_strings.environmentdictionary),
"%s.environment", toku_product_name);
assert(n >= 0);
assert((unsigned)n < sizeof(toku_product_name_strings.environmentdictionary));
}
{
int n = snprintf(toku_product_name_strings.rollback_cachefile,
sizeof(toku_product_name_strings.rollback_cachefile),
"%s.rollback", toku_product_name);
assert(n >= 0);
assert((unsigned)n < sizeof(toku_product_name_strings.rollback_cachefile));
}
{
int n = snprintf(toku_product_name_strings.single_process_lock,
sizeof(toku_product_name_strings.single_process_lock),
"__%s_lock_dont_delete_me", toku_product_name);
assert(n >= 0);
assert((unsigned)n < sizeof(toku_product_name_strings.single_process_lock));
}
}
#undef xstr
#undef str
int
toku_single_process_lock(const char *lock_dir, const char *which, int *lockfd) {
if (!lock_dir)
return ENOENT;
int namelen=strlen(lock_dir)+strlen(which);
char lockfname[namelen+sizeof("/_") + strlen(toku_product_name_strings.single_process_lock)];
int l = snprintf(lockfname, sizeof(lockfname), "%s/%s_%s",
lock_dir, toku_product_name_strings.single_process_lock, which);
assert(l+1 == (signed)(sizeof(lockfname)));
*lockfd = toku_os_lock_file(lockfname);
if (*lockfd < 0) {
int e = get_error_errno();
fprintf(stderr, "Couldn't start tokudb because some other tokudb process is using the same directory [%s] for [%s]\n", lock_dir, which);
return e;
}
return 0;
}
int
toku_single_process_unlock(int *lockfd) {
int fd = *lockfd;
*lockfd = -1;
if (fd>=0) {
int r = toku_os_unlock_file(fd);
if (r != 0)
return get_error_errno();
}
return 0;
}
......@@ -198,4 +198,21 @@ int get_num_cores(void);
struct toku_thread_pool *get_ft_pool(void);
void dump_bad_block(unsigned char *vp, uint64_t size);
int toku_single_process_lock(const char *lock_dir, const char *which, int *lockfd);
int toku_single_process_unlock(int *lockfd);
void tokudb_update_product_name_strings(void);
#define TOKU_MAX_PRODUCT_NAME_LENGTH (256)
extern char toku_product_name[TOKU_MAX_PRODUCT_NAME_LENGTH];
struct toku_product_name_strings_struct {
char db_version[sizeof(toku_product_name) + sizeof("1.2.3 build ") + 256];
char environmentdictionary[sizeof(toku_product_name) + sizeof(".environment")];
char fileopsdirectory[sizeof(toku_product_name) + sizeof(".directory")];
char single_process_lock[sizeof(toku_product_name) + sizeof("___lock_dont_delete_me")];
char rollback_cachefile[sizeof(toku_product_name) + sizeof(".rollback")];
};
extern struct toku_product_name_strings_struct toku_product_name_strings;
#endif
......@@ -289,7 +289,7 @@ toku_logger_open_rollback(TOKULOGGER logger, CACHETABLE cachetable, bool create)
FT_HANDLE t = NULL; // Note, there is no DB associated with this BRT.
toku_ft_handle_create(&t);
int r = toku_ft_handle_open(t, ROLLBACK_CACHEFILE_NAME, create, create, cachetable, NULL_TXN);
int r = toku_ft_handle_open(t, toku_product_name_strings.rollback_cachefile, create, create, cachetable, NULL_TXN);
assert_zero(r);
logger->rollback_cachefile = t->ft->cf;
toku_logger_initialize_rollback_cache(logger, t->ft);
......
......@@ -102,7 +102,6 @@ enum {
TOKU_LOG_VERSION = FT_LAYOUT_VERSION,
TOKU_LOG_MIN_SUPPORTED_VERSION = FT_LAYOUT_MIN_SUPPORTED_VERSION,
};
#define ROLLBACK_CACHEFILE_NAME "tokudb.rollback"
int toku_logger_create (TOKULOGGER *resultp);
int toku_logger_open (const char *directory, TOKULOGGER logger);
......
......@@ -97,8 +97,6 @@ PATENT RIGHTS GRANT:
#include "checkpoint.h"
#include "txn_manager.h"
static const char recovery_lock_file[] = "/__tokudb_recoverylock_dont_delete_me";
int tokudb_recovery_trace = 0; // turn on recovery tracing, default off.
//#define DO_VERIFY_COUNTS
......@@ -500,13 +498,13 @@ static int toku_recover_fassociate (struct logtype_fassociate *l, RECOVER_ENV re
// If rollback file, specify which checkpointed version of file we need (not just the latest)
// because we cannot use a rollback log that is later than the last complete checkpoint. See #3113.
{
bool rollback_file = (0==strcmp(fname, ROLLBACK_CACHEFILE_NAME));
bool rollback_file = (0==strcmp(fname, toku_product_name_strings.rollback_cachefile));
LSN max_acceptable_lsn = MAX_LSN;
if (rollback_file) {
max_acceptable_lsn = renv->ss.checkpoint_begin_lsn;
FT_HANDLE t;
toku_ft_handle_create(&t);
r = toku_ft_handle_open_recovery(t, ROLLBACK_CACHEFILE_NAME, false, false, renv->ct, (TOKUTXN)NULL, l->filenum, max_acceptable_lsn);
r = toku_ft_handle_open_recovery(t, toku_product_name_strings.rollback_cachefile, false, false, renv->ct, (TOKUTXN)NULL, l->filenum, max_acceptable_lsn);
renv->logger->rollback_cachefile = t->ft->cf;
toku_logger_initialize_rollback_cache(renv->logger, t->ft);
} else {
......@@ -826,7 +824,7 @@ static int toku_recover_fcreate (struct logtype_fcreate *l, RECOVER_ENV renv) {
return r;
}
}
assert(0!=strcmp(iname, ROLLBACK_CACHEFILE_NAME)); //Creation of rollback cachefile never gets logged.
assert(0!=strcmp(iname, toku_product_name_strings.rollback_cachefile)); //Creation of rollback cachefile never gets logged.
toku_free(iname_in_cwd);
toku_free(iname);
......@@ -854,7 +852,7 @@ static int toku_recover_fopen (struct logtype_fopen *l, RECOVER_ENV renv) {
TOKUTXN txn = NULL;
char *fname = fixup_fname(&l->iname);
assert(0!=strcmp(fname, ROLLBACK_CACHEFILE_NAME)); //Rollback cachefile can be opened only via fassociate.
assert(0!=strcmp(fname, toku_product_name_strings.rollback_cachefile)); //Rollback cachefile can be opened only via fassociate.
r = internal_recover_fopen_or_fcreate(renv, must_create, 0, &l->iname, l->filenum, l->treeflags, txn, 0, 0, TOKU_DEFAULT_COMPRESSION_METHOD, MAX_LSN);
toku_free(fname);
......@@ -910,7 +908,7 @@ static int toku_recover_fclose (struct logtype_fclose *l, RECOVER_ENV renv) {
char *iname = fixup_fname(&l->iname);
assert(strcmp(tuple->iname, iname) == 0); // verify that file_map has same iname as log entry
if (0!=strcmp(iname, ROLLBACK_CACHEFILE_NAME)) {
if (0!=strcmp(iname, toku_product_name_strings.rollback_cachefile)) {
//Rollback cachefile is closed manually at end of recovery, not here
toku_ft_handle_close_recovery(tuple->ft_handle, l->lsn);
}
......@@ -1569,35 +1567,21 @@ static int do_recovery(RECOVER_ENV renv, const char *env_dir, const char *log_di
int
toku_recover_lock(const char *lock_dir, int *lockfd) {
if (!lock_dir)
return ENOENT;
int namelen=strlen(lock_dir);
char lockfname[namelen+sizeof(recovery_lock_file)];
int l = snprintf(lockfname, sizeof(lockfname), "%s%s", lock_dir, recovery_lock_file);
assert(l+1 == (signed)(sizeof(lockfname)));
*lockfd = toku_os_lock_file(lockfname);
if (*lockfd < 0) {
int e = get_error_errno();
fprintf(stderr, "Couldn't run recovery because some other process holds the recovery lock %s\n", lockfname);
return e;
int e = toku_single_process_lock(lock_dir, "recovery", lockfd);
if (e != 0 && e != ENOENT) {
fprintf(stderr, "Couldn't run recovery because some other process holds the recovery lock\n");
}
return 0;
return e;
}
int
toku_recover_unlock(int lockfd) {
int r = toku_os_unlock_file(lockfd);
if (r != 0) {
return get_error_errno();
}
return 0;
int lockfd_copy = lockfd;
return toku_single_process_unlock(&lockfd_copy);
}
int tokudb_recover(DB_ENV *env,
prepared_txn_callback_t prepared_txn_callback,
prepared_txn_callback_t prepared_txn_callback,
keep_cachetable_callback_t keep_cachetable_callback,
TOKULOGGER logger,
const char *env_dir, const char *log_dir,
......
......@@ -28,6 +28,7 @@
db_env_enable_engine_status;
db_env_set_flusher_thread_callback;
db_env_set_num_bucket_mutexes;
db_env_set_toku_product_name;
read_partitioned_counter;
......
......@@ -229,50 +229,18 @@ ydb_layer_get_status(DB_ENV* env, YDB_LAYER_STATUS statp) {
static DB_ENV * volatile most_recent_env; // most recently opened env, used for engine status on crash. Note there are likely to be races on this if you have multiple threads creating and closing environments in parallel. We'll declare it volatile since at least that helps make sure the compiler doesn't optimize away certain code (e.g., if while debugging, you write a code that spins on most_recent_env, you'd like to compiler not to optimize your code away.)
const char * environmentdictionary = "tokudb.environment";
const char * fileopsdirectory = "tokudb.directory";
static int env_get_iname(DB_ENV* env, DBT* dname_dbt, DBT* iname_dbt);
static int toku_maybe_get_engine_status_text (char* buff, int buffsize); // for use by toku_assert
static void toku_maybe_set_env_panic(int code, const char * msg); // for use by toku_assert
static const char single_process_lock_file[] = "/__tokudb_lock_dont_delete_me_";
static int
single_process_lock(const char *lock_dir, const char *which, int *lockfd) {
if (!lock_dir)
return ENOENT;
int namelen=strlen(lock_dir)+strlen(which);
char lockfname[namelen+sizeof(single_process_lock_file)];
int l = snprintf(lockfname, sizeof(lockfname), "%s%s%s", lock_dir, single_process_lock_file, which);
assert(l+1 == (signed)(sizeof(lockfname)));
*lockfd = toku_os_lock_file(lockfname);
if (*lockfd < 0) {
int e = get_error_errno();
fprintf(stderr, "Couldn't start tokudb because some other tokudb process is using the same directory [%s] for [%s]\n", lock_dir, which);
return e;
}
return 0;
}
static int
single_process_unlock(int *lockfd) {
int fd = *lockfd;
*lockfd = -1;
if (fd>=0) {
int r = toku_os_unlock_file(fd);
if (r != 0)
return get_error_errno();
}
return 0;
}
int
toku_ydb_init(void) {
int r = 0;
//Lower level must be initialized first.
r = toku_ft_layer_init();
if (r!=0) goto exit;
r = db_env_set_toku_product_name("tokudb");
exit:
return r;
}
......@@ -751,7 +719,7 @@ validate_env(DB_ENV * env, bool * valid_newenv, bool need_rollback_cachefile) {
char* path = NULL;
// Test for persistent environment
path = toku_construct_full_name(2, env->i->dir, environmentdictionary);
path = toku_construct_full_name(2, env->i->dir, toku_product_name_strings.environmentdictionary);
assert(path);
r = toku_stat(path, &buf);
if (r == 0) {
......@@ -772,7 +740,7 @@ validate_env(DB_ENV * env, bool * valid_newenv, bool need_rollback_cachefile) {
// Test for existence of rollback cachefile if it is expected to exist
if (r == 0 && need_rollback_cachefile) {
path = toku_construct_full_name(2, env->i->dir, ROLLBACK_CACHEFILE_NAME);
path = toku_construct_full_name(2, env->i->dir, toku_product_name_strings.rollback_cachefile);
assert(path);
r = toku_stat(path, &buf);
if (r == 0) {
......@@ -797,7 +765,7 @@ validate_env(DB_ENV * env, bool * valid_newenv, bool need_rollback_cachefile) {
// Test for fileops directory
if (r == 0) {
path = toku_construct_full_name(2, env->i->dir, fileopsdirectory);
path = toku_construct_full_name(2, env->i->dir, toku_product_name_strings.fileopsdirectory);
assert(path);
r = toku_stat(path, &buf);
if (r == 0) {
......@@ -856,13 +824,13 @@ ydb_maybe_upgrade_env (DB_ENV *env, LSN * last_lsn_of_clean_shutdown_read_from_l
static void
unlock_single_process(DB_ENV *env) {
int r;
r = single_process_unlock(&env->i->envdir_lockfd);
r = toku_single_process_unlock(&env->i->envdir_lockfd);
lazy_assert_zero(r);
r = single_process_unlock(&env->i->datadir_lockfd);
r = toku_single_process_unlock(&env->i->datadir_lockfd);
lazy_assert_zero(r);
r = single_process_unlock(&env->i->logdir_lockfd);
r = toku_single_process_unlock(&env->i->logdir_lockfd);
lazy_assert_zero(r);
r = single_process_unlock(&env->i->tmpdir_lockfd);
r = toku_single_process_unlock(&env->i->tmpdir_lockfd);
lazy_assert_zero(r);
}
......@@ -934,13 +902,13 @@ env_open(DB_ENV * env, const char *home, uint32_t flags, int mode) {
env_setup_real_log_dir(env);
env_setup_real_tmp_dir(env);
r = single_process_lock(env->i->dir, "environment", &env->i->envdir_lockfd);
r = toku_single_process_lock(env->i->dir, "environment", &env->i->envdir_lockfd);
if (r!=0) goto cleanup;
r = single_process_lock(env->i->real_data_dir, "data", &env->i->datadir_lockfd);
r = toku_single_process_lock(env->i->real_data_dir, "data", &env->i->datadir_lockfd);
if (r!=0) goto cleanup;
r = single_process_lock(env->i->real_log_dir, "logs", &env->i->logdir_lockfd);
r = toku_single_process_lock(env->i->real_log_dir, "logs", &env->i->logdir_lockfd);
if (r!=0) goto cleanup;
r = single_process_lock(env->i->real_tmp_dir, "temp", &env->i->tmpdir_lockfd);
r = toku_single_process_lock(env->i->real_tmp_dir, "temp", &env->i->tmpdir_lockfd);
if (r!=0) goto cleanup;
bool need_rollback_cachefile;
......@@ -961,7 +929,7 @@ env_open(DB_ENV * env, const char *home, uint32_t flags, int mode) {
if (upgrade_in_progress) {
// Delete old rollback file. There was a clean shutdown, so it has nothing useful,
// and there is no value in upgrading it. It is simpler to just create a new one.
char* rollback_filename = toku_construct_full_name(2, env->i->dir, ROLLBACK_CACHEFILE_NAME);
char* rollback_filename = toku_construct_full_name(2, env->i->dir, toku_product_name_strings.rollback_cachefile);
assert(rollback_filename);
r = unlink(rollback_filename);
if (r != 0) {
......@@ -1057,7 +1025,7 @@ env_open(DB_ENV * env, const char *home, uint32_t flags, int mode) {
assert_zero(r);
r = db_use_builtin_key_cmp(env->i->persistent_environment);
assert_zero(r);
r = toku_db_open_iname(env->i->persistent_environment, txn, environmentdictionary, DB_CREATE, mode);
r = toku_db_open_iname(env->i->persistent_environment, txn, toku_product_name_strings.environmentdictionary, DB_CREATE, mode);
assert_zero(r);
if (newenv) {
// create new persistent_environment
......@@ -1092,7 +1060,7 @@ env_open(DB_ENV * env, const char *home, uint32_t flags, int mode) {
assert_zero(r);
r = db_use_builtin_key_cmp(env->i->directory);
assert_zero(r);
r = toku_db_open_iname(env->i->directory, txn, fileopsdirectory, DB_CREATE, mode);
r = toku_db_open_iname(env->i->directory, txn, toku_product_name_strings.fileopsdirectory, DB_CREATE, mode);
assert_zero(r);
}
if (using_txns) {
......@@ -1225,6 +1193,7 @@ env_close(DB_ENV * env, uint32_t flags) {
unlock_single_process(env);
toku_free(env->i);
toku_free(env);
toku_sync_fetch_and_add(&tokudb_num_envs, -1);
if (flags != 0) {
r = EINVAL;
}
......@@ -2261,6 +2230,8 @@ env_get_cursor_for_directory(DB_ENV* env, DB_TXN* txn, DBC** c) {
return toku_db_cursor(env->i->directory, txn, c, 0);
}
int tokudb_num_envs = 0;
static int
toku_env_create(DB_ENV ** envp, uint32_t flags) {
int r = ENOSYS;
......@@ -2374,6 +2345,7 @@ toku_env_create(DB_ENV ** envp, uint32_t flags) {
*envp = result;
r = 0;
toku_sync_fetch_and_add(&tokudb_num_envs, 1);
cleanup:
if (r!=0) {
if (result) {
......@@ -2761,13 +2733,7 @@ db_version(int *major, int *minor, int *patch) {
*minor = DB_VERSION_MINOR;
if (patch)
*patch = DB_VERSION_PATCH;
#if defined(TOKUDB_REVISION)
#define xstr(X) str(X)
#define str(X) #X
return "tokudb " xstr(DB_VERSION_MAJOR) "." xstr(DB_VERSION_MINOR) "." xstr(DB_VERSION_PATCH) " build " xstr(TOKUDB_REVISION);
#else
#error
#endif
return toku_product_name_strings.db_version;
}
// HACK: To ensure toku_pthread_yield gets included in the .so
......
......@@ -114,5 +114,4 @@ extern "C" uint64_t toku_test_get_latest_lsn(DB_ENV *env) __attribute__((__visib
// test-only function
extern "C" int toku_test_get_checkpointing_user_data_status(void) __attribute__((__visibility__("default")));
#endif
......@@ -167,16 +167,17 @@ create_iname(DB_ENV *env, uint64_t id1, uint64_t id2, char *hint, const char *ma
8 + // hex file format version
24 + // hex id (normally the txnid's parent and child)
8 + // hex value of n if non-neg
sizeof("_B___.tokudb")]; // extra pieces
sizeof("_B___.") + // extra pieces
strlen(toku_product_name)];
if (n < 0)
bytes = snprintf(inamebase, sizeof(inamebase),
"%s_%" PRIx64 "_%" PRIx64 "_%" PRIx32 ".tokudb",
hint, id1, id2, FT_LAYOUT_VERSION);
"%s_%" PRIx64 "_%" PRIx64 "_%" PRIx32 ".%s",
hint, id1, id2, FT_LAYOUT_VERSION, toku_product_name);
else {
invariant(strlen(mark) == 1);
bytes = snprintf(inamebase, sizeof(inamebase),
"%s_%" PRIx64 "_%" PRIx64 "_%" PRIx32 "_%s_%" PRIx32 ".tokudb",
hint, id1, id2, FT_LAYOUT_VERSION, mark, n);
"%s_%" PRIx64 "_%" PRIx64 "_%" PRIx32 "_%s_%" PRIx32 ".%s",
hint, id1, id2, FT_LAYOUT_VERSION, mark, n, toku_product_name);
}
assert(bytes>0);
assert(bytes<=(int)sizeof(inamebase)-1);
......
......@@ -93,6 +93,7 @@ PATENT RIGHTS GRANT:
#include <memory.h>
#include <db.h>
#include <ft/ft.h>
#include <ft/ft-ops.h>
#include <ft/ft-flusher.h>
#include <ft/checkpoint.h>
......@@ -225,3 +226,21 @@ db_env_set_num_bucket_mutexes(uint32_t num_mutexes) {
toku_pair_list_set_lock_size(num_mutexes);
}
int
db_env_set_toku_product_name(const char *name) {
if (tokudb_num_envs > 0) {
return EINVAL;
}
if (!name || strlen(name) < 1) {
return EINVAL;
}
if (strlen(name) >= sizeof(toku_product_name)) {
return ENAMETOOLONG;
}
if (strncmp(toku_product_name, name, sizeof(toku_product_name))) {
strcpy(toku_product_name, name);
tokudb_update_product_name_strings();
}
return 0;
}
......@@ -105,4 +105,6 @@ void setup_dlmalloc(void) __attribute__((__visibility__("default")));
// Test-only function
void toku_env_increase_last_xid(DB_ENV *env, uint64_t increment);
extern int tokudb_num_envs;
#endif
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