summaryrefslogtreecommitdiff
path: root/src/cstore/unionfs
diff options
context:
space:
mode:
authorAn-Cheng Huang <ancheng@vyatta.com>2011-03-17 11:48:54 -0700
committerAn-Cheng Huang <ancheng@vyatta.com>2011-03-17 11:48:54 -0700
commiteb9f5718d412022015bb65eb08c30785c79e79e6 (patch)
treebe0b6a9de27965e39c44c5c8a88adf9caa13abf8 /src/cstore/unionfs
parentcda3f423c311fd30e8cc24e2de67d99baf352b2a (diff)
downloadvyatta-cfg-eb9f5718d412022015bb65eb08c30785c79e79e6.tar.gz
vyatta-cfg-eb9f5718d412022015bb65eb08c30785c79e79e6.zip
add config path abstraction and high-level caching
* part of the config backend cleanup/optimization work. * improves the performance of "load" (w/o commit) by ~55% and "show" by ~15%.
Diffstat (limited to 'src/cstore/unionfs')
-rw-r--r--src/cstore/unionfs/cstore-unionfs.cpp407
-rw-r--r--src/cstore/unionfs/cstore-unionfs.hpp117
-rw-r--r--src/cstore/unionfs/fspath.hpp92
3 files changed, 376 insertions, 240 deletions
diff --git a/src/cstore/unionfs/cstore-unionfs.cpp b/src/cstore/unionfs/cstore-unionfs.cpp
index b59ddd3..f926540 100644
--- a/src/cstore/unionfs/cstore-unionfs.cpp
+++ b/src/cstore/unionfs/cstore-unionfs.cpp
@@ -26,7 +26,8 @@
#include <cli_cstore.h>
#include <cstore/unionfs/cstore-unionfs.hpp>
-using namespace cstore;
+namespace cstore { // begin namespace cstore
+namespace unionfs { // begin namespace unionfs
////// constants
// environment vars defining root dirs
@@ -205,7 +206,8 @@ UnionfsCstore::UnionfsCstore(bool use_edit_level)
* starts with '/', so only append it if it is at least two chars
* (i.e., it is not "/").
*/
- tmpl_path /= val;
+ FsPath tlvl(val);
+ tmpl_path /= tlvl;
}
}
_init_fs_escape_chars();
@@ -239,11 +241,11 @@ UnionfsCstore::UnionfsCstore(const string& sid, string& env)
string declr = " declare -x -r "; // readonly vars
env += " umask 002; {";
- env += (declr + C_ENV_ACTIVE_ROOT + "=" + active_root.file_string());
- env += (declr + C_ENV_CHANGE_ROOT + "=" + change_root.file_string() + ";");
- env += (declr + C_ENV_WORK_ROOT + "=" + work_root.file_string() + ";");
- env += (declr + C_ENV_TMP_ROOT + "=" + tmp_root.file_string() + ";");
- env += (declr + C_ENV_TMPL_ROOT + "=" + tmpl_root.file_string() + ";");
+ env += (declr + C_ENV_ACTIVE_ROOT + "=" + active_root.path_cstr());
+ env += (declr + C_ENV_CHANGE_ROOT + "=" + change_root.path_cstr() + ";");
+ env += (declr + C_ENV_WORK_ROOT + "=" + work_root.path_cstr() + ";");
+ env += (declr + C_ENV_TMP_ROOT + "=" + tmp_root.path_cstr() + ";");
+ env += (declr + C_ENV_TMPL_ROOT + "=" + tmpl_root.path_cstr() + ";");
env += " } >&/dev/null || true";
// set up path strings using level vars
@@ -254,7 +256,8 @@ UnionfsCstore::UnionfsCstore(const string& sid, string& env)
}
if ((val = getenv(C_ENV_TMPL_LEVEL.c_str())) && val[0] && val[1]) {
// see comment in the other constructor
- tmpl_path /= val;
+ FsPath tlvl(val);
+ tmpl_path /= tlvl;
}
_init_fs_escape_chars();
@@ -269,14 +272,14 @@ UnionfsCstore::~UnionfsCstore()
bool
UnionfsCstore::markSessionUnsaved()
{
- b_fs::path marker = work_root / C_MARKER_UNSAVED;
- if (path_exists(marker.file_string().c_str())) {
+ FsPath marker = work_root;
+ marker.push(C_MARKER_UNSAVED);
+ if (path_exists(marker)) {
// already marked. treat as success.
return true;
}
- if (!create_file(marker.file_string())) {
- output_internal("failed to mark unsaved [%s]\n",
- marker.file_string().c_str());
+ if (!create_file(marker)) {
+ output_internal("failed to mark unsaved [%s]\n", marker.path_cstr());
return false;
}
return true;
@@ -285,16 +288,16 @@ UnionfsCstore::markSessionUnsaved()
bool
UnionfsCstore::unmarkSessionUnsaved()
{
- b_fs::path marker = work_root / C_MARKER_UNSAVED;
- if (!path_exists(marker.file_string().c_str())) {
+ FsPath marker = work_root;
+ marker.push(C_MARKER_UNSAVED);
+ if (!path_exists(marker)) {
// not marked. treat as success.
return true;
}
try {
- b_fs::remove(marker);
+ b_fs::remove(marker.path_cstr());
} catch (...) {
- output_internal("failed to unmark unsaved [%s]\n",
- marker.file_string().c_str());
+ output_internal("failed to unmark unsaved [%s]\n", marker.path_cstr());
return false;
}
return true;
@@ -303,15 +306,17 @@ UnionfsCstore::unmarkSessionUnsaved()
bool
UnionfsCstore::sessionUnsaved()
{
- b_fs::path marker = work_root / C_MARKER_UNSAVED;
- return path_exists(marker.file_string().c_str());
+ FsPath marker = work_root;
+ marker.push(C_MARKER_UNSAVED);
+ return path_exists(marker);
}
bool
UnionfsCstore::sessionChanged()
{
- b_fs::path marker = work_root / C_MARKER_CHANGED;
- return path_exists(marker.file_string().c_str());
+ FsPath marker = work_root;
+ marker.push(C_MARKER_CHANGED);
+ return path_exists(marker);
}
/* set up the session associated with this object.
@@ -321,15 +326,15 @@ UnionfsCstore::sessionChanged()
bool
UnionfsCstore::setupSession()
{
- if (!path_exists(work_root.file_string().c_str())) {
+ if (!path_exists(work_root)) {
// session doesn't exist. create dirs.
try {
- b_fs::create_directories(work_root);
- b_fs::create_directories(change_root);
- b_fs::create_directories(tmp_root);
- if (!path_exists(active_root.file_string().c_str())) {
+ b_fs::create_directories(work_root.path_cstr());
+ b_fs::create_directories(change_root.path_cstr());
+ b_fs::create_directories(tmp_root.path_cstr());
+ if (!path_exists(active_root)) {
// this should only be needed on boot
- b_fs::create_directories(active_root);
+ b_fs::create_directories(active_root.path_cstr());
}
} catch (...) {
output_internal("setup session failed to create session directories\n");
@@ -337,17 +342,20 @@ UnionfsCstore::setupSession()
}
// union mount
- string mopts = ("dirs=" + change_root.file_string() + "=rw:"
- + active_root.file_string() + "=ro");
- if (mount("unionfs", work_root.file_string().c_str(), "unionfs", 0,
+ string mopts = "dirs=";
+ mopts += change_root.path_cstr();
+ mopts += "=rw:";
+ mopts += active_root.path_cstr();
+ mopts += "=ro";
+ if (mount("unionfs", work_root.path_cstr(), "unionfs", 0,
mopts.c_str()) != 0) {
output_internal("setup session mount failed [%s][%s]\n",
- strerror(errno), work_root.file_string().c_str());
+ strerror(errno), work_root.path_cstr());
return false;
}
- } else if (!path_is_directory(work_root.file_string().c_str())) {
+ } else if (!path_is_directory(work_root)) {
output_internal("setup session not dir [%s]\n",
- work_root.file_string().c_str());
+ work_root.path_cstr());
return false;
}
return true;
@@ -361,10 +369,9 @@ bool
UnionfsCstore::teardownSession()
{
// check if session exists
- string wstr = work_root.file_string();
+ string wstr = work_root.path_cstr();
if (wstr.empty() || wstr.find(C_DEF_WORK_PREFIX) != 0
- || !path_exists(work_root.file_string().c_str())
- || !path_is_directory(work_root.file_string().c_str())) {
+ || !path_exists(work_root) || !path_is_directory(work_root)) {
// no session
output_internal("teardown invalid session [%s]\n", wstr.c_str());
return false;
@@ -380,9 +387,9 @@ UnionfsCstore::teardownSession()
// remove session directories
bool ret = false;
try {
- if (b_fs::remove_all(work_root) != 0
- && b_fs::remove_all(change_root) != 0
- && b_fs::remove_all(tmp_root) != 0) {
+ if (b_fs::remove_all(work_root.path_cstr()) != 0
+ && b_fs::remove_all(change_root.path_cstr()) != 0
+ && b_fs::remove_all(tmp_root.path_cstr()) != 0) {
ret = true;
}
} catch (...) {
@@ -400,10 +407,9 @@ UnionfsCstore::teardownSession()
bool
UnionfsCstore::inSession()
{
- string wstr = work_root.file_string();
+ string wstr = work_root.path_cstr();
return (!wstr.empty() && wstr.find(C_DEF_WORK_PREFIX) == 0
- && path_exists(work_root.file_string().c_str())
- && path_is_directory(work_root.file_string().c_str()));
+ && path_exists(work_root) && path_is_directory(work_root));
}
@@ -414,11 +420,11 @@ UnionfsCstore::inSession()
bool
UnionfsCstore::tmpl_node_exists()
{
- return (path_exists(tmpl_path.file_string().c_str())
- && path_is_directory(tmpl_path.file_string().c_str()));
+ return (path_exists(tmpl_path) && path_is_directory(tmpl_path));
}
-typedef Cstore::MapT<string, tr1::shared_ptr<vtw_def> > ParsedTmplCacheT;
+typedef Cstore::MapT<FsPath, tr1::shared_ptr<vtw_def>, FsPathHash>
+ ParsedTmplCacheT;
static ParsedTmplCacheT _parsed_tmpl_cache;
/* parse template at current tmpl_path and return an allocated Ctemplate
@@ -427,14 +433,14 @@ static ParsedTmplCacheT _parsed_tmpl_cache;
Ctemplate *
UnionfsCstore::tmpl_parse()
{
- b_fs::path tp = tmpl_path / C_DEF_NAME;
- if (!path_exists(tp.file_string().c_str())
- || !path_is_regular(tp.file_string().c_str())) {
+ FsPath tp = tmpl_path;
+ tp.push(C_DEF_NAME);
+ if (!path_exists(tp) || !path_is_regular(tp)) {
// invalid
return 0;
}
- ParsedTmplCacheT::iterator p = _parsed_tmpl_cache.find(tp.file_string());
+ ParsedTmplCacheT::iterator p = _parsed_tmpl_cache.find(tp);
if (p != _parsed_tmpl_cache.end()) {
// found in cache
return (new Ctemplate(p->second));
@@ -443,9 +449,9 @@ UnionfsCstore::tmpl_parse()
// new template => parse
tr1::shared_ptr<vtw_def> def(new vtw_def);
vtw_def *_def = def.get();
- if (_def && parse_def(_def, tp.file_string().c_str(), 0) == 0) {
+ if (_def && parse_def(_def, tp.path_cstr(), 0) == 0) {
// succes => cache and return
- _parsed_tmpl_cache[tp.file_string()] = def;
+ _parsed_tmpl_cache[tp] = def;
return (new Ctemplate(def));
}
return 0;
@@ -454,9 +460,8 @@ UnionfsCstore::tmpl_parse()
bool
UnionfsCstore::cfg_node_exists(bool active_cfg)
{
- b_fs::path p = (active_cfg ? get_active_path() : get_work_path());
- return (path_exists(p.file_string().c_str())
- && path_is_directory(p.file_string().c_str()));
+ FsPath p = (active_cfg ? get_active_path() : get_work_path());
+ return (path_exists(p) && path_is_directory(p));
}
bool
@@ -464,7 +469,7 @@ UnionfsCstore::add_node()
{
bool ret = true;
try {
- if (!b_fs::create_directory(get_work_path())) {
+ if (!b_fs::create_directory(get_work_path().path_cstr())) {
// already exists. shouldn't call this function.
ret = false;
}
@@ -473,7 +478,7 @@ UnionfsCstore::add_node()
}
if (!ret) {
output_internal("failed to add node [%s]\n",
- get_work_path().file_string().c_str());
+ get_work_path().path_cstr());
}
return ret;
}
@@ -481,15 +486,15 @@ UnionfsCstore::add_node()
bool
UnionfsCstore::remove_node()
{
- if (!path_exists(get_work_path().file_string().c_str())
- || !path_is_directory(get_work_path().file_string().c_str())) {
+ if (!path_exists(get_work_path())
+ || !path_is_directory(get_work_path())) {
output_internal("remove non-existent node [%s]\n",
- get_work_path().file_string().c_str());
+ get_work_path().path_cstr());
return false;
}
bool ret = false;
try {
- if (b_fs::remove_all(get_work_path()) != 0) {
+ if (b_fs::remove_all(get_work_path().path_cstr()) != 0) {
ret = true;
}
} catch (...) {
@@ -497,7 +502,7 @@ UnionfsCstore::remove_node()
}
if (!ret) {
output_internal("failed to remove node [%s]\n",
- get_work_path().file_string().c_str());
+ get_work_path().path_cstr());
}
return ret;
}
@@ -506,7 +511,7 @@ void
UnionfsCstore::get_all_child_node_names_impl(vector<string>& cnodes,
bool active_cfg)
{
- b_fs::path p = (active_cfg ? get_active_path() : get_work_path());
+ FsPath p = (active_cfg ? get_active_path() : get_work_path());
get_all_child_dir_names(p, cnodes);
/* XXX special cases to emulate original perl API behavior.
@@ -530,8 +535,8 @@ UnionfsCstore::get_all_child_node_names_impl(vector<string>& cnodes,
bool
UnionfsCstore::read_value_vec(vector<string>& vvec, bool active_cfg)
{
- b_fs::path vpath = (active_cfg ? get_active_path() : get_work_path());
- vpath /= C_VAL_NAME;
+ FsPath vpath = (active_cfg ? get_active_path() : get_work_path());
+ vpath.push(C_VAL_NAME);
string ostr;
if (!read_whole_file(vpath, ostr)) {
@@ -564,14 +569,13 @@ UnionfsCstore::read_value_vec(vector<string>& vvec, bool active_cfg)
bool
UnionfsCstore::write_value_vec(const vector<string>& vvec, bool active_cfg)
{
- b_fs::path wp = (active_cfg ? get_active_path() : get_work_path());
- wp /= C_VAL_NAME;
+ FsPath wp = (active_cfg ? get_active_path() : get_work_path());
+ wp.push(C_VAL_NAME);
- if (path_exists(wp.file_string().c_str())
- && !path_is_regular(wp.file_string().c_str())) {
+ if (path_exists(wp) && !path_is_regular(wp)) {
// not a file
output_internal("failed to write node value (file) [%s]\n",
- wp.file_string().c_str());
+ wp.path_cstr());
return false;
}
@@ -584,9 +588,9 @@ UnionfsCstore::write_value_vec(const vector<string>& vvec, bool active_cfg)
ostr += vvec[i];
}
- if (!write_file(wp.file_string().c_str(), ostr)) {
+ if (!write_file(wp, ostr)) {
output_internal("failed to write node value (write) [%s]\n",
- wp.file_string().c_str());
+ wp.path_cstr());
return false;
}
@@ -594,16 +598,16 @@ UnionfsCstore::write_value_vec(const vector<string>& vvec, bool active_cfg)
}
bool
-UnionfsCstore::rename_child_node(const string& oname, const string& nname)
+UnionfsCstore::rename_child_node(const char *oname, const char *nname)
{
- b_fs::path opath = get_work_path() / oname;
- b_fs::path npath = get_work_path() / nname;
- if (!path_exists(opath.file_string().c_str())
- || !path_is_directory(opath.file_string().c_str())
- || path_exists(npath.file_string().c_str())) {
+ FsPath opath = get_work_path();
+ opath.push(oname);
+ FsPath npath = get_work_path();
+ npath.push(nname);
+ if (!path_exists(opath) || !path_is_directory(opath)
+ || path_exists(npath)) {
output_internal("cannot rename node [%s,%s,%s]\n",
- get_work_path().file_string().c_str(),
- oname.c_str(), nname.c_str());
+ get_work_path().path_cstr(), oname, nname);
return false;
}
bool ret = true;
@@ -614,39 +618,37 @@ UnionfsCstore::rename_child_node(const string& oname, const string& nname)
* do it the hard way.
*/
recursive_copy_dir(opath, npath);
- if (b_fs::remove_all(opath) == 0) {
+ if (b_fs::remove_all(opath.path_cstr()) == 0) {
ret = false;
}
} catch (...) {
ret = false;
}
if (!ret) {
- output_internal("failed to rename node [%s,%s]\n",
- opath.file_string().c_str(),
- npath.file_string().c_str());
+ output_internal("failed to rename node [%s,%s]\n", opath.path_cstr(),
+ npath.path_cstr());
}
return ret;
}
bool
-UnionfsCstore::copy_child_node(const string& oname, const string& nname)
+UnionfsCstore::copy_child_node(const char *oname, const char *nname)
{
- b_fs::path opath = get_work_path() / oname;
- b_fs::path npath = get_work_path() / nname;
- if (!path_exists(opath.file_string().c_str())
- || !path_is_directory(opath.file_string().c_str())
- || path_exists(npath.file_string().c_str())) {
+ FsPath opath = get_work_path();
+ opath.push(oname);
+ FsPath npath = get_work_path();
+ npath.push(nname);
+ if (!path_exists(opath) || !path_is_directory(opath)
+ || path_exists(npath)) {
output_internal("cannot copy node [%s,%s,%s]\n",
- get_work_path().file_string().c_str(),
- oname.c_str(), nname.c_str());
+ get_work_path().path_cstr(), oname, nname);
return false;
}
try {
recursive_copy_dir(opath, npath);
} catch (...) {
output_internal("failed to copy node [%s,%s,%s]\n",
- get_work_path().file_string().c_str(),
- oname.c_str(), nname.c_str());
+ get_work_path().path_cstr(), oname, nname);
return false;
}
return true;
@@ -655,14 +657,15 @@ UnionfsCstore::copy_child_node(const string& oname, const string& nname)
bool
UnionfsCstore::mark_display_default()
{
- b_fs::path marker = get_work_path() / C_MARKER_DEF_VALUE;
- if (path_exists(marker.file_string().c_str())) {
+ FsPath marker = get_work_path();
+ marker.push(C_MARKER_DEF_VALUE);
+ if (path_exists(marker)) {
// already marked. treat as success.
return true;
}
- if (!create_file(marker.file_string())) {
+ if (!create_file(marker)) {
output_internal("failed to mark default [%s]\n",
- get_work_path().file_string().c_str());
+ get_work_path().path_cstr());
return false;
}
return true;
@@ -671,16 +674,17 @@ UnionfsCstore::mark_display_default()
bool
UnionfsCstore::unmark_display_default()
{
- b_fs::path marker = get_work_path() / C_MARKER_DEF_VALUE;
- if (!path_exists(marker.file_string().c_str())) {
+ FsPath marker = get_work_path();
+ marker.push(C_MARKER_DEF_VALUE);
+ if (!path_exists(marker)) {
// not marked. treat as success.
return true;
}
try {
- b_fs::remove(marker);
+ b_fs::remove(marker.path_cstr());
} catch (...) {
output_internal("failed to unmark default [%s]\n",
- get_work_path().file_string().c_str());
+ get_work_path().path_cstr());
return false;
}
return true;
@@ -689,30 +693,31 @@ UnionfsCstore::unmark_display_default()
bool
UnionfsCstore::marked_display_default(bool active_cfg)
{
- b_fs::path marker = (active_cfg ? get_active_path() : get_work_path())
- / C_MARKER_DEF_VALUE;
- return path_exists(marker.file_string().c_str());
+ FsPath marker = (active_cfg ? get_active_path() : get_work_path());
+ marker.push(C_MARKER_DEF_VALUE);
+ return path_exists(marker);
}
bool
UnionfsCstore::marked_deactivated(bool active_cfg)
{
- b_fs::path p = (active_cfg ? get_active_path() : get_work_path());
- b_fs::path marker = p / C_MARKER_DEACTIVATE;
- return path_exists(marker.file_string().c_str());
+ FsPath marker = (active_cfg ? get_active_path() : get_work_path());
+ marker.push(C_MARKER_DEACTIVATE);
+ return path_exists(marker);
}
bool
UnionfsCstore::mark_deactivated()
{
- b_fs::path marker = get_work_path() / C_MARKER_DEACTIVATE;
- if (path_exists(marker.file_string().c_str())) {
+ FsPath marker = get_work_path();
+ marker.push(C_MARKER_DEACTIVATE);
+ if (path_exists(marker)) {
// already marked. treat as success.
return true;
}
- if (!create_file(marker.file_string())) {
+ if (!create_file(marker)) {
output_internal("failed to mark deactivated [%s]\n",
- get_work_path().file_string().c_str());
+ get_work_path().path_cstr());
return false;
}
return true;
@@ -721,16 +726,17 @@ UnionfsCstore::mark_deactivated()
bool
UnionfsCstore::unmark_deactivated()
{
- b_fs::path marker = get_work_path() / C_MARKER_DEACTIVATE;
- if (!path_exists(marker.file_string().c_str())) {
+ FsPath marker = get_work_path();
+ marker.push(C_MARKER_DEACTIVATE);
+ if (!path_exists(marker)) {
// not deactivated. treat as success.
return true;
}
try {
- b_fs::remove(marker);
+ b_fs::remove(marker.path_cstr());
} catch (...) {
output_internal("failed to unmark deactivated [%s]\n",
- get_work_path().file_string().c_str());
+ get_work_path().path_cstr());
return false;
}
return true;
@@ -742,20 +748,21 @@ UnionfsCstore::unmark_deactivated_descendants()
bool ret = false;
do {
// sanity check
- if (!path_is_directory(get_work_path().file_string().c_str())) {
+ if (!path_is_directory(get_work_path())) {
break;
}
try {
vector<b_fs::path> markers;
- b_fs::recursive_directory_iterator di(get_work_path());
+ b_fs::recursive_directory_iterator di(get_work_path().path_cstr());
for (; di != b_fs::recursive_directory_iterator(); ++di) {
if (!path_is_regular(di->path().file_string().c_str())
|| di->path().filename() != C_MARKER_DEACTIVATE) {
// not marker
continue;
}
- if (di->path().parent_path() == get_work_path()) {
+ const char *ppath = di->path().parent_path().file_string().c_str();
+ if (strcmp(ppath, get_work_path().path_cstr()) == 0) {
// don't unmark the node itself
continue;
}
@@ -771,7 +778,7 @@ UnionfsCstore::unmark_deactivated_descendants()
} while (0);
if (!ret) {
output_internal("failed to unmark deactivated descendants [%s]\n",
- get_work_path().file_string().c_str());
+ get_work_path().path_cstr());
}
return ret;
}
@@ -780,29 +787,27 @@ UnionfsCstore::unmark_deactivated_descendants()
bool
UnionfsCstore::mark_changed_with_ancestors()
{
- b_fs::path opath = mutable_cfg_path; // use a copy
+ FsPath opath = mutable_cfg_path; // use a copy
bool done = false;
while (!done) {
- b_fs::path marker = work_root;
+ FsPath marker = work_root;
if (opath.has_parent_path()) {
marker /= opath;
pop_path(opath);
} else {
done = true;
}
- if (!path_exists(marker.file_string().c_str())
- || !path_is_directory(marker.file_string().c_str())) {
+ if (!path_exists(marker) || !path_is_directory(marker)) {
// don't do anything if the node is not there
continue;
}
- marker /= C_MARKER_CHANGED;
- if (path_exists(marker.file_string().c_str())) {
+ marker.push(C_MARKER_CHANGED);
+ if (path_exists(marker)) {
// reached a node already marked => done
break;
}
- if (!create_file(marker.file_string())) {
- output_internal("failed to mark changed [%s]\n",
- marker.file_string().c_str());
+ if (!create_file(marker)) {
+ output_internal("failed to mark changed [%s]\n", marker.path_cstr());
return false;
}
}
@@ -817,7 +822,7 @@ UnionfsCstore::unmark_changed_with_descendants()
{
try {
vector<b_fs::path> markers;
- b_fs::recursive_directory_iterator di(get_work_path());
+ b_fs::recursive_directory_iterator di(get_work_path().path_cstr());
for (; di != b_fs::recursive_directory_iterator(); ++di) {
if (!path_is_regular(di->path().file_string().c_str())
|| di->path().filename() != C_MARKER_CHANGED) {
@@ -831,7 +836,7 @@ UnionfsCstore::unmark_changed_with_descendants()
}
} catch (...) {
output_internal("failed to unmark changed with descendants [%s]\n",
- get_work_path().file_string().c_str());
+ get_work_path().path_cstr());
return false;
}
return true;
@@ -841,15 +846,15 @@ UnionfsCstore::unmark_changed_with_descendants()
bool
UnionfsCstore::remove_comment()
{
- b_fs::path cfile = get_work_path() / C_COMMENT_FILE;
- if (!path_exists(cfile.file_string().c_str())) {
+ FsPath cfile = get_work_path();
+ cfile.push(C_COMMENT_FILE);
+ if (!path_exists(cfile)) {
return false;
}
try {
- b_fs::remove(cfile);
+ b_fs::remove(cfile.path_cstr());
} catch (...) {
- output_internal("failed to remove comment [%s]\n",
- cfile.file_string().c_str());
+ output_internal("failed to remove comment [%s]\n", cfile.path_cstr());
return false;
}
return true;
@@ -859,8 +864,9 @@ UnionfsCstore::remove_comment()
bool
UnionfsCstore::set_comment(const string& comment)
{
- b_fs::path cfile = get_work_path() / C_COMMENT_FILE;
- return write_file(cfile.file_string(), comment);
+ FsPath cfile = get_work_path();
+ cfile.push(C_COMMENT_FILE);
+ return write_file(cfile, comment);
}
// discard all changes in working config
@@ -875,7 +881,7 @@ UnionfsCstore::discard_changes(unsigned long long& num_removed)
vector<b_fs::path> directories;
try {
// iterate through all entries in change root
- b_fs::directory_iterator di(change_root);
+ b_fs::directory_iterator di(change_root.path_cstr());
for (; di != b_fs::directory_iterator(); ++di) {
if (path_is_directory(di->path().file_string().c_str())) {
directories.push_back(di->path());
@@ -894,8 +900,7 @@ UnionfsCstore::discard_changes(unsigned long long& num_removed)
num_removed += b_fs::remove_all(directories[i]);
}
} catch (...) {
- output_internal("discard failed [%s]\n",
- change_root.file_string().c_str());
+ output_internal("discard failed [%s]\n", change_root.path_cstr());
ret = false;
}
@@ -911,8 +916,8 @@ UnionfsCstore::discard_changes(unsigned long long& num_removed)
bool
UnionfsCstore::get_comment(string& comment, bool active_cfg)
{
- b_fs::path cfile = (active_cfg ? get_active_path() : get_work_path());
- cfile /= C_COMMENT_FILE;
+ FsPath cfile = (active_cfg ? get_active_path() : get_work_path());
+ cfile.push(C_COMMENT_FILE);
return read_whole_file(cfile, comment);
}
@@ -920,8 +925,9 @@ UnionfsCstore::get_comment(string& comment, bool active_cfg)
bool
UnionfsCstore::cfg_node_changed()
{
- b_fs::path marker = get_work_path() / C_MARKER_CHANGED;
- return path_exists(marker.file_string().c_str());
+ FsPath marker = get_work_path();
+ marker.push(C_MARKER_CHANGED);
+ return path_exists(marker);
}
/* XXX currently "committed marking" is done inside commit.
@@ -934,14 +940,17 @@ UnionfsCstore::cfg_node_changed()
* be only one operation on the path).
*/
bool
-UnionfsCstore::marked_committed(const Ctemplate *def, bool is_set)
+UnionfsCstore::marked_committed(const tr1::shared_ptr<Ctemplate>& def,
+ bool is_set)
{
- b_fs::path cpath = mutable_cfg_path;
- string com_str = cpath.file_string() + "/";
+ FsPath cpath = mutable_cfg_path;
+ string com_str = cpath.path_cstr();
+ com_str += "/";
if (def->isLeafValue()) {
// path includes leaf value. construct the right string.
- string val = _unescape_path_name(cpath.filename());
- cpath = cpath.parent_path();
+ string val;
+ cpath.pop(val);
+ val = _unescape_path_name(val);
/* XXX current commit implementation escapes value strings for
* single-value nodes but not for multi-value nodes for some
* reason. the following match current behavior.
@@ -949,14 +958,17 @@ UnionfsCstore::marked_committed(const Ctemplate *def, bool is_set)
if (!def->isMulti()) {
val = _escape_path_name(val);
}
- com_str = cpath.file_string() + "/value:" + val;
+ com_str = cpath.path_cstr();
+ com_str += "/value:";
+ com_str += val;
}
com_str = (is_set ? "+ " : "- ") + com_str;
return committed_marker_exists(com_str);
}
bool
-UnionfsCstore::validate_val_impl(const Ctemplate *def, char *value)
+UnionfsCstore::validate_val_impl(const tr1::shared_ptr<Ctemplate>& def,
+ char *value)
{
/* XXX filesystem paths/accesses are completely embedded in var ref lib.
* for now, treat the lib as a unionfs-specific implementation.
@@ -971,16 +983,23 @@ UnionfsCstore::validate_val_impl(const Ctemplate *def, char *value)
}
void
-UnionfsCstore::get_edit_level(vector<string>& pcomps) {
- b_fs::path opath = mutable_cfg_path; // use a copy
+UnionfsCstore::get_edit_level(Cpath& pcomps) {
+ FsPath opath = mutable_cfg_path; // use a copy
+ vector<string> tmp;
while (opath.has_parent_path()) {
- pcomps.insert(pcomps.begin(), pop_path(opath));
+ string last;
+ pop_path(opath, last);
+ tmp.push_back(last);
+ }
+ while (tmp.size() > 0) {
+ pcomps.push(tmp.back());
+ tmp.pop_back();
}
}
string
UnionfsCstore::cfg_path_to_str() {
- string cpath = mutable_cfg_path.file_string();
+ string cpath = mutable_cfg_path.path_cstr();
if (cpath.length() == 0) {
cpath = "/";
}
@@ -990,8 +1009,8 @@ UnionfsCstore::cfg_path_to_str() {
string
UnionfsCstore::tmpl_path_to_str() {
// return only the mutable part
- string tpath = tmpl_path.file_string();
- tpath.erase(0, tmpl_root.file_string().length());
+ string tpath = tmpl_path.path_cstr();
+ tpath.erase(0, tmpl_root.length());
if (tpath.length() == 0) {
tpath = "/";
}
@@ -1001,33 +1020,35 @@ UnionfsCstore::tmpl_path_to_str() {
////// private functions
void
-UnionfsCstore::push_path(b_fs::path& old_path, const string& new_comp)
+UnionfsCstore::push_path(FsPath& old_path, const char *new_comp)
{
string comp = _escape_path_name(new_comp);
- old_path /= comp;
+ old_path.push(comp);
}
-string
-UnionfsCstore::pop_path(b_fs::path& path)
+void
+UnionfsCstore::pop_path(FsPath& path)
{
- string ret = _unescape_path_name(path.filename());
- /* note: contrary to documentation, remove_filename() does not remove
- * trailing slash.
- */
- path = path.parent_path();
- return ret;
+ path.pop();
}
void
-UnionfsCstore::get_all_child_dir_names(b_fs::path root, vector<string>& nodes)
+UnionfsCstore::pop_path(FsPath& path, string& last)
{
- if (!path_exists(root.file_string().c_str())
- || !path_is_directory(root.file_string().c_str())) {
+ path.pop(last);
+ last = _unescape_path_name(last);
+}
+
+void
+UnionfsCstore::get_all_child_dir_names(const FsPath& root,
+ vector<string>& nodes)
+{
+ if (!path_exists(root) || !path_is_directory(root)) {
// not a valid root. nop.
return;
}
try {
- b_fs::directory_iterator di(root);
+ b_fs::directory_iterator di(root.path_cstr());
for (; di != b_fs::directory_iterator(); ++di) {
// must be directory
if (!path_is_directory(di->path().file_string().c_str())) {
@@ -1047,7 +1068,7 @@ UnionfsCstore::get_all_child_dir_names(b_fs::path root, vector<string>& nodes)
}
bool
-UnionfsCstore::write_file(const string& file, const string& data)
+UnionfsCstore::write_file(const FsPath& file, const string& data)
{
if (data.size() > C_UNIONFS_MAX_FILE_SIZE) {
output_internal("write_file too large\n");
@@ -1055,13 +1076,14 @@ UnionfsCstore::write_file(const string& file, const string& data)
}
try {
// make sure the path exists
- b_fs::path fpath(file);
- b_fs::create_directories(fpath.parent_path());
+ FsPath ppath(file);
+ ppath.pop();
+ b_fs::create_directories(ppath.path_cstr());
// write the file
ofstream fout;
fout.exceptions(ofstream::failbit | ofstream::badbit);
- fout.open(file.c_str(), ios_base::out | ios_base::trunc);
+ fout.open(file.path_cstr(), ios_base::out | ios_base::trunc);
fout << data;
fout.close();
} catch (...) {
@@ -1071,23 +1093,22 @@ UnionfsCstore::write_file(const string& file, const string& data)
}
bool
-UnionfsCstore::read_whole_file(const b_fs::path& fpath, string& data)
+UnionfsCstore::read_whole_file(const FsPath& fpath, string& data)
{
/* must exist, be a regular file, and smaller than limit (we're going
* to read the whole thing).
*/
- if (!path_exists(fpath.file_string().c_str())
- || !path_is_regular(fpath.file_string().c_str())) {
+ if (!path_exists(fpath) || !path_is_regular(fpath)) {
return false;
}
try {
- if (b_fs::file_size(fpath) > C_UNIONFS_MAX_FILE_SIZE) {
+ if (b_fs::file_size(fpath.path_cstr()) > C_UNIONFS_MAX_FILE_SIZE) {
output_internal("read_whole_file too large\n");
return false;
}
stringbuf sbuf;
- ifstream fin(fpath.file_string().c_str());
+ ifstream fin(fpath.path_cstr());
fin >> &sbuf;
fin.close();
/* note: if file contains just a newline => (eof() && fail())
@@ -1132,22 +1153,21 @@ UnionfsCstore::committed_marker_exists(const string& marker)
* will throw exception (from b_fs) if fail.
*/
void
-UnionfsCstore::recursive_copy_dir(const b_fs::path& src, const b_fs::path& dst)
+UnionfsCstore::recursive_copy_dir(const FsPath& src, const FsPath& dst)
{
- string src_str = src.file_string();
- string dst_str = dst.file_string();
- b_fs::create_directory(dst);
+ string src_str = src.path_cstr();
+ string dst_str = dst.path_cstr();
+ b_fs::create_directory(dst.path_cstr());
- b_fs::recursive_directory_iterator di(src);
+ b_fs::recursive_directory_iterator di(src_str);
for (; di != b_fs::recursive_directory_iterator(); ++di) {
- b_fs::path opath = di->path();
- string nname = opath.file_string();
+ const char *oname = di->path().file_string().c_str();
+ string nname = oname;
nname.replace(0, src_str.length(), dst_str);
- b_fs::path npath = nname;
- if (path_is_directory(opath.file_string().c_str())) {
- b_fs::create_directory(npath);
+ if (path_is_directory(oname)) {
+ b_fs::create_directory(nname);
} else {
- b_fs::copy_file(opath, npath);
+ b_fs::copy_file(oname, nname);
}
}
}
@@ -1182,3 +1202,6 @@ UnionfsCstore::path_is_regular(const char *path)
return b_fs::is_regular(result);
}
+} // end namespace unionfs
+} // end namespace cstore
+
diff --git a/src/cstore/unionfs/cstore-unionfs.hpp b/src/cstore/unionfs/cstore-unionfs.hpp
index 53c6396..afb65a6 100644
--- a/src/cstore/unionfs/cstore-unionfs.hpp
+++ b/src/cstore/unionfs/cstore-unionfs.hpp
@@ -28,8 +28,10 @@
#include <cli_cstore.h>
#include <cstore/cstore.hpp>
+#include <cstore/unionfs/fspath.hpp>
namespace cstore { // begin namespace cstore
+namespace unionfs { // begin namespace unionfs
namespace b_fs = boost::filesystem;
namespace b_s = boost::system;
@@ -80,21 +82,19 @@ private:
static const size_t C_UNIONFS_MAX_FILE_SIZE = 262144;
// root dirs (constant)
- b_fs::path work_root; // working root (union)
- b_fs::path active_root; // active root (readonly part of union)
- b_fs::path change_root; // change root (r/w part of union)
- b_fs::path tmp_root; // temp root
- b_fs::path tmpl_root; // template root
+ FsPath work_root; // working root (union)
+ FsPath active_root; // active root (readonly part of union)
+ FsPath change_root; // change root (r/w part of union)
+ FsPath tmp_root; // temp root
+ FsPath tmpl_root; // template root
// path buffers
- b_fs::path mutable_cfg_path; // mutable part of config path
- b_fs::path tmpl_path; // whole template path
- Cstore::MapT<const void *, pair<b_fs::path, b_fs::path> > saved_paths;
- // saved mutable part of cfg path and whole template path
+ FsPath mutable_cfg_path; // mutable part of config path
+ FsPath tmpl_path; // whole template path
////// virtual functions defined in base class
// begin path modifiers
- void push_tmpl_path(const string& new_comp) {
+ void push_tmpl_path(const char *new_comp) {
push_path(tmpl_path, new_comp);
};
void push_tmpl_path_tag() {
@@ -105,18 +105,24 @@ private:
* however, since current C_TAG_NAME doesn't contain any escape
* sequences, this cannot happen for now.
*/
- tmpl_path /= C_TAG_NAME;
+ tmpl_path.push(C_TAG_NAME);
};
- string pop_tmpl_path() {
- return pop_path(tmpl_path);
+ void pop_tmpl_path() {
+ pop_path(tmpl_path);
};
- void push_cfg_path(const string& new_comp) {
+ void pop_tmpl_path(string& last) {
+ pop_path(tmpl_path, last);
+ };
+ void push_cfg_path(const char *new_comp) {
push_path(mutable_cfg_path, new_comp);
};
- string pop_cfg_path() {
- return pop_path(mutable_cfg_path);
+ void pop_cfg_path() {
+ pop_path(mutable_cfg_path);
+ };
+ void pop_cfg_path(string& last) {
+ pop_path(mutable_cfg_path, last);
};
- void append_cfg_path(const vector<string>& path_comps) {
+ void append_cfg_path(const Cpath& path_comps) {
for (size_t i = 0; i < path_comps.size(); i++) {
push_cfg_path(path_comps[i]);
}
@@ -125,27 +131,31 @@ private:
tmpl_path = tmpl_root;
mutable_cfg_path = "";
};
- void save_paths(const void *handle = NULL) {
- pair<b_fs::path, b_fs::path> p;
- p.first = mutable_cfg_path;
- p.second = tmpl_path;
- saved_paths[handle] = p;
- };
- void restore_paths(const void *handle = NULL) {
- Cstore::MapT<const void *, pair<b_fs::path, b_fs::path> >::iterator it
- = saved_paths.find(handle);
- if (it == saved_paths.end()) {
- exit_internal("restore_paths: handle not found\n");
- }
- pair<b_fs::path, b_fs::path> p = it->second;
- mutable_cfg_path = p.first;
- tmpl_path = p.second;
+
+ class UnionfsSavePaths : public SavePaths {
+ public:
+ UnionfsSavePaths(UnionfsCstore *cs)
+ : cstore(cs), cpath(cs->mutable_cfg_path), tpath(cs->tmpl_path) {};
+
+ ~UnionfsSavePaths() {
+ cstore->mutable_cfg_path = cpath;
+ cstore->tmpl_path = tpath;
+ };
+
+ private:
+ UnionfsCstore *cstore;
+ FsPath cpath;
+ FsPath tpath;
};
+ auto_ptr<SavePaths> create_save_paths() {
+ return auto_ptr<SavePaths>(new UnionfsSavePaths(this));
+ };
+
bool cfg_path_at_root() {
return (!mutable_cfg_path.has_parent_path());
};
bool tmpl_path_at_root() {
- return (tmpl_path.file_string() == tmpl_root.file_string());
+ return (tmpl_path == tmpl_root);
};
// end path modifiers
@@ -161,8 +171,8 @@ private:
get_all_child_dir_names(tmpl_path, cnodes);
};
bool write_value_vec(const vector<string>& vvec, bool active_cfg);
- bool rename_child_node(const string& oname, const string& nname);
- bool copy_child_node(const string& oname, const string& nname);
+ bool rename_child_node(const char *oname, const char *nname);
+ bool copy_child_node(const char *oname, const char *nname);
bool mark_display_default();
bool unmark_display_default();
bool mark_deactivated();
@@ -185,10 +195,10 @@ private:
bool marked_display_default(bool active_cfg);
// observers during commit operation
- bool marked_committed(const Ctemplate *def, bool is_set);
+ bool marked_committed(const tr1::shared_ptr<Ctemplate>& def, bool is_set);
// these operate on both current tmpl and work paths
- bool validate_val_impl(const Ctemplate *def, char *value);
+ bool validate_val_impl(const tr1::shared_ptr<Ctemplate>& def, char *value);
// observers for "edit/tmpl levels" (for "edit"-related operations).
// note that these should be moved to base class in the future.
@@ -198,7 +208,7 @@ private:
string get_tmpl_level_path() {
return tmpl_path_to_str();
};
- void get_edit_level(vector<string>& path_comps);
+ void get_edit_level(Cpath& path_comps);
bool edit_level_at_root() {
return cfg_path_at_root();
};
@@ -208,19 +218,20 @@ private:
string tmpl_path_to_str();
////// private functions
- b_fs::path get_work_path() { return (work_root / mutable_cfg_path); };
- b_fs::path get_active_path() { return (active_root / mutable_cfg_path); };
- b_fs::path get_change_path() { return (change_root / mutable_cfg_path); };
- void push_path(b_fs::path& old_path, const string& new_comp);
- string pop_path(b_fs::path& path);
- void get_all_child_dir_names(b_fs::path root, vector<string>& nodes);
- bool write_file(const string& file, const string& data);
- bool create_file(const string& file) {
+ FsPath get_work_path() { return (work_root / mutable_cfg_path); };
+ FsPath get_active_path() { return (active_root / mutable_cfg_path); };
+ FsPath get_change_path() { return (change_root / mutable_cfg_path); };
+ void push_path(FsPath& old_path, const char *new_comp);
+ void pop_path(FsPath& path);
+ void pop_path(FsPath& path, string& last);
+ void get_all_child_dir_names(const FsPath& root, vector<string>& nodes);
+ bool write_file(const FsPath& file, const string& data);
+ bool create_file(const FsPath& file) {
return write_file(file, "");
};
- bool read_whole_file(const b_fs::path& file, string& data);
+ bool read_whole_file(const FsPath& file, string& data);
bool committed_marker_exists(const string& marker);
- void recursive_copy_dir(const b_fs::path& src, const b_fs::path& dst);
+ void recursive_copy_dir(const FsPath& src, const FsPath& dst);
// boost fs operations wrappers
bool b_fs_get_file_status(const char *path, b_fs::file_status& fs) {
@@ -229,10 +240,20 @@ private:
return (!ec);
};
bool path_exists(const char *path);
+ bool path_exists(const FsPath& path) {
+ return path_exists(path.path_cstr());
+ };
bool path_is_directory(const char *path);
+ bool path_is_directory(const FsPath& path) {
+ return path_is_directory(path.path_cstr());
+ };
bool path_is_regular(const char *path);
+ bool path_is_regular(const FsPath& path) {
+ return path_is_regular(path.path_cstr());
+ };
};
+} // end namespace unionfs
} // end namespace cstore
#endif /* _CSTORE_UNIONFS_H_ */
diff --git a/src/cstore/unionfs/fspath.hpp b/src/cstore/unionfs/fspath.hpp
new file mode 100644
index 0000000..35985ed
--- /dev/null
+++ b/src/cstore/unionfs/fspath.hpp
@@ -0,0 +1,92 @@
+/*
+ * Copyright (C) 2011 Vyatta, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef _FSPATH_HPP_
+#define _FSPATH_HPP_
+#include <string>
+
+#include <cstore/svector.hpp>
+
+namespace cstore { // begin namespace cstore
+namespace unionfs { // begin namespace unionfs
+
+class FsPath {
+public:
+ FsPath() : _data() {};
+ explicit FsPath(const char *full_path) : _data() { operator=(full_path); };
+ explicit FsPath(const std::string& full_path) : _data() {
+ operator=(full_path);
+ };
+ FsPath(const FsPath& p) : _data() { operator=(p); };
+ ~FsPath() {};
+
+ void push(const char *comp) { _data.push_back(comp); };
+ void push(const std::string& comp) { _data.push_back(comp.c_str()); };
+ void pop() { _data.pop_back(); };
+ void pop(std::string& last) { _data.pop_back(last); };
+
+ FsPath& operator=(const char *full_path) {
+ _data = full_path;
+ return *this;
+ };
+ FsPath& operator=(const std::string& full_path) {
+ _data = full_path;
+ return *this;
+ };
+ FsPath& operator=(const FsPath& p) {
+ _data = p._data;
+ return *this;
+ };
+ FsPath& operator/=(const FsPath& p) {
+ _data /= p._data;
+ return *this;
+ }
+ FsPath operator/(const FsPath& rhs) {
+ FsPath lhs(*this);
+ lhs /= rhs;
+ return lhs;
+ };
+
+ bool operator==(const FsPath& rhs) const {
+ return (_data == rhs._data);
+ };
+
+ size_t length() const { return _data.length(); };
+ bool has_parent_path() const { return (_data.size() > 0); };
+ const char *path_cstr() const { return _data.get_cstr(); };
+ size_t hash() const { return _data.hash(); };
+
+private:
+ struct FsPathParams {
+ static const char separator = '/';
+ static const size_t static_num_elems = 24;
+ static const size_t static_buf_len = 256;
+ };
+
+ cstore::svector<FsPathParams> _data;
+};
+
+struct FsPathHash {
+ inline size_t operator()(const FsPath& p) const {
+ return p.hash();
+ };
+};
+
+} // end namespace unionfs
+} // end namespace cstore
+
+#endif /* _FSPATH_HPP_ */
+