diff --git a/middletier/CMakeLists.txt b/middletier/CMakeLists.txt index bf665aff844110dc55ab21b04efb4177fa40e41a..06e6d8d0ce98d95565e98cb7a88ca521b2e7360e 100644 --- a/middletier/CMakeLists.txt +++ b/middletier/CMakeLists.txt @@ -32,8 +32,10 @@ set (MIDDLE_TIER_LIB_SRC_FILES cta/LogicalLibrary.cpp cta/MiddleTierAdmin.cpp cta/MiddleTierUser.cpp + cta/MockNameServer.cpp cta/Mount.cpp cta/MountCriteria.cpp + cta/NameServer.cpp cta/RemoteStorage.cpp cta/RetrievalFileTransfer.cpp cta/RetrievalJob.cpp @@ -69,7 +71,7 @@ set (MIDDLE_TIER_UNIT_TESTS_LIB_SRC_FILES cta/SqliteMiddleTierAdminTest.cpp cta/SqliteMiddleTierUserTest.cpp cta/UtilsTest.cpp - cta/VfsTest.cpp) + cta/MockNameServerTest.cpp) add_library (ctamiddletierunittests SHARED ${MIDDLE_TIER_UNIT_TESTS_LIB_SRC_FILES}) diff --git a/middletier/cta/MockNameServer.cpp b/middletier/cta/MockNameServer.cpp new file mode 100644 index 0000000000000000000000000000000000000000..885543e88b2e155d314280574fdcf7e55a15f99e --- /dev/null +++ b/middletier/cta/MockNameServer.cpp @@ -0,0 +1,402 @@ +/** + * The CERN Tape Archive (CTA) project + * Copyright (C) 2015 CERN + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * 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/>. + */ + +#include <dirent.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <unistd.h> +#include <iostream> +#include <sstream> +#include <stdlib.h> +#include <string.h> +#include <errno.h> +#include <attr/xattr.h> +#include <fcntl.h> + +#include "cta/Exception.hpp" +#include "cta/Utils.hpp" +#include "cta/MockNameServer.hpp" + +//------------------------------------------------------------------------------ +// assertFsDirExists +//------------------------------------------------------------------------------ +void cta::MockNameServer::assertFsDirExists(const std::string &path) const { + struct stat stat_result; + + if(::stat(path.c_str(), &stat_result)) { + char buf[256]; + std::ostringstream message; + message << "assertFsDirExists() - " << path << " stat error. Reason: " + << strerror_r(errno, buf, sizeof(buf)); + throw(Exception(message.str())); + } + + if(!S_ISDIR(stat_result.st_mode)) { + std::ostringstream message; + message << "assertFsDirExists() - " << path << " is not a directory"; + throw(Exception(message.str())); + } +} + +//------------------------------------------------------------------------------ +// assertFsPathDoesNotExist +//------------------------------------------------------------------------------ +void cta::MockNameServer::assertFsPathDoesNotExist(const std::string &path) + const { + struct stat stat_result; + + if(::stat(path.c_str(), &stat_result) == 0) { + std::ostringstream message; + message << "assertFsPathExist() - " << path << " exists."; + throw(Exception(message.str())); + } +} + +//------------------------------------------------------------------------------ +// dirExists +//------------------------------------------------------------------------------ +bool cta::MockNameServer::dirExists(const SecurityIdentity &requester, + const std::string &path) const { + Utils::checkAbsolutePathSyntax(path); + const std::string fsPath = m_fsDir + path; + struct stat stat_result; + + if(::stat(fsPath.c_str(), &stat_result)) { + return false; + } + + if(!S_ISDIR(stat_result.st_mode)) { + return false; + } + + return true; +} + +//------------------------------------------------------------------------------ +// checkStorageClassIsNotInUse +//------------------------------------------------------------------------------ +void cta::MockNameServer::checkStorageClassIsNotInUse( + const SecurityIdentity &requester, + const std::string &storageClass, + const std::string &path) const { + + if(getDirStorageClass(requester, path) == storageClass) { + std::ostringstream message; + message << "checkStorageClassIsNotInUse() - " << path << " has the " << + storageClass << " storage class."; + throw(Exception(message.str())); + } + + const std::string fsPath = m_fsDir + path; + + struct dirent *entry; + DIR *const dp = opendir(fsPath.c_str()); + if (dp == NULL) { + char buf[256]; + std::ostringstream message; + message << "checkStorageClassIsNotInUse() - opendir " << fsPath << + " error. Reason: \n" << strerror_r(errno, buf, sizeof(buf)); + throw(Exception(message.str())); + } + + const bool pathEndsWithASlash = path.at(path.length()-1) == '/'; + while((entry = readdir(dp))) { + const std::string entryName(entry->d_name); + if(entry->d_type == DT_DIR && entryName != "." && entryName != "..") { + const std::string entryPath = pathEndsWithASlash ? + path + entryName : path + "/" + entryName; + try { + checkStorageClassIsNotInUse(requester, storageClass, entryPath); + } catch (...) { + closedir(dp); + throw; + } + } + } + + closedir(dp); +} + +//------------------------------------------------------------------------------ +// constructor +//------------------------------------------------------------------------------ +cta::MockNameServer::MockNameServer() { + m_baseDir = "/tmp"; + m_fsDir = m_baseDir + "/CTATmpFs"; + + assertFsDirExists(m_baseDir); + assertFsPathDoesNotExist(m_fsDir); + + if(mkdir(m_fsDir.c_str(), 0777)) { + char buf[256]; + std::ostringstream message; + message << "MockNameServer() - mkdir " << m_fsDir << " error. Reason: \n" << strerror_r(errno, buf, sizeof(buf)); + throw(Exception(message.str())); + } + + if(setxattr(m_fsDir.c_str(), "user.CTAStorageClass", "", 0, 0)) { + char buf[256]; + std::ostringstream message; + message << "MockNameServer() - " << m_fsDir << " setxattr error. Reason: " << strerror_r(errno, buf, sizeof(buf)); + throw(Exception(message.str())); + } +} + +//------------------------------------------------------------------------------ +// destructor +//------------------------------------------------------------------------------ +cta::MockNameServer::~MockNameServer() throw() { + system("rm -rf /tmp/CTATmpFs"); +} + +//------------------------------------------------------------------------------ +// setDirStorageClass +//------------------------------------------------------------------------------ +void cta::MockNameServer::setDirStorageClass(const SecurityIdentity &requester, const std::string &path, const std::string &storageClassName) { + Utils::checkAbsolutePathSyntax(path); + const std::string fsPath = m_fsDir + path; + assertFsDirExists(fsPath); + + if(setxattr(fsPath.c_str(), "user.CTAStorageClass", storageClassName.c_str(), storageClassName.length(), 0)) { + char buf[256]; + std::ostringstream message; + message << "setDirStorageClass() - " << fsPath << " setxattr error. Reason: " << strerror_r(errno, buf, sizeof(buf)); + throw(Exception(message.str())); + } +} + +//------------------------------------------------------------------------------ +// clearDirStorageClass +//------------------------------------------------------------------------------ +void cta::MockNameServer::clearDirStorageClass( + const SecurityIdentity &requester, + const std::string &path) { + Utils::checkAbsolutePathSyntax(path); + const std::string fsPath = m_fsDir + path; + assertFsDirExists(fsPath); + + if(setxattr(fsPath.c_str(), "user.CTAStorageClass", "", 0, 0)) { + char buf[256]; + std::ostringstream message; + message << "clearDirStorageClass() - " << fsPath << " setxattr error. Reason: " << strerror_r(errno, buf, sizeof(buf)); + throw(Exception(message.str())); + } +} + +//------------------------------------------------------------------------------ +// getDirStorageClass +//------------------------------------------------------------------------------ +std::string cta::MockNameServer::getDirStorageClass( + const SecurityIdentity &requester, + const std::string &path) const { + Utils::checkAbsolutePathSyntax(path); + const std::string fsPath = m_fsDir + path; + assertFsDirExists(fsPath); + + char value[1024]; + bzero(value, sizeof(value)); + if(0 > getxattr(fsPath.c_str(), "user.CTAStorageClass", value, sizeof(value))) { + char buf[256]; + std::ostringstream message; + message << "getDirStorageClass() - " << fsPath << " getxattr error. Reason: " << strerror_r(errno, buf, sizeof(buf)); + throw(Exception(message.str())); + } + return std::string(value); +} + +//------------------------------------------------------------------------------ +// createFile +//------------------------------------------------------------------------------ +void cta::MockNameServer::createFile( + const SecurityIdentity &requester, + const std::string &path, + const uint16_t mode) { + Utils::checkAbsolutePathSyntax(path); + assertFsDirExists(m_fsDir + Utils::getEnclosingDirPath(path)); + const std::string fsPath = m_fsDir + path; + assertFsPathDoesNotExist(fsPath); + + const int fd = open(fsPath.c_str(), O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK, mode); + if(fd<0) { + char buf[256]; + std::ostringstream message; + message << "createFile() - " << fsPath << " open error. Reason: " << strerror_r(errno, buf, sizeof(buf)); + throw(Exception(message.str())); + } + if(utimensat(AT_FDCWD, fsPath.c_str(), NULL, 0)) { + char buf[256]; + std::ostringstream message; + message << "createFile() - " << fsPath << " utimensat error. Reason: " << strerror_r(errno, buf, sizeof(buf)); + throw(Exception(message.str())); + } +} + +//------------------------------------------------------------------------------ +// createDir +//------------------------------------------------------------------------------ +void cta::MockNameServer::createDir(const SecurityIdentity &requester, + const std::string &path, const uint16_t mode) { + Utils::checkAbsolutePathSyntax(path); + const std::string enclosingDirPath = Utils::getEnclosingDirPath(path); + assertFsDirExists(m_fsDir + enclosingDirPath); + + const std::string inheritedStorageClass = getDirStorageClass(requester, + enclosingDirPath); + const std::string fsPath = m_fsDir + path; + + if(mkdir(fsPath.c_str(), mode)) { + char buf[256]; + std::ostringstream message; + message << "createDir() - mkdir " << fsPath << " error. Reason: \n" << strerror_r(errno, buf, sizeof(buf)); + throw(Exception(message.str())); + } + + setDirStorageClass(requester, path, inheritedStorageClass); +} + +//------------------------------------------------------------------------------ +// deleteFile +//------------------------------------------------------------------------------ +void cta::MockNameServer::deleteFile(const SecurityIdentity &requester, const std::string &path) { + Utils::checkAbsolutePathSyntax(path); + const std::string fsPath = m_fsDir + path; + + if(unlink(fsPath.c_str())) { + char buf[256]; + std::ostringstream message; + message << "deleteFile() - unlink " << fsPath << " error. Reason: \n" << + strerror_r(errno, buf, sizeof(buf)); + throw(Exception(message.str())); + } +} + +//------------------------------------------------------------------------------ +// deleteDir +//------------------------------------------------------------------------------ +void cta::MockNameServer::deleteDir(const SecurityIdentity &requester, const std::string &path) { + if(path == "/") { + std::ostringstream message; + message << "deleteDir() - Cannot delete root directory"; + throw(Exception(message.str())); + } + Utils::checkAbsolutePathSyntax(path); + const std::string fsPath = m_fsDir + path; + + if(rmdir(fsPath.c_str())) { + char buf[256]; + std::ostringstream message; + message << "deleteDir() - rmdir " << fsPath << " error. Reason: \n" << + strerror_r(errno, buf, sizeof(buf)); + throw(Exception(message.str())); + } +} + +//------------------------------------------------------------------------------ +// statDirEntry +//------------------------------------------------------------------------------ +cta::DirEntry cta::MockNameServer::statDirEntry( + const SecurityIdentity &requester, + const std::string &path) const { + Utils::checkAbsolutePathSyntax(path); + const std::string name = Utils::getEnclosedName(path); + const std::string enclosingPath = Utils::getEnclosingDirPath(path); + const std::string fsPath = m_fsDir + path; + + struct stat stat_result; + if(::stat(fsPath.c_str(), &stat_result)) { + char buf[256]; + std::ostringstream message; + message << "statDirEntry() - " << fsPath << " stat error. Reason: " << + strerror_r(errno, buf, sizeof(buf)); + throw(Exception(message.str())); + } + + DirEntry::EntryType entryType; + std::string storageClassName; + + if(S_ISDIR(stat_result.st_mode)) { + entryType = DirEntry::ENTRYTYPE_DIRECTORY; + storageClassName = getDirStorageClass(requester, path); + } + else if(S_ISREG(stat_result.st_mode)) { + entryType = DirEntry::ENTRYTYPE_FILE; + storageClassName = getDirStorageClass(requester, enclosingPath); + } + else { + std::ostringstream message; + message << "statDirEntry() - " << m_fsDir+path << + " is not a directory nor a regular file"; + throw(Exception(message.str())); + } + + return DirEntry(entryType, name, storageClassName); +} + +//------------------------------------------------------------------------------ +// getDirEntries +//------------------------------------------------------------------------------ +std::list<cta::DirEntry> cta::MockNameServer::getDirEntries( + const SecurityIdentity &requester, + const std::string &path) const { + const std::string fsPath = m_fsDir + path; + DIR *const dp = opendir(fsPath.c_str()); + + if(dp == NULL) { + char buf[256]; + std::ostringstream message; + message << "getDirEntries() - opendir " << fsPath << " error. Reason: \n" << + strerror_r(errno, buf, sizeof(buf)); + throw(Exception(message.str())); + } + + std::list<DirEntry> entries; + struct dirent *entry; + + const bool pathEndsWithASlash = path.at(path.length()-1) == '/'; + while((entry = readdir(dp))) { + const std::string entryName(entry->d_name); + if(entryName != "." && entryName != "..") { + const std::string entryPath = pathEndsWithASlash ? + path + entryName : path + "/" + entryName; + entries.push_back(statDirEntry(requester, entryPath)); + } + } + + closedir(dp); + return entries; +} + +//------------------------------------------------------------------------------ +// getDirContents +//------------------------------------------------------------------------------ +cta::DirIterator cta::MockNameServer::getDirContents( + const SecurityIdentity &requester, const std::string &path) const { + Utils::checkAbsolutePathSyntax(path); + assertFsDirExists(m_fsDir+path); + return getDirEntries(requester, path); +} + +//------------------------------------------------------------------------------ +// getVidOfFile +//------------------------------------------------------------------------------ +std::string cta::MockNameServer::getVidOfFile( + const SecurityIdentity &requester, + const std::string &path, + uint16_t copyNb) const { + return "T00001"; //everything is on one tape for the moment:) +} diff --git a/middletier/cta/MockNameServer.hpp b/middletier/cta/MockNameServer.hpp new file mode 100644 index 0000000000000000000000000000000000000000..924dddbb8bfd393995607841024ec6a705f430e1 --- /dev/null +++ b/middletier/cta/MockNameServer.hpp @@ -0,0 +1,86 @@ +/** + * The CERN Tape Archive (CTA) project + * Copyright (C) 2015 CERN + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * 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/>. + */ + +#pragma once + +#include "cta/DirIterator.hpp" +#include "cta/NameServer.hpp" +#include "cta/SecurityIdentity.hpp" + +#include <list> +#include <string> + +namespace cta { + +/** + * Local file system implementation of a name server to contain the archive + * namespace. + */ +class MockNameServer: public NameServer { + +public: + + /** + * Constructor. + */ + MockNameServer(); + + /** + * Destructor. + */ + ~MockNameServer() throw(); + + void setDirStorageClass(const SecurityIdentity &requester, const std::string &path, const std::string &storageClassName); + + void clearDirStorageClass(const SecurityIdentity &requester, const std::string &path); + + std::string getDirStorageClass(const SecurityIdentity &requester, const std::string &path) const; + + void createFile(const SecurityIdentity &requester, const std::string &path, const uint16_t mode); + + void createDir(const SecurityIdentity &requester, const std::string &path, const uint16_t mode); + + void deleteFile(const SecurityIdentity &requester, const std::string &path); + + void deleteDir(const SecurityIdentity &requester, const std::string &path); + + cta::DirEntry statDirEntry(const SecurityIdentity &requester, const std::string &path) const; + + cta::DirIterator getDirContents(const SecurityIdentity &requester, const std::string &path) const; + + bool dirExists(const SecurityIdentity &requester, const std::string &path) const; + + std::string getVidOfFile(const SecurityIdentity &requester, const std::string &path, uint16_t copyNb) const; + + void checkStorageClassIsNotInUse(const SecurityIdentity &requester, const std::string &storageClass, const std::string &path) const; + +private: + + std::string m_baseDir; + + std::string m_fsDir; + + void assertFsDirExists(const std::string &path) const; + + void assertFsPathDoesNotExist(const std::string &path) const; + + std::list<cta::DirEntry> getDirEntries(const SecurityIdentity &requester, const std::string &path) const; + +}; // class MockNameServer + +} // namespace cta diff --git a/middletier/cta/MockNameServerTest.cpp b/middletier/cta/MockNameServerTest.cpp new file mode 100644 index 0000000000000000000000000000000000000000..1a71a52515ebad582ba526e9fcbf2c249c8ed635 --- /dev/null +++ b/middletier/cta/MockNameServerTest.cpp @@ -0,0 +1,177 @@ +/** + * The CERN Tape Archive (CTA) project + * Copyright (C) 2015 CERN + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * 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/>. + */ + +#include "cta/MockNameServer.hpp" + +#include <gtest/gtest.h> +#include <memory> + +namespace unitTests { + +class cta_MockNameServerTest: public ::testing::Test { +protected: + + virtual void SetUp() { + } + + virtual void TearDown() { + } +}; + +TEST_F(cta_MockNameServerTest, constructor_consistency) { + using namespace cta; + + std::auto_ptr<MockNameServer> ns; + ASSERT_NO_THROW(ns.reset(new MockNameServer())); + + cta::SecurityIdentity requester; + DirIterator itor; + + ASSERT_NO_THROW(itor = ns->getDirContents(requester, "/")); + ASSERT_FALSE(itor.hasMore()); + ASSERT_EQ(std::string(""), ns->getDirStorageClass(requester, "/")); +} + +TEST_F(cta_MockNameServerTest, mkdir_functionality) { + using namespace cta; + + std::auto_ptr<MockNameServer> ns; + ASSERT_NO_THROW(ns.reset(new MockNameServer())); + + cta::SecurityIdentity requester; + DirIterator itor; + + ASSERT_NO_THROW(ns->createDir(requester, "/dir1", 0777)); + ASSERT_THROW(ns->createDir(requester, "/dir1", 0777), std::exception); + ASSERT_NO_THROW(itor = ns->getDirContents(requester, "/")); + ASSERT_EQ(itor.hasMore(), true); + ASSERT_EQ(itor.next().getName(), "dir1"); + ASSERT_EQ(itor.hasMore(), false); +} + +TEST_F(cta_MockNameServerTest, createFile_functionality) { + using namespace cta; + + std::auto_ptr<MockNameServer> ns; + ASSERT_NO_THROW(ns.reset(new MockNameServer())); + + cta::SecurityIdentity requester; + DirIterator itor; + + ASSERT_NO_THROW(ns->createFile(requester, "/file1", 0666)); + ASSERT_THROW(ns->createFile(requester, "/file1", 0666), std::exception); + ASSERT_NO_THROW(itor = ns->getDirContents(requester, "/")); + ASSERT_EQ(itor.hasMore(), true); + ASSERT_EQ(itor.next().getName(), "file1"); + ASSERT_EQ(itor.hasMore(), false); +} + +TEST_F(cta_MockNameServerTest, rmdir_functionality) { + using namespace cta; + + std::auto_ptr<MockNameServer> ns; + ASSERT_NO_THROW(ns.reset(new MockNameServer())); + + cta::SecurityIdentity requester; + DirIterator itor; + + ASSERT_NO_THROW(ns->createDir(requester, "/dir1", 0777)); + ASSERT_NO_THROW(ns->deleteDir(requester, "/dir1")); + ASSERT_THROW(ns->deleteDir(requester, "/dir1"), std::exception); + ASSERT_NO_THROW(ns->createDir(requester, "/dir2", 0777)); + ASSERT_NO_THROW(ns->createFile(requester, "/dir2/file1", 0666)); + ASSERT_THROW(ns->deleteDir(requester, "/dir2"), std::exception); + ASSERT_NO_THROW(ns->deleteFile(requester, "/dir2/file1")); + ASSERT_NO_THROW(ns->deleteDir(requester, "/dir2")); + ASSERT_NO_THROW(itor = ns->getDirContents(requester, "/")); + ASSERT_FALSE(itor.hasMore()); + ASSERT_EQ(std::string(""), ns->getDirStorageClass(requester, "/")); +} + +TEST_F(cta_MockNameServerTest, storageClass_functionality) { + using namespace cta; + + std::auto_ptr<MockNameServer> ns; + ASSERT_NO_THROW(ns.reset(new MockNameServer())); + + cta::SecurityIdentity requester; + DirIterator itor; + + ASSERT_NO_THROW(ns->createDir(requester, "/dir1", 0777)); + ASSERT_EQ(std::string(""), ns->getDirStorageClass(requester, "/dir1")); + ASSERT_NO_THROW(ns->setDirStorageClass(requester, "/dir1", "cms")); + { + std::string storageClass; + ASSERT_NO_THROW(storageClass = ns->getDirStorageClass(requester, "/dir1")); + ASSERT_EQ(std::string("cms"), storageClass); + } + ASSERT_NO_THROW(ns->clearDirStorageClass(requester, "/dir1")); + { + std::string storageClass; + ASSERT_NO_THROW(storageClass = ns->getDirStorageClass(requester, "/dir1")); + ASSERT_EQ(std::string(""), storageClass); + } + ASSERT_NO_THROW(ns->setDirStorageClass(requester, "/dir1", "atlas")); + { + std::string storageClass; + ASSERT_NO_THROW(storageClass = ns->getDirStorageClass(requester, "/dir1")); + ASSERT_EQ(std::string("atlas"), storageClass); + } +} + +TEST_F(cta_MockNameServerTest, storageClass_inheritance) { + using namespace cta; + + std::auto_ptr<MockNameServer> ns; + ASSERT_NO_THROW(ns.reset(new MockNameServer())); + + cta::SecurityIdentity requester; + DirIterator itor; + + ASSERT_NO_THROW(ns->createDir(requester, "/dir1", 0777)); + { + std::string storageClass; + ASSERT_NO_THROW(storageClass = ns->getDirStorageClass(requester, "/dir1")); + ASSERT_EQ(std::string(""), storageClass); + } + ASSERT_NO_THROW(ns->createDir(requester, "/dir1/dir1_1", 0777)); + { + std::string storageClass; + ASSERT_NO_THROW(storageClass = ns->getDirStorageClass(requester, "/dir1/dir1_1")); + ASSERT_EQ(std::string(""), storageClass); + } + ASSERT_NO_THROW(ns->setDirStorageClass(requester, "/dir1", "cms")); + { + std::string storageClass; + ASSERT_NO_THROW(storageClass = ns->getDirStorageClass(requester, "/dir1")); + ASSERT_EQ(std::string("cms"), storageClass); + } + ASSERT_NO_THROW(ns->createDir(requester, "/dir1/dir1_2", 0777)); + { + std::string storageClass; + ASSERT_NO_THROW(storageClass = ns->getDirStorageClass(requester, "/dir1/dir1_2")); + ASSERT_EQ(std::string("cms"), storageClass); + } + { + std::string storageClass; + ASSERT_NO_THROW(storageClass = ns->getDirStorageClass(requester, "/dir1/dir1_1")); + ASSERT_EQ(std::string(""), storageClass); + } +} + +} diff --git a/middletier/cta/NameServer.cpp b/middletier/cta/NameServer.cpp new file mode 100644 index 0000000000000000000000000000000000000000..947bbac42a0bbf99fcf70ab3873dfbe8d6f3d68f --- /dev/null +++ b/middletier/cta/NameServer.cpp @@ -0,0 +1,25 @@ +/** + * The CERN Tape Archive (CTA) project + * Copyright (C) 2015 CERN + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * 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/>. + */ + +#include "cta/NameServer.hpp" + +//------------------------------------------------------------------------------ +// destructor +//------------------------------------------------------------------------------ +cta::NameServer::~NameServer() throw() { +} diff --git a/middletier/cta/NameServer.hpp b/middletier/cta/NameServer.hpp new file mode 100644 index 0000000000000000000000000000000000000000..986ca3ce57dfaa73208c78c891bb05559218a6e0 --- /dev/null +++ b/middletier/cta/NameServer.hpp @@ -0,0 +1,156 @@ +/** + * The CERN Tape Archive (CTA) project + * Copyright (C) 2015 CERN + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * 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/>. + */ + +#pragma once + +#include "cta/DirIterator.hpp" +#include "cta/SecurityIdentity.hpp" + +#include <string> + +namespace cta { + +/** + * Abstract class specifying the interface to the name server containing the + * archive namespace. + */ +class NameServer { +public: + + /** + * Destructor. + */ + virtual ~NameServer() throw() = 0; + + /** + * Creates the specified directory. + * + * @param requester The identity of the requester. + * @param path The absolute path of the directory. + * @param mode The mode bits of the directory entry. + */ + virtual void createDir( + const SecurityIdentity &requester, + const std::string &path, + const uint16_t mode) = 0; + + /** + * Deletes the specified directory. + * + * @param requester The identity of the requester. + * @param path The absolute path of the directory. + */ + virtual void deleteDir( + const SecurityIdentity &requester, + const std::string &path) = 0; + + /** + * Gets the contents of the specified directory. + * + * @param requester The identity of the requester. + * @param path The absolute path of the directory. + * @return An iterator over the contents of the directory. + */ + virtual DirIterator getDirContents( + const SecurityIdentity &requester, + const std::string &path) const = 0; + + /** + * Returns the directory entry information for the specified directory or file + * within the archive namespace. + * + * @param requester The identity of the requester. + * @param path The absolute path of the directory or file within the archive + * namespace. + * @return The directory entry information for the specified directory or file + * within the archive namespace. + */ + virtual DirEntry statDirEntry( + const SecurityIdentity &requester, + const std::string &path) const = 0; + + /** + * Sets the storage class of the specified directory to the specified value. + * + * @param requester The identity of the requester. + * @param path The absolute path of the directory. + * @param storageClassName The name of the storage class. + */ + virtual void setDirStorageClass( + const SecurityIdentity &requester, + const std::string &path, + const std::string &storageClassName) = 0; + + /** + * Clears the storage class of the specified directory. + * + * @param requester The identity of the requester. + * @param path The absolute path of the directory. + */ + virtual void clearDirStorageClass( + const SecurityIdentity &requester, + const std::string &path) = 0; + + /** + * Returns the name of the storage class of the specified directory. + * + * @param requester The identity of the requester. + * @param path The absolute path of the directory. + * @return The name of the storage class of the specified directory. + */ + virtual std::string getDirStorageClass( + const SecurityIdentity &requester, + const std::string &path) const = 0; + + /** + * Creates the specified file entry. + * + * @param requester The identity of the requester. + * @param path The absolute path of the directory. + * @param mode The mode bits of the file entry. + */ + virtual void createFile( + const SecurityIdentity &requester, + const std::string &path, + const uint16_t mode) = 0; + + /** + * Deletes the specified file entry. + * + * @param requester The identity of the requester. + * @param path The absolute path of the file. + */ + virtual void deleteFile( + const SecurityIdentity &requester, + const std::string &path) = 0; + + /** + * Returns true if the specified directory exists. + * + * @param requester The identity of the requester. + * @param path The absolute path of the file. + + * @return True if the specified directory exists. + */ + virtual bool dirExists( + const SecurityIdentity &requester, + const std::string &path) const = 0; + +}; // class NameServer + +} // namespace