Commit def09b6f authored by Daniele Kruse's avatar Daniele Kruse
Browse files

Implemented the listdrivestatus command

parent 5042cfb0
......@@ -51,6 +51,7 @@ set(CMAKE_DISABLE_IN_SOURCE_BUILD ON)
list(APPEND CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/cmake)
include_directories(${PROJECT_SOURCE_DIR})
include_directories(${CMAKE_BINARY_DIR})
add_subdirectory(cmdline)
add_subdirectory(common)
......
/*
* 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 "scheduler/MountType.hpp"
namespace cta {
enum DriveStatus {
Down,
Up,
Starting, // This status allows drive register to represent drives committed
// to mounting a tape before the mounting is confirmed. It is necessary to
// allow race-free scheduling
Mounting,
Transfering,
Unloading,
Unmounting,
DrainingToDisk,
CleaningUp
};
struct DriveState {
std::string name;
std::string logicalLibrary;
uint64_t sessionId;
uint64_t bytesTransferedInSession;
uint64_t filesTransferedInSession;
double latestBandwidth; /** < Byte per seconds */
time_t sessionStartTime;
time_t mountStartTime;
time_t transferStartTime;
time_t unloadStartTime;
time_t unmountStartTime;
time_t drainingStartTime;
time_t downOrUpStartTime;
time_t cleanupStartTime;
time_t lastUpdateTime;
time_t startStartTime;
cta::MountType::Enum mountType;
DriveStatus status;
std::string currentVid;
std::string currentTapePool;
};
}
\ No newline at end of file
......@@ -2,7 +2,7 @@ cmake_minimum_required (VERSION 2.6)
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/..)
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../middletier)
include_directories(${CMAKE_BINARY_DIR})
find_package(Protobuf)
......
......@@ -20,6 +20,7 @@
#include "ProtocolBuffersAlgorithms.hpp"
#include "GenericObject.hpp"
#include "RootEntry.hpp"
#include "common/DriveState.hpp"
#include <set>
cta::objectstore::DriveRegister::DriveRegister(const std::string & address, Backend & os):
......@@ -120,7 +121,7 @@ cta::objectstore::serializers::DriveStatus
}
}
cta::objectstore::DriveRegister::DriveStatus
cta::DriveStatus
cta::objectstore::DriveRegister::deserializeDriveStatus(
serializers::DriveStatus driveStatus) {
switch (driveStatus) {
......@@ -148,28 +149,28 @@ cta::objectstore::DriveRegister::DriveStatus
}
cta::objectstore::serializers::MountType
cta::objectstore::DriveRegister::serializeMountType(MountType mountType) {
cta::objectstore::DriveRegister::serializeMountType(cta::MountType::Enum mountType) {
switch (mountType) {
case MountType::NoMount:
case MountType::NONE:
return serializers::MountType::NoMount;
case MountType::Archive:
case MountType::ARCHIVE:
return serializers::MountType::Archive;
case MountType::Retrieve:
case MountType::RETRIEVE:
return serializers::MountType::Retrieve;
default:
throw exception::Exception("In DriveRegister::serializeMountType: unexpected MountType");
}
}
cta::objectstore::DriveRegister::MountType
cta::MountType::Enum
cta::objectstore::DriveRegister::deserializeMountType(serializers::MountType mountType) {
switch (mountType) {
case serializers::MountType::NoMount:
return MountType::NoMount;
return MountType::NONE;
case serializers::MountType::Archive:
return MountType::Archive;
return MountType::ARCHIVE;
case serializers::MountType::Retrieve:
return MountType::Retrieve;
return MountType::RETRIEVE;
default:
throw exception::Exception("In DriveRegister::serializeMountType: unexpected MountType");
}
......@@ -185,7 +186,7 @@ namespace {
void cta::objectstore::DriveRegister::reportDriveStatus(const std::string& driveName,
const std::string& logicalLibary, DriveStatus status, time_t reportTime,
MountType mountType, uint64_t mountSessionId, uint64_t byteTransfered,
cta::MountType::Enum mountType, uint64_t mountSessionId, uint64_t byteTransfered,
uint64_t filesTransfered, double latestBandwidth, const std::string & vid,
const std::string & tapepool) {
// Wrap all the parameters together for easier manipulation by sub-functions
......
......@@ -19,9 +19,9 @@
#pragma once
#include "ObjectOps.hpp"
#include "objectstore/cta.pb.h"
#include <list>
#include <limits>
#include "common/DriveState.hpp"
namespace cta { namespace objectstore {
......@@ -44,48 +44,9 @@ public:
void addDrive (const std::string & driveName, const std::string & logicalLibrary,
const CreationLog & creationLog);
void removeDrive (const std::string & name);
enum class MountType {
NoMount,
Archive,
Retrieve
};
enum class DriveStatus {
Down,
Up,
Starting, // This status allows drive register to represent drives committed
// to mounting a tape before the mounting is confirmed. It is necessary to
// allow race-free scheduling
Mounting,
Transfering,
Unloading,
Unmounting,
DrainingToDisk,
CleaningUp
};
struct DriveState {
std::string name;
std::string logicalLibrary;
uint64_t sessionId;
uint64_t bytesTransferedInSession;
uint64_t filesTransferedInSession;
double latestBandwidth; /** < Byte per seconds */
time_t sessionStartTime;
time_t mountStartTime;
time_t transferStartTime;
time_t unloadStartTime;
time_t unmountStartTime;
time_t drainingStartTime;
time_t downOrUpStartTime;
time_t cleanupStartTime;
time_t lastUpdateTime;
MountType mountType;
DriveStatus status;
std::string currentVid;
std::string currentTapePool;
};
private:
MountType deserializeMountType(serializers::MountType);
serializers::MountType serializeMountType(MountType);
cta::MountType::Enum deserializeMountType(serializers::MountType);
serializers::MountType serializeMountType(cta::MountType::Enum);
DriveStatus deserializeDriveStatus(serializers::DriveStatus);
serializers::DriveStatus serializeDriveStatus(DriveStatus);
public:
......@@ -100,7 +61,7 @@ public:
*/
void reportDriveStatus (const std::string & drive, const std::string & logicalLibary,
DriveStatus status, time_t reportTime,
MountType mountType = MountType::NoMount,
cta::MountType::Enum mountType = cta::MountType::NONE,
uint64_t mountSessionId = std::numeric_limits<uint64_t>::max(),
uint64_t byteTransfered = std::numeric_limits<uint64_t>::max(),
uint64_t filesTransfered = std::numeric_limits<uint64_t>::max(),
......@@ -113,7 +74,7 @@ private:
const std::string & drive;
const std::string & logicalLibary;
DriveStatus status;
MountType mountType;
cta::MountType::Enum mountType;
time_t reportTime;
uint64_t mountSessionId;
uint64_t byteTransfered;
......
......@@ -152,25 +152,16 @@ std::unique_ptr<SchedulerDatabase::TapeMountDecisionInfo>
dr.fetch();
auto dl = dr.dumpDrives();
std::set<int> activeDriveStatuses = {
(int)objectstore::DriveRegister::DriveStatus::Starting,
(int)objectstore::DriveRegister::DriveStatus::Mounting,
(int)objectstore::DriveRegister::DriveStatus::Transfering,
(int)objectstore::DriveRegister::DriveStatus::Unloading,
(int)objectstore::DriveRegister::DriveStatus::Unmounting,
(int)objectstore::DriveRegister::DriveStatus::DrainingToDisk };
(int)cta::DriveStatus::Starting,
(int)cta::DriveStatus::Mounting,
(int)cta::DriveStatus::Transfering,
(int)cta::DriveStatus::Unloading,
(int)cta::DriveStatus::Unmounting,
(int)cta::DriveStatus::DrainingToDisk };
for (auto d=dl.begin(); d!= dl.end(); d++) {
if (activeDriveStatuses.count((int)d->status)) {
tmdi.existingMounts.push_back(ExistingMount());
switch (d->mountType) {
case objectstore::DriveRegister::MountType::Archive:
tmdi.existingMounts.back().type = cta::MountType::ARCHIVE;
break;
case objectstore::DriveRegister::MountType::Retrieve:
tmdi.existingMounts.back().type = cta::MountType::RETRIEVE;
break;
default:
throw exception::Exception("In OStoreDB::getMountInfo(): got drive with unexpected mount type");
}
tmdi.existingMounts.back().type = d->mountType;
tmdi.existingMounts.back().tapePool = d->currentTapePool;
}
}
......@@ -1109,6 +1100,17 @@ void OStoreDB::deleteRetrieveRequest(const SecurityIdentity& requester,
throw exception::Exception("Not Implemented");
}
std::list<cta::DriveState> OStoreDB::getDriveStates() const {
RootEntry re(m_objectStore);
ScopedSharedLock rel(re);
re.fetch();
auto driveRegisterAddress = re.getDriveRegisterAddress();
objectstore::DriveRegister dr(driveRegisterAddress, m_objectStore);
objectstore::ScopedExclusiveLock drl(dr);
dr.fetch();
return dr.dumpDrives();
}
std::unique_ptr<SchedulerDatabase::ArchiveMount>
OStoreDB::TapeMountDecisionInfo::createArchiveMount(
const std::string& vid, const std::string & tapePool, const std::string driveName,
......@@ -1204,8 +1206,8 @@ std::unique_ptr<SchedulerDatabase::ArchiveMount>
// goes to mount state. If the work to be done gets depleted in the mean time,
// we will switch back to up.
dr.reportDriveStatus(driveName, logicalLibrary,
objectstore::DriveRegister::DriveStatus::Starting, startTime,
objectstore::DriveRegister::MountType::Archive, privateRet->mountInfo.mountId,
cta::DriveStatus::Starting, startTime,
cta::MountType::ARCHIVE, privateRet->mountInfo.mountId,
0, 0, 0, vid, tapePool);
dr.commit();
}
......@@ -1311,8 +1313,8 @@ std::unique_ptr<SchedulerDatabase::RetrieveMount>
// goes to mount state. If the work to be done gets depleted in the mean time,
// we will switch back to up.
dr.reportDriveStatus(driveName, logicalLibrary,
objectstore::DriveRegister::DriveStatus::Starting, startTime,
objectstore::DriveRegister::MountType::Retrieve, privateRet->mountInfo.mountId,
cta::DriveStatus::Starting, startTime,
cta::MountType::RETRIEVE, privateRet->mountInfo.mountId,
0, 0, 0, vid, tapePool);
dr.commit();
}
......@@ -1422,8 +1424,8 @@ void OStoreDB::ArchiveMount::complete(time_t completionTime) {
dr.fetch();
// Reset the drive state.
dr.reportDriveStatus(mountInfo.drive, mountInfo.logicalLibrary,
objectstore::DriveRegister::DriveStatus::Up, completionTime,
objectstore::DriveRegister::MountType::NoMount, 0,
cta::DriveStatus::Up, completionTime,
cta::MountType::NONE, 0,
0, 0, 0, "", "");
dr.commit();
// Find the tape and unbusy it.
......@@ -1543,8 +1545,8 @@ void OStoreDB::RetrieveMount::complete(time_t completionTime) {
dr.fetch();
// Reset the drive state.
dr.reportDriveStatus(mountInfo.drive, mountInfo.logicalLibrary,
objectstore::DriveRegister::DriveStatus::Up, completionTime,
objectstore::DriveRegister::MountType::NoMount, 0,
cta::DriveStatus::Up, completionTime,
cta::MountType::NONE, 0,
0, 0, 0, "", "");
dr.commit();
// Find the tape and unbusy it.
......
......@@ -21,6 +21,7 @@
#include "scheduler/SchedulerDatabase.hpp"
#include "objectstore/Agent.hpp"
#include "objectstore/ArchiveToFileRequest.hpp"
#include "objectstore/DriveRegister.hpp"
#include "objectstore/RetrieveToFileRequest.hpp"
#include "objectstore/SchedulerGlobalLock.hpp"
......@@ -294,6 +295,8 @@ public:
virtual void deleteRetrieveRequest(const SecurityIdentity& requester,
const std::string& remoteFile);
/* === Drive state handling ============================================== */
virtual std::list<cta::DriveState> getDriveStates() const;
private:
objectstore::Backend & m_objectStore;
objectstore::Agent * m_agent;
......
......@@ -230,6 +230,10 @@ public:
virtual void queue(const RetrieveToDirRequest& rqst) {
m_OStoreDB.queue(rqst);
}
virtual std::list<cta::DriveState> getDriveStates() const {
return m_OStoreDB.getDriveStates();
}
private:
BackendType m_backend;
cta::OStoreDB m_OStoreDB;
......
......@@ -593,32 +593,6 @@ void cta::Scheduler::queueArchiveRequest(
}
}
//------------------------------------------------------------------------------
// queueArchiveToDirRequest
//------------------------------------------------------------------------------
//void cta::Scheduler::queueArchiveToDirRequest(
// const SecurityIdentity &requester,
// const std::list<RemotePathAndStatus> &remoteFiles,
// const std::string &archiveDir) {
//
// const uint64_t priority = 0; // TO BE DONE
//
// const auto storageClassName = m_ns.getDirStorageClass(requester, archiveDir);
// const auto storageClass = m_db.getStorageClass(storageClassName);
// assertStorageClassHasAtLeastOneCopy(storageClass);
// const auto archiveToFileRequests = createArchiveToFileRequests(requester,
// remoteFiles, archiveDir, priority);
//
// CreationLog log(requester.getUser(), requester.getHost(), time(NULL), "");
// m_db.queue(ArchiveToDirRequest(archiveDir, archiveToFileRequests, priority,
// log));
//
// for(auto itor = archiveToFileRequests.cbegin(); itor !=
// archiveToFileRequests.cend(); itor++) {
// createNSEntryAndUpdateSchedulerDatabase(requester, *itor);
// }
//}
//------------------------------------------------------------------------------
// assertStorageClassHasAtLeastOneCopy
//------------------------------------------------------------------------------
......@@ -671,38 +645,6 @@ void cta::Scheduler::queueArchiveToFileRequest(
requestCreation->complete();
}
//------------------------------------------------------------------------------
// queueArchiveToFileRequest
//------------------------------------------------------------------------------
//void cta::Scheduler::queueArchiveToFileRequest(
// const SecurityIdentity &requester,
// const RemotePathAndStatus &remoteFile,
// const std::string &archiveFile) {
//
// const uint64_t priority = 0; // TO BE DONE
// const ArchiveToFileRequest rqst = createArchiveToFileRequest(requester,
// remoteFile, archiveFile, priority);
//
// std::unique_ptr<SchedulerDatabase::ArchiveToFileRequestCreation>
// requestCreation (m_db.queue(rqst));
// try {
// m_ns.createFile(requester, rqst.archiveFile.path, remoteFile.status.mode, remoteFile.status.size);
// } catch(std::exception &nsEx) {
// // Try our best to cleanup the scheduler database. The garbage collection
// // logic will try again if we fail.
// try {
// requestCreation->cancel();
// //m_db.deleteArchiveRequest(requester, rqst.archiveFile);
// } catch(...) {
// }
//
// // Whether or not we were able to clean up the scheduler database, the real
// // problem here was the failure to create an entry in the NS
// throw nsEx;
// }
// requestCreation->complete();
//}
//------------------------------------------------------------------------------
// createArchiveToFileRequest
//------------------------------------------------------------------------------
......@@ -939,51 +881,9 @@ std::unique_ptr<cta::TapeMount> cta::Scheduler::getNextMount(
return std::unique_ptr<TapeMount>();
}
//
////------------------------------------------------------------------------------
//// finishedMount
////------------------------------------------------------------------------------
//void cta::Scheduler::finishedMount(const std::string &mountId) {
//}
//
////------------------------------------------------------------------------------
//// getNextArchive
////------------------------------------------------------------------------------
//cta::ArchiveJob *cta::Scheduler::getNextArchive(
// const std::string &mountId) {
// return NULL;
//}
//
////------------------------------------------------------------------------------
//// archiveSuccessful
////------------------------------------------------------------------------------
//void cta::Scheduler::archiveSuccessful(const std::string &transferId) {
//}
//
////------------------------------------------------------------------------------
//// archiveFailed
////------------------------------------------------------------------------------
//void cta::Scheduler::archiveFailed(const std::string &transferId,
// const TapeJobFailure failureType, const std::string &errorMessage) {
//}
//
////------------------------------------------------------------------------------
//// getNextRetrieve
////------------------------------------------------------------------------------
//cta::RetrieveJob *cta::Scheduler::getNextRetrieve(
// const std::string &mountId) {
// return NULL;
//}
//
////------------------------------------------------------------------------------
//// retrieveSucceeded
////------------------------------------------------------------------------------
//void cta::Scheduler::retrieveSucceeded(const std::string &transferId) {
//}
//
////------------------------------------------------------------------------------
//// retrieveFailed
////------------------------------------------------------------------------------
//void cta::Scheduler::retrieveFailed(const std::string &transferId,
// const TapeJobFailure failureType, const std::string &errorMessage) {
//}
//------------------------------------------------------------------------------
// getDriveStates
//------------------------------------------------------------------------------
std::list<cta::DriveState> cta::Scheduler::getDriveStates(const SecurityIdentity &requester) const {
return m_db.getDriveStates();
}
......@@ -18,8 +18,9 @@
#pragma once
#include "scheduler/SchedulerDatabase.hpp"
#include "common/exception/Exception.hpp"
#include "scheduler/SchedulerDatabase.hpp"
#include "objectstore/DriveRegister.hpp"
#include <list>
#include <map>
......@@ -652,6 +653,13 @@ public:
*/
virtual std::unique_ptr<TapeMount> getNextMount(const std::string &logicalLibraryName,
const std::string & driveName);
/**
* Returns the current list of registered drives.
*
* @return The current list of registered drives.
*/
virtual std::list<cta::DriveState> getDriveStates(const SecurityIdentity &requester) const;
private:
......
......@@ -31,9 +31,10 @@
#include "common/admin/AdminHost.hpp"
#include "common/archiveRoutes/ArchiveRoute.hpp"
#include "common/remoteFS/RemotePathAndStatus.hpp"
#include "scheduler/MountType.hpp"
#include "common/MountControl.hpp"
#include "nameserver/NameServerTapeFile.hpp"
#include "objectstore/DriveRegister.hpp"
#include "scheduler/MountType.hpp"
namespace cta {
......@@ -625,6 +626,14 @@ public:
* volume identifiers.
*/
virtual std::list<Tape> getTapes() const = 0;
/* === Drive state handling ============================================== */
/**
* Returns the current list of registered drives.
*
* @return The current list of registered drives.
*/
virtual std::list<cta::DriveState> getDriveStates() const = 0;
}; // class SchedulerDatabase
......
......@@ -1077,6 +1077,57 @@ void XrdProFile::xCom_listpendingretrieves(const std::vector<std::string> &token
}
m_data = responseSS.str();
}
std::string fromDriveStatusToString(cta::DriveStatus status) {
switch(status) {
case cta::DriveStatus::CleaningUp:
return "CleaningUp";
case cta::DriveStatus::Down:
return "Down";
case cta::DriveStatus::DrainingToDisk:
return "DrainingToDisk";
case cta::DriveStatus::Mounting:
return "Mounting";
case cta::DriveStatus::Starting:
return "Starting";
case cta::DriveStatus::Transfering:
return "Transfering";
case cta::DriveStatus::Unloading:
return "Unloading";
case cta::DriveStatus::Unmounting:
return "Unmounting";
case cta::DriveStatus::Up:
return "Up";
default:
return "UnknownState";
}
}
time_t getDurationSinceStatusBegin(const cta::DriveState &state) {
time_t now = time(0);
switch(state.status) {
case cta::DriveStatus::CleaningUp:
return now-state.cleanupStartTime;
case cta::DriveStatus::Down:
return now-state.downOrUpStartTime;
case cta::DriveStatus::DrainingToDisk:
return now-state.drainingStartTime;
case cta::DriveStatus::Mounting:
return now-state.mountStartTime;
case cta::DriveStatus::Starting:
return now-state.startStartTime;
case cta::DriveStatus::Transfering:
return now-state.transferStartTime;
case cta::DriveStatus::Unloading:
return now-state.unloadStartTime;
case cta::DriveStatus::Unmounting:
return now-state.unmountStartTime;
case cta::DriveStatus::Up:
return now-state.downOrUpStartTime;
default:
return 0;
}
}
//------------------------------------------------------------------------------
// xCom_listdrivestates
......@@ -1084,7 +1135,23 @@ void XrdProFile::xCom_listpendingretrieves(const std::vector<std::string> &token
void XrdProFile::xCom_listdrivestates(const std::vector<std::string> &tokens, const cta::SecurityIdentity &requester) {
std::stringstream help;
help << tokens[0] << " lds/listdrivestates" << std::endl;
m_data = "Not implemented yet!\n";
auto list = m_scheduler->getDriveStates(requester);
std::ostringstream responseSS;
for(auto it = list.begin(); it != list.end(); it++) {
responseSS << it->name
<< " " << fromDriveStatusToString(it->status)
<< " " << cta::MountType::toString(it->mountType)
<< " " << getDurationSinceStatusBegin(*it)
<< " " << it->currentVid
<< " " << it->bytesTransferedInSession
<< " " << it->filesTransferedInSession
<< " " << it->latestBandwidth
<< " " << it->logicalLibrary
<< " " << it->sessionId
<< " " << time(0)-it->startStartTime
<< " " << it->lastUpdateTime << std::endl;
}
m_data = responseSS.str();
}
//------------------------------------------------------------------------------
......