diff --git a/objectstore/Action.hpp b/objectstore/Action.hpp new file mode 100644 index 0000000000000000000000000000000000000000..59a45634f81b81f2fdfd3b0bfdccde6295cd8e6a --- /dev/null +++ b/objectstore/Action.hpp @@ -0,0 +1,6 @@ +#pragma once + +class Action { +public: + void execute() {} +}; \ No newline at end of file diff --git a/objectstore/Agent.cpp b/objectstore/Agent.cpp new file mode 100644 index 0000000000000000000000000000000000000000..2fca9ee5b0018fa0c0f0cd10f32c8bf4b298bd9f --- /dev/null +++ b/objectstore/Agent.cpp @@ -0,0 +1,235 @@ +#include "Agent.hpp" +#include "AgentRegister.hpp" +#include "RootEntry.hpp" +#include <string> +#include <sstream> +#include <sys/syscall.h> +#include <ctime> + +Agent::Agent(ObjectStore & os): + ObjectOps<cta::objectstore::Agent>(os), + m_nextId(0), m_setupDone(false), m_creationDone(false), m_observerVersion(false) {}; + +Agent::Agent(ObjectStore & os, const std::string & typeName): + ObjectOps<cta::objectstore::Agent>(os), + m_nextId(0), m_setupDone(false), m_creationDone(false), m_observerVersion(false) { + setup(typeName); +} + +// Passive constructor, used for looking at existing agent records +Agent::Agent(const std::string & name, Agent & agent): + ObjectOps<cta::objectstore::Agent>(agent.objectStore(), name), + m_nextId(0), m_setupDone(true), m_creationDone(true), m_observerVersion(true) +{ + // check the presence of the entry + cta::objectstore::Agent as; + updateFromObjectStore(as, agent.getFreeContext()); +} + +void Agent::setup(const std::string & typeName) { + std::stringstream aid; + // Get time + time_t now = time(0); + struct tm localNow; + localtime_r(&now, &localNow); + // Get hostname + char host[200]; + cta::exception::Errnum::throwOnMinusOne(gethostname(host, sizeof(host)), + "In AgentId::AgentId: failed to gethostname"); + // gettid is a safe system call (never fails) + aid << typeName << "-" << host << "-" << syscall(SYS_gettid) << "-" + << 1900 + localNow.tm_year + << std::setfill('0') << std::setw(2) + << 1 + localNow.tm_mon + << localNow.tm_mday << "-" + << localNow.tm_hour << ":" + << localNow.tm_min << ":" + << localNow.tm_sec; + ObjectOps<cta::objectstore::Agent>::setName(aid.str()); + m_setupDone = true; +} + +void Agent::create() { + if (!m_setupDone) + throw SetupNotDone("In Agent::create(): setup() not yet done"); + RootEntry re(*this); + AgentRegister ar(re.allocateOrGetAgentRegister(*this), *this); + ar.addIntendedElement(selfName(), *this); + cta::objectstore::Agent as; + as.set_name(selfName()); + writeChild(selfName(), as); + ar.upgradeIntendedElementToActual(selfName(), *this); + m_creationDone = true; +} + +std::string Agent::type() { + if (!m_setupDone) + throw SetupNotDone("In Agent::type(): setup() not yet done"); + return m_typeName; +} + +std::string Agent::name() { + if (!m_setupDone) + throw SetupNotDone("In Agent::name(): setup() not yet done"); + return selfName(); +} + +Agent::~Agent() { + for (size_t i=0; i < c_handleCount; i++) { + m_contexts[i].release(); + } + if (m_creationDone) { + try { + remove(); + RootEntry re(*this); + AgentRegister ar(re.getAgentRegister(*this), *this); + ar.removeElement(selfName(),*this); + } catch(...) {} + } +} + +std::string Agent::nextId(const std::string & childType) { + if (!m_setupDone) + throw SetupNotDone("In Agent::nextId(): setup() not yet done"); + if (m_observerVersion) + throw ObserverOnly("In Agent::nextId(): this object is observer only"); + std::stringstream id; + id << childType << "-" << name() << "-" << m_nextId++; + return id.str(); +} + +ContextHandleImplementation<myOS> & Agent::getFreeContext() { + for (size_t i=0; i < c_handleCount; i++) { + if (!m_contexts[i].isSet()) + return m_contexts[i]; + } + throw cta::exception::Exception("Could not find free context slot"); +} + +void Agent::addToIntend (std::string container, std::string name, std::string typeName) { + if (!m_creationDone) + throw CreationNotDone("In Agent::addToIntend(): creation() not yet done"); + cta::objectstore::Agent as; + ContextHandle & ctx = getFreeContext(); + lockExclusiveAndRead(as, ctx); + cta::objectstore::ObjectCreationIntent * oca = + as.mutable_creationintent()->Add(); + oca->set_container(container); + oca->set_name(name); + oca->set_type(typeName); + write(as); + unlock(ctx); +} + +void Agent::removeFromIntent (std::string container, std::string name, std::string typeName) { + if (!m_creationDone) + throw CreationNotDone("In Agent::removeFromIntent(): creation() not yet done"); + cta::objectstore::Agent as; + ContextHandle & ctx = getFreeContext(); + lockExclusiveAndRead(as, ctx); + bool found; + do { + found = false; + for (int i=0; i<as.creationintent_size(); i++) { + if (container == as.creationintent(i).container() && + name == as.creationintent(i).name() && + typeName == as.creationintent(i).type()) { + found = true; + as.mutable_creationintent()->SwapElements(i, as.creationintent_size()-1); + as.mutable_creationintent()->RemoveLast(); + break; + } + } + } while (found); + write(as); + unlock(ctx); +} + +void Agent::addToOwnership(std::string name, std::string typeName) { + if (!m_creationDone) + throw CreationNotDone("In Agent::addToOwnership(): creation() not yet done"); + cta::objectstore::Agent as; + ContextHandle & ctx = getFreeContext(); + lockExclusiveAndRead(as, ctx); + cta::objectstore::ObjectOwnershipIntent * ooi = + as.mutable_ownershipintent()->Add(); + ooi->set_name(name); + ooi->set_type(typeName); + write(as); + unlock(ctx); +} + +void Agent::removeFromOwnership(std::string name, std::string typeName) { + if (!m_creationDone) + throw CreationNotDone("In Agent::removeFromOwnership(): creation() not yet done"); + cta::objectstore::Agent as; + ContextHandle & ctx = getFreeContext(); + lockExclusiveAndRead(as, ctx); + bool found; + do { + found = false; + for (int i=0; i<as.ownershipintent_size(); i++) { + if (name == as.ownershipintent(i).name() && + typeName == as.ownershipintent(i).type()) { + found = true; + as.mutable_creationintent()->SwapElements(i, as.ownershipintent_size()-1); + as.mutable_creationintent()->RemoveLast(); + break; + } + } + } while (found); + write(as); + unlock(ctx); +} + +std::list<Agent::intentEntry> Agent::getIntentLog() { + if (!m_creationDone) + throw CreationNotDone("In Agent::getIntentLog(): creation() not yet done"); + cta::objectstore::Agent as; + updateFromObjectStore(as, getFreeContext()); + std::list<intentEntry> ret; + for (int i=0; i<as.creationintent_size(); i++) { + ret.push_back(intentEntry(as.creationintent(i).container(), + as.creationintent(i).name(), + as.creationintent(i).type())); + } + return ret; +} + +std::list<Agent::ownershipEntry> Agent::getOwnershipLog() { + if (!m_creationDone) + throw CreationNotDone("In Agent::getOwnershipLog(): creation() not yet done"); + cta::objectstore::Agent as; + updateFromObjectStore(as, getFreeContext()); + std::list<ownershipEntry> ret; + for (int i=0; i<as.creationintent_size(); i++) { + ret.push_back(ownershipEntry(as.creationintent(i).name(), + as.creationintent(i).type())); + } + return ret; +} + +ObjectStore & Agent::objectStore() { + return ObjectOps<cta::objectstore::Agent>::objectStore(); +} + +std::string Agent::dump(Agent & agent) { + cta::objectstore::Agent as; + updateFromObjectStore(as, agent.getFreeContext()); + std::stringstream ret; + ret<< "<<<< Agent " << selfName() << " dump start" << std::endl + << "name=" << as.name() + << "Ownership intent size=" << as.ownershipintent_size() << std::endl; + for (int i=0; i<as.ownershipintent_size(); i++) { + ret << "ownershipIntent[" << i << "]: name=" << as.ownershipintent(i).name() + << " type=" << as.ownershipintent(i).type() << std::endl; + } + ret << "Creation intent size=" << as.creationintent_size() << std::endl; + for (int i=0; i<as.creationintent_size(); i++) { + ret << "creationIntent[" << i << "]: name=" << as.creationintent(i).name() + << " type=" << as.creationintent(i).type() + << " container=" << as.creationintent(i).container() << std::endl; + } + ret<< ">>>> AgentRegister " << selfName() << " dump end" << std::endl; + return ret.str(); +} \ No newline at end of file diff --git a/objectstore/Agent.hpp b/objectstore/Agent.hpp index 782e5cc813fd25224a682b9cad034d5d6b080d8e..72a6e696c8e0e84b57b8f5b89ee7afce7fd358c6 100644 --- a/objectstore/Agent.hpp +++ b/objectstore/Agent.hpp @@ -20,6 +20,8 @@ public: Agent(ObjectStore & os, const std::string & typeName); + Agent(const std::string & name, Agent & agent); + void setup(const std::string & typeName); class SetupNotDone: public cta::exception::Exception { @@ -32,6 +34,11 @@ public: CreationNotDone(const std::string & w): cta::exception::Exception(w) {} }; + class ObserverOnly: public cta::exception::Exception { + public: + ObserverOnly(const std::string & w): cta::exception::Exception(w) {} + }; + void create(); std::string type(); @@ -76,10 +83,13 @@ public: ObjectStore & objectStore(); + std::string dump(Agent & agent); + private: std::string m_typeName; bool m_setupDone; bool m_creationDone; + bool m_observerVersion; uint64_t m_nextId; static const size_t c_handleCount = 100; ContextHandleImplementation<myOS> m_contexts[c_handleCount]; diff --git a/objectstore/AgentRegister.cpp b/objectstore/AgentRegister.cpp new file mode 100644 index 0000000000000000000000000000000000000000..4bcda54d164953abd93a324bd318402fdc3c2875 --- /dev/null +++ b/objectstore/AgentRegister.cpp @@ -0,0 +1,118 @@ +#include "AgentRegister.hpp" + +AgentRegister::AgentRegister(const std::string & name, Agent & agent): +ObjectOps<cta::objectstore::AgentRegister>(agent.objectStore(), name) { + // Check that the entry is present and readable (depending on implementation + // of object store, locking might or might not succeed) + cta::objectstore::AgentRegister rs; + updateFromObjectStore(rs, agent.getFreeContext()); +} + +void AgentRegister::addElement (std::string name, Agent & agent) { + cta::objectstore::AgentRegister rs; + ContextHandle & context = agent.getFreeContext(); + lockExclusiveAndRead(rs, context); + rs.add_elements(name); + write(rs); + unlock(context); +} + +void AgentRegister::removeElement (const std::string & name, Agent & agent) { + cta::objectstore::AgentRegister rs; + ContextHandle & context = agent.getFreeContext(); + lockExclusiveAndRead(rs, context); + bool found; + do { + found = false; + for (int i=0; i<rs.elements_size(); i++) { + if (name == rs.elements(i)) { + found = true; + rs.mutable_elements()->SwapElements(i, rs.elements_size()-1); + rs.mutable_elements()->RemoveLast(); + break; + } + } + } while (found); + write(rs); + unlock(context); +} + +void AgentRegister::addIntendedElement(std::string name, Agent& agent) { + cta::objectstore::AgentRegister rs; + ContextHandle & context = agent.getFreeContext(); + lockExclusiveAndRead(rs, context); + rs.add_intendedelements(name); + write(rs); + unlock(context); +} + +void AgentRegister::upgradeIntendedElementToActual(std::string name, Agent& agent) { + cta::objectstore::AgentRegister rs; + ContextHandle & context = agent.getFreeContext(); + lockExclusiveAndRead(rs, context); + bool found; + do { + found = false; + for (int i=0; i<rs.intendedelements_size(); i++) { + if (name == rs.intendedelements(i)) { + found = true; + rs.mutable_intendedelements()->SwapElements(i, rs.intendedelements_size()-1); + rs.mutable_intendedelements()->RemoveLast(); + break; + } + } + } while (found); + rs.add_elements(name); + write(rs); + unlock(context); +} + + +void AgentRegister::removeIntendedElement(const std::string& name, Agent& agent) { + cta::objectstore::AgentRegister rs; + ContextHandle & context = agent.getFreeContext(); + lockExclusiveAndRead(rs, context); + bool found; + do { + found = false; + for (int i=0; i<rs.intendedelements_size(); i++) { + if (name == rs.intendedelements(i)) { + found = true; + rs.mutable_intendedelements()->SwapElements(i, rs.intendedelements_size()-1); + rs.mutable_intendedelements()->RemoveLast(); + break; + } + } + } while (found); + write(rs); + unlock(context); +} + + + +std::list<std::string> AgentRegister::getElements(Agent & agent) { + cta::objectstore::AgentRegister rs; + updateFromObjectStore(rs, agent.getFreeContext()); + std::list<std::string> ret; + for (int i=0; i<rs.elements_size(); i++) { + ret.push_back(rs.elements(i)); + } + return ret; +} + +std::string AgentRegister::dump(const std::string & title, Agent & agent) { + cta::objectstore::AgentRegister rs; + updateFromObjectStore(rs, agent.getFreeContext()); + std::stringstream ret; + ret<< "<<<< AgentRegister " << title << " dump start" << std::endl + << "Array size=" << rs.elements_size() << std::endl; + for (int i=0; i<rs.elements_size(); i++) { + ret << "element[" << i << "]=" << rs.elements(i) << std::endl; + } + ret << "Intent array size=" << rs.intendedelements_size() << std::endl; + for (int i=0; i<rs.intendedelements_size(); i++) { + ret << "intendedElement[" << i << "]=" << rs.intendedelements(i) << std::endl; + } + ret<< ">>>> AgentRegister " << title << " dump end" << std::endl; + return ret.str(); +} \ No newline at end of file diff --git a/objectstore/AgentRegister.hpp b/objectstore/AgentRegister.hpp new file mode 100644 index 0000000000000000000000000000000000000000..da84b72d124fd024b94f5d7cae72d4edb998a695 --- /dev/null +++ b/objectstore/AgentRegister.hpp @@ -0,0 +1,17 @@ +#pragma once + +#include "ObjectOps.hpp" +#include "Agent.hpp" +#include <algorithm> + +class AgentRegister: private ObjectOps<cta::objectstore::AgentRegister> { +public: + AgentRegister(const std::string & name, Agent & agent); + void addElement (std::string name, Agent & agent); + void removeElement (const std::string & name, Agent & agent); + void addIntendedElement (std::string name, Agent & agent); + void upgradeIntendedElementToActual(std::string name, Agent & agent); + void removeIntendedElement (const std::string & name, Agent & agent); + std::list<std::string> getElements(Agent & agent); + std::string dump(const std::string & title, Agent & agent); +}; \ No newline at end of file diff --git a/objectstore/ObjectStoreChoice.hpp b/objectstore/ObjectStoreChoice.hpp new file mode 100644 index 0000000000000000000000000000000000000000..14e20225f83b2d0b9cb5b61b3b77a2d86082ef1e --- /dev/null +++ b/objectstore/ObjectStoreChoice.hpp @@ -0,0 +1,4 @@ +#pragma once + +#include "ObjectOps.hpp" +typedef ObjectStoreRados myOS; \ No newline at end of file diff --git a/objectstore/ObjectStructureDumper.hpp b/objectstore/ObjectStructureDumper.hpp index d812b2bafbb3ec032c8c073a470a7f2eda46eead..b4a5b61407b254dc3133cd341c1b3e05e30a0b55 100644 --- a/objectstore/ObjectStructureDumper.hpp +++ b/objectstore/ObjectStructureDumper.hpp @@ -1,7 +1,8 @@ #pragma once #include "RootEntry.hpp" -#include "Register.hpp" +#include "AgentRegister.hpp" +#include "Agent.hpp" #include <iostream> class ObjectStrucutreDumper { @@ -12,8 +13,13 @@ public: RootEntry re(agent); ret << re.dump(agent); try { - Register ar(re.getAgentRegister(agent), agent); + AgentRegister ar(re.getAgentRegister(agent), agent); ret << ar.dump("root->agentRegister", agent); + std::list<std::string> agList = ar.getElements(agent); + for (std::list<std::string>::iterator i=agList.begin(); i!=agList.end(); i++) { + Agent a(*i, agent); + ret << a.dump(agent); + } } catch (RootEntry::NotAllocatedEx &) {} ret << ">> Structure dump end" << std::endl; return ret.str(); diff --git a/objectstore/cta.proto b/objectstore/cta.proto index cc21bd259006effa56f754b3b0ff4a26a92d2dfd..7bf0ff0c68e7485be85a62f35f462f4c7cc69575 100644 --- a/objectstore/cta.proto +++ b/objectstore/cta.proto @@ -6,11 +6,8 @@ message RootEntry { optional string agentregister = 1; repeated string agentregisterintentlog = 2; optional string jobpool = 3; - repeated string jobpoolintentlog = 4; - optional string driveregister = 5; - repeated string driveregisterintentlog = 6; - optional string taperegister = 7; - repeated string taperegisterintentlog = 8; + optional string driveregister = 4; + optional string taperegister = 5; } // The registers (simple name arrays) diff --git a/objectstore/tapeResourceManagerTest.cpp b/objectstore/tapeResourceManagerTest.cpp index 3c7fd760181aa9b97b1db3224ec0044d3563a501..72062fde30466bbd668adcb3dfe82f7acada4183 100644 --- a/objectstore/tapeResourceManagerTest.cpp +++ b/objectstore/tapeResourceManagerTest.cpp @@ -9,6 +9,7 @@ #include "ContextHandle.hpp" #include "ObjectStructureDumper.hpp" #include "JobPool.hpp" +#include "AgentRegister.hpp" @@ -64,7 +65,7 @@ int main(void){ // Get hold of the root entry RootEntry re(self); // Create and populate the job queues - Register agentRegister(re.allocateOrGetAgentRegister(self), self); + AgentRegister agentRegister(re.allocateOrGetAgentRegister(self), self); JobPool jobPool(re.allocateOrGetJobPool(self), self); // Dump again std::cout << osd.dump(self) << std::endl;