Migrate global functions out of env_universal. Have env operate directly

on an env_universal_t.
This commit is contained in:
ridiculousfish 2014-06-15 17:30:50 -07:00
parent 84faa60c4e
commit 6277a2e4a4
8 changed files with 118 additions and 339 deletions

141
env.cpp
View file

@ -50,6 +50,7 @@
#include "reader.h"
#include "parser.h"
#include "env_universal.h"
#include "env_universal_common.h"
#include "input.h"
#include "event.h"
#include "path.h"
@ -129,6 +130,13 @@ static env_node_t *top = NULL;
/** Bottom node on the function stack */
static env_node_t *global_env = NULL;
/** Universal variables global instance. Initialized in env_init. */
static env_universal_t *s_universal_variables = NULL;
/* Getter for universal variables */
static env_universal_t *uvars() {
return s_universal_variables;
}
/**
Table for global variables
@ -331,9 +339,7 @@ static void react_to_variable_change(const wcstring &key)
Universal variable callback function. This function makes sure the
proper events are triggered when an event occurs.
*/
static void universal_callback(fish_message_type_t type,
const wchar_t *name,
const wchar_t *val)
static void universal_callback(fish_message_type_t type, const wchar_t *name, const wchar_t *val)
{
const wchar_t *str = NULL;
@ -554,7 +560,9 @@ void env_init(const struct config_paths_t *paths /* or NULL */)
env_set(L"version", version.c_str(), ENV_GLOBAL);
env_set(L"FISH_VERSION", version.c_str(), ENV_GLOBAL);
env_universal_init(universal_callback);
/* Set up universal variables. The empty string means to use the deafult path. */
assert(s_universal_variables == NULL);
s_universal_variables = new env_universal_t(L"");
/*
Set up SHLVL variable
@ -586,32 +594,6 @@ void env_init(const struct config_paths_t *paths /* or NULL */)
env_set(FISH_BIND_MODE_VAR, DEFAULT_BIND_MODE, ENV_GLOBAL);
}
void env_destroy()
{
env_universal_destroy();
while (&top->env != global)
{
env_pop();
}
env_read_only.clear();
env_electric.clear();
var_table_t::iterator iter;
for (iter = global->begin(); iter != global->end(); ++iter)
{
const var_entry_t &entry = iter->second;
if (entry.exportv)
{
mark_changed_exported();
break;
}
}
delete top;
}
/**
Search all visible scopes in order for the specified key. Return
the first scope in which it was found.
@ -688,23 +670,32 @@ int env_set(const wcstring &key, const wchar_t *val, int var_mode)
if (var_mode & ENV_UNIVERSAL)
{
bool exportv;
const bool old_export = uvars() && uvars()->get_export(key);
bool new_export;
if (var_mode & ENV_EXPORT)
{
// export
exportv = true;
new_export = true;
}
else if (var_mode & ENV_UNEXPORT)
{
// unexport
exportv = false;
new_export = false;
}
else
{
// not changing the export
exportv = env_universal_get_export(key);
new_export = old_export;
}
if (uvars())
{
uvars()->set(key, val, new_export);
env_universal_barrier();
if (old_export || new_export)
{
mark_changed_exported();
}
}
env_universal_set(key, val, exportv);
is_universal = 1;
}
@ -753,7 +744,7 @@ int env_set(const wcstring &key, const wchar_t *val, int var_mode)
env_universal_barrier();
}
if (! env_universal_get(key).missing())
if (uvars() && ! uvars()->get(key).missing())
{
bool exportv;
if (var_mode & ENV_EXPORT)
@ -766,10 +757,11 @@ int env_set(const wcstring &key, const wchar_t *val, int var_mode)
}
else
{
exportv = env_universal_get_export(key);
exportv = uvars()->get_export(key);
}
env_universal_set(key, val, exportv);
uvars()->set(key, val, exportv);
env_universal_barrier();
is_universal = 1;
done = 1;
@ -817,7 +809,6 @@ int env_set(const wcstring &key, const wchar_t *val, int var_mode)
if (has_changed_old || has_changed_new)
mark_changed_exported();
}
}
if (!is_universal)
@ -917,7 +908,7 @@ int env_remove(const wcstring &key, int var_mode)
!(var_mode & ENV_GLOBAL) &&
!(var_mode & ENV_LOCAL))
{
erased = env_universal_remove(key);
erased = uvars() && uvars()->remove(key);
}
react_to_variable_change(key);
@ -1000,16 +991,12 @@ env_var_t env_get_string(const wcstring &key)
env_universal_barrier();
}
env_var_t item = env_universal_get(key);
if (item.missing() || (wcscmp(item.c_str(), ENV_NULL)==0))
env_var_t env_var = uvars() ? uvars()->get(key) : env_var_t::missing_var();
if (env_var == ENV_NULL)
{
return env_var_t::missing_var();
}
else
{
return item;
env_var = env_var_t::missing_var();
}
return env_var;
}
}
@ -1079,15 +1066,15 @@ bool env_exist(const wchar_t *key, int mode)
env_universal_barrier();
}
if (! env_universal_get(key).missing())
if (uvars() && ! uvars()->get(key).missing())
{
if (mode & ENV_EXPORT)
{
return env_universal_get_export(key) == 1;
return uvars()->get_export(key);
}
else if (mode & ENV_UNEXPORT)
{
return env_universal_get_export(key) == 0;
return ! uvars()->get_export(key);
}
return 1;
@ -1254,13 +1241,9 @@ wcstring_list_t env_get_names(int flags)
}
if (show_universal)
if (show_universal && uvars())
{
wcstring_list_t uni_list;
env_universal_get_names(uni_list,
show_exported,
show_unexported);
const wcstring_list_t uni_list = uvars()->get_names(show_exported, show_unexported);
names.insert(uni_list.begin(), uni_list.end());
}
@ -1340,18 +1323,20 @@ static void update_export_array_if_necessary(bool recalc)
get_exported(top, vals);
wcstring_list_t uni;
env_universal_get_names(uni, 1, 0);
for (i=0; i<uni.size(); i++)
if (uvars())
{
const wcstring &key = uni.at(i);
const env_var_t val = env_universal_get(key);
if (! val.missing() && wcscmp(val.c_str(), ENV_NULL))
const wcstring_list_t uni = uvars()->get_names(true, false);
for (i=0; i<uni.size(); i++)
{
// Note that std::map::insert does NOT overwrite a value already in the map,
// which we depend on here
vals.insert(std::pair<wcstring, wcstring>(key, val));
const wcstring &key = uni.at(i);
const env_var_t val = uvars()->get(key);
if (! val.missing() && val != ENV_NULL)
{
// Note that std::map::insert does NOT overwrite a value already in the map,
// which we depend on here
vals.insert(std::pair<wcstring, wcstring>(key, val));
}
}
}
@ -1385,6 +1370,28 @@ env_vars_snapshot_t::env_vars_snapshot_t(const wchar_t * const *keys)
}
}
void env_universal_barrier()
{
ASSERT_IS_MAIN_THREAD();
if (uvars())
{
callback_data_list_t changes;
bool changed = uvars()->sync(&changes);
if (changed)
{
universal_notifier_t::default_notifier().post_notification();
}
/* Post callbacks */
for (size_t i=0; i < changes.size(); i++)
{
const callback_data_t &data = changes.at(i);
universal_callback(data.type, data.key.c_str(), data.val.c_str());
}
}
}
env_vars_snapshot_t::env_vars_snapshot_t() { }
/* The "current" variables are not a snapshot at all, but instead trampoline to env_get_string, etc. We identify the current snapshot based on pointer values. */

