diff --git a/libs/middletier/ArchiveRoute.hpp b/libs/middletier/ArchiveRoute.hpp index 1c93c1e0ba22caf07901d9a216c8fd7c36ae6160..7cac25af331e8697e14a5fb49f2fb5eac139d6bc 100644 --- a/libs/middletier/ArchiveRoute.hpp +++ b/libs/middletier/ArchiveRoute.hpp @@ -24,7 +24,7 @@ public: * * @param storageClassName The name of the storage class that identifies the * source disk files. - * @param copyNb The tape copy number. + * @param copyNb The tape copy number. Copy numbers start from 1. * @param tapePoolName The name of the destination tape pool. * @param creator The identity of the user that created the storage class. * @param comment Comment describing the storage class. diff --git a/libs/middletier/FileSystemStorageClasses.cpp b/libs/middletier/FileSystemStorageClasses.cpp index c303fb8579cc4654db5a01d8aeaac258e3964917..6b10a629bb2ea75914e13783343f96a20a64cdc4 100644 --- a/libs/middletier/FileSystemStorageClasses.cpp +++ b/libs/middletier/FileSystemStorageClasses.cpp @@ -97,6 +97,21 @@ std::list<cta::StorageClass> cta::FileSystemStorageClasses::getStorageClasses() return storageClasses; } +//------------------------------------------------------------------------------ +// getStorageClass +//------------------------------------------------------------------------------ +const cta::StorageClass &cta::FileSystemStorageClasses::getStorageClass( + const std::string &name) const { + std::map<std::string, FileSystemStorageClass>::const_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()); + } + return itor->second.getStorageClass(); +} + //------------------------------------------------------------------------------ // incStorageClassUsageCount //------------------------------------------------------------------------------ diff --git a/libs/middletier/FileSystemStorageClasses.hpp b/libs/middletier/FileSystemStorageClasses.hpp index 5a4fcff7a71d70e6e2f0fefa24897ab5b94b3d36..461dcd7e0ee83a31133091fb9c698f40f55a04f4 100644 --- a/libs/middletier/FileSystemStorageClasses.hpp +++ b/libs/middletier/FileSystemStorageClasses.hpp @@ -47,6 +47,14 @@ public: */ std::list<StorageClass> getStorageClasses() const; + /** + * Returns the specified storage class. + * + * @param name The name of the storage class. + * @return The specified storage class. + */ + const StorageClass &getStorageClass(const std::string &name) const; + /** * Throws an exception if the specified storage class does not exist. * diff --git a/libs/middletier/MockArchivalJobTable.cpp b/libs/middletier/MockArchivalJobTable.cpp index 6f99653c4d6057231c359e3a16e18d14276029b1..32a1f9b5ebf645156992c95a68afe410bb12b97b 100644 --- a/libs/middletier/MockArchivalJobTable.cpp +++ b/libs/middletier/MockArchivalJobTable.cpp @@ -13,7 +13,8 @@ void cta::MockArchivalJobTable::createArchivalJob( const std::string &dstPath) { checkArchivalJobDoesNotAlreadyExist(dstPath); - ArchivalJob job(ArchivalJobState::NONE, srcUrl, dstPath, requester.user, time(NULL)); + ArchivalJob job(ArchivalJobState::PENDING, srcUrl, dstPath, requester.user, + time(NULL)); std::map<std::string, std::map<time_t, ArchivalJob> >::iterator poolItor = m_jobsTree.find(tapePoolName); diff --git a/libs/middletier/MockArchiveRouteTable.cpp b/libs/middletier/MockArchiveRouteTable.cpp index 06d5d7fade29daa03e6dbc4f656f536c3caca470..b0543efc63c1d7ca582fc7c4da11536ed4e38cf8 100644 --- a/libs/middletier/MockArchiveRouteTable.cpp +++ b/libs/middletier/MockArchiveRouteTable.cpp @@ -72,6 +72,24 @@ std::list<cta::ArchiveRoute> cta::MockArchiveRouteTable:: return routes; } +//------------------------------------------------------------------------------ +// getArchiveRoute +//------------------------------------------------------------------------------ +const cta::ArchiveRoute &cta::MockArchiveRouteTable::getArchiveRoute( + const std::string &storageClassName, + const uint8_t copyNb) const { + const ArchiveRouteId routeId(storageClassName, copyNb); + std::map<ArchiveRouteId, ArchiveRoute>::const_iterator itor = + m_archiveRoutes.find(routeId); + if(itor == m_archiveRoutes.end()) { + std::ostringstream message; + message << "No archive route for storage class " << storageClassName << + " copy number " << copyNb; + throw Exception(message.str()); + } + return itor->second; +} + //------------------------------------------------------------------------------ // checkArchiveRouteExists //------------------------------------------------------------------------------ diff --git a/libs/middletier/MockArchiveRouteTable.hpp b/libs/middletier/MockArchiveRouteTable.hpp index 14577e792ebc99fb5ad69a94fb13e6de7a690ce1..f863a82087d95a191fd5d404fd5db94cef0c9bc2 100644 --- a/libs/middletier/MockArchiveRouteTable.hpp +++ b/libs/middletier/MockArchiveRouteTable.hpp @@ -51,6 +51,18 @@ public: */ std::list<ArchiveRoute> getArchiveRoutes() const; + /** + * Returns the specified archive route. + * + * @param storageClassName The name of the storage class that identifies the + * source disk files. + * @param copyNb The tape copy number. + * @return The specified archive route. + */ + const ArchiveRoute &getArchiveRoute( + const std::string &storageClassName, + const uint8_t copyNb) const; + /** * Throws an exception if the specified archive route does not exist. * diff --git a/libs/middletier/MockMiddleTierUser.cpp b/libs/middletier/MockMiddleTierUser.cpp index 67f8856b31ce222f3620c0607c2a8ec1b14d1c69..ec8f4669327d69255189389f3a11ed85f11b6268 100644 --- a/libs/middletier/MockMiddleTierUser.cpp +++ b/libs/middletier/MockMiddleTierUser.cpp @@ -259,12 +259,41 @@ void cta::MockMiddleTierUser::archiveToDirectory( const std::string inheritedStorageClassName = dstDirNode.getFileSystemEntry(). getEntry().getStorageClassName(); + if(inheritedStorageClassName.empty()) { + std::ostringstream message; + message << "Directory " << inheritedStorageClassName << " does not have a " + "storage class"; + throw Exception(message.str()); + } + + const StorageClass storageClass = m_db.storageClasses.getStorageClass( + inheritedStorageClassName); + if(0 == storageClass.getNbCopies()) { + std::ostringstream message; + message << "Storage class " << inheritedStorageClassName << " of directory " + << dstDir << " has zero tape copies"; + throw Exception(message.str()); + } + + checkStorageClassIsFullyRouted(storageClass); + const std::list<std::string> dstFileNames = Utils::getEnclosedNames(srcUrls); checkDirNodeDoesNotContainFiles(dstDir, dstDirNode, dstFileNames); - for(std::list<std::string>::const_iterator itor = dstFileNames.begin(); - itor != dstFileNames.end(); itor++) { - const std::string &dstFileName = *itor; + std::list<std::string>::const_iterator srcItor = srcUrls.begin(); + for(std::list<std::string>::const_iterator dstItor = dstFileNames.begin(); + dstItor != dstFileNames.end(); srcItor++, dstItor++) { + const std::string &srcUrl = *srcItor; + const std::string &dstFileName = *dstItor; + const std::string dstPath = dstDir + dstFileName; + + for(uint8_t copyNb = 1; copyNb <= storageClass.getNbCopies(); copyNb++) { + const ArchiveRoute &route = m_db.archiveRoutes.getArchiveRoute( + inheritedStorageClassName, copyNb); + m_db.archivalJobs.createArchivalJob(requester, route.getTapePoolName(), + srcUrl, dstPath); + } + DirectoryEntry dirEntry(DirectoryEntry::ENTRYTYPE_FILE, dstFileName, inheritedStorageClassName); dstDirNode.addChild(new FileSystemNode(m_db.storageClasses, dirEntry)); @@ -289,6 +318,17 @@ void cta::MockMiddleTierUser::checkDirNodeDoesNotContainFiles( } } +//------------------------------------------------------------------------------ +// checkStorageClassIsFullyRouted +//------------------------------------------------------------------------------ +void cta::MockMiddleTierUser::checkStorageClassIsFullyRouted( + const StorageClass &storageClass) const { + for(uint8_t copyNb = 1; copyNb <= storageClass.getNbCopies(); copyNb++) { + m_db.archiveRoutes.checkArchiveRouteExists(storageClass.getName(), + copyNb); + } +} + //------------------------------------------------------------------------------ // archiveToFile //------------------------------------------------------------------------------ @@ -314,6 +354,33 @@ void cta::MockMiddleTierUser::archiveToFile( const std::string inheritedStorageClassName = enclosingNode.getFileSystemEntry().getEntry().getStorageClassName(); + + if(inheritedStorageClassName.empty()) { + std::ostringstream message; + message << "Directory " << inheritedStorageClassName << " does not have a " + "storage class"; + throw Exception(message.str()); + } + + const StorageClass &storageClass = m_db.storageClasses.getStorageClass( + inheritedStorageClassName); + if(0 == storageClass.getNbCopies()) { + std::ostringstream message; + message << "Storage class " << inheritedStorageClassName << " of directory " + << enclosingDir << " has zero tape copies"; + throw Exception(message.str()); + } + + checkStorageClassIsFullyRouted(storageClass); + + const std::string &srcUrl = srcUrls.front(); + for(uint8_t copyNb = 1; copyNb <= storageClass.getNbCopies(); copyNb++) { + const ArchiveRoute &route = m_db.archiveRoutes.getArchiveRoute( + inheritedStorageClassName, copyNb); + m_db.archivalJobs.createArchivalJob(requester, route.getTapePoolName(), + srcUrl, dstFile); + } + DirectoryEntry dirEntry(DirectoryEntry::ENTRYTYPE_FILE, enclosedName, inheritedStorageClassName); enclosingNode.addChild(new FileSystemNode(m_db.storageClasses, dirEntry)); @@ -334,18 +401,29 @@ void cta::MockMiddleTierUser::checkUserIsAuthorisedToArchive( std::map<cta::TapePool, std::list<cta::ArchivalJob> > cta::MockMiddleTierUser::getArchivalJobs( const SecurityIdentity &requester) const { - const std::map<std::string, std::map<time_t, cta::ArchivalJob> > + const std::map<std::string, std::map<time_t, ArchivalJob> > jobsByPoolName = m_db.archivalJobs.getArchivalJobs(requester); - std::map<cta::TapePool, std::list<cta::ArchivalJob> > jobs; - - for(std::map<std::string, std::map<time_t, cta::ArchivalJob> >::const_iterator - byPoolNameItor = jobsByPoolName.begin(); - byPoolNameItor != jobsByPoolName.end(); - byPoolNameItor++) { + std::map<TapePool, std::list<ArchivalJob> > allJobs; + + for(std::map<std::string, std::map<time_t, ArchivalJob> >::const_iterator + poolItor = jobsByPoolName.begin(); + poolItor != jobsByPoolName.end(); + poolItor++) { + const std::string &tapePoolName = poolItor->first; + const std::map<time_t, ArchivalJob> &timeToJobMap = poolItor->second; + if(!timeToJobMap.empty()) { + const TapePool tapePool = m_db.tapePools.getTapePool(tapePoolName); + std::list<cta::ArchivalJob> poolJobs; + for(std::map<time_t, ArchivalJob>::const_iterator jobItor = + timeToJobMap.begin(); jobItor != timeToJobMap.end(); jobItor++) { + poolJobs.push_back(jobItor->second); + } + allJobs[tapePool] = poolJobs; + } } - return jobs; + return allJobs; } //------------------------------------------------------------------------------ diff --git a/libs/middletier/MockMiddleTierUser.hpp b/libs/middletier/MockMiddleTierUser.hpp index 12ce3a08ec6ae5c75cc321627df74319db2913c5..6a1dc907c9ae608aaab49daae496b267daed6270 100644 --- a/libs/middletier/MockMiddleTierUser.hpp +++ b/libs/middletier/MockMiddleTierUser.hpp @@ -276,6 +276,13 @@ private: const std::list<std::string> &srcUrls, const std::string &dstDir); + /** + * Throws an exception if the specified storage class is not fully routed. + * + * @param storageClass The storage class; + */ + void checkStorageClassIsFullyRouted(const StorageClass &storageClass) const; + /** * Archives the specified list of source files to the specified destination * file within the archive namespace. @@ -313,10 +320,10 @@ private: * @param dirNode The file-system node representing the directory. * @param fileNames The file names to be searched for. */ -void checkDirNodeDoesNotContainFiles( - const std::string &dirPath, - const FileSystemNode &dirNode, - const std::list<std::string> &fileNames); + void checkDirNodeDoesNotContainFiles( + const std::string &dirPath, + const FileSystemNode &dirNode, + const std::list<std::string> &fileNames); }; // class MockMiddleTierUser diff --git a/libs/middletier/MockTapePoolTable.cpp b/libs/middletier/MockTapePoolTable.cpp index d38bb9cc8bfbe2283af2d1403cb7a921af66ba79..3a0e17bf48050b59cc5eb48c6e237d09ea18ff06 100644 --- a/libs/middletier/MockTapePoolTable.cpp +++ b/libs/middletier/MockTapePoolTable.cpp @@ -72,3 +72,17 @@ std::list<cta::TapePool> cta::MockTapePoolTable::getTapePools( } return tapePools; } + +//------------------------------------------------------------------------------ +// getTapePool +//------------------------------------------------------------------------------ +const cta::TapePool &cta::MockTapePoolTable::getTapePool( + const std::string &name) const { + std::map<std::string, TapePool>::const_iterator itor = m_tapePools.find(name); + if(itor == m_tapePools.end()) { + std::ostringstream message; + message << "Tape pool " << name << " does not exist"; + throw(Exception(message.str())); + } + return itor->second; +} diff --git a/libs/middletier/MockTapePoolTable.hpp b/libs/middletier/MockTapePoolTable.hpp index e15e51ca33b4ed30f8d4de0d93edc47e292e715f..e280299348f5c86442e71922dce930df5f7b55ef 100644 --- a/libs/middletier/MockTapePoolTable.hpp +++ b/libs/middletier/MockTapePoolTable.hpp @@ -69,6 +69,14 @@ public: std::list<TapePool> getTapePools( const SecurityIdentity &requester) const; + /** + * Returns the specified tape pool. + * + * @param name The name of the tape pool. + * @return The specified tape pool. + */ + const TapePool &getTapePool(const std::string &name) const; + private: /** diff --git a/libs/middletier/TapePool.cpp b/libs/middletier/TapePool.cpp index 307672fc75a8e99888ab2c5797ed9543ca9b9154..244d8b0fdac65c2cea970cebf2c581693d3e98c9 100644 --- a/libs/middletier/TapePool.cpp +++ b/libs/middletier/TapePool.cpp @@ -27,6 +27,13 @@ cta::TapePool::TapePool( m_comment(comment) { } +//------------------------------------------------------------------------------ +// operator< +//------------------------------------------------------------------------------ +bool cta::TapePool::operator<(const TapePool &rhs) const throw() { + return m_name < rhs.m_name; +} + //------------------------------------------------------------------------------ // getName //------------------------------------------------------------------------------ diff --git a/libs/middletier/TapePool.hpp b/libs/middletier/TapePool.hpp index 8c23c0487e12b36e21fa1cb03f89747984c8e10a..4bc122b19c8eb9e5012a3dd3737b4d25fe54f782 100644 --- a/libs/middletier/TapePool.hpp +++ b/libs/middletier/TapePool.hpp @@ -37,6 +37,13 @@ public: const time_t creationTime, const std::string &comment); + /** + * Less than operator. + * + * @param rhs The right-hand side of the operator. + */ + bool operator<(const TapePool &rhs) const throw(); + /** * Returns the name of the tape pool. *