Permalink
Browse files

Preliminary periodic stat snapshot support.

Change-Id: I541c99f181264eb17490800d9fb674aaff4d6ef2
Reviewed-on: http://review.membase.org/2406
Reviewed-by: Chiyoung Seo <chiyoung.seo@gmail.com>
Tested-by: Chiyoung Seo <chiyoung.seo@gmail.com>
  • Loading branch information...
1 parent 8e17a85 commit 71a115af45e2dcfb73ed022311b8de0ba94270b5 @dustin dustin committed with chiyoung Sep 14, 2010
Showing with 168 additions and 1 deletion.
  1. +1 −0 Makefile.am
  2. +5 −0 ep_engine.cc
  3. +1 −0 priority.cc
  4. +1 −0 priority.hh
  5. +27 −0 sqlite-kvstore.cc
  6. +5 −0 sqlite-kvstore.hh
  7. +19 −0 sqlite-strategies.cc
  8. +15 −1 sqlite-strategies.hh
  9. +40 −0 statsnap.cc
  10. +54 −0 statsnap.hh
View
@@ -28,6 +28,7 @@ ep_la_SOURCES = \
histo.hh \
item.cc item.hh \
item_pager.cc item_pager.hh \
+ statsnap.cc statsnap.hh \
locks.hh \
mutex.hh \
priority.hh priority.cc \
View
@@ -25,6 +25,7 @@
#include <memcached/protocol_binary.h>
#include "ep_engine.h"
+#include "statsnap.hh"
static size_t percentOf(size_t val, double percent) {
return static_cast<size_t>(static_cast<double>(val) * percent);
@@ -964,6 +965,10 @@ ENGINE_ERROR_CODE EventuallyPersistentEngine::initialize(const char* config) {
epstore->getDispatcher()->schedule(exp_cb, NULL, Priority::ItemPagerPriority,
expiryPagerSleeptime);
}
+
+ shared_ptr<StatSnap> sscb(new StatSnap(this));
+ epstore->getDispatcher()->schedule(sscb, NULL, Priority::StatSnapPriority,
+ STATSNAP_FREQ);
}
if (ret == ENGINE_SUCCESS) {
View
@@ -26,3 +26,4 @@ const Priority Priority::FlusherPriority("flusher_priority", 5);
const Priority Priority::ItemPagerPriority("item_pager_priority", 7);
const Priority Priority::VBucketDeletionPriority("vbucket_deletion_priority", 9);
const Priority Priority::VBucketPersistPriority("vbucket_persist_priority", 9);
+const Priority Priority::StatSnapPriority("statsnap_priority", 9);
View
@@ -20,6 +20,7 @@ public:
static const Priority ItemPagerPriority;
static const Priority VBucketDeletionPriority;
static const Priority VBucketPersistPriority;
+ static const Priority StatSnapPriority;
bool operator==(const Priority &other) const {
return other.getPriorityValue() == this->priority;
View
@@ -171,6 +171,33 @@ bool StrategicSqlite3::setVBState(uint16_t vbucket, const std::string& state_str
return rv;
}
+bool StrategicSqlite3::snapshotStats(const std::map<std::string, std::string> &m) {
+ bool rv(false);
+ execute("begin transaction");
+ try {
+ PreparedStatement *delst = strategy->getClearStatsST();
+ bool deleted = delst->execute() >= 0;
+ rv &= deleted;
+ delst->reset();
+
+ PreparedStatement *ins = strategy->getInsStatST();
+ std::map<std::string, std::string>::const_iterator it;
+ for (it = m.begin(); it != m.end(); ++it) {
+ ins->bind(1, it->first.data(), it->first.size());
+ ins->bind(2, it->second.data(), it->second.size());
+ bool inserted = ins->execute() == 1;
+ ins->reset();
+ rv &= inserted;
+ }
+
+ execute("commit");
+ rv = true;
+ } catch(...) {
+ execute("rollback");
+ }
+ return rv;
+}
+
void StrategicSqlite3::dump(Callback<GetValue> &cb) {
const std::vector<Statements*> statements = strategy->allStatements();
View
@@ -108,6 +108,11 @@ public:
std::map<uint16_t, std::string> listPersistedVbuckets(void);
/**
+ * Take a snapshot of the stats in the main DB.
+ */
+ bool snapshotStats(const std::map<std::string, std::string> &m);
+
+ /**
* Overrides dump
*/
void dump(Callback<GetValue> &cb);
View
@@ -48,6 +48,8 @@ void SqliteStrategy::destroyMetaStatements(void) {
delete set_vb_stmt;
delete del_vb_stmt;
delete sel_vb_stmt;
+ delete clear_stats_stmt;
+ delete ins_stat_stmt;
}
void SqliteStrategy::initMetaTables() {
@@ -79,6 +81,13 @@ void SqliteStrategy::initMetaStatements(void) {
const char *sel_query = "select vbid, state from vbucket_states";
sel_vb_stmt = new PreparedStatement(db, sel_query);
+
+ const char *clear_stats_query = "delete from stats_snap";
+ clear_stats_stmt = new PreparedStatement(db, clear_stats_query);
+
+ const char *ins_stat_query = "insert into stats_snap "
+ "(name, value, last_change) values (?, ?, current_timestamp)";
+ ins_stat_stmt = new PreparedStatement(db, ins_stat_query);
}
void SqliteStrategy::initStatements(void) {
@@ -114,6 +123,16 @@ void SqliteStrategy::execute(const char * const query) {
void MultiDBSqliteStrategy::initTables() {
char buf[1024];
+ execute("create table if not exists vbucket_states"
+ " (vbid integer primary key on conflict replace,"
+ " state varchar(16),"
+ " last_change datetime)");
+
+ execute("create table if not exists stats_snap"
+ " (name varchar(16),"
+ " value varchar(24),"
+ " last_change datetime)");
+
for (int i = 0; i < numTables; i++) {
snprintf(buf, sizeof(buf), "attach database \"%s-%d.sqlite\" as kv_%d",
filename, i, i);
View
@@ -23,7 +23,8 @@ public:
postInitFile(pfinit),
db(NULL),
statements(),
- set_vb_stmt(NULL), del_vb_stmt(NULL), sel_vb_stmt(NULL)
+ set_vb_stmt(NULL), del_vb_stmt(NULL), sel_vb_stmt(NULL),
+ clear_stats_stmt(NULL), ins_stat_stmt(NULL)
{ }
virtual ~SqliteStrategy() {
@@ -59,7 +60,17 @@ public:
return sel_vb_stmt;
}
+
virtual void initMetaTables();
+
+ PreparedStatement *getClearStatsST() {
+ return clear_stats_stmt;
+ }
+
+ PreparedStatement *getInsStatST() {
+ return ins_stat_stmt;
+ }
+
virtual void initTables(void);
virtual void initStatements(void);
virtual void destroyTables(void);
@@ -87,6 +98,9 @@ protected:
void doFile(const char * const filename);
+ PreparedStatement *clear_stats_stmt;
+ PreparedStatement *ins_stat_stmt;
+
private:
DISALLOW_COPY_AND_ASSIGN(SqliteStrategy);
};
View
@@ -0,0 +1,40 @@
+/* -*- Mode: C++; tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- */
+
+#include "config.h"
+#include <iostream>
+#include <cstdlib>
+#include <string>
+#include <map>
+
+#include "common.hh"
+#include "statsnap.hh"
+#include "ep_engine.h"
+
+extern "C" {
+ static void add_stat(const char *key, const uint16_t klen,
+ const char *val, const uint32_t vlen,
+ const void *cookie) {
+ assert(cookie);
+ void *cokie = const_cast<void *>(cookie);
+ std::map<std::string, std::string> *m =
+ static_cast<std::map<std::string, std::string>*>(cokie);
+
+ std::string k(key, klen);
+ std::string v(val, vlen);
+ (*m)[k] = v;
+ }
+}
+
+bool StatSnap::getStats(const char *s) {
+ map.clear();
+ return engine->getStats(&map, s, s ? strlen(s) : 0,
+ add_stat) == ENGINE_SUCCESS;
+}
+
+bool StatSnap::callback(Dispatcher &d, TaskId t) {
+ if (getStats()) {
+ engine->getEpStore()->getUnderlying()->snapshotStats(map);
+ }
+ d.snooze(t, STATSNAP_FREQ);
+ return true;
+}
View
@@ -0,0 +1,54 @@
+/* -*- Mode: C++; tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- */
+#ifndef STATSNAP_HH
+#define STATSNAP_HH 1
+
+#include "common.hh"
+
+#include <string>
+#include <map>
+
+#include "dispatcher.hh"
+#include "stats.hh"
+
+const int STATSNAP_FREQ(60);
+
+// Forward declaration.
+class EventuallyPersistentEngine;
+
+/**
+ * Periodically take a snapshot of the stats and record it in the main
+ * DB.
+ */
+class StatSnap : public DispatcherCallback {
+public:
+ StatSnap(EventuallyPersistentEngine *e) : engine(e) { }
+
+ bool callback(Dispatcher &d, TaskId t);
+
+ /**
+ * Grab stats from the engine.
+ *
+ * @param stats the optional stat parameter
+ * @return true if the stat fetch was successful
+ */
+ bool getStats(const char *stats=NULL);
+
+ /**
+ * Get the current map of data.
+ */
+ std::map<std::string, std::string> &getMap() { return map; }
+
+ /**
+ * Description of task.
+ */
+ std::string description() {
+ std::string rv("Updating stat snapshot on disk");
+ return rv;
+ }
+
+private:
+ EventuallyPersistentEngine *engine;
+ std::map<std::string, std::string> map;
+};
+
+#endif /* STATSNAP_HH */

0 comments on commit 71a115a

Please sign in to comment.