9
env.h
View file

@ -68,12 +68,6 @@ struct config_paths_t
*/
void env_init(const struct config_paths_t *paths = NULL);
/**
Destroy environment variable data
*/
void env_destroy();
/**
Set the value of the environment variable whose name matches key to val.
@ -205,6 +199,9 @@ void env_push(bool new_scope);
*/
void env_pop();
/** Synchronizes all universal variable changes: writes everything out, reads stuff in */
void env_universal_barrier();
/** Returns an array containing all exported variables in a format suitable for execv. */
const char * const * env_export_arr(bool recalc);

View file

@ -40,88 +40,3 @@
#include "env.h"
/**
Set to true after initialization has been performed
*/
static bool s_env_univeral_inited = false;
static void (*external_callback)(fish_message_type_t type, const wchar_t *name, const wchar_t *val);
void env_universal_barrier();
/**
Callback function used whenever a new fishd message is recieved
*/
static void callback(fish_message_type_t type, const wchar_t *name, const wchar_t *val)
{
if (external_callback)
external_callback(type, name, val);
}
void env_universal_init(void (*cb)(fish_message_type_t type, const wchar_t *name, const wchar_t *val))
{
external_callback = cb;
env_universal_common_init(&callback);
s_env_univeral_inited = true;
}
void env_universal_destroy()
{
s_env_univeral_inited = false;
}
env_var_t env_universal_get(const wcstring &name)
{
if (!s_env_univeral_inited)
return env_var_t::missing_var();
return env_universal_common_get(name);
}
bool env_universal_get_export(const wcstring &name)
{
if (!s_env_univeral_inited)
return false;
return env_universal_common_get_export(name);
}
void env_universal_barrier()
{
ASSERT_IS_MAIN_THREAD();
UNIVERSAL_LOG("BARRIER");
env_universal_common_sync();
}
void env_universal_set(const wcstring &name, const wcstring &value, bool exportv)
{
if (!s_env_univeral_inited)
return;
debug(3, L"env_universal_set( \"%ls\", \"%ls\" )", name.c_str(), value.c_str());
env_universal_common_set(name.c_str(), value.c_str(), exportv);
env_universal_barrier();
}
bool env_universal_remove(const wcstring &name)
{
if (!s_env_univeral_inited)
return false;
return env_universal_common_remove(name);
}
void env_universal_get_names(wcstring_list_t &lst,
bool show_exported,
bool show_unexported)
{
if (!s_env_univeral_inited)
return;
env_universal_common_get_names(lst,
show_exported,
show_unexported);
}

