msg/Message.cc \
msg/msg_types.cc \
common/BackTrace.cc \
- common/Logger.cc \
+ common/ProfLogger.cc \
common/ClassLibrary.cc \
common/Clock.cc \
common/Timer.cc \
common/ConfUtils.h\
common/DecayCounter.h\
common/Finisher.h\
- common/LogType.h\
- common/Logger.h\
+ common/ProfLogType.h\
+ common/ProfLogger.h\
common/MemoryModel.h\
common/Mutex.h\
common/RWLock.h\
; ---------------------
[global]
pid file = /home/sage/ceph/src/out/$name.pid
- logger dir = /home/sage/ceph/src/log
+ profiling logger dir = /home/sage/ceph/src/log
log sym dir = /home/sage/ceph/src/out
chdir = /home/sage/ceph/src
restart on core dump = false
#include "common/Cond.h"
#include "common/Mutex.h"
-#include "common/Logger.h"
+#include "common/ProfLogger.h"
// static logger
Mutex client_logger_lock("client_logger_lock");
-LogType client_logtype(l_c_first, l_c_last);
-Logger *client_logger = 0;
+ProfLogType client_logtype(l_c_first, l_c_last);
+ProfLogger *client_logger = 0;
char hostname[80];
gethostname(hostname, 79);
snprintf(s, sizeof(s), "clients.%s.%d", hostname, getpid());
- client_logger = new Logger(s, &client_logtype);
+ client_logger = new ProfLogger(s, &client_logtype);
}
client_logger_lock.Unlock();
}
class Objecter;
class ObjectCacher;
-extern class LogType client_logtype;
-extern class Logger *client_logger;
+extern class ProfLogType client_logtype;
+extern class ProfLogger *client_logger;
// ============================================
#include "include/filepath.h"
-#include "common/Logger.h"
+#include "common/ProfLogger.h"
#include <sys/types.h>
#include <sys/stat.h>
+++ /dev/null
-// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
-// vim: ts=8 sw=2 smarttab
-/*
- * Ceph - scalable distributed file system
- *
- * Copyright (C) 2004-2006 Sage Weil <sage@newdream.net>
- *
- * This is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License version 2.1, as published by the Free Software
- * Foundation. See file COPYING.
- *
- */
-
-
-#ifndef CEPH_LOGTYPE_H
-#define CEPH_LOGTYPE_H
-
-#include "include/types.h"
-
-#include <vector>
-using std::vector;
-
-class LogType {
- protected:
- int first_key, num_keys;
- vector<const char*> key_name;
- vector<bool> inc_keys, avg_keys;
-
- friend class Logger;
-
- public:
- LogType(int first, int tail) :
- first_key(first), num_keys(tail-first - 1),
- key_name(num_keys), inc_keys(num_keys), avg_keys(num_keys) {
- for (int i=0; i<num_keys; i++) {
- key_name[i] = 0;
- inc_keys[i] = 0;
- avg_keys[i] = 0;
- }
- }
- int lookup_key(int key, bool isnew=false) {
- int i = key - first_key - 1;
- assert(i >= 0 && i < num_keys);
- assert(isnew || key_name[i]);
- return i;
- }
- void add_key(int key, const char *name, bool is_inc, bool is_avg) {
- int i = lookup_key(key, true);
- assert(!key_name[i]); // only register each type once!
- key_name[i] = name;
- inc_keys[i] = is_inc;
- avg_keys[i] = is_avg;
- }
- void add_inc(int key, const char *name) {
- return add_key(key, name, true, false);
- }
- void add_set(int key, const char *name) {
- return add_key(key, name, false, false);
- }
- void add_avg(int key, const char *name) {
- return add_key(key, name, true, true);
- }
- void validate() {
- for (int i=0; i<num_keys; i++)
- assert(key_name[i]);
- }
-};
-
-#endif
+++ /dev/null
-// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
-// vim: ts=8 sw=2 smarttab
-/*
- * Ceph - scalable distributed file system
- *
- * Copyright (C) 2004-2006 Sage Weil <sage@newdream.net>
- *
- * This is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License version 2.1, as published by the Free Software
- * Foundation. See file COPYING.
- *
- */
-
-
-
-#include <string>
-
-#include "LogType.h"
-#include "Logger.h"
-
-#include <iostream>
-#include <memory>
-#include "Clock.h"
-
-#include "config.h"
-
-#include <sys/stat.h>
-#include <sys/types.h>
-
-#include "common/Timer.h"
-
-// per-process lock. lame, but this way I protect LogType too!
-Mutex logger_lock("logger_lock");
-SafeTimer logger_timer(logger_lock);
-Context *logger_event = 0;
-list<Logger*> logger_list;
-utime_t start;
-int last_flush = 0; // in seconds since start
-
-bool logger_need_reopen = true;
-bool logger_need_reset = false;
-
-static void flush_all_loggers();
-static void stop();
-
-static struct FlusherStopper {
- ~FlusherStopper() {
- stop();
- }
-} stopper;
-
-class C_FlushLoggers : public Context {
-public:
- void finish(int r) {
- if (logger_event == this) {
- logger_event = 0;
- flush_all_loggers();
- }
- }
-};
-
-
-void logger_reopen_all()
-{
- logger_need_reopen = true;
-}
-
-void logger_reset_all()
-{
- logger_need_reopen = true;
- logger_need_reset = true;
-}
-
-void logger_start()
-{
- Mutex::Locker l(logger_lock);
- logger_timer.init();
- flush_all_loggers();
-}
-
-void logger_tare(utime_t s)
-{
- Mutex::Locker l(logger_lock);
-
- generic_dout(10) << "logger_tare " << s << dendl;
-
- start = s;
-
- utime_t fromstart = g_clock.now();
- if (fromstart < start) {
- derr << "logger_tare time jumped backwards from "
- << start << " to " << fromstart << dendl;
- fromstart = start;
- }
- fromstart -= start;
- last_flush = fromstart.sec();
-}
-
-void logger_add(Logger *logger)
-{
- Mutex::Locker l(logger_lock);
-
- if (logger_list.empty()) {
- if (start == utime_t())
- start = g_clock.now();
- last_flush = 0;
- }
- logger_list.push_back(logger);
-}
-
-void logger_remove(Logger *logger)
-{
- Mutex::Locker l(logger_lock);
-
- for (list<Logger*>::iterator p = logger_list.begin();
- p != logger_list.end();
- p++) {
- if (*p == logger) {
- logger_list.erase(p);
- break;
- }
- }
-}
-
-static void flush_all_loggers()
-{
- generic_dout(20) << "flush_all_loggers" << dendl;
-
- if (!g_conf.logger)
- return;
-
- utime_t now = g_clock.now();
- utime_t fromstart = now;
- if (fromstart < start) {
- derr << "logger time jumped backwards from " << start << " to "
- << fromstart << dendl;
- //assert(0);
- start = fromstart;
- }
- fromstart -= start;
- int now_sec = fromstart.sec();
-
- // do any catching up we need to
- bool twice = now_sec - last_flush >= 2 * g_conf.logger_interval;
- again:
- generic_dout(20) << "fromstart " << fromstart << " last_flush " << last_flush << " flushing" << dendl;
-
- bool reopen = logger_need_reopen;
- bool reset = logger_need_reset;
-
- for (list<Logger*>::iterator p = logger_list.begin();
- p != logger_list.end();
- ++p)
- (*p)->_flush();
-
- // did full pass while true?
- if (reopen && logger_need_reopen)
- logger_need_reopen = false;
- if (reset && logger_need_reset)
- logger_need_reset = false;
-
- last_flush = now_sec - (now_sec % g_conf.logger_interval);
- if (twice) {
- twice = false;
- goto again;
- }
-
- // schedule next flush event
- utime_t next;
- next.sec_ref() = start.sec() + last_flush + g_conf.logger_interval;
- next.nsec_ref() = start.nsec();
- generic_dout(20) << "logger now=" << now
- << " start=" << start
- << " next=" << next
- << dendl;
- logger_event = new C_FlushLoggers;
- logger_timer.add_event_at(next, logger_event);
-}
-
-static void stop()
-{
- logger_lock.Lock();
- logger_timer.shutdown();
- logger_lock.Unlock();
-}
-
-
-
-// ---------
-
-void Logger::_open_log()
-{
- struct stat st;
-
- filename = "";
- if (g_conf.chdir && g_conf.chdir[0] && g_conf.logger_dir[0] != '/') {
- char cwd[PATH_MAX];
- char *c = getcwd(cwd, sizeof(cwd));
- assert(c);
- filename = c;
- filename += "/";
- }
-
- filename = g_conf.logger_dir;
-
- // make (feeble) attempt to create logger_dir
- if (::stat(filename.c_str(), &st))
- ::mkdir(filename.c_str(), 0750);
-
- filename += "/";
- if (g_conf.logger_subdir) {
- filename += g_conf.logger_subdir;
- ::mkdir( filename.c_str(), 0755 ); // make sure dir exists
- filename += "/";
- }
- filename += name;
-
- generic_dout(10) << "Logger::_open " << filename << dendl;
- if (out.is_open())
- out.close();
- out.open(filename.c_str(),
- (need_reset || logger_need_reset) ? ofstream::out : ofstream::out|ofstream::app);
- if (!out.is_open()) {
- generic_dout(10) << "failed to open '" << filename << "'" << dendl;
- return; // we fail
- }
-
- // success
- need_open = false;
-}
-
-
-Logger::~Logger()
-{
- Mutex::Locker l(logger_lock);
-
- _flush();
- out.close();
- logger_list.remove(this); // slow, but rare.
- if (logger_list.empty())
- logger_event = 0; // stop the timer events.
-}
-
-void Logger::reopen()
-{
- Mutex::Locker l(logger_lock);
- need_open = true;
-}
-
-void Logger::reset()
-{
- Mutex::Locker l(logger_lock);
- need_open = true;
- need_reset = true;
-}
-
-
-void Logger::_flush()
-{
- if (need_open || logger_need_reopen)
- _open_log();
- if (need_reset || logger_need_reset) {
- // reset the counters
- for (int i=0; i<type->num_keys; i++) {
- this->vals[i] = 0;
- this->fvals[i] = 0;
- }
- need_reset = false;
- }
-
- generic_dout(20) << "Logger::_flush on " << this << dendl;
-
- // header?
- wrote_header_last++;
- if (wrote_header_last > 10) {
- out << "#" << type->num_keys;
- for (int i=0; i<type->num_keys; i++) {
- out << "\t" << (type->key_name[i] ? type->key_name[i] : "???");
- if (type->avg_keys[i])
- out << "\t(n)\t(var)";
- }
- out << std::endl; //out << "\t (" << type->keymap.size() << ")" << endl;
- wrote_header_last = 0;
- }
-
- // write line to log
- out << last_flush;
- for (int i=0; i<type->num_keys; i++) {
- if (type->avg_keys[i]) {
- if (vals[i] > 0) {
- double avg = (fvals[i] / (double)vals[i]);
- double var = 0.0;
- if (g_conf.logger_calc_variance &&
- (unsigned)vals[i] == vals_to_avg[i].size()) {
- for (vector<double>::iterator p = vals_to_avg[i].begin(); p != vals_to_avg[i].end(); ++p)
- var += (avg - *p) * (avg - *p);
- }
- char s[256];
- snprintf(s, sizeof(s), "\t%.5lf\t%lld\t%.5lf", avg, (long long int)vals[i], var);
- out << s;
- } else
- out << "\t0\t0\t0";
- } else {
- if (fvals[i] > 0 && vals[i] == 0)
- out << "\t" << fvals[i];
- else {
- //cout << this << " p " << i << " and size is " << vals.size() << std::endl;
- out << "\t" << vals[i];
- }
- }
- }
-
- // reset the counters
- for (int i=0; i<type->num_keys; i++) {
- if (type->inc_keys[i]) {
- this->vals[i] = 0;
- this->fvals[i] = 0;
- }
- }
-
- out << std::endl;
-}
-
-
-
-int64_t Logger::inc(int key, int64_t v)
-{
- if (!g_conf.logger)
- return 0;
- logger_lock.Lock();
- int i = type->lookup_key(key);
- vals[i] += v;
- int64_t r = vals[i];
- logger_lock.Unlock();
- return r;
-}
-
-double Logger::finc(int key, double v)
-{
- if (!g_conf.logger)
- return 0;
- logger_lock.Lock();
- int i = type->lookup_key(key);
- fvals[i] += v;
- double r = fvals[i];
- logger_lock.Unlock();
- return r;
-}
-
-int64_t Logger::set(int key, int64_t v)
-{
- if (!g_conf.logger)
- return 0;
- logger_lock.Lock();
- int i = type->lookup_key(key);
- //cout << this << " set " << i << " to " << v << std::endl;
- int64_t r = vals[i] = v;
- logger_lock.Unlock();
- return r;
-}
-
-
-double Logger::fset(int key, double v)
-{
- if (!g_conf.logger)
- return 0;
- logger_lock.Lock();
- int i = type->lookup_key(key);
- //cout << this << " fset " << i << " to " << v << std::endl;
- double r = fvals[i] = v;
- logger_lock.Unlock();
- return r;
-}
-
-double Logger::favg(int key, double v)
-{
- if (!g_conf.logger)
- return 0;
- logger_lock.Lock();
- int i = type->lookup_key(key);
- vals[i]++;
- double r = fvals[i] += v;
- if (g_conf.logger_calc_variance)
- vals_to_avg[i].push_back(v);
- logger_lock.Unlock();
- return r;
-}
-
-int64_t Logger::get(int key)
-{
- if (!g_conf.logger)
- return 0;
- logger_lock.Lock();
- int i = type->lookup_key(key);
- int64_t r = 0;
- if (i >= 0 && i < (int)vals.size())
- r = vals[i];
- logger_lock.Unlock();
- return r;
-}
-
+++ /dev/null
-// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
-// vim: ts=8 sw=2 smarttab
-/*
- * Ceph - scalable distributed file system
- *
- * Copyright (C) 2004-2006 Sage Weil <sage@newdream.net>
- *
- * This is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License version 2.1, as published by the Free Software
- * Foundation. See file COPYING.
- *
- */
-
-
-#ifndef CEPH_LOGGER_H
-#define CEPH_LOGGER_H
-
-#include "include/types.h"
-#include "Clock.h"
-
-#include <string>
-#include <fstream>
-#include <vector>
-using std::vector;
-using std::string;
-using std::ofstream;
-
-
-#include "LogType.h"
-
-extern void logger_reopen_all();
-extern void logger_reset_all();
-extern void logger_add(class Logger *l);
-extern void logger_remove(class Logger *l);
-extern void logger_tare(utime_t when);
-extern void logger_start();
-
-class Logger {
- protected:
- // my type
- string name, filename;
- LogType *type;
-
- bool need_open;
- bool need_reset;
- bool need_close;
-
- // values for this instance
- vector<int64_t> vals;
- vector<double> fvals;
- vector< vector<double> > vals_to_avg; // for calculating variance
-
- ofstream out;
-
- // what i've written
- //int last_logged;
- int wrote_header_last;
-
- void _open_log();
-
- public:
- Logger(string n, LogType *t) :
- name(n), type(t),
- need_open(true), need_reset(false), need_close(false),
- vals(t->num_keys), fvals(t->num_keys), vals_to_avg(t->num_keys),
- wrote_header_last(10000) { }
- ~Logger();
-
- int64_t inc(int f, int64_t v = 1);
- int64_t set(int f, int64_t v);
- int64_t get(int f);
-
- double fset(int f, double v);
- double finc(int f, double v);
- double favg(int f, double v);
-
- void _flush();
-
- void reopen();
- void reset();
- void close();
-};
-
-#endif
--- /dev/null
+// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
+// vim: ts=8 sw=2 smarttab
+/*
+ * Ceph - scalable distributed file system
+ *
+ * Copyright (C) 2004-2006 Sage Weil <sage@newdream.net>
+ *
+ * This is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software
+ * Foundation. See file COPYING.
+ *
+ */
+
+
+#ifndef CEPH_LOGTYPE_H
+#define CEPH_LOGTYPE_H
+
+#include "include/types.h"
+
+#include <vector>
+using std::vector;
+
+class ProfLogType {
+ protected:
+ int first_key, num_keys;
+ vector<const char*> key_name;
+ vector<bool> inc_keys, avg_keys;
+
+ friend class ProfLogger;
+
+ public:
+ ProfLogType(int first, int tail) :
+ first_key(first), num_keys(tail-first - 1),
+ key_name(num_keys), inc_keys(num_keys), avg_keys(num_keys) {
+ for (int i=0; i<num_keys; i++) {
+ key_name[i] = 0;
+ inc_keys[i] = 0;
+ avg_keys[i] = 0;
+ }
+ }
+ int lookup_key(int key, bool isnew=false) {
+ int i = key - first_key - 1;
+ assert(i >= 0 && i < num_keys);
+ assert(isnew || key_name[i]);
+ return i;
+ }
+ void add_key(int key, const char *name, bool is_inc, bool is_avg) {
+ int i = lookup_key(key, true);
+ assert(!key_name[i]); // only register each type once!
+ key_name[i] = name;
+ inc_keys[i] = is_inc;
+ avg_keys[i] = is_avg;
+ }
+ void add_inc(int key, const char *name) {
+ return add_key(key, name, true, false);
+ }
+ void add_set(int key, const char *name) {
+ return add_key(key, name, false, false);
+ }
+ void add_avg(int key, const char *name) {
+ return add_key(key, name, true, true);
+ }
+ void validate() {
+ for (int i=0; i<num_keys; i++)
+ assert(key_name[i]);
+ }
+};
+
+#endif
--- /dev/null
+// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
+// vim: ts=8 sw=2 smarttab
+/*
+ * Ceph - scalable distributed file system
+ *
+ * Copyright (C) 2004-2006 Sage Weil <sage@newdream.net>
+ *
+ * This is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software
+ * Foundation. See file COPYING.
+ *
+ */
+
+
+
+#include <string>
+
+#include "ProfLogType.h"
+#include "ProfLogger.h"
+
+#include <iostream>
+#include <memory>
+#include "Clock.h"
+
+#include "config.h"
+
+#include <sys/stat.h>
+#include <sys/types.h>
+
+#include "common/Timer.h"
+
+// per-process lock. lame, but this way I protect ProfLogType too!
+Mutex prof_logger_lock("prof_logger_lock");
+SafeTimer logger_timer(prof_logger_lock);
+Context *logger_event = 0;
+list<ProfLogger*> logger_list;
+utime_t start;
+int last_flush = 0; // in seconds since start
+
+bool logger_need_reopen = true;
+bool logger_need_reset = false;
+
+static void flush_all_loggers();
+static void stop();
+
+static struct FlusherStopper {
+ ~FlusherStopper() {
+ stop();
+ }
+} stopper;
+
+class C_FlushProfLoggers : public Context {
+public:
+ void finish(int r) {
+ if (logger_event == this) {
+ logger_event = 0;
+ flush_all_loggers();
+ }
+ }
+};
+
+
+void logger_reopen_all()
+{
+ logger_need_reopen = true;
+}
+
+void logger_reset_all()
+{
+ logger_need_reopen = true;
+ logger_need_reset = true;
+}
+
+void logger_start()
+{
+ Mutex::Locker l(prof_logger_lock);
+ logger_timer.init();
+ flush_all_loggers();
+}
+
+void logger_tare(utime_t s)
+{
+ Mutex::Locker l(prof_logger_lock);
+
+ generic_dout(10) << "logger_tare " << s << dendl;
+
+ start = s;
+
+ utime_t fromstart = g_clock.now();
+ if (fromstart < start) {
+ derr << "logger_tare time jumped backwards from "
+ << start << " to " << fromstart << dendl;
+ fromstart = start;
+ }
+ fromstart -= start;
+ last_flush = fromstart.sec();
+}
+
+void logger_add(ProfLogger *logger)
+{
+ Mutex::Locker l(prof_logger_lock);
+
+ if (logger_list.empty()) {
+ if (start == utime_t())
+ start = g_clock.now();
+ last_flush = 0;
+ }
+ logger_list.push_back(logger);
+}
+
+void logger_remove(ProfLogger *logger)
+{
+ Mutex::Locker l(prof_logger_lock);
+
+ for (list<ProfLogger*>::iterator p = logger_list.begin();
+ p != logger_list.end();
+ p++) {
+ if (*p == logger) {
+ logger_list.erase(p);
+ break;
+ }
+ }
+}
+
+static void flush_all_loggers()
+{
+ generic_dout(20) << "flush_all_loggers" << dendl;
+
+ if (!g_conf.profiling_logger)
+ return;
+
+ utime_t now = g_clock.now();
+ utime_t fromstart = now;
+ if (fromstart < start) {
+ derr << "logger time jumped backwards from " << start << " to "
+ << fromstart << dendl;
+ //assert(0);
+ start = fromstart;
+ }
+ fromstart -= start;
+ int now_sec = fromstart.sec();
+
+ // do any catching up we need to
+ bool twice = now_sec - last_flush >= 2 * g_conf.profiling_logger_interval;
+ again:
+ generic_dout(20) << "fromstart " << fromstart << " last_flush " << last_flush << " flushing" << dendl;
+
+ bool reopen = logger_need_reopen;
+ bool reset = logger_need_reset;
+
+ for (list<ProfLogger*>::iterator p = logger_list.begin();
+ p != logger_list.end();
+ ++p)
+ (*p)->_flush();
+
+ // did full pass while true?
+ if (reopen && logger_need_reopen)
+ logger_need_reopen = false;
+ if (reset && logger_need_reset)
+ logger_need_reset = false;
+
+ last_flush = now_sec - (now_sec % g_conf.profiling_logger_interval);
+ if (twice) {
+ twice = false;
+ goto again;
+ }
+
+ // schedule next flush event
+ utime_t next;
+ next.sec_ref() = start.sec() + last_flush + g_conf.profiling_logger_interval;
+ next.nsec_ref() = start.nsec();
+ generic_dout(20) << "logger now=" << now
+ << " start=" << start
+ << " next=" << next
+ << dendl;
+ logger_event = new C_FlushProfLoggers;
+ logger_timer.add_event_at(next, logger_event);
+}
+
+static void stop()
+{
+ prof_logger_lock.Lock();
+ logger_timer.shutdown();
+ prof_logger_lock.Unlock();
+}
+
+
+
+// ---------
+
+void ProfLogger::_open_log()
+{
+ struct stat st;
+
+ filename = "";
+ if (g_conf.chdir && g_conf.chdir[0] && g_conf.profiling_logger_dir[0] != '/') {
+ char cwd[PATH_MAX];
+ char *c = getcwd(cwd, sizeof(cwd));
+ assert(c);
+ filename = c;
+ filename += "/";
+ }
+
+ filename = g_conf.profiling_logger_dir;
+
+ // make (feeble) attempt to create logger_dir
+ if (::stat(filename.c_str(), &st))
+ ::mkdir(filename.c_str(), 0750);
+
+ filename += "/";
+ if (g_conf.profiling_logger_subdir) {
+ filename += g_conf.profiling_logger_subdir;
+ ::mkdir( filename.c_str(), 0755 ); // make sure dir exists
+ filename += "/";
+ }
+ filename += name;
+
+ generic_dout(10) << "ProfLogger::_open " << filename << dendl;
+ if (out.is_open())
+ out.close();
+ out.open(filename.c_str(),
+ (need_reset || logger_need_reset) ? ofstream::out : ofstream::out|ofstream::app);
+ if (!out.is_open()) {
+ generic_dout(10) << "failed to open '" << filename << "'" << dendl;
+ return; // we fail
+ }
+
+ // success
+ need_open = false;
+}
+
+
+ProfLogger::~ProfLogger()
+{
+ Mutex::Locker l(prof_logger_lock);
+
+ _flush();
+ out.close();
+ logger_list.remove(this); // slow, but rare.
+ if (logger_list.empty())
+ logger_event = 0; // stop the timer events.
+}
+
+void ProfLogger::reopen()
+{
+ Mutex::Locker l(prof_logger_lock);
+ need_open = true;
+}
+
+void ProfLogger::reset()
+{
+ Mutex::Locker l(prof_logger_lock);
+ need_open = true;
+ need_reset = true;
+}
+
+
+void ProfLogger::_flush()
+{
+ if (need_open || logger_need_reopen)
+ _open_log();
+ if (need_reset || logger_need_reset) {
+ // reset the counters
+ for (int i=0; i<type->num_keys; i++) {
+ this->vals[i] = 0;
+ this->fvals[i] = 0;
+ }
+ need_reset = false;
+ }
+
+ generic_dout(20) << "ProfLogger::_flush on " << this << dendl;
+
+ // header?
+ wrote_header_last++;
+ if (wrote_header_last > 10) {
+ out << "#" << type->num_keys;
+ for (int i=0; i<type->num_keys; i++) {
+ out << "\t" << (type->key_name[i] ? type->key_name[i] : "???");
+ if (type->avg_keys[i])
+ out << "\t(n)\t(var)";
+ }
+ out << std::endl; //out << "\t (" << type->keymap.size() << ")" << endl;
+ wrote_header_last = 0;
+ }
+
+ // write line to log
+ out << last_flush;
+ for (int i=0; i<type->num_keys; i++) {
+ if (type->avg_keys[i]) {
+ if (vals[i] > 0) {
+ double avg = (fvals[i] / (double)vals[i]);
+ double var = 0.0;
+ if (g_conf.profiling_logger_calc_variance &&
+ (unsigned)vals[i] == vals_to_avg[i].size()) {
+ for (vector<double>::iterator p = vals_to_avg[i].begin(); p != vals_to_avg[i].end(); ++p)
+ var += (avg - *p) * (avg - *p);
+ }
+ char s[256];
+ snprintf(s, sizeof(s), "\t%.5lf\t%lld\t%.5lf", avg, (long long int)vals[i], var);
+ out << s;
+ } else
+ out << "\t0\t0\t0";
+ } else {
+ if (fvals[i] > 0 && vals[i] == 0)
+ out << "\t" << fvals[i];
+ else {
+ //cout << this << " p " << i << " and size is " << vals.size() << std::endl;
+ out << "\t" << vals[i];
+ }
+ }
+ }
+
+ // reset the counters
+ for (int i=0; i<type->num_keys; i++) {
+ if (type->inc_keys[i]) {
+ this->vals[i] = 0;
+ this->fvals[i] = 0;
+ }
+ }
+
+ out << std::endl;
+}
+
+
+
+int64_t ProfLogger::inc(int key, int64_t v)
+{
+ if (!g_conf.profiling_logger)
+ return 0;
+ prof_logger_lock.Lock();
+ int i = type->lookup_key(key);
+ vals[i] += v;
+ int64_t r = vals[i];
+ prof_logger_lock.Unlock();
+ return r;
+}
+
+double ProfLogger::finc(int key, double v)
+{
+ if (!g_conf.profiling_logger)
+ return 0;
+ prof_logger_lock.Lock();
+ int i = type->lookup_key(key);
+ fvals[i] += v;
+ double r = fvals[i];
+ prof_logger_lock.Unlock();
+ return r;
+}
+
+int64_t ProfLogger::set(int key, int64_t v)
+{
+ if (!g_conf.profiling_logger)
+ return 0;
+ prof_logger_lock.Lock();
+ int i = type->lookup_key(key);
+ //cout << this << " set " << i << " to " << v << std::endl;
+ int64_t r = vals[i] = v;
+ prof_logger_lock.Unlock();
+ return r;
+}
+
+
+double ProfLogger::fset(int key, double v)
+{
+ if (!g_conf.profiling_logger)
+ return 0;
+ prof_logger_lock.Lock();
+ int i = type->lookup_key(key);
+ //cout << this << " fset " << i << " to " << v << std::endl;
+ double r = fvals[i] = v;
+ prof_logger_lock.Unlock();
+ return r;
+}
+
+double ProfLogger::favg(int key, double v)
+{
+ if (!g_conf.profiling_logger)
+ return 0;
+ prof_logger_lock.Lock();
+ int i = type->lookup_key(key);
+ vals[i]++;
+ double r = fvals[i] += v;
+ if (g_conf.profiling_logger_calc_variance)
+ vals_to_avg[i].push_back(v);
+ prof_logger_lock.Unlock();
+ return r;
+}
+
+int64_t ProfLogger::get(int key)
+{
+ if (!g_conf.profiling_logger)
+ return 0;
+ prof_logger_lock.Lock();
+ int i = type->lookup_key(key);
+ int64_t r = 0;
+ if (i >= 0 && i < (int)vals.size())
+ r = vals[i];
+ prof_logger_lock.Unlock();
+ return r;
+}
+
--- /dev/null
+// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
+// vim: ts=8 sw=2 smarttab
+/*
+ * Ceph - scalable distributed file system
+ *
+ * Copyright (C) 2004-2006 Sage Weil <sage@newdream.net>
+ *
+ * This is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software
+ * Foundation. See file COPYING.
+ *
+ */
+
+
+#ifndef CEPH_LOGGER_H
+#define CEPH_LOGGER_H
+
+#include "common/Clock.h"
+#include "common/ProfLogType.h"
+#include "include/types.h"
+
+#include <string>
+#include <fstream>
+#include <vector>
+
+extern void logger_reopen_all();
+extern void logger_reset_all();
+extern void logger_add(class ProfLogger *l);
+extern void logger_remove(class ProfLogger *l);
+extern void logger_tare(utime_t when);
+extern void logger_start();
+
+class ProfLogger {
+ protected:
+ // my type
+ std::string name, filename;
+ ProfLogType *type;
+
+ bool need_open;
+ bool need_reset;
+ bool need_close;
+
+ // values for this instance
+ std::vector<int64_t> vals;
+ std::vector<double> fvals;
+ std::vector< std::vector<double> > vals_to_avg; // for calculating variance
+
+ std::ofstream out;
+
+ // what i've written
+ //int last_logged;
+ int wrote_header_last;
+
+ void _open_log();
+
+ public:
+ ProfLogger(const std::string &n, ProfLogType *t) :
+ name(n), type(t),
+ need_open(true), need_reset(false), need_close(false),
+ vals(t->num_keys), fvals(t->num_keys), vals_to_avg(t->num_keys),
+ wrote_header_last(10000) { }
+ ~ProfLogger();
+
+ int64_t inc(int f, int64_t v = 1);
+ int64_t set(int f, int64_t v);
+ int64_t get(int f);
+
+ double fset(int f, double v);
+ double finc(int f, double v);
+ double favg(int f, double v);
+
+ void _flush();
+
+ void reopen();
+ void reset();
+ void close();
+};
+
+#endif
cout << TEXT_YELLOW << " ** testing and review. Do not trust it with important data. **" << TEXT_NORMAL << std::endl;
g_conf.daemonize = true;
- g_conf.logger = true;
+ g_conf.profiling_logger = true;
} else {
g_conf.pid_file = 0;
}
*/
#include "common/BackTrace.h"
-#include "common/Logger.h"
+#include "common/ProfLogger.h"
#include "common/debug.h"
#include "common/signal.h"
#include "config.h"
#include "common/BackTrace.h"
#include "common/Clock.h"
#include "common/ConfUtils.h"
-#include "common/Logger.h"
+#include "common/ProfLogger.h"
#include "common/common_init.h"
#include "common/dyn_snprintf.h"
#include "config.h"
OPTION(tcmalloc_profiler_run, 0, OPT_BOOL, false),
OPTION(profiler_allocation_interval, 0, OPT_INT, 1073741824),
OPTION(profiler_highwater_interval, 0, OPT_INT, 104857600),
- OPTION(logger, 0, OPT_BOOL, false),
- OPTION(logger_interval, 0, OPT_INT, 1),
- OPTION(logger_calc_variance, 0, OPT_BOOL, false),
- OPTION(logger_subdir, 0, OPT_STR, 0),
- OPTION(logger_dir, 0, OPT_STR, "/var/log/ceph/stat"),
+ OPTION(profiling_logger, 0, OPT_BOOL, false),
+ OPTION(profiling_logger_interval, 0, OPT_INT, 1),
+ OPTION(profiling_logger_calc_variance, 0, OPT_BOOL, false),
+ OPTION(profiling_logger_subdir, 0, OPT_STR, 0),
+ OPTION(profiling_logger_dir, 0, OPT_STR, "/var/log/ceph/stat"),
OPTION(log_file, 0, OPT_STR, 0),
OPTION(log_dir, 0, OPT_STR, "/var/log/ceph"),
OPTION(log_sym_dir, 0, OPT_STR, 0),
int profiler_allocation_interval;
int profiler_highwater_interval;
- // logger (profiling)
- bool logger;
- int logger_interval;
- bool logger_calc_variance;
- const char *logger_subdir;
- const char *logger_dir;
+ // profiling logger
+ bool profiling_logger;
+ int profiling_logger_interval;
+ bool profiling_logger_calc_variance;
+ const char *profiling_logger_subdir;
+ const char *profiling_logger_dir;
const char *log_file;
const char *log_dir;
#include "msg/Message.h"
#include "msg/Messenger.h"
-#include "common/Logger.h"
+#include "common/ProfLogger.h"
#include "common/MemoryModel.h"
#include "osdc/Journaler.h"
#include "osdc/Filer.h"
#include "messages/MClientRequest.h"
#include "messages/MMDSSlaveRequest.h"
-class Logger;
+class ProfLogger;
class MDS;
class Session;
#include "osdc/Journaler.h"
-#include "common/LogType.h"
-#include "common/Logger.h"
+#include "common/ProfLogType.h"
+#include "common/ProfLogger.h"
#include "events/ESubtreeMap.h"
// cons/des
-LogType mdlog_logtype(l_mdl_first, l_mdl_last);
+ProfLogType mdlog_logtype(l_mdl_first, l_mdl_last);
MDLog::~MDLog()
// logger
char name[80];
snprintf(name, sizeof(name), "mds.%s.log", g_conf.id);
- logger = new Logger(name, &mdlog_logtype);
+ logger = new ProfLogger(name, &mdlog_logtype);
logger_add(logger);
}
class LogSegment;
class ESubtreeMap;
-class Logger;
+class ProfLogger;
#include <map>
using std::map;
inodeno_t ino;
Journaler *journaler;
- Logger *logger;
+ ProfLogger *logger;
// -- replay --
#include "InoTable.h"
-#include "common/Logger.h"
-#include "common/LogType.h"
+#include "common/ProfLogger.h"
+#include "common/ProfLogType.h"
#include "common/Timer.h"
void MDS::open_logger()
{
- static LogType mds_logtype(l_mds_first, l_mds_last);
- static LogType mdm_logtype(l_mdm_first, l_mdm_last);
+ static ProfLogType mds_logtype(l_mds_first, l_mds_last);
+ static ProfLogType mdm_logtype(l_mdm_first, l_mdm_last);
static bool didit = false;
if (!didit) {
char name[80];
snprintf(name, sizeof(name), "mds.%s.%llu.log", g_conf.id,
(unsigned long long) monc->get_global_id());
- logger = new Logger(name, (LogType*)&mds_logtype);
+ logger = new ProfLogger(name, (ProfLogType*)&mds_logtype);
logger_add(logger);
snprintf(name, sizeof(name), "mds.%s.%llu.mem.log", g_conf.id,
(unsigned long long) monc->get_global_id());
- mlogger = new Logger(name, (LogType*)&mdm_logtype);
+ mlogger = new ProfLogger(name, (ProfLogType*)&mdm_logtype);
logger_add(mlogger);
mdlog->open_logger();
#include "include/types.h"
#include "include/Context.h"
#include "common/DecayCounter.h"
-#include "common/Logger.h"
+#include "common/ProfLogger.h"
#include "common/Mutex.h"
#include "common/Cond.h"
#include "common/Timer.h"
MDSTableClient *get_table_client(int t);
MDSTableServer *get_table_server(int t);
- Logger *logger, *mlogger;
+ ProfLogger *logger, *mlogger;
int orig_argc;
const char **orig_argv;
#include "include/filepath.h"
#include "common/Timer.h"
-#include "common/Logger.h"
-#include "common/LogType.h"
+#include "common/ProfLogger.h"
+#include "common/ProfLogType.h"
#include <errno.h>
#include <fcntl.h>
void Server::open_logger()
{
- static LogType mdserver_logtype(l_mdss_first, l_mdss_last);
+ static ProfLogType mdserver_logtype(l_mdss_first, l_mdss_last);
static bool didit = false;
if (!didit) {
didit = true;
char name[80];
snprintf(name, sizeof(name), "mds.%s.server.log", g_conf.id);
- logger = new Logger(name, &mdserver_logtype);
+ logger = new ProfLogger(name, &mdserver_logtype);
logger_add(logger);
}
#include "MDS.h"
-class Logger;
+class ProfLogger;
class LogEvent;
class MDRequest;
class Mutation;
MDCache *mdcache;
MDLog *mdlog;
Messenger *messenger;
- Logger *logger;
+ ProfLogger *logger;
public:
int failed_reconnects;
#include "messages/MWatchNotify.h"
-#include "common/Logger.h"
-#include "common/LogType.h"
+#include "common/ProfLogger.h"
+#include "common/ProfLogType.h"
#include "common/Timer.h"
#include "common/LogClient.h"
{
dout(10) << "open_logger" << dendl;
- static LogType osd_logtype(l_osd_first, l_osd_last);
+ static ProfLogType osd_logtype(l_osd_first, l_osd_last);
static bool didit = false;
if (!didit) {
didit = true;
char name[80];
snprintf(name, sizeof(name), "osd.%d.log", whoami);
- logger = new Logger(name, (LogType*)&osd_logtype);
+ logger = new ProfLogger(name, (ProfLogType*)&osd_logtype);
logger_add(logger);
if (osdmap->get_epoch() > 0)
class Messenger;
class Message;
class MonClient;
-class Logger;
+class ProfLogger;
class ObjectStore;
class OSDMap;
class MLog;
Messenger *cluster_messenger;
Messenger *client_messenger;
MonClient *monc;
- Logger *logger;
+ ProfLogger *logger;
bool logger_started;
ObjectStore *store;
#include "RAID4PG.h"
#include "OSD.h"
-#include "common/Logger.h"
+#include "common/ProfLogger.h"
#include "messages/MOSDOp.h"
#include "messages/MOSDOpReply.h"
#include "common/arch.h"
#include "common/errno.h"
-#include "common/Logger.h"
+#include "common/ProfLogger.h"
#include "messages/MOSDOp.h"
#include "messages/MOSDOpReply.h"
#include "Journaler.h"
#include "include/Context.h"
-#include "common/Logger.h"
+#include "common/ProfLogger.h"
#include "msg/Messenger.h"
#include "config.h"
#include <map>
class Context;
-class Logger;
+class ProfLogger;
class Journaler {
Objecter *objecter;
Filer filer;
- Logger *logger;
+ ProfLogger *logger;
int logger_key_lat;
SafeTimer *timer;
}
public:
- Journaler(inodeno_t ino_, int pool, const char *mag, Objecter *obj, Logger *l, int lkey, SafeTimer *tim) :
+ Journaler(inodeno_t ino_, int pool, const char *mag, Objecter *obj, ProfLogger *l, int lkey, SafeTimer *tim) :
last_written(mag), last_committed(mag),
ino(ino_), pg_pool(pool), readonly(false), magic(mag),
objecter(obj), filer(objecter), logger(l), logger_key_lat(lkey),
log dir = out
log per instance = true
log sym history = 100
- logger = true
- logger dir = log
+ profiling logger = true
+ profiling logger dir = log
chdir = ""
pid file = out/\$name.pid
$extra_conf