-
Notifications
You must be signed in to change notification settings - Fork 177
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
integrate open source expiry features into eleveldb option processing #203
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -43,6 +43,7 @@ | |
#include "leveldb/perf_count.h" | ||
#define LEVELDB_PLATFORM_POSIX | ||
#include "util/hot_threads.h" | ||
#include "leveldb_os/expiry_os.h" | ||
|
||
#ifndef INCL_WORKITEMS_H | ||
#include "workitems.h" | ||
|
@@ -133,6 +134,9 @@ ERL_NIF_TERM ATOM_TIERED_SLOW_LEVEL; | |
ERL_NIF_TERM ATOM_TIERED_FAST_PREFIX; | ||
ERL_NIF_TERM ATOM_TIERED_SLOW_PREFIX; | ||
ERL_NIF_TERM ATOM_CACHE_OBJECT_WARMING; | ||
ERL_NIF_TERM ATOM_EXPIRY_ENABLED; | ||
ERL_NIF_TERM ATOM_EXPIRY_MINUTES; | ||
ERL_NIF_TERM ATOM_WHOLE_FILE_EXPIRY; | ||
} // namespace eleveldb | ||
|
||
|
||
|
@@ -217,6 +221,8 @@ class eleveldb_priv_data | |
public: | ||
EleveldbOptions m_Opts; | ||
leveldb::HotThreadPool thread_pool; | ||
leveldb::ExpiryPtr_t m_ExpiryModule; // only populated if expiry options seen | ||
// (self deleting pointer) | ||
|
||
explicit eleveldb_priv_data(EleveldbOptions & Options) | ||
: m_Opts(Options), | ||
|
@@ -459,6 +465,45 @@ ERL_NIF_TERM parse_open_option(ErlNifEnv* env, ERL_NIF_TERM item, leveldb::Optio | |
opts.cache_object_warming = false; | ||
} | ||
|
||
else if (option[0] == eleveldb::ATOM_EXPIRY_ENABLED) | ||
{ | ||
if (option[1] == eleveldb::ATOM_TRUE) | ||
{ | ||
if (NULL==opts.expiry_module.get()) | ||
opts.expiry_module.assign(new leveldb::ExpiryModuleOS); | ||
((leveldb::ExpiryModuleOS *)opts.expiry_module.get())->expiry_enabled = true; | ||
} // if | ||
else | ||
{ | ||
if (NULL!=opts.expiry_module.get()) | ||
((leveldb::ExpiryModuleOS *)opts.expiry_module.get())->expiry_enabled = false; | ||
} // else | ||
} // else if | ||
else if (option[0] == eleveldb::ATOM_EXPIRY_MINUTES) | ||
{ | ||
unsigned long minutes(0); | ||
if (enif_get_ulong(env, option[1], &minutes)) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Should we log (syslog?) an error if the enif_Xxx function fails? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Created issue to track suggestion for future. This is of same nature as your suggestion to have pthread creation errors post to syslog. I think I will do all of these at once. |
||
{ | ||
if (NULL==opts.expiry_module.get()) | ||
opts.expiry_module.assign(new leveldb::ExpiryModuleOS); | ||
((leveldb::ExpiryModuleOS *)opts.expiry_module.get())->expiry_minutes = minutes; | ||
} // if | ||
} // else if | ||
else if (option[0] == eleveldb::ATOM_WHOLE_FILE_EXPIRY) | ||
{ | ||
if (option[1] == eleveldb::ATOM_TRUE) | ||
{ | ||
if (NULL==opts.expiry_module.get()) | ||
opts.expiry_module.assign(new leveldb::ExpiryModuleOS); | ||
((leveldb::ExpiryModuleOS *)opts.expiry_module.get())->whole_file_expiry = true; | ||
} // if | ||
else | ||
{ | ||
if (NULL!=opts.expiry_module.get()) | ||
((leveldb::ExpiryModuleOS *)opts.expiry_module.get())->whole_file_expiry = false; | ||
} // else | ||
} // else if | ||
|
||
} | ||
|
||
return eleveldb::ATOM_OK; | ||
|
@@ -568,8 +613,13 @@ async_open( | |
eleveldb_priv_data& priv = *static_cast<eleveldb_priv_data *>(enif_priv_data(env)); | ||
|
||
leveldb::Options *opts = new leveldb::Options; | ||
opts->expiry_module.assign(priv.m_ExpiryModule.get()); | ||
|
||
fold(env, argv[2], parse_open_option, *opts); | ||
|
||
opts->fadvise_willneed = priv.m_Opts.m_FadviseWillNeed; | ||
if (NULL==priv.m_ExpiryModule.get() && NULL!=opts->expiry_module.get()) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I am unclear on the purpose of this code. A few lines above, you assigned opts->expiry_module from priv.m_ExpiryModule, so they should be the same. If there's some reason why they may not be the same, a comment here would be helpful. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Line 616: has a previous vnode opened and created an expiry module? Give me the previously created object if it exists. This squirrel code defends against the future possibility of having different expiry modules by vnode and yet still a global default. Not likely ... but possible given that the future code is not yet written. |
||
priv.m_ExpiryModule.assign(opts->expiry_module.get()); | ||
|
||
// convert total_leveldb_mem to byte count if it arrived as percent | ||
// This happens now because there is no guarantee as to when the total_memory | ||
|
@@ -1282,6 +1332,9 @@ try | |
ATOM(eleveldb::ATOM_TIERED_FAST_PREFIX, "tiered_fast_prefix"); | ||
ATOM(eleveldb::ATOM_TIERED_SLOW_PREFIX, "tiered_slow_prefix"); | ||
ATOM(eleveldb::ATOM_CACHE_OBJECT_WARMING, "cache_object_warming"); | ||
ATOM(eleveldb::ATOM_EXPIRY_ENABLED, "expiry_enabled"); | ||
ATOM(eleveldb::ATOM_EXPIRY_MINUTES, "expiry_minutes"); | ||
ATOM(eleveldb::ATOM_WHOLE_FILE_EXPIRY, "whole_file_expiry"); | ||
#undef ATOM | ||
|
||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -239,3 +239,31 @@ | |
{datatype, {enum, [true, false]}}, | ||
hidden | ||
]}. | ||
|
||
%% @doc Enable global expiry. All leveldb databases / vnodes | ||
%% will use same expiry_minutes and whole_file_expiry settings. | ||
%% Same settings apply to all leveldb instances in multi_backend. | ||
{mapping, "leveldb.expiry_enabled", "eleveldb.expiry_enabled", [ | ||
{default, off}, | ||
{datatype, flag}, | ||
hidden | ||
]}. | ||
|
||
%% @doc Minutes until object expires. Gives number of minutes | ||
%% a stored key/value will stay within the database before automatic | ||
%% deletion. Zero disables expiry by age (minutes) feature | ||
{mapping, "leveldb.expiry_minutes", "eleveldb.expiry_minutes", [ | ||
{default, 0}, | ||
{datatype, integer}, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. When you parse the expiry_minutes option in eleveldb.cc, you use the enif_get_ulong() function. Is that compatible with declaring it as an "integer" here? I'm not sure of the type system in this schema, which is why I'm asking (e.g., perhaps integers are always long and unsigned). There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. cuttlefish is its own little world. I do copy/paste of previous options as my base. The enif_get_XxX() functions used in eleveldb.cc are defined as filtering out of range values. Therefore my defense is at that layer, not here or other weirdness in eleveldb.erl. |
||
hidden | ||
]}. | ||
|
||
%% @doc Expire entire .sst table file. Authorizes leveldb to | ||
%% eliminate entire files that contain expired data (delete files | ||
%% instead of removing expired key/values during compaction). | ||
{mapping, "leveldb.whole_file_expiry", "eleveldb.whole_file_expiry", [ | ||
{default, off}, | ||
{datatype, flag}, | ||
hidden | ||
]}. | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should checking/creating the expiry_module member be moved outside the ATOM_TRUE conditional? That way, we set the expiry_enabled member, regardless of whether the expiry_module member was previously created. Then we don't have to worry about the order in which the various expiry options are declared or what their defaults are in the leveldb::ExpiryModuleOS class.
The same question/comment applies to the other expiry options below.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No. Keep in mind that we do not know what order options will arrive. And that cuttlefish often passes default values to common options.
I am intentionally not creating the object unless absolutely necessary. It is highly likely that the default options will get passed ... and defaults currently leave expiry disabled. So only creating the object if non-defaults seen. However, I do update the object if a different non-default option caused its creation.