View file

@ -10,56 +10,4 @@
#include "env_universal_common.h"
#include "env.h"
/**
Initialize the envuni library
*/
void env_universal_init(void (*cb)(fish_message_type_t type, const wchar_t *name, const wchar_t *val));
/**
Free memory used by envuni
*/
void env_universal_destroy();
/**
Get the value of a universal variable
*/
env_var_t env_universal_get(const wcstring &name);
/**
Get the export flag of the variable with the specified
name. Returns 0 if the variable doesn't exist.
*/
bool env_universal_get_export(const wcstring &name);
/**
Set the value of a universal variable
*/
void env_universal_set(const wcstring &name, const wcstring &val, bool exportv);
/**
Erase a universal variable
\return true if the variable existed, and false if the variable did not exist
*/
bool env_universal_remove(const wcstring &name);
/**
Read all available messages from the server.
*/
int env_universal_read_all();
/**
Get the names of all universal variables
\param l the list to insert the names into
\param show_exported whether exported variables should be shown
\param show_unexported whether unexported variables should be shown
*/
void env_universal_get_names(wcstring_list_t &list,
bool show_exported,
bool show_unexported);
/**
Synchronize with fishd
*/
void env_universal_barrier();
#endif

View file

@ -34,6 +34,17 @@
#include <notify.h>
#endif
/**
The set command
*/
#define SET_STR L"SET"
/**
The set_export command
*/
#define SET_EXPORT_STR L"SET_EXPORT"
/**
Non-wide version of the set command
*/
@ -76,37 +87,10 @@ static env_universal_t &default_universal_vars()
return s_default_vars;
}
/**
Callback function, should be called on all events
*/
struct callback_data_t
{
fish_message_type_t type;
wcstring key;
wcstring val;
callback_data_t(fish_message_type_t t, const wcstring &k, const wcstring &v) : type(t), key(k), val(v)
{
}
};
static void (*callback)(fish_message_type_t type,
const wchar_t *key,
const wchar_t *val);
/* Post callbacks that we have determined in this list. We do this here, instead of at the point where we determined that the values changed, because we determine those under a lock, and reentrancy would cause a deadlock */
static void post_callbacks(const callback_data_list_t &callbacks)
{
if (callback != NULL)
{
for (size_t i=0; i < callbacks.size(); i++)
{
const callback_data_t &data = callbacks.at(i);
callback(data.type, data.key.c_str(), data.val.c_str());
}
}
}
void env_universal_common_init(void (*cb)(fish_message_type_t type, const wchar_t *key, const wchar_t *val))
{
callback = cb;
@ -148,18 +132,6 @@ void env_universal_common_set(const wchar_t *key, const wchar_t *val, bool expor
}
}
void env_universal_common_sync()
{
assert(! synchronizes_via_fishd());
callback_data_list_t callbacks;
bool changed = default_universal_vars().sync(&callbacks);
if (changed)
{
universal_notifier_t::default_notifier().post_notification();
}
post_callbacks(callbacks);
}
static void report_error(int err_code, const wchar_t *err_format, ...)
{
va_list va;
@ -279,17 +251,14 @@ static bool append_file_entry(fish_message_type_t type, const wcstring &key_in,
return success;
}
/**
Put exported or unexported variables in a string list
*/
void env_universal_common_get_names(wcstring_list_t &lst, bool show_exported, bool show_unexported)
wcstring_list_t env_universal_get_names(bool show_exported, bool show_unexported)
{
const wcstring_list_t names = default_universal_vars().get_names(show_exported, show_unexported);
lst.insert(lst.end(), names.begin(), names.end());
return default_universal_vars().get_names(show_exported, show_unexported);
}
env_var_t env_universal_common_get(const wcstring &name)
env_var_t env_universal_get(const wcstring &name)
{
return default_universal_vars().get(name);
}
@ -531,8 +500,7 @@ static env_var_t fishd_env_get(const char *key)
}
else
{
const wcstring wkey = str2wcstring(key);
return env_universal_common_get(wkey);
return env_var_t::missing_var();
}
}
@ -725,6 +693,7 @@ bool env_universal_t::open_and_acquire_lock(const wcstring &path, int *out_fd)
/* Returns true if modified variables were written, false if not. (There may still be variable changes due to other processes on a false return). */
bool env_universal_t::sync(callback_data_list_t *callbacks)
{
UNIVERSAL_LOG("sync");
scoped_lock locker(lock);
/* Our saving strategy:
@ -844,14 +813,15 @@ void env_universal_t::read_message_internal(int fd, callback_data_list_t *callba
{
break;
}
const size_t bufflen = (size_t)amt;
// Walk over it by lines. The contents of an unterminated line will be left in 'line' for the next iteration.
size_t line_start = 0;
while (line_start < sizeof buffer)
while (line_start < amt)
{
// Run until we hit a newline
size_t cursor = line_start;
while (cursor < sizeof buffer && buffer[cursor] != '\n')
while (cursor < bufflen && buffer[cursor] != '\n')
{
cursor++;
}
@ -860,13 +830,11 @@ void env_universal_t::read_message_internal(int fd, callback_data_list_t *callba
line.append(buffer + line_start, cursor - line_start);
// Process it if it's a newline (which is true if we are before the end of the buffer)
if (cursor < sizeof buffer && ! line.empty())
if (cursor < bufflen && ! line.empty())
{
if (utf8_to_wchar_string(line, &wide_line))
{
wchar_t *tmp = wcsdup(wide_line.c_str());
this->parse_message_internal(tmp, callbacks);
free(tmp);
this->parse_message_internal(wide_line, callbacks);
}
line.clear();
}
@ -882,9 +850,10 @@ void env_universal_t::read_message_internal(int fd, callback_data_list_t *callba
/**
Parse message msg
*/
void env_universal_t::parse_message_internal(wchar_t *msg, callback_data_list_t *callbacks)
void env_universal_t::parse_message_internal(const wcstring &msgstr, callback_data_list_t *callbacks)
{
ASSERT_IS_LOCKED(lock);
const wchar_t *msg = msgstr.c_str();
// debug( 3, L"parse_message( %ls );", msg );
@ -893,11 +862,11 @@ void env_universal_t::parse_message_internal(wchar_t *msg, callback_data_list_t
if (match(msg, SET_STR) || match(msg, SET_EXPORT_STR))
{
wchar_t *name, *tmp;
const wchar_t *name, *tmp;
bool exportv = match(msg, SET_EXPORT_STR);
name = msg+(exportv?wcslen(SET_EXPORT_STR):wcslen(SET_STR));
while (wcschr(L"\t ", *name))
while (name[0] == L'\t' || name[0] == L' ')
name++;
tmp = wcschr(name, L':');
@ -1516,11 +1485,6 @@ class universal_notifier_null_t : public universal_notifier_t
static universal_notifier_t::notifier_strategy_t fetch_default_strategy_from_environment()
{
if (synchronizes_via_fishd())
{
return universal_notifier_t::strategy_null;
}
universal_notifier_t::notifier_strategy_t result = universal_notifier_t::strategy_default;
const struct

View file

@ -9,16 +9,6 @@
#include "util.h"
#include "env.h"
/**
The set command
*/
#define SET_STR L"SET"
/**
The set_export command
*/
#define SET_EXPORT_STR L"SET_EXPORT"
/**
The different types of messages found in the fishd file
*/
@ -33,59 +23,22 @@ typedef enum
*/
#define ENV_UNIVERSAL_BUFFER_SIZE 1024
/**
Init the library
*/
void env_universal_common_init(void (*cb)(fish_message_type_t type, const wchar_t *key, const wchar_t *val));
/**
Add all variable names to the specified list
This function operate agains the local copy of all universal
variables, it does not communicate with any other process.
*/
void env_universal_common_get_names(wcstring_list_t &lst,
bool show_exported,
bool show_unexported);
/**
Perform the specified variable assignment.
This function operate agains the local copy of all universal
variables, it does not communicate with any other process.
Do not call this function. Create a message to do it. This function
is only to be used when fishd is dead.
*/
void env_universal_common_set(const wchar_t *key, const wchar_t *val, bool exportv);
/**
Remove the specified variable. Returns true if it was removed, false if it was not found.
*/
bool env_universal_common_remove(const wcstring &key);
/**
Get the value of the variable with the specified name
This function operate agains the local copy of all universal
variables, it does not communicate with any other process.
*/
env_var_t env_universal_common_get(const wcstring &name);
/**
Get the export flag of the variable with the specified
name. Returns false if the variable doesn't exist.
This function operate agains the local copy of all universal
variables, it does not communicate with any other process.
*/
bool env_universal_common_get_export(const wcstring &name);
/** Synchronizes all changse: writes everything out, reads stuff in */
void env_universal_common_sync();
typedef std::vector<struct callback_data_t> callback_data_list_t;
/**
Callback data, reflecting a change in universal variables
*/
struct callback_data_t
{
fish_message_type_t type;
wcstring key;
wcstring val;
callback_data_t(fish_message_type_t t, const wcstring &k, const wcstring &v) : type(t), key(k), val(v)
{
}
};
/** Class representing universal variables */
class env_universal_t
{
@ -104,7 +57,7 @@ class env_universal_t
void load_from_fd(int fd, callback_data_list_t *callbacks);
void erase_unmodified_values();
void parse_message_internal(wchar_t *msg, callback_data_list_t *callbacks);
void parse_message_internal(const wcstring &msg, callback_data_list_t *callbacks);
void set_internal(const wcstring &key, const wcstring &val, bool exportv, bool overwrite);
bool remove_internal(const wcstring &name);
@ -216,8 +169,6 @@ public:
std::string get_machine_identifier();
bool get_hostname_identifier(std::string *result);
/* Temporary */
bool synchronizes_via_fishd();
bool universal_log_enabled();
#define UNIVERSAL_LOG(x) if (universal_log_enabled()) fprintf(stderr, "UNIVERSAL LOG: %s\n", x)

View file

@ -540,8 +540,6 @@ int main(int argc, char **argv)
wutil_destroy();
event_destroy();
env_destroy();
if (g_log_forks)
printf("%d: g_fork_count: %d\n", __LINE__, g_fork_count);

View file

@ -3469,7 +3469,6 @@ int main(int argc, char **argv)
// say( L"Testing performance" );
// perf_complete();
env_destroy();
reader_destroy();
builtin_destroy();
wutil_destroy();