From: František Dvořák Date: Sun, 8 Dec 2013 22:59:55 +0000 (+0100) Subject: Implement extendedStatByRFN(), accessReplica(), and getReplicaByRFN(). X-Git-Url: http://scientific.zcu.cz/git/?a=commitdiff_plain;h=c3a58308ad9d95fcb34b53192e40f5d17290e513;p=dmlite-plugins-vfs.git Implement extendedStatByRFN(), accessReplica(), and getReplicaByRFN(). --- diff --git a/src/VfsNs.cpp b/src/VfsNs.cpp index 73cca7a..e6f5d81 100644 --- a/src/VfsNs.cpp +++ b/src/VfsNs.cpp @@ -401,6 +401,77 @@ ExtendedStat VfsCatalog::extendedStat(const std::string& path, bool follow) thro +std::string VfsCatalog::vfsPathByRFN(const std::string& rfn) throw (DmException) +{ + std::string curdir, path; + struct stat entry; + FILE *f; + + curdir = rfn2path(rfn); + if (curdir.empty()) + vfsThrow(EINVAL, "server or path required in replica file name"); + + if (vfsCheckPermissions("", S_IREAD)) + vfsThrow(EACCES, "not enough permissions for '%s'", clientName.c_str()); + + // read the catalog path + curdir = this->prefix_ + "/" + VFS_REPLICAS_TREE + curdir; + try { + wrapCall(stat(curdir.c_str(), &entry), "could not stat replica entry '%s'", rfn.c_str()); + if (!S_ISREG(entry.st_mode)) + vfsThrow(DMLITE_NO_SUCH_REPLICA, "replica entry '%s' is not valid", rfn.c_str()); + if ((f = fopen(curdir.c_str(), "r")) == NULL) + vfsThrowErrno("could not open replica entry '%s'", rfn.c_str()); + } catch (DmException e) { + if (e.code() == ENOTDIR || e.code() == ENOENT) + vfsThrow(DMLITE_NO_SUCH_REPLICA, "replica entry '%s' not found", rfn.c_str()); + throw; + } + try { + fgets(this->buffer, sizeof this->buffer, f); + wrapCall(ferror(f), "error reading replica entry '%s'", rfn.c_str()); + } catch (DmException e) { + fclose(f); + throw; + } + wrapCall(fclose(f), "could not close replica entry '%s'", rfn.c_str()); + + path = this->buffer; + + return path; +} + + + +ExtendedStat VfsCatalog::extendedStatByRFN(const std::string& rfn) throw (DmException) +{ + ExtendedStat meta; + std::string path; + Extensible xattrs; + + path = vfsPathByRFN(rfn); + meta = vfsExtendedStat(path, true, false, false); + + // + // User extended attributes are not supported on symlinks. We need the same + // owner, permissions and other atributes like the original file anyway. + // ==> always follow the symlinks. + // + try { + xattrs = vfsGetXattrs(path, getLocalPath(path), true, VFS_XATTR_TYPE_ALL); + } catch (DmException& e) { + // ignore - default owner and no ACLs + } + // use the retrieved xattrs + vfsUpdateExtendedStat(meta, xattrs); + + vfsUpdateInode(meta, path); + + return meta; +} + + + bool VfsCatalog::access(const std::string& path, int mode) throw (DmException) { ExtendedStat meta; @@ -447,8 +518,10 @@ bool VfsCatalog::access(const std::string& path, int mode) throw (DmException) bool VfsCatalog::accessReplica(const std::string& replica, int mode) throw (DmException) { - vfsThrow(ENOSYS, "searching by replica file names not supported"); - return false; + std::string path; + + path = vfsPathByRFN(replica); + return this->access(path, mode); } @@ -1426,25 +1499,42 @@ void VfsCatalog::removeDir(const std::string& path) throw (DmException) Replica VfsCatalog::getReplicaByRFN(const std::string& rfn) throw (DmException) { + std::string path; + ExtendedStat meta; Replica replica; - struct stat fstat; - - if (vfsCheckPermissions(rfn, S_IREAD)) - vfsThrow(EACCES, "not enough permissions for '%s'", clientName.c_str()); + Extensible::const_iterator it; - wrapCall(stat(getLocalPath(rfn).c_str(), &fstat)); - - replica.atime = fstat.st_atime; - replica.fileid = fstat.st_ino; - replica.ltime = 0; - replica.nbaccesses = 0; - replica.ptime = 0; - replica.replicaid = 0; - replica.rfn = rfn; - replica.server = this->hostName_; - replica.status = Replica::kAvailable; - replica.type = Replica::kPermanent; + path = vfsPathByRFN(rfn); + meta = vfsExtendedStat(path, true, false, true); + + vfsUpdateInode(meta, path); + + // look for rfn in replicas + for (it = meta.begin(); it != meta.end(); it++) { + std::string key, value, value2, repidstr; + + key = it->first; + if (key.compare(0, VFS_XATTR_LENGTH + 8, VFS_XATTR "replica.") == 0) { + repidstr = key.c_str() + VFS_XATTR_LENGTH + 8; + value = Extensible::anyToString(it->second); + value2 = meta.getString(VFS_XATTR "repattrs." + repidstr, ""); + + replica = replicaDeserialize(value, value2); + replica.replicaid = atoll(repidstr.c_str()); + replica.fileid = meta.stat.st_ino; + if (rfn.compare(replica.rfn) == 0) break; + } + } + + if (it == meta.end()) { + // + // Internal Inconsistency: + // Replica entry found but detailed info is missing in attributes. + // + vfsThrow(DMLITE_NO_SUCH_REPLICA, "replica entry '%s' found in '%s', but detailed info missing", rfn.c_str(), path.c_str()); + } + return replica; } diff --git a/src/VfsNs.h b/src/VfsNs.h index 7338211..1cef2a6 100644 --- a/src/VfsNs.h +++ b/src/VfsNs.h @@ -49,6 +49,7 @@ namespace dmlite { std::string getWorkingDir (void) throw (DmException); ExtendedStat extendedStat(const std::string&, bool = true) throw (DmException); + ExtendedStat extendedStatByRFN(const std::string& rfn) throw (DmException); bool access(const std::string& path, int mode) throw (DmException); bool accessReplica(const std::string& replica, int mode) throw (DmException); @@ -110,6 +111,7 @@ namespace dmlite { void vfsUpdateExtendedStat(ExtendedStat &xStat, Extensible xattrs) throw (DmException); ExtendedStat vfsSimpleStat(const std::string& name, const std::string& path, const std::string& lpath, bool follow, bool perms, bool replicas) throw (DmException); ExtendedStat vfsExtendedStat(const std::string& path, bool follow = true, bool perms = true, bool replicas = false) throw (DmException); + std::string vfsPathByRFN(const std::string& rfn) throw (DmException); PrivateDir* vfsOpenDir(const std::string& lpath, const std::string& path) throw (DmException); Extensible vfsGetXattrs(const std::string& path, const std::string& lpath, bool follow, int amount) throw (DmException); std::string vfsGetXattr(const std::string& path, const std::string &lpath, const std::string key, int flags);