Ceph rgw CephContext _log属性
_log是CephContext类的属性,他代表一个线程实例,主要用于日志的处理,在CephContext的对象的实例化过程中会初始化该对象并开启该线程。
log线程的主要逻辑如下:
void *Log::entry()
{
pthread_mutex_lock(&m_queue_mutex);
m_queue_mutex_holder = pthread_self();//获取线程自身的ID
//log线程在运行且有新的日志记录写入到m_new中才刷新日志(持久化)
while (!m_stop) {
if (!m_new.empty()) {
m_queue_mutex_holder = 0;
pthread_mutex_unlock(&m_queue_mutex);
flush();
pthread_mutex_lock(&m_queue_mutex);
m_queue_mutex_holder = pthread_self();
continue;
}
pthread_cond_wait(&m_cond_flusher, &m_queue_mutex);
}
m_queue_mutex_holder = 0;
pthread_mutex_unlock(&m_queue_mutex);
flush();
return NULL;
}
void Log::flush()
{
pthread_mutex_lock(&m_flush_mutex);
m_flush_mutex_holder = pthread_self();
pthread_mutex_lock(&m_queue_mutex);
m_queue_mutex_holder = pthread_self();
EntryQueue t;
t.swap(m_new);
pthread_cond_broadcast(&m_cond_loggers);
m_queue_mutex_holder = 0;
pthread_mutex_unlock(&m_queue_mutex);
_flush(&t, &m_recent, false);
// trim
while (m_recent.m_len > m_max_recent) {
delete m_recent.dequeue();
}
m_flush_mutex_holder = 0;
pthread_mutex_unlock(&m_flush_mutex);
}
void Log::_flush(EntryQueue *t, EntryQueue *requeue, bool crash)
{
Entry *e;
char buf[80];
while ((e = t->dequeue()) != NULL) {
unsigned sub = e->m_subsys;
bool should_log = crash || m_subs->get_log_level(sub) >= e->m_prio;
bool do_fd = m_fd >= 0 && should_log;
bool do_syslog = m_syslog_crash >= e->m_prio && should_log;
bool do_stderr = m_stderr_crash >= e->m_prio && should_log;
if (do_fd || do_syslog || do_stderr) {
int buflen = 0;
if (crash)
buflen += snprintf(buf, sizeof(buf), "%6d> ", -t->m_len);
buflen += e->m_stamp.sprintf(buf + buflen, sizeof(buf)-buflen);
buflen += snprintf(buf + buflen, sizeof(buf)-buflen, " %lx %2d ",
(unsigned long)e->m_thread, e->m_prio);
// FIXME: this is slow
string s = e->get_str();
//写到日志文件中
if (do_fd) {
int r = safe_write(m_fd, buf, buflen);
if (r >= 0)
r = safe_write(m_fd, s.data(), s.size());
if (r >= 0)
r = write(m_fd, "\n", 1);
if (r < 0)
cerr << "problem writing to " << m_log_file << ": " << cpp_strerror(r) << std::endl;
}
//调用系统日志,系统调用写日志
if (do_syslog) {
syslog(LOG_USER, "%s%s", buf, s.c_str());
}
//日志打印到标准错误终端。
if (do_stderr) {
cerr << buf << s << std::endl;
}
}
//把打印的日志条目,保存到Mrecent队列中。
requeue->enqueue(e);
}
}