summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAn-Cheng Huang <ancheng@vyatta.com>2011-05-17 11:04:53 -0700
committerAn-Cheng Huang <ancheng@vyatta.com>2011-05-17 11:04:53 -0700
commite9a2127e7fc20673e3aa1b09d54743077947c70e (patch)
tree1df056ff8f61cc7a81b9a42f2395828905e38a63
parent9d5b213893a79939ac8f2e871e18ba3163eeab50 (diff)
downloadvyatta-cfg-e9a2127e7fc20673e3aa1b09d54743077947c70e.tar.gz
vyatta-cfg-e9a2127e7fc20673e3aa1b09d54743077947c70e.zip
reimplement commit locking
-rw-r--r--src/commit/commit-algorithm.cpp12
-rw-r--r--src/cstore/cstore.hpp5
-rw-r--r--src/cstore/unionfs/cstore-unionfs.cpp18
-rw-r--r--src/cstore/unionfs/cstore-unionfs.hpp2
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.