diff --git a/objectstore/GarbageCollector.cpp b/objectstore/GarbageCollector.cpp index 55575ffb30ef39551ad7898023d6dbc7336c390f..7b87d0789dd358d4377cb2e5e2abae7f61a45f46 100644 --- a/objectstore/GarbageCollector.cpp +++ b/objectstore/GarbageCollector.cpp @@ -34,20 +34,13 @@ GarbageCollector::GarbageCollector(Backend & os, Agent & agent): m_agentRegister.fetch(); } -void GarbageCollector::runOnePass() { - // Bump our own heart beat - { - ScopedExclusiveLock lock (m_ourAgent); - m_ourAgent.fetch(); - m_ourAgent.bumpHeartbeat(); - m_ourAgent.commit(); - } - trimGoneTargets(); - aquireTargets(); - checkHeartbeats(); +void GarbageCollector::runOnePass(log::LogContext & lc) { + trimGoneTargets(lc); + aquireTargets(lc); + checkHeartbeats(lc); } -void GarbageCollector::trimGoneTargets() { +void GarbageCollector::trimGoneTargets(log::LogContext & lc) { ScopedSharedLock arLock(m_agentRegister); m_agentRegister.fetch(); arLock.release(); @@ -59,17 +52,21 @@ void GarbageCollector::trimGoneTargets() { ScopedExclusiveLock oaLock(m_ourAgent); m_ourAgent.fetch(); m_ourAgent.removeFromOwnership(wa->first); + std::string removedAgent = wa->first; m_ourAgent.commit(); oaLock.release(); delete wa->second; m_watchedAgents.erase(wa++); + log::ScopedParamContainer params(lc); + params.add("agentAddress", removedAgent); + lc.log(log::INFO, "In GarbageCollector::trimGoneTargets(): removed now gone agent."); } else { wa++; } } } -void GarbageCollector::aquireTargets() { +void GarbageCollector::aquireTargets(log::LogContext & lc) { ScopedExclusiveLock arLock(m_agentRegister); m_agentRegister.fetch(); // Get the list of untracked agents @@ -110,6 +107,10 @@ void GarbageCollector::aquireTargets() { // We now have a pointer to the agent, we can make the ownership official ag.setOwner(m_ourAgent.getAddressIfSet()); ag.commit(); + log::ScopedParamContainer params(lc); + params.add("agentAddress", ag.getAddressIfSet()) + .add("gcAgentAddress", m_ourAgent.getAddressIfSet()); + lc.log(log::INFO, "In GarbageCollector::aquireTargets(): started tracking an untracked agent"); // And we can remove the now dangling pointer from the agent register // (we hold an exclusive lock all along) m_agentRegister.trackAgent(ag.getAddressIfSet()); @@ -132,14 +133,14 @@ void GarbageCollector::aquireTargets() { m_agentRegister.commit(); } -void GarbageCollector::checkHeartbeats() { +void GarbageCollector::checkHeartbeats(log::LogContext & lc) { // Check the heartbeats of the watched agents // We can still fail on many steps for (std::map<std::string, AgentWatchdog * >::iterator wa = m_watchedAgents.begin(); wa != m_watchedAgents.end();) { // Get the heartbeat. Clean dead agents and remove references to them if (!wa->second->checkAlive()) { - cleanupDeadAgent(wa->first); + cleanupDeadAgent(wa->first, lc); ScopedExclusiveLock oaLock(m_ourAgent); m_ourAgent.removeFromOwnership(wa->first); m_ourAgent.commit(); @@ -151,19 +152,27 @@ void GarbageCollector::checkHeartbeats() { } } - void GarbageCollector::cleanupDeadAgent(const std::string & address) { + void GarbageCollector::cleanupDeadAgent(const std::string & address, log::LogContext & lc) { // Check that we are still owners of the agent (sanity check). Agent agent(address, m_objectStore); ScopedExclusiveLock agLock(agent); agent.fetch(); + log::ScopedParamContainer params(lc); + params.add("agentAddress", agent.getAddressIfSet()) + .add("gcAgentAddress", m_ourAgent.getAddressIfSet()); if (agent.getOwner() != m_ourAgent.getAddressIfSet()) { - throw cta::exception::Exception("In GarbageCollector::cleanupDeadAgent: the ownership is not ours as expected"); + log::ScopedParamContainer params(lc); + lc.log(log::WARNING, "In GarbageCollector::cleanupDeadAgent(): skipping agent which is not owned by this garbage collector as thought."); + // The agent is removed from our ownership by the calling function: we're done. + return; } // Return all objects owned by the agent to their respective backup owners auto ownedObjects = agent.getOwnershipList(); for (auto obj = ownedObjects.begin(); obj!= ownedObjects.end(); obj++) { // Find the object GenericObject go(*obj, m_objectStore); + log::ScopedParamContainer params2(lc); + params2.add("objectAddress", go.getAddressIfSet()); // If the object does not exist, we're done. if (go.exists()) { ScopedExclusiveLock goLock(go); @@ -171,6 +180,9 @@ void GarbageCollector::checkHeartbeats() { // Call GenericOpbject's garbage collect method, which in turn will // delegate to the object type's garbage collector. go.garbageCollect(goLock, address); + lc.log(log::INFO, "In GarbageCollector::cleanupDeadAgent(): garbage collected owned object."); + } else { + lc.log(log::INFO, "In GarbageCollector::cleanupDeadAgent(): skipping garbage collection of now gone object."); } // In all cases, relinquish ownership for this object agent.removeFromOwnership(*obj); diff --git a/objectstore/GarbageCollector.hpp b/objectstore/GarbageCollector.hpp index 007d70a8bca015b049bbdd922ffbfdd9ee0f4d51..2fe2d29414ae1d51f58daef4b7c80826b03d7069 100644 --- a/objectstore/GarbageCollector.hpp +++ b/objectstore/GarbageCollector.hpp @@ -22,6 +22,7 @@ #include "Agent.hpp" #include "AgentWatchdog.hpp" #include "AgentRegister.hpp" +#include "common/log/LogContext.hpp" /** * Plan => Garbage collector keeps track of the agents. @@ -37,17 +38,17 @@ class GarbageCollector { public: GarbageCollector(Backend & os, Agent & agent); - void runOnePass(); + void runOnePass(log::LogContext & lc); - void aquireTargets(); + void aquireTargets(log::LogContext & lc); - void trimGoneTargets(); + void trimGoneTargets(log::LogContext & lc); - void checkHeartbeats(); + void checkHeartbeats(log::LogContext & lc); - void cleanupDeadAgent(const std::string & name); + void cleanupDeadAgent(const std::string & name, log::LogContext & lc); - void reinjectOwnedObject(); + void reinjectOwnedObject(log::LogContext & lc); private: Backend & m_objectStore; Agent & m_ourAgent; diff --git a/objectstore/GarbageCollectorTest.cpp b/objectstore/GarbageCollectorTest.cpp index 0516fddfc4c6b9aa9b641c639d671f4ab48e23fa..0617bcb6f9ea362511c6f71fcb1aafd90cf34f6f 100644 --- a/objectstore/GarbageCollectorTest.cpp +++ b/objectstore/GarbageCollectorTest.cpp @@ -20,6 +20,7 @@ #include "BackendVFS.hpp" #include "common/exception/Exception.hpp" #include "common/dataStructures/ArchiveFile.hpp" +#include "common/log/DummyLogger.hpp" #include "GarbageCollector.hpp" #include "RootEntry.hpp" #include "Agent.hpp" @@ -33,6 +34,9 @@ namespace unitTests { TEST(ObjectStore, GarbageCollectorBasicFuctionnality) { + // We will need a log object + cta::log::DummyLogger dl("unitTest"); + cta::log::LogContext lc(dl); // Here we check for the ability to detect dead (but empty agents) // and clean them up. cta::objectstore::BackendVFS be; @@ -67,8 +71,8 @@ TEST(ObjectStore, GarbageCollectorBasicFuctionnality) { gcAgent.insertAndRegisterSelf(); { cta::objectstore::GarbageCollector gc(be, gcAgent); - gc.runOnePass(); - gc.runOnePass(); + gc.runOnePass(lc); + gc.runOnePass(lc); } // Unregister gc's agent cta::objectstore::ScopedExclusiveLock gcal(gcAgent); @@ -81,6 +85,9 @@ TEST(ObjectStore, GarbageCollectorBasicFuctionnality) { } TEST(ObjectStore, GarbageCollectorRegister) { + // We will need a log object + cta::log::DummyLogger dl("unitTest"); + cta::log::LogContext lc(dl); // Here we check that can successfully call agentRegister's garbage collector cta::objectstore::BackendVFS be; cta::objectstore::AgentReference agentRef("unitTestGarbageCollector"); @@ -122,8 +129,8 @@ TEST(ObjectStore, GarbageCollectorRegister) { gcAgent.insertAndRegisterSelf(); { cta::objectstore::GarbageCollector gc(be, gcAgent); - gc.runOnePass(); - gc.runOnePass(); + gc.runOnePass(lc); + gc.runOnePass(lc); } ASSERT_FALSE(be.exists(arName)); // Unregister gc's agent @@ -137,6 +144,9 @@ TEST(ObjectStore, GarbageCollectorRegister) { } TEST(ObjectStore, GarbageCollectorArchiveQueue) { + // We will need a log object + cta::log::DummyLogger dl("unitTest"); + cta::log::LogContext lc(dl); // Here we check that can successfully call agentRegister's garbage collector cta::objectstore::BackendVFS be; cta::objectstore::AgentReference agentRef("unitTestGarbageCollector"); @@ -179,8 +189,8 @@ TEST(ObjectStore, GarbageCollectorArchiveQueue) { gcAgent.insertAndRegisterSelf(); { cta::objectstore::GarbageCollector gc(be, gcAgent); - gc.runOnePass(); - gc.runOnePass(); + gc.runOnePass(lc); + gc.runOnePass(lc); } ASSERT_FALSE(be.exists(tpName)); // Unregister gc's agent @@ -194,6 +204,9 @@ TEST(ObjectStore, GarbageCollectorArchiveQueue) { } TEST(ObjectStore, GarbageCollectorDriveRegister) { + // We will need a log object + cta::log::DummyLogger dl("unitTest"); + cta::log::LogContext lc(dl); // Here we check that can successfully call agentRegister's garbage collector cta::objectstore::BackendVFS be; cta::objectstore::AgentReference agentRef("unitTestGarbageCollector"); @@ -236,8 +249,8 @@ TEST(ObjectStore, GarbageCollectorDriveRegister) { gcAgent.insertAndRegisterSelf(); { cta::objectstore::GarbageCollector gc(be, gcAgent); - gc.runOnePass(); - gc.runOnePass(); + gc.runOnePass(lc); + gc.runOnePass(lc); } ASSERT_FALSE(be.exists(tpName)); // Unregister gc's agent @@ -251,6 +264,9 @@ TEST(ObjectStore, GarbageCollectorDriveRegister) { } TEST(ObjectStore, GarbageCollectorArchiveRequest) { + // We will need a log object + cta::log::DummyLogger dl("unitTest"); + cta::log::LogContext lc(dl); // Here we check that can successfully call ArchiveRequests's garbage collector cta::objectstore::BackendVFS be; cta::objectstore::AgentReference agentRef("unitTestGarbageCollector"); @@ -388,8 +404,8 @@ TEST(ObjectStore, GarbageCollectorArchiveRequest) { gcAgent.insertAndRegisterSelf(); { cta::objectstore::GarbageCollector gc(be, gcAgent); - gc.runOnePass(); - gc.runOnePass(); + gc.runOnePass(lc); + gc.runOnePass(lc); } // All 4 requests should be linked in both tape pools { diff --git a/tapeserver/daemon/GarbageCollectorHandler.cpp b/tapeserver/daemon/GarbageCollectorHandler.cpp index 4b269c4f7aca8628bdae124233142e570975878c..4d939f57529636ebe5e24bbabb2d71a91fbbd7d5 100644 --- a/tapeserver/daemon/GarbageCollectorHandler.cpp +++ b/tapeserver/daemon/GarbageCollectorHandler.cpp @@ -238,6 +238,9 @@ SubprocessHandler::ProcessingStatus GarbageCollectorHandler::processTimeout() { // GarbageCollectorHandler::runChild //------------------------------------------------------------------------------ int GarbageCollectorHandler::runChild() { + // We will need a log object + cta::log::DummyLogger dl("unitTest"); + cta::log::LogContext lc(dl); // We are in the child process. It is time to open connections to the catalogue // and object store, and run the garbage collector. // We do not have to care for previous crashed sessions as we will garbage @@ -296,7 +299,7 @@ int GarbageCollectorHandler::runChild() { pollList["0"]=m_socketPair.get(); do { m_processManager.logContext().log(log::INFO, "In GarbageCollectorHandler::runChild(): About to run a GC pass."); - gc.runOnePass(); + gc.runOnePass(lc); server::SocketPair::poll(pollList, s_pollInterval, server::SocketPair::Side::parent); } while (!m_socketPair->pollFlag()); m_processManager.logContext().log(log::INFO, "In GarbageCollectorHandler::runChild(): Received shutdown message. Exiting.");