Check duplicity of RFN during adding or updating replicas.
authorFrantišek Dvořák <valtri@civ.zcu.cz>
Sun, 1 Dec 2013 20:41:50 +0000 (21:41 +0100)
committerFrantišek Dvořák <valtri@civ.zcu.cz>
Sun, 23 Feb 2014 13:16:20 +0000 (14:16 +0100)
src/VfsNs.cpp

index 0bf63b9..6e5f8a2 100644 (file)
@@ -450,6 +450,7 @@ void VfsCatalog::addReplica(const Replica& replica) throw (DmException)
   if (checkPermissions(this->secCtx_, meta.acl, meta.stat, S_IWRITE) != 0)
     vfsThrow(EACCES, "not enough permissions for '%s' to add replica '%s'", clientName.c_str(), path.c_str());
 
+  // new replica ID
   replicaid = 0;
   do {
     replicaid++;
@@ -458,6 +459,21 @@ void VfsCatalog::addReplica(const Replica& replica) throw (DmException)
   } while (meta.hasField(attr1));
   attr2 = std::string(VFS_XATTR "repattrs.") + buf;
 
+  // check duplicity of RFN
+  for (Extensible::const_iterator it = meta.begin(); it != meta.end(); it++) {
+    std::string key, value;
+    Replica rep;
+
+    key = it->first;
+    value = Extensible::anyToString(it->second);
+    if (key.compare(0, VFS_XATTR_LENGTH + 8, VFS_XATTR "replica.") == 0) {
+      rep = replicaDeserialize(value, "");
+      if (rep.rfn.compare(replica.rfn) == 0) {
+        vfsThrow(EEXIST, "RFN '%s' already exists on '%s'", replica.rfn.c_str(), path.c_str());
+      }
+    }
+  }
+
   replicaSerialize(replica, attrval1, attrval2);
 
   vfsSetXattr(path, getLocalPath(path), attr1, attrval1, ATTR_CREATE);
@@ -1389,6 +1405,25 @@ void VfsCatalog::updateReplica(const Replica& replica) throw (DmException)
     vfsThrow(DMLITE_NO_SUCH_REPLICA, "replica %lu of '%s' doesn't exist", replica.replicaid, path.c_str());
   attr2 = std::string(VFS_XATTR "repattrs.") + buf;
 
+  // check duplicity of RFN
+  for (Extensible::const_iterator it = meta.begin(); it != meta.end(); it++) {
+    std::string key, value;
+    Replica rep;
+    int64_t repid;
+
+    key = it->first;
+    value = Extensible::anyToString(it->second);
+    if (key.compare(0, VFS_XATTR_LENGTH + 8, VFS_XATTR "replica.") == 0) {
+      repid = atoll(key.c_str() + VFS_XATTR_LENGTH + 8);
+      // skip the currently updated replica (RFN may be the same)
+      if (repid == replica.replicaid) continue;
+      rep = replicaDeserialize(value, "");
+      if (rep.rfn.compare(replica.rfn) == 0) {
+        vfsThrow(EEXIST, "RFN '%s' already exists on '%s'", replica.rfn.c_str(), path.c_str());
+      }
+    }
+  }
+
   replicaSerialize(replica, attrval1, attrval2);
   vfsSetXattr(path, getLocalPath(path), attr1, attrval1, ATTR_REPLACE);
   if (attrval2.empty()) {