content server caches ObjectDbPtr
use Hash instead of Hash string
use constant instead of raw number
Change-Id: Ib3f5f2d4cd755bfb73b38c2621ad2383522b2621
diff --git a/src/content-server.cc b/src/content-server.cc
index 66bf26b..2aa19ca 100644
--- a/src/content-server.cc
+++ b/src/content-server.cc
@@ -21,6 +21,11 @@
#include "content-server.h"
#include "logging.h"
+#include <boost/make_shared.hpp>
+#include <utility>
+#include "task.h"
+#include "periodic-task.h"
+#include "simple-interval-generator.h"
#include <boost/lexical_cast.hpp>
INIT_LOGGER ("ContentServer");
@@ -29,6 +34,8 @@
using namespace std;
using namespace boost;
+static const int DB_CACHE_LIFETIME = 60;
+
ContentServer::ContentServer(CcnxWrapperPtr ccnx, ActionLogPtr actionLog,
const boost::filesystem::path &rootDir,
const Ccnx::Name &deviceName, const std::string &sharedFolderName,
@@ -38,17 +45,19 @@
, m_actionLog(actionLog)
, m_dbFolder(rootDir / ".chronoshare")
, m_freshness(freshness)
- , m_executor (1)
+ , m_scheduler (new Scheduler())
, m_deviceName (deviceName)
, m_sharedFolderName (sharedFolderName)
, m_appName (appName)
{
- m_executor.start ();
+ m_scheduler->start ();
+ TaskPtr flushStaleDbCacheTask = boost::make_shared<PeriodicTask>(boost::bind(&ContentServer::flushStaleDbCache, this), "flush-state-db-cache", m_scheduler, boost::make_shared<SimpleIntervalGenerator>(DB_CACHE_LIFETIME));
+ m_scheduler->addTask(flushStaleDbCacheTask);
}
ContentServer::~ContentServer()
{
- m_executor.shutdown ();
+ m_scheduler->shutdown ();
ScopedLock lock (m_mutex);
for (PrefixIt it = m_prefixes.begin(); it != m_prefixes.end(); ++it)
@@ -123,7 +132,7 @@
ContentServer::serve_Action (Name forwardingHint, Name locatorPrefix, Name interest)
{
_LOG_DEBUG (">> content server serving ACTION, hint: " << forwardingHint << ", locatorPrefix: " << locatorPrefix << ", interest: " << interest);
- m_executor.execute (bind (&ContentServer::serve_Action_Execute, this, forwardingHint, locatorPrefix, interest));
+ m_scheduler->scheduleOneTimeTask (m_scheduler, 0, bind (&ContentServer::serve_Action_Execute, this, forwardingHint, locatorPrefix, interest), boost::lexical_cast<string>(interest));
// need to unlock ccnx mutex... or at least don't lock it
}
@@ -132,7 +141,7 @@
{
_LOG_DEBUG (">> content server serving FILE, hint: " << forwardingHint << ", locatorPrefix: " << locatorPrefix << ", interest: " << interest);
- m_executor.execute (bind (&ContentServer::serve_File_Execute, this, forwardingHint, locatorPrefix, interest));
+ m_scheduler->scheduleOneTimeTask (m_scheduler, 0, bind (&ContentServer::serve_File_Execute, this, forwardingHint, locatorPrefix, interest), boost::lexical_cast<string>(interest));
// need to unlock ccnx mutex... or at least don't lock it
}
@@ -153,42 +162,59 @@
_LOG_DEBUG (" server FILE for device: " << deviceName << ", file_hash: " << hash.shortHash () << " segment: " << segment);
string hashStr = lexical_cast<string> (hash);
- if (ObjectDb::DoesExist (m_dbFolder, deviceName, hashStr)) // this is kind of overkill, as it counts available segments
+
+ ObjectDbPtr db;
+
+ ScopedLock(m_dbCacheMutex);
+ {
+ DbCache::iterator it = m_dbCache.find(hash);
+ if (it != m_dbCache.end())
{
- ObjectDb db (m_dbFolder, hashStr);
- // may do prefetching
-
- BytesPtr co = db.fetchSegment (deviceName, segment);
- if (co)
+ db = it->second;
+ }
+ else
+ {
+ if (ObjectDb::DoesExist (m_dbFolder, deviceName, hashStr)) // this is kind of overkill, as it counts available segments
{
- if (forwardingHint.size () == 0)
- {
- _LOG_DEBUG (ParsedContentObject (*co).name ());
- m_ccnx->putToCcnd (*co);
- }
- else
- {
- if (m_freshness > 0)
- {
- m_ccnx->publishData(interest, *co, m_freshness);
- }
- else
- {
- m_ccnx->publishData(interest, *co);
- }
- }
-
+ db = boost::make_shared<ObjectDb>(m_dbFolder, hashStr);
+ m_dbCache.insert(make_pair(hash, db));
}
else
{
- _LOG_ERROR ("ObjectDd exists, but no segment " << segment << " for device: " << deviceName << ", file_hash: " << hash.shortHash ());
+ _LOG_ERROR ("ObjectDd doesn't exist for device: " << deviceName << ", file_hash: " << hash.shortHash ());
}
}
- else
- {
- _LOG_ERROR ("ObjectDd doesn't exist for device: " << deviceName << ", file_hash: " << hash.shortHash ());
- }
+ }
+ if (db)
+ {
+ BytesPtr co = db->fetchSegment (deviceName, segment);
+ if (co)
+ {
+ if (forwardingHint.size () == 0)
+ {
+ _LOG_DEBUG (ParsedContentObject (*co).name ());
+ m_ccnx->putToCcnd (*co);
+ }
+ else
+ {
+ if (m_freshness > 0)
+ {
+ m_ccnx->publishData(interest, *co, m_freshness);
+ }
+ else
+ {
+ m_ccnx->publishData(interest, *co);
+ }
+ }
+
+ }
+ else
+ {
+ _LOG_ERROR ("ObjectDd exists, but no segment " << segment << " for device: " << deviceName << ", file_hash: " << hash.shortHash ());
+ }
+
+ }
}
void
@@ -231,3 +257,22 @@
_LOG_ERROR ("ACTION not found for device: " << deviceName << " and seqno: " << seqno);
}
}
+
+void
+ContentServer::flushStaleDbCache()
+{
+ ScopedLock(m_dbCacheMutex);
+ DbCache::iterator it = m_dbCache.begin();
+ while (it != m_dbCache.end())
+ {
+ ObjectDbPtr db = it->second;
+ if (db->secondsSinceLastUse() >= DB_CACHE_LIFETIME)
+ {
+ m_dbCache.erase(it++);
+ }
+ else
+ {
+ ++it;
+ }
+ }
+}