diff --git a/libs/client/CMakeLists.txt b/libs/client/CMakeLists.txt index 701f42bcdbd63cca61d47e2345ee36cdc1150bf3..9d5cfe4d1860142228b4bc2a98b444520668792a 100644 --- a/libs/client/CMakeLists.txt +++ b/libs/client/CMakeLists.txt @@ -7,10 +7,11 @@ set (CLIENT_LIB_SRC_FILES Exception.cpp FileAttribute.cpp FileSystemNode.cpp + FileSystemStorageClass.cpp + FileSystemStorageClasses.cpp MockClientAPI.cpp SecurityIdentity.cpp StorageClass.cpp - StorageClassAndUsageCount.cpp UserIdentity.cpp) add_library (ctaclient SHARED diff --git a/libs/client/ClientAPI.hpp b/libs/client/ClientAPI.hpp index ba67ac3153328860ce12cc36e15f4457a5a1d150..81b3c8d7f01a7fbab432515dd83163d012deca30 100644 --- a/libs/client/ClientAPI.hpp +++ b/libs/client/ClientAPI.hpp @@ -91,11 +91,13 @@ public: * @param name The name of the storage class. * @param nbCopies The number of copies a file associated with this storage * class should have on tape. + * @param comment The comment describing the storage class. */ virtual void createStorageClass( const SecurityIdentity &requester, const std::string &name, - const uint8_t nbCopies) = 0; + const uint8_t nbCopies, + const std::string &comment) = 0; /** * Deletes the specified storage class. diff --git a/libs/client/StorageClassAndUsageCount.cpp b/libs/client/FileSystemStorageClass.cpp similarity index 73% rename from libs/client/StorageClassAndUsageCount.cpp rename to libs/client/FileSystemStorageClass.cpp index d26df6319bf3ee520e05b3b1cf709d461398b152..3269d6d7e639edc66fa1c92e1e71d1a10dbb924d 100644 --- a/libs/client/StorageClassAndUsageCount.cpp +++ b/libs/client/FileSystemStorageClass.cpp @@ -1,18 +1,18 @@ #define __STDC_LIMIT_MACROS -#include "StorageClassAndUsageCount.hpp" +#include "FileSystemStorageClass.hpp" //------------------------------------------------------------------------------ // constructor //------------------------------------------------------------------------------ -cta::StorageClassAndUsageCount::StorageClassAndUsageCount(): +cta::FileSystemStorageClass::FileSystemStorageClass(): m_usageCount(0) { } //------------------------------------------------------------------------------ // constructor //------------------------------------------------------------------------------ -cta::StorageClassAndUsageCount::StorageClassAndUsageCount( +cta::FileSystemStorageClass::FileSystemStorageClass( const StorageClass &storageClass): m_storageClass(storageClass), m_usageCount(0) { @@ -21,7 +21,7 @@ cta::StorageClassAndUsageCount::StorageClassAndUsageCount( //------------------------------------------------------------------------------ // getStorageClass //------------------------------------------------------------------------------ -const cta::StorageClass &cta::StorageClassAndUsageCount::getStorageClass() +const cta::StorageClass &cta::FileSystemStorageClass::getStorageClass() const throw() { return m_storageClass; } @@ -29,19 +29,19 @@ const cta::StorageClass &cta::StorageClassAndUsageCount::getStorageClass() //------------------------------------------------------------------------------ // getUsageCount //------------------------------------------------------------------------------ -uint64_t cta::StorageClassAndUsageCount::getUsageCount() const throw() { +uint64_t cta::FileSystemStorageClass::getUsageCount() const throw() { return m_usageCount; } //------------------------------------------------------------------------------ // incUsageCount //------------------------------------------------------------------------------ -void cta::StorageClassAndUsageCount::incUsageCount() { +void cta::FileSystemStorageClass::incUsageCount() { if(UINT64_MAX == m_usageCount) { std::ostringstream message; message << "Cannot increment usage count of storage class " << - m_storageClass.name << " because its maximum value of UINT64_MAX has " - "already been reached"; + m_storageClass.getName() << " because its maximum value of UINT64_MAX" + " has already been reached"; throw Exception(message.str()); } m_usageCount++; @@ -50,11 +50,11 @@ void cta::StorageClassAndUsageCount::incUsageCount() { //------------------------------------------------------------------------------ // decUsageCount //------------------------------------------------------------------------------ -void cta::StorageClassAndUsageCount::decUsageCount() { +void cta::FileSystemStorageClass::decUsageCount() { if(0 == m_usageCount) { std::ostringstream message; message << "Cannot decrement usage count of storage class " << - m_storageClass.name << " because it is already at zero"; + m_storageClass.getName() << " because it is already at zero"; throw Exception(message.str()); } m_usageCount--; diff --git a/libs/client/StorageClassAndUsageCount.hpp b/libs/client/FileSystemStorageClass.hpp similarity index 70% rename from libs/client/StorageClassAndUsageCount.hpp rename to libs/client/FileSystemStorageClass.hpp index 91b3ea05d3e0c9939e686db66210cd81eb4bb9c3..a61b2abb5b99f54efd07734b689ca1d998b53bec 100644 --- a/libs/client/StorageClassAndUsageCount.hpp +++ b/libs/client/FileSystemStorageClass.hpp @@ -2,15 +2,19 @@ #include "Exception.hpp" #include "StorageClass.hpp" +#include "UserIdentity.hpp" #include <sstream> +#include <string> +#include <time.h> namespace cta { /** - * Class used to store a storage class and it usage count. + * Class used to store a storage class together with the other information + * required by the file system. */ -class StorageClassAndUsageCount { +class FileSystemStorageClass { public: /** @@ -18,14 +22,14 @@ public: * * Initialisez the usage count to 0. */ - StorageClassAndUsageCount(); + FileSystemStorageClass(); /** * Constructor. * * Initialisez the usage count to 0. */ - StorageClassAndUsageCount(const StorageClass &storageClass); + FileSystemStorageClass(const StorageClass &storageClass); /** * Returns the storage class. @@ -59,6 +63,6 @@ private: */ uint64_t m_usageCount; -}; // class StorageClassAndUsageCount +}; // class FileSystemStorageClass } // namespace cta diff --git a/libs/client/FileSystemStorageClasses.cpp b/libs/client/FileSystemStorageClasses.cpp new file mode 100644 index 0000000000000000000000000000000000000000..7556d0216c70411a389afb7fd64a3169dc54b6e0 --- /dev/null +++ b/libs/client/FileSystemStorageClasses.cpp @@ -0,0 +1,144 @@ +#include "Exception.hpp" +#include "FileSystemStorageClasses.hpp" + +#include <sstream> + +//------------------------------------------------------------------------------ +// createStorageClass +//------------------------------------------------------------------------------ +void cta::FileSystemStorageClasses::createStorageClass( + const std::string &name, + const uint8_t nbCopies, + const UserIdentity &creator, + const std::string &comment) { + try { + checkStorageClassDoesNotAlreadyExist(name); + StorageClass storageClass(name, nbCopies, creator, comment); + m_storageClasses[name] = storageClass; + } catch(std::exception &ex) { + throw Exception(std::string("Failed to create storage class: ") + + ex.what()); + } +} + +//------------------------------------------------------------------------------ +// checkStorageClassDoesNotAlreadyExist +//------------------------------------------------------------------------------ +void cta::FileSystemStorageClasses::checkStorageClassDoesNotAlreadyExist( + const std::string &name) const { + std::map<std::string, FileSystemStorageClass>::const_iterator itor = + m_storageClasses.find(name); + if(itor != m_storageClasses.end()) { + std::ostringstream msg; + msg << "Storage class " << name << " already exists"; + throw Exception(msg.str()); + } +} + +//------------------------------------------------------------------------------ +// deleteStorageClass +//------------------------------------------------------------------------------ +void cta::FileSystemStorageClasses::deleteStorageClass( + const std::string &name) { + try { + checkStorageClassExists(name); + checkStorageClassIsNotInUse(name); + m_storageClasses.erase(name); + } catch(std::exception &ex) { + throw Exception(std::string("Failed to delete storage class: ") + + ex.what()); + } +} + +//------------------------------------------------------------------------------ +// checkStorageClassExists +//------------------------------------------------------------------------------ +void cta::FileSystemStorageClasses::checkStorageClassExists( + const std::string &name) const { + std::map<std::string, FileSystemStorageClass>::const_iterator itor = + m_storageClasses.find(name); + if(itor == m_storageClasses.end()) { + std::ostringstream msg; + msg << "Storage class " << name << " does not exist"; + throw Exception(msg.str()); + } +} + +//------------------------------------------------------------------------------ +// checkStorageClassIsNotInUse +//------------------------------------------------------------------------------ +void cta::FileSystemStorageClasses::checkStorageClassIsNotInUse( + const std::string &name) const { + std::map<std::string, FileSystemStorageClass>::const_iterator itor = + m_storageClasses.find(name); + + // If the storage class does not exists then it cannot be in use + if(itor == m_storageClasses.end()) { + return; + } + + if(itor->second.getUsageCount() > 0) { + std::ostringstream message; + message << "Storage class " << name << " is in use"; + throw Exception(message.str()); + } +} + +//------------------------------------------------------------------------------ +// getStorageClasses +//------------------------------------------------------------------------------ +std::list<cta::StorageClass> cta::FileSystemStorageClasses::getStorageClasses() + const { + std::list<StorageClass> storageClasses; + for(std::map<std::string, FileSystemStorageClass>::const_iterator itor = + m_storageClasses.begin(); itor != m_storageClasses.end(); itor++) { + storageClasses.push_back(itor->second.getStorageClass()); + } + return storageClasses; +} + +//------------------------------------------------------------------------------ +// incStorageClassUsageCount +//------------------------------------------------------------------------------ +void cta::FileSystemStorageClasses::incStorageClassUsageCount( + const std::string &name) { + // If no storage class has been specified then there is no usage count to + // increment + if(name.empty()) { + return; + } + + std::map<std::string, FileSystemStorageClass>::iterator itor = + m_storageClasses.find(name); + + if(itor == m_storageClasses.end()) { + std::ostringstream message; + message << "Storage class " << name << " does not exist"; + throw Exception(message.str()); + } + + itor->second.incUsageCount(); +} + +//------------------------------------------------------------------------------ +// decStorageClassUsageCount +//------------------------------------------------------------------------------ +void cta::FileSystemStorageClasses::decStorageClassUsageCount( + const std::string &name) { + // If no storage class has been specified then there is no usage count to + // decrement + if(name.empty()) { + return; + } + + std::map<std::string, FileSystemStorageClass>::iterator itor = + m_storageClasses.find(name); + + if(itor == m_storageClasses.end()) { + std::ostringstream message; + message << "Storage class " << name << " does not exist"; + throw Exception(message.str()); + } + + itor->second.decUsageCount(); +} diff --git a/libs/client/FileSystemStorageClasses.hpp b/libs/client/FileSystemStorageClasses.hpp new file mode 100644 index 0000000000000000000000000000000000000000..60c7c431717652b4376eb8f2dd5a8cdab047fd65 --- /dev/null +++ b/libs/client/FileSystemStorageClasses.hpp @@ -0,0 +1,97 @@ +#pragma once + +#include "FileSystemStorageClass.hpp" +#include "SecurityIdentity.hpp" + +#include <list> +#include <map> +#include <string> + +namespace cta { + +/** + * Container ofthe storage classes current used in the file system. + */ +class FileSystemStorageClasses { +public: + + /** + * Creates the specified storage class. + * + * @param name The name of the storage class. + * @param nbCopies The number of copies a file associated with this storage + * class should have on tape. + * @param creator The identity of the user that created the storage class. + * @param comment The comment describing the storage class. + */ + void createStorageClass( + const std::string &name, + const uint8_t nbCopies, + const UserIdentity &creator, + const std::string &comment); + + /** + * Deletes the specified storage class. + * + * @param requester The identity of the user requesting the deletion of the + * storage class. + * @param name The name of the storage class. + */ + void deleteStorageClass(const std::string &name); + + /** + * Gets the current list of storage classes in lexicographical order. + * + * @param requester The identity of the user requesting the list. + * @return The current list of storage classes in lexicographical order. + */ + std::list<StorageClass> getStorageClasses() const; + + /** + * Throws an exception if the specified storage class does not exist. + * + * @param name The name of the storage class. + */ + void checkStorageClassExists(const std::string &name) const; + + /** + * Increments the usage count of the specified storage class. + * + * @param name The name of the storage class. If this parameter is set to the + * empty string then this method does nothing. + */ + void incStorageClassUsageCount(const std::string &name); + + /** + * Decrements the usage count of the specified storage class. + * + * @param name The name of the storage class. If this parameter is set to the + * empty string then this method does nothing. + */ + void decStorageClassUsageCount(const std::string &name); + + /** + * Throws an exception if the specified storage class is use. + * + * @param name The name of the storage class. + */ + void checkStorageClassIsNotInUse(const std::string &name) const; + +protected: + + /** + * The current mapping from storage class names to storage classes and their + * usage counts. + */ + std::map<std::string, FileSystemStorageClass> m_storageClasses; + + /** + * Throws an exception if the specified storage class already exists. + * + * @param name The name of teh storage class. + */ + void checkStorageClassDoesNotAlreadyExist(const std::string &name) const; + +}; // class FileSystemStorageClasses + +} // namespace cta diff --git a/libs/client/MockClientAPI.cpp b/libs/client/MockClientAPI.cpp index cb61b59487f665913e36258444ec229dd4b7e666..eef6da83d85dd60b8900735bd6a36014dd201b96 100644 --- a/libs/client/MockClientAPI.cpp +++ b/libs/client/MockClientAPI.cpp @@ -131,29 +131,8 @@ std::list<std::string> cta::MockClientAPI::getAdminHosts( // createStorageClass //------------------------------------------------------------------------------ void cta::MockClientAPI::createStorageClass(const SecurityIdentity &requester, - const std::string &name, const uint8_t nbCopies) { - try { - checkStorageClassDoesNotAlreadyExist(name); - StorageClass storageClass(name, nbCopies); - m_storageClasses[name] = storageClass; - } catch(std::exception &ex) { - throw Exception(std::string("Failed to create storage class: ") + - ex.what()); - } -} - -//------------------------------------------------------------------------------ -// checkStorageClassDoesNotAlreadyExist -//------------------------------------------------------------------------------ -void cta::MockClientAPI::checkStorageClassDoesNotAlreadyExist( - const std::string &name) const { - std::map<std::string, StorageClassAndUsageCount>::const_iterator itor = - m_storageClasses.find(name); - if(itor != m_storageClasses.end()) { - std::ostringstream msg; - msg << "Storage class " << name << " already exists"; - throw Exception(msg.str()); - } + const std::string &name, const uint8_t nbCopies, const std::string &comment) { + m_storageClasses.createStorageClass(name, nbCopies, requester.user, comment); } //------------------------------------------------------------------------------ @@ -161,48 +140,7 @@ void cta::MockClientAPI::checkStorageClassDoesNotAlreadyExist( //------------------------------------------------------------------------------ void cta::MockClientAPI::deleteStorageClass(const SecurityIdentity &requester, const std::string &name) { - try { - checkStorageClassExists(name); - checkStorageClassIsNotInUse(name); - m_storageClasses.erase(name); - } catch(std::exception &ex) { - throw Exception(std::string("Failed to delete storage class: ") + - ex.what()); - } -} - -//------------------------------------------------------------------------------ -// checkStorageClassExists -//------------------------------------------------------------------------------ -void cta::MockClientAPI::checkStorageClassExists( - const std::string &name) const { - std::map<std::string, StorageClassAndUsageCount>::const_iterator itor = - m_storageClasses.find(name); - if(itor == m_storageClasses.end()) { - std::ostringstream msg; - msg << "Storage class " << name << " does not exist"; - throw Exception(msg.str()); - } -} - -//------------------------------------------------------------------------------ -// checkStorageClassIsNotInUse -//------------------------------------------------------------------------------ -void cta::MockClientAPI::checkStorageClassIsNotInUse( - const std::string &name) const { - std::map<std::string, StorageClassAndUsageCount>::const_iterator itor = - m_storageClasses.find(name); - - // If the storage class does not exists then it cannot be in use - if(itor == m_storageClasses.end()) { - return; - } - - if(itor->second.getUsageCount() > 0) { - std::ostringstream message; - message << "Storage class " << name << " is in use"; - throw Exception(message.str()); - } + m_storageClasses.deleteStorageClass(name); } //------------------------------------------------------------------------------ @@ -210,12 +148,7 @@ void cta::MockClientAPI::checkStorageClassIsNotInUse( //------------------------------------------------------------------------------ std::list<cta::StorageClass> cta::MockClientAPI::getStorageClasses( const SecurityIdentity &requester) const { - std::list<StorageClass> storageClasses; - for(std::map<std::string, StorageClassAndUsageCount>::const_iterator itor = - m_storageClasses.begin(); itor != m_storageClasses.end(); itor++) { - storageClasses.push_back(itor->second.getStorageClass()); - } - return storageClasses; + return m_storageClasses.getStorageClasses(); } //------------------------------------------------------------------------------ @@ -407,28 +340,6 @@ const cta::FileSystemNode &cta::MockClientAPI::getFileSystemNode( return *node; } -//------------------------------------------------------------------------------ -// incStorageClassUsageCount -//------------------------------------------------------------------------------ -void cta::MockClientAPI::incStorageClassUsageCount(const std::string &name) { - // If no storage class has been specified then there is no usage count to - // increment - if(name.empty()) { - return; - } - - std::map<std::string, StorageClassAndUsageCount>::iterator itor = - m_storageClasses.find(name); - - if(itor == m_storageClasses.end()) { - std::ostringstream message; - message << "Storage class " << name << " does not exist"; - throw Exception(message.str()); - } - - itor->second.incUsageCount(); -} - //------------------------------------------------------------------------------ // deleteDirectory //------------------------------------------------------------------------------ @@ -537,7 +448,7 @@ void cta::MockClientAPI::setDirectoryStorageClass( const SecurityIdentity &requester, const std::string &dirPath, const std::string &storageClassName) { - checkStorageClassExists(storageClassName); + m_storageClasses.checkStorageClassExists(storageClassName); FileSystemNode &dirNode = getFileSystemNode(dirPath); if(DirectoryEntry::ENTRYTYPE_DIRECTORY != dirNode.getEntry().entryType) { diff --git a/libs/client/MockClientAPI.hpp b/libs/client/MockClientAPI.hpp index 4925cf3a94cf5ba8ae49586c9010f6a0c41e8241..0a022963f3cbe41dfdded22ca14e6a2d5cd3f1c2 100644 --- a/libs/client/MockClientAPI.hpp +++ b/libs/client/MockClientAPI.hpp @@ -2,10 +2,9 @@ #include "ClientAPI.hpp" #include "FileSystemNode.hpp" +#include "FileSystemStorageClasses.hpp" #include "StorageClass.hpp" -#include "StorageClassAndUsageCount.hpp" -#include <map> #include <vector> namespace cta { @@ -95,11 +94,13 @@ public: * @param name The name of the storage class. * @param nbCopies The number of copies a file associated with this storage * class should have on tape. + * @param comment The comment describing the storage class. */ void createStorageClass( const SecurityIdentity &requester, const std::string &name, - const uint8_t nbCopies); + const uint8_t nbCopies, + const std::string &comment); /** * Deletes the specified storage class. @@ -229,10 +230,9 @@ protected: std::list<std::string> m_adminHosts; /** - * The current mapping from storage class names to storage classes and their - * usage counts. + * Container of the storage classes used by the file system. */ - std::map<std::string, StorageClassAndUsageCount> m_storageClasses; + FileSystemStorageClasses m_storageClasses; /** * The root node of the file-system. @@ -253,27 +253,6 @@ protected: */ void checkAdminHostDoesNotAlreadyExist(const std::string &adminHost); - /** - * Throws an exception if the specified storage class already exists. - * - * @param name The name of teh storage class. - */ - void checkStorageClassDoesNotAlreadyExist(const std::string &name) const; - - /** - * Throws an exception if the specified storage class does not exist. - * - * @param name The name of the storage class. - */ - void checkStorageClassExists(const std::string &name) const; - - /** - * Throws an exception if the specified storage class is use. - * - * @param name The name of the storage class. - */ - void checkStorageClassIsNotInUse(const std::string &name) const; - /** * Throws an exception if the specified absolute path constains a * syntax error. diff --git a/libs/client/MockClientAPITest.cpp b/libs/client/MockClientAPITest.cpp index 931980c5690d772dd50bbaf77eb54c7efd02d9e8..85af6ebbbf39dd4b651fc18b79601783482c67fe 100644 --- a/libs/client/MockClientAPITest.cpp +++ b/libs/client/MockClientAPITest.cpp @@ -226,7 +226,8 @@ TEST_F(cta_client_MockClientAPITest, createStorageClass_new) { const std::string name = "TestStorageClass"; const uint8_t nbCopies = 2; - ASSERT_NO_THROW(api.createStorageClass(requester, name, nbCopies)); + const std::string comment = "Comment"; + ASSERT_NO_THROW(api.createStorageClass(requester, name, nbCopies, comment)); { std::list<StorageClass> storageClasses; @@ -235,8 +236,8 @@ TEST_F(cta_client_MockClientAPITest, createStorageClass_new) { StorageClass storageClass; ASSERT_NO_THROW(storageClass = storageClasses.front()); - ASSERT_EQ(name, storageClass.name); - ASSERT_EQ(nbCopies, storageClass.nbCopies); + ASSERT_EQ(name, storageClass.getName()); + ASSERT_EQ(nbCopies, storageClass.getNbCopies()); } } @@ -254,7 +255,8 @@ TEST_F(cta_client_MockClientAPITest, createStorageClass_already_existing) { const std::string name = "TestStorageClass"; const uint8_t nbCopies = 2; - ASSERT_NO_THROW(api.createStorageClass(requester, name, nbCopies)); + const std::string comment = "Comment"; + ASSERT_NO_THROW(api.createStorageClass(requester, name, nbCopies, comment)); { std::list<StorageClass> storageClasses; @@ -263,11 +265,11 @@ TEST_F(cta_client_MockClientAPITest, createStorageClass_already_existing) { StorageClass storageClass; ASSERT_NO_THROW(storageClass = storageClasses.front()); - ASSERT_EQ(name, storageClass.name); - ASSERT_EQ(nbCopies, storageClass.nbCopies); + ASSERT_EQ(name, storageClass.getName()); + ASSERT_EQ(nbCopies, storageClass.getNbCopies()); } - ASSERT_THROW(api.createStorageClass(requester, name, nbCopies), + ASSERT_THROW(api.createStorageClass(requester, name, nbCopies, comment), std::exception); } @@ -283,23 +285,23 @@ TEST_F(cta_client_MockClientAPITest, createStorageClass_lexicographical_order) { ASSERT_TRUE(storageClasses.empty()); } - ASSERT_NO_THROW(api.createStorageClass(requester, "d", 1)); - ASSERT_NO_THROW(api.createStorageClass(requester, "b", 1)); - ASSERT_NO_THROW(api.createStorageClass(requester, "a", 1)); - ASSERT_NO_THROW(api.createStorageClass(requester, "c", 1)); + ASSERT_NO_THROW(api.createStorageClass(requester, "d", 1, "Comment d")); + ASSERT_NO_THROW(api.createStorageClass(requester, "b", 1, "Comment b")); + ASSERT_NO_THROW(api.createStorageClass(requester, "a", 1, "Comment a")); + ASSERT_NO_THROW(api.createStorageClass(requester, "c", 1, "Comment c")); { std::list<StorageClass> storageClasses; ASSERT_NO_THROW(storageClasses = api.getStorageClasses(requester)); ASSERT_EQ(4, storageClasses.size()); - ASSERT_EQ(std::string("a"), storageClasses.front().name); + ASSERT_EQ(std::string("a"), storageClasses.front().getName()); storageClasses.pop_front(); - ASSERT_EQ(std::string("b"), storageClasses.front().name); + ASSERT_EQ(std::string("b"), storageClasses.front().getName()); storageClasses.pop_front(); - ASSERT_EQ(std::string("c"), storageClasses.front().name); + ASSERT_EQ(std::string("c"), storageClasses.front().getName()); storageClasses.pop_front(); - ASSERT_EQ(std::string("d"), storageClasses.front().name); + ASSERT_EQ(std::string("d"), storageClasses.front().getName()); } } @@ -317,7 +319,8 @@ TEST_F(cta_client_MockClientAPITest, deleteStorageClass_existing) { const std::string name = "TestStorageClass"; const uint8_t nbCopies = 2; - ASSERT_NO_THROW(api.createStorageClass(requester, name, nbCopies)); + const std::string comment = "Comment"; + ASSERT_NO_THROW(api.createStorageClass(requester, name, nbCopies, comment)); { std::list<StorageClass> storageClasses; @@ -326,8 +329,8 @@ TEST_F(cta_client_MockClientAPITest, deleteStorageClass_existing) { StorageClass storageClass; ASSERT_NO_THROW(storageClass = storageClasses.front()); - ASSERT_EQ(name, storageClass.name); - ASSERT_EQ(nbCopies, storageClass.nbCopies); + ASSERT_EQ(name, storageClass.getName()); + ASSERT_EQ(nbCopies, storageClass.getNbCopies()); ASSERT_NO_THROW(api.deleteStorageClass(requester, name)); } @@ -353,7 +356,8 @@ TEST_F(cta_client_MockClientAPITest, deleteStorageClass_in_use) { const std::string name = "TestStorageClass"; const uint8_t nbCopies = 2; - ASSERT_NO_THROW(api.createStorageClass(requester, name, nbCopies)); + const std::string comment = "Comment"; + ASSERT_NO_THROW(api.createStorageClass(requester, name, nbCopies, comment)); { std::list<StorageClass> storageClasses; @@ -362,8 +366,8 @@ TEST_F(cta_client_MockClientAPITest, deleteStorageClass_in_use) { StorageClass storageClass; ASSERT_NO_THROW(storageClass = storageClasses.front()); - ASSERT_EQ(name, storageClass.name); - ASSERT_EQ(nbCopies, storageClass.nbCopies); + ASSERT_EQ(name, storageClass.getName()); + ASSERT_EQ(nbCopies, storageClass.getNbCopies()); } ASSERT_NO_THROW(api.setDirectoryStorageClass(requester, "/", name)); @@ -377,8 +381,8 @@ TEST_F(cta_client_MockClientAPITest, deleteStorageClass_in_use) { StorageClass storageClass; ASSERT_NO_THROW(storageClass = storageClasses.front()); - ASSERT_EQ(name, storageClass.name); - ASSERT_EQ(nbCopies, storageClass.nbCopies); + ASSERT_EQ(name, storageClass.getName()); + ASSERT_EQ(nbCopies, storageClass.getNbCopies()); } } @@ -546,7 +550,8 @@ TEST_F(cta_client_MockClientAPITest, createDirectory_inherit_storage_class) { { const std::string name = "TestStorageClass"; const uint8_t nbCopies = 2; - ASSERT_NO_THROW(api.createStorageClass(requester, name, nbCopies)); + const std::string comment = "Comment"; + ASSERT_NO_THROW(api.createStorageClass(requester, name, nbCopies, comment)); } { @@ -770,8 +775,9 @@ TEST_F(cta_client_MockClientAPITest, setDirectoryStorageClass_top_level) { const std::string storageClassName = "TestStorageClass"; const uint8_t nbCopies = 2; + const std::string comment = "Comment"; ASSERT_NO_THROW(api.createStorageClass(requester, storageClassName, - nbCopies)); + nbCopies, comment)); ASSERT_NO_THROW(api.setDirectoryStorageClass(requester, dirPath, storageClassName)); @@ -812,8 +818,9 @@ TEST_F(cta_client_MockClientAPITest, clearDirectoryStorageClass_top_level) { const std::string storageClassName = "TestStorageClass"; const uint8_t nbCopies = 2; + const std::string comment = "Comment"; ASSERT_NO_THROW(api.createStorageClass(requester, storageClassName, - nbCopies)); + nbCopies, comment)); ASSERT_NO_THROW(api.setDirectoryStorageClass(requester, dirPath, storageClassName)); diff --git a/libs/client/StorageClass.cpp b/libs/client/StorageClass.cpp index 763d3060485cce66af0fee711a4024e60cf7ef4d..1653b02809a30cad127155da4779224f5ae29ebc 100644 --- a/libs/client/StorageClass.cpp +++ b/libs/client/StorageClass.cpp @@ -3,12 +3,58 @@ //------------------------------------------------------------------------------ // constructor //------------------------------------------------------------------------------ -cta::StorageClass::StorageClass(): nbCopies(0) { +cta::StorageClass::StorageClass(): + m_nbCopies(0), + m_creationTime(time(NULL)) { } //------------------------------------------------------------------------------ // constructor //------------------------------------------------------------------------------ -cta::StorageClass::StorageClass(const std::string &name, - const uint8_t nbCopies): name(name), nbCopies(nbCopies) { +cta::StorageClass::StorageClass( + const std::string &name, + const uint8_t nbCopies, + const UserIdentity &creator, + const std::string &comment): + m_name(name), + m_nbCopies(nbCopies), + m_creationTime(time(NULL)), + m_creator(creator), + m_comment(comment) { +} + +//------------------------------------------------------------------------------ +// getName +//------------------------------------------------------------------------------ +const std::string &cta::StorageClass::getName() const throw() { + return m_name; +} + +//------------------------------------------------------------------------------ +// getNbCopies +//------------------------------------------------------------------------------ +uint8_t cta::StorageClass::getNbCopies() const throw() { + return m_nbCopies; +} + +//------------------------------------------------------------------------------ +// getCreationTime +//------------------------------------------------------------------------------ +time_t cta::StorageClass::getCreationTime() const throw() { + return m_creationTime; +} + +//------------------------------------------------------------------------------ +// getCreator +//------------------------------------------------------------------------------ +const cta::UserIdentity &cta::StorageClass::getCreator() + const throw() { + return m_creator; +} + +//------------------------------------------------------------------------------ +// getComment +//------------------------------------------------------------------------------ +const std::string &cta::StorageClass::getComment() const throw() { + return m_comment; } diff --git a/libs/client/StorageClass.hpp b/libs/client/StorageClass.hpp index a7b0f1f303b59626507457df8c2f1a6491dbfa2a..aae056e61402166d3c7d8747a4a539f59e03ce44 100644 --- a/libs/client/StorageClass.hpp +++ b/libs/client/StorageClass.hpp @@ -1,5 +1,7 @@ #pragma once +#include "UserIdentity.hpp" + #include <stdint.h> #include <string> @@ -11,31 +13,89 @@ namespace cta { struct StorageClass { /** - * The name of the storage class. + * Constructor. */ - std::string name; + StorageClass(); /** - * The number of copies a file associated with this storage + * Constructor. + * + * @param name The name of the storage class. + * @param nbCopies The number of copies a file associated with this storage * class should have on tape. + * @param creator The identity of the user that created the storage class. + * @param comment The comment describing the storage class. */ - uint8_t nbCopies; + StorageClass( + const std::string &name, + const uint8_t nbCopies, + const UserIdentity &creator, + const std::string &comment); /** - * Constructor. + * Returns the name of the storage class. * - * Initialises nbCopies to 0. + * @return The name of the storage class. */ - StorageClass(); + const std::string &getName() const throw(); /** - * Constructor. + * Returns the number of copies a file associated with this storage + * class should have on tape. * - * @param name The name of the storage class. - * @param nbCopies The number of copies a file associated with this storage + * @return The number of copies a file associated with this storage + * class should have on tape. + */ + uint8_t getNbCopies() const throw(); + + /** + * Returns the time when the storage class was created. + * + * @return The time when the storage class was created. + */ + time_t getCreationTime() const throw(); + + /** + * Returns the identity of the user that created the storage class. + * + * @return The identity of the user that created the storage class. + */ + const UserIdentity &getCreator() const throw(); + + /** + * Returns the comment describing the storage class. + * + * @return The comment describing the storage class. + */ + const std::string &getComment() const throw(); + +private: + + /** + * The name of the storage class. + */ + std::string m_name; + + /** + * The number of copies a file associated with this storage * class should have on tape. */ - StorageClass(const std::string &name, const uint8_t nbCopies); + uint8_t m_nbCopies; + + /** + * The time when the storage class was created. + */ + time_t m_creationTime; + + /** + * The identity of the user that created the storage class. + */ + UserIdentity m_creator; + + /** + * Comment describing the storage class. + */ + std::string m_comment; }; // struct StorageClass diff --git a/xroot_plugins/XrdProFilesystem.cpp b/xroot_plugins/XrdProFilesystem.cpp index 7c981f81bfe4232075bfb98b4231ba64d5d88145..cef2ff6d077aac47cfdab7e94f37567d48a9aa65 100644 --- a/xroot_plugins/XrdProFilesystem.cpp +++ b/xroot_plugins/XrdProFilesystem.cpp @@ -150,7 +150,8 @@ int XrdProFilesystem::executeMkclassCommand(const ParsedRequest &req, XrdOucErrI std::istringstream ss(req.args.at(1)); ss >> numberOfCopies; cta::SecurityIdentity requester; - m_clientAPI->createStorageClass(requester, req.args.at(0), numberOfCopies); + const std::string comment = "Comment"; // TO BE DONE + m_clientAPI->createStorageClass(requester, req.args.at(0), numberOfCopies, comment); std::ostringstream responseSS; responseSS << "[OK] Created storage class " << req.args.at(0) << " with " << req.args.at(1) << " tape copies"; eInfo.setErrInfo(responseSS.str().length()+1, responseSS.str().c_str()); @@ -319,7 +320,7 @@ int XrdProFilesystem::executeLsclassCommand(const ParsedRequest &req, XrdOucErrI std::ostringstream responseSS; responseSS << "[OK] Listing of the storage class names and no of copies:"; for(std::list<cta::StorageClass>::iterator it = stgList.begin(); it != stgList.end(); it++) { - responseSS << "\n" << it->name << " " << it->nbCopies; + responseSS << "\n" << it->getName() << " " << it->getNbCopies(); } eInfo.setErrInfo(responseSS.str().length()+1, responseSS.str().c_str()); return SFS_DATA; @@ -418,8 +419,9 @@ int XrdProFilesystem::executeLsCommand(const ParsedRequest &req, XrdOucErrInfo & cta::DirectoryIterator itor = m_clientAPI->getDirectoryContents(requester, req.args.at(0)); while(itor.hasMore()) { const cta::DirectoryEntry &entry = itor.next(); + responseSS << "\n"; - responseSS << ((S_ISDIR(entry.mode)) ? "d" : "-"); + responseSS << ((entry.entryType == cta::DirectoryEntry::ENTRYTYPE_DIRECTORY) ? "d" : "-"); responseSS << ((entry.mode & S_IRUSR) ? "r" : "-"); responseSS << ((entry.mode & S_IWUSR) ? "w" : "-"); responseSS << ((entry.mode & S_IXUSR) ? "x" : "-");