diff options
author | An-Cheng Huang <ancheng@vyatta.com> | 2011-05-17 11:04:53 -0700 |
---|---|---|
committer | An-Cheng Huang <ancheng@vyatta.com> | 2011-05-17 11:04:53 -0700 |
commit | e9a2127e7fc20673e3aa1b09d54743077947c70e (patch) | |
tree | 1df056ff8f61cc7a81b9a42f2395828905e38a63 | |
parent | 9d5b213893a79939ac8f2e871e18ba3163eeab50 (diff) | |
download | vyatta-cfg-e9a2127e7fc20673e3aa1b09d54743077947c70e.tar.gz vyatta-cfg-e9a2127e7fc20673e3aa1b09d54743077947c70e.zip |
reimplement commit locking
-rw-r--r-- | src/commit/commit-algorithm.cpp | 12 | ||||
-rw-r--r-- | src/cstore/cstore.hpp | 5 | ||||
-rw-r--r-- | src/cstore/unionfs/cstore-unionfs.cpp | 18 | ||||
-rw-r--r-- | src/cstore/unionfs/cstore-unionfs.hpp | 2 |
4 files changed, 37 insertions, 0 deletions
diff --git a/src/commit/commit-algorithm.cpp b/src/commit/commit-algorithm.cpp index a5d3415..46cfa58 100644 --- a/src/commit/commit-algorithm.cpp +++ b/src/commit/commit-algorithm.cpp @@ -1157,6 +1157,18 @@ commit::isCommitPathEffective(Cstore& cs, const Cpath& pcomps, bool commit::doCommit(Cstore& cs, CfgNode& cfg1, CfgNode& cfg2) { + /* get the lock first. + * note: the getCommitLock() interface provided by Cstore guarantees + * that the lock will be released upon process termination (either + * normally or abnormally), so this is all that is required in terms + * of commit locking. + */ + if (!cs.getCommitLock()) { + OUTPUT_USER("Configuration system temporarily locked " + "due to another commit in progress\n"); + return false; + } + Cpath p; CfgNode *root = getCommitTree(&cfg1, &cfg2, p); if (!root) { diff --git a/src/cstore/cstore.hpp b/src/cstore/cstore.hpp index af4a56d..d6f6d67 100644 --- a/src/cstore/cstore.hpp +++ b/src/cstore/cstore.hpp @@ -177,6 +177,11 @@ public: bool markCfgPathCommitted(const Cpath& path_comps, bool is_delete); virtual bool clearCommittedMarkers() = 0; virtual bool commitConfig(commit::PrioNode& pnode) = 0; + virtual bool getCommitLock() = 0; + /* note: the getCommitLock() function must guarantee lock release/cleanup + * upon process termination (either normally or abnormally). there is no + * separate call for releasing the lock. + */ // load bool loadFile(const char *filename); diff --git a/src/cstore/unionfs/cstore-unionfs.cpp b/src/cstore/unionfs/cstore-unionfs.cpp index 6ccdbf2..41ce008 100644 --- a/src/cstore/unionfs/cstore-unionfs.cpp +++ b/src/cstore/unionfs/cstore-unionfs.cpp @@ -63,6 +63,7 @@ const string UnionfsCstore::C_COMMENT_FILE = ".comment"; const string UnionfsCstore::C_TAG_NAME = "node.tag"; const string UnionfsCstore::C_VAL_NAME = "node.val"; const string UnionfsCstore::C_DEF_NAME = "node.def"; +const string UnionfsCstore::C_COMMIT_LOCK_FILE = "/opt/vyatta/config/.lock"; ////// static @@ -696,6 +697,23 @@ UnionfsCstore::commitConfig(commit::PrioNode& node) return true; } +bool +UnionfsCstore::getCommitLock() +{ + int fd = creat(C_COMMIT_LOCK_FILE.c_str(), 0777); + if (fd < 0) { + // should not happen since all commit processes should have write access + output_internal("getCommitLock() failed to open lock file\n"); + return false; + } + if (lockf(fd, F_TLOCK, 0) < 0) { + // locked by someone else + return false; + } + // got the lock + return true; +} + ////// virtual functions defined in base class /* check if current tmpl_path is a valid tmpl dir. diff --git a/src/cstore/unionfs/cstore-unionfs.hpp b/src/cstore/unionfs/cstore-unionfs.hpp index c7cd2d9..1240488 100644 --- a/src/cstore/unionfs/cstore-unionfs.hpp +++ b/src/cstore/unionfs/cstore-unionfs.hpp @@ -57,6 +57,7 @@ public: bool inSession(); bool clearCommittedMarkers(); bool commitConfig(commit::PrioNode& pnode); + bool getCommitLock(); private: // constants @@ -82,6 +83,7 @@ private: static const string C_TAG_NAME; static const string C_VAL_NAME; static const string C_DEF_NAME; + static const string C_COMMIT_LOCK_FILE; /* max size for a file. * currently this includes value file and comment file. |