logd: rename LogTimes -> LogReaderThread

LogTimes has evolved from being simply a store of the last timestamp
that each reader has read to being a class representing an individual
reader thread, including the thread function, so name it
appropriately.

Test: logging unit tests
Change-Id: I6914824376a6ff1f7509e657fa4dc044ead62954
This commit is contained in:
Tom Cherry 2020-05-04 12:53:36 -07:00
parent 794acfc0fe
commit 6ec71e9253
8 changed files with 77 additions and 97 deletions

View File

@ -36,9 +36,9 @@ cc_library_static {
"CommandListener.cpp",
"LogListener.cpp",
"LogReader.cpp",
"LogReaderThread.cpp",
"LogBuffer.cpp",
"LogBufferElement.cpp",
"LogTimes.cpp",
"LogStatistics.cpp",
"LogWhiteBlackList.cpp",
"libaudit.c",

View File

@ -93,16 +93,16 @@ void LogBuffer::init() {
}
// Release any sleeping reader threads to dump their current content.
LogTimeEntry::wrlock();
LogReaderThread::wrlock();
LastLogTimes::iterator times = mTimes.begin();
while (times != mTimes.end()) {
LogTimeEntry* entry = times->get();
LogReaderThread* entry = times->get();
entry->triggerReader_Locked();
times++;
}
LogTimeEntry::unlock();
LogReaderThread::unlock();
}
LogBuffer::LogBuffer(LastLogTimes* times, LogTags* tags, PruneList* prune)
@ -579,7 +579,7 @@ class LogBufferElementLast {
// If the selected reader is blocking our pruning progress, decide on
// what kind of mitigation is necessary to unblock the situation.
void LogBuffer::kickMe(LogTimeEntry* me, log_id_t id, unsigned long pruneRows) {
void LogBuffer::kickMe(LogReaderThread* me, log_id_t id, unsigned long pruneRows) {
if (stats.sizes(id) > (2 * log_buffer_size(id))) { // +100%
// A misbehaving or slow reader has its connection
// dropped if we hit too much memory pressure.
@ -647,16 +647,16 @@ void LogBuffer::kickMe(LogTimeEntry* me, log_id_t id, unsigned long pruneRows) {
// LogBuffer::wrlock() must be held when this function is called.
//
bool LogBuffer::prune(log_id_t id, unsigned long pruneRows, uid_t caller_uid) {
LogTimeEntry* oldest = nullptr;
LogReaderThread* oldest = nullptr;
bool busy = false;
bool clearAll = pruneRows == ULONG_MAX;
LogTimeEntry::rdlock();
LogReaderThread::rdlock();
// Region locked?
LastLogTimes::iterator times = mTimes.begin();
while (times != mTimes.end()) {
LogTimeEntry* entry = times->get();
LogReaderThread* entry = times->get();
if (entry->isWatching(id) &&
(!oldest || (oldest->mStart > entry->mStart) ||
((oldest->mStart == entry->mStart) &&
@ -692,7 +692,7 @@ bool LogBuffer::prune(log_id_t id, unsigned long pruneRows, uid_t caller_uid) {
break;
}
}
LogTimeEntry::unlock();
LogReaderThread::unlock();
return busy;
}
@ -953,7 +953,7 @@ bool LogBuffer::prune(log_id_t id, unsigned long pruneRows, uid_t caller_uid) {
}
}
LogTimeEntry::unlock();
LogReaderThread::unlock();
return (pruneRows > 0) && busy;
}
@ -976,10 +976,10 @@ bool LogBuffer::clear(log_id_t id, uid_t uid) {
// readers and let the clear run (below) deal with determining
// if we are still blocked and return an error code to caller.
if (busy) {
LogTimeEntry::wrlock();
LogReaderThread::wrlock();
LastLogTimes::iterator times = mTimes.begin();
while (times != mTimes.end()) {
LogTimeEntry* entry = times->get();
LogReaderThread* entry = times->get();
// Killer punch
if (entry->isWatching(id)) {
android::prdebug(
@ -989,7 +989,7 @@ bool LogBuffer::clear(log_id_t id, uid_t uid) {
}
times++;
}
LogTimeEntry::unlock();
LogReaderThread::unlock();
}
}
wrlock();

View File

@ -27,9 +27,9 @@
#include <sysutils/SocketClient.h>
#include "LogBufferElement.h"
#include "LogReaderThread.h"
#include "LogStatistics.h"
#include "LogTags.h"
#include "LogTimes.h"
#include "LogWhiteBlackList.h"
//
@ -152,7 +152,7 @@ class LogBuffer {
static constexpr size_t maxPrune = 256;
void maybePrune(log_id_t id);
void kickMe(LogTimeEntry* me, log_id_t id, unsigned long pruneRows);
void kickMe(LogReaderThread* me, log_id_t id, unsigned long pruneRows);
bool prune(log_id_t id, unsigned long pruneRows, uid_t uid = AID_ROOT);
LogBufferElementCollection::iterator erase(

View File

@ -42,7 +42,7 @@ LogReader::LogReader(LogBuffer* logbuf)
void LogReader::notifyNewLog(log_mask_t log_mask) {
LastLogTimes& times = mLogbuf.mTimes;
LogTimeEntry::wrlock();
LogReaderThread::wrlock();
for (const auto& entry : times) {
if (!entry->isWatchingMultiple(log_mask)) {
continue;
@ -52,7 +52,7 @@ void LogReader::notifyNewLog(log_mask_t log_mask) {
}
entry->triggerReader_Locked();
}
LogTimeEntry::unlock();
LogReaderThread::unlock();
}
// Note returning false will release the SocketClient instance.
@ -74,15 +74,15 @@ bool LogReader::onDataAvailable(SocketClient* cli) {
// Clients are only allowed to send one command, disconnect them if they
// send another.
LogTimeEntry::wrlock();
LogReaderThread::wrlock();
for (const auto& entry : mLogbuf.mTimes) {
if (entry->mClient == cli) {
entry->release_Locked();
LogTimeEntry::unlock();
LogReaderThread::unlock();
return false;
}
}
LogTimeEntry::unlock();
LogReaderThread::unlock();
unsigned long tail = 0;
static const char _tail[] = " tail=";
@ -137,8 +137,8 @@ bool LogReader::onDataAvailable(SocketClient* cli) {
if (!fastcmp<strncmp>(buffer, "dumpAndClose", 12)) {
// Allow writer to get some cycles, and wait for pending notifications
sched_yield();
LogTimeEntry::wrlock();
LogTimeEntry::unlock();
LogReaderThread::wrlock();
LogReaderThread::unlock();
sched_yield();
nonBlock = true;
}
@ -217,11 +217,12 @@ bool LogReader::onDataAvailable(SocketClient* cli) {
timeout = 0;
}
LogTimeEntry::wrlock();
auto entry = std::make_unique<LogTimeEntry>(*this, cli, nonBlock, tail, logMask, pid, start,
sequence, timeout, privileged, can_read_security);
LogReaderThread::wrlock();
auto entry =
std::make_unique<LogReaderThread>(*this, cli, nonBlock, tail, logMask, pid, start,
sequence, timeout, privileged, can_read_security);
if (!entry->startReader_Locked()) {
LogTimeEntry::unlock();
LogReaderThread::unlock();
return false;
}
@ -234,24 +235,24 @@ bool LogReader::onDataAvailable(SocketClient* cli) {
setsockopt(cli->getSocket(), SOL_SOCKET, SO_SNDTIMEO, (const char*)&t,
sizeof(t));
LogTimeEntry::unlock();
LogReaderThread::unlock();
return true;
}
void LogReader::doSocketDelete(SocketClient* cli) {
LastLogTimes& times = mLogbuf.mTimes;
LogTimeEntry::wrlock();
LogReaderThread::wrlock();
LastLogTimes::iterator it = times.begin();
while (it != times.end()) {
LogTimeEntry* entry = it->get();
LogReaderThread* entry = it->get();
if (entry->mClient == cli) {
entry->release_Locked();
break;
}
it++;
}
LogTimeEntry::unlock();
LogReaderThread::unlock();
}
int LogReader::getLogSocket() {

View File

@ -14,12 +14,11 @@
* limitations under the License.
*/
#ifndef _LOGD_LOG_WRITER_H__
#define _LOGD_LOG_WRITER_H__
#pragma once
#include <sysutils/SocketListener.h>
#include "LogTimes.h"
#include "LogReaderThread.h"
#define LOGD_SNDTIMEO 32
@ -44,5 +43,3 @@ class LogReader : public SocketListener {
void doSocketDelete(SocketClient* cli);
};
#endif

View File

@ -14,23 +14,24 @@
* limitations under the License.
*/
#include "LogReaderThread.h"
#include <errno.h>
#include <string.h>
#include <sys/prctl.h>
#include "LogBuffer.h"
#include "LogReader.h"
#include "LogTimes.h"
pthread_mutex_t LogTimeEntry::timesLock = PTHREAD_MUTEX_INITIALIZER;
pthread_mutex_t LogReaderThread::timesLock = PTHREAD_MUTEX_INITIALIZER;
LogTimeEntry::LogTimeEntry(LogReader& reader, SocketClient* client, bool nonBlock,
unsigned long tail, log_mask_t logMask, pid_t pid, log_time start_time,
uint64_t start, uint64_t timeout, bool privileged,
bool can_read_security_logs)
LogReaderThread::LogReaderThread(LogReader& reader, SocketClient* client, bool non_block,
unsigned long tail, log_mask_t log_mask, pid_t pid,
log_time start_time, uint64_t start, uint64_t timeout,
bool privileged, bool can_read_security_logs)
: leadingDropped(false),
mReader(reader),
mLogMask(logMask),
mLogMask(log_mask),
mPid(pid),
mCount(0),
mTail(tail),
@ -38,7 +39,7 @@ LogTimeEntry::LogTimeEntry(LogReader& reader, SocketClient* client, bool nonBloc
mClient(client),
mStartTime(start_time),
mStart(start),
mNonBlock(nonBlock),
mNonBlock(non_block),
privileged_(privileged),
can_read_security_logs_(can_read_security_logs) {
mTimeout.tv_sec = timeout / NS_PER_SEC;
@ -48,13 +49,12 @@ LogTimeEntry::LogTimeEntry(LogReader& reader, SocketClient* client, bool nonBloc
cleanSkip_Locked();
}
bool LogTimeEntry::startReader_Locked() {
bool LogReaderThread::startReader_Locked() {
pthread_attr_t attr;
if (!pthread_attr_init(&attr)) {
if (!pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED)) {
if (!pthread_create(&mThread, &attr, LogTimeEntry::threadStart,
this)) {
if (!pthread_create(&mThread, &attr, LogReaderThread::threadStart, this)) {
pthread_attr_destroy(&attr);
return true;
}
@ -65,10 +65,10 @@ bool LogTimeEntry::startReader_Locked() {
return false;
}
void* LogTimeEntry::threadStart(void* obj) {
void* LogReaderThread::threadStart(void* obj) {
prctl(PR_SET_NAME, "logd.reader.per");
LogTimeEntry* me = reinterpret_cast<LogTimeEntry*>(obj);
LogReaderThread* me = reinterpret_cast<LogReaderThread*>(obj);
SocketClient* client = me->mClient;
@ -136,9 +136,8 @@ void* LogTimeEntry::threadStart(void* obj) {
client->decRef();
LastLogTimes& times = reader.logbuf().mTimes;
auto it =
std::find_if(times.begin(), times.end(),
[&me](const auto& other) { return other.get() == me; });
auto it = std::find_if(times.begin(), times.end(),
[&me](const auto& other) { return other.get() == me; });
if (it != times.end()) {
times.erase(it);
@ -150,14 +149,14 @@ void* LogTimeEntry::threadStart(void* obj) {
}
// A first pass to count the number of elements
int LogTimeEntry::FilterFirstPass(const LogBufferElement* element, void* obj) {
LogTimeEntry* me = reinterpret_cast<LogTimeEntry*>(obj);
int LogReaderThread::FilterFirstPass(const LogBufferElement* element, void* obj) {
LogReaderThread* me = reinterpret_cast<LogReaderThread*>(obj);
LogTimeEntry::wrlock();
LogReaderThread::wrlock();
if (me->leadingDropped) {
if (element->getDropped()) {
LogTimeEntry::unlock();
LogReaderThread::unlock();
return false;
}
me->leadingDropped = false;
@ -172,16 +171,16 @@ int LogTimeEntry::FilterFirstPass(const LogBufferElement* element, void* obj) {
++me->mCount;
}
LogTimeEntry::unlock();
LogReaderThread::unlock();
return false;
}
// A second pass to send the selected elements
int LogTimeEntry::FilterSecondPass(const LogBufferElement* element, void* obj) {
LogTimeEntry* me = reinterpret_cast<LogTimeEntry*>(obj);
int LogReaderThread::FilterSecondPass(const LogBufferElement* element, void* obj) {
LogReaderThread* me = reinterpret_cast<LogReaderThread*>(obj);
LogTimeEntry::wrlock();
LogReaderThread::wrlock();
me->mStart = element->getSequence();
@ -234,20 +233,20 @@ int LogTimeEntry::FilterSecondPass(const LogBufferElement* element, void* obj) {
ok:
if (!me->skipAhead[element->getLogId()]) {
LogTimeEntry::unlock();
LogReaderThread::unlock();
return true;
}
// FALLTHRU
// FALLTHRU
skip:
LogTimeEntry::unlock();
LogReaderThread::unlock();
return false;
stop:
LogTimeEntry::unlock();
LogReaderThread::unlock();
return -1;
}
void LogTimeEntry::cleanSkip_Locked(void) {
void LogReaderThread::cleanSkip_Locked(void) {
memset(skipAhead, 0, sizeof(skipAhead));
}

View File

@ -14,8 +14,7 @@
* limitations under the License.
*/
#ifndef _LOGD_LOG_TIMES_H__
#define _LOGD_LOG_TIMES_H__
#pragma once
#include <pthread.h>
#include <sys/socket.h>
@ -33,7 +32,7 @@ typedef unsigned int log_mask_t;
class LogReader;
class LogBufferElement;
class LogTimeEntry {
class LogReaderThread {
static pthread_mutex_t timesLock;
bool mRelease = false;
bool leadingDropped;
@ -50,9 +49,9 @@ class LogTimeEntry {
unsigned long mIndex;
public:
LogTimeEntry(LogReader& reader, SocketClient* client, bool nonBlock, unsigned long tail,
log_mask_t logMask, pid_t pid, log_time start_time, uint64_t sequence,
uint64_t timeout, bool privileged, bool can_read_security_logs);
LogReaderThread(LogReader& reader, SocketClient* client, bool non_block, unsigned long tail,
log_mask_t log_mask, pid_t pid, log_time start_time, uint64_t sequence,
uint64_t timeout, bool privileged, bool can_read_security_logs);
SocketClient* mClient;
log_time mStartTime;
@ -61,40 +60,26 @@ class LogTimeEntry {
const bool mNonBlock;
// Protect List manipulations
static void wrlock(void) {
pthread_mutex_lock(&timesLock);
}
static void rdlock(void) {
pthread_mutex_lock(&timesLock);
}
static void unlock(void) {
pthread_mutex_unlock(&timesLock);
}
static void wrlock() { pthread_mutex_lock(&timesLock); }
static void rdlock() { pthread_mutex_lock(&timesLock); }
static void unlock() { pthread_mutex_unlock(&timesLock); }
bool startReader_Locked();
void triggerReader_Locked(void) {
pthread_cond_signal(&threadTriggeredCondition);
}
void triggerReader_Locked() { pthread_cond_signal(&threadTriggeredCondition); }
void triggerSkip_Locked(log_id_t id, unsigned int skip) {
skipAhead[id] = skip;
}
void cleanSkip_Locked(void);
void triggerSkip_Locked(log_id_t id, unsigned int skip) { skipAhead[id] = skip; }
void cleanSkip_Locked();
void release_Locked(void) {
void release_Locked() {
// gracefully shut down the socket.
shutdown(mClient->getSocket(), SHUT_RDWR);
mRelease = true;
pthread_cond_signal(&threadTriggeredCondition);
}
bool isWatching(log_id_t id) const {
return mLogMask & (1 << id);
}
bool isWatchingMultiple(log_mask_t logMask) const {
return mLogMask & logMask;
}
bool isWatching(log_id_t id) const { return mLogMask & (1 << id); }
bool isWatchingMultiple(log_mask_t log_mask) const { return mLogMask & log_mask; }
// flushTo filter callbacks
static int FilterFirstPass(const LogBufferElement* element, void* me);
static int FilterSecondPass(const LogBufferElement* element, void* me);
@ -104,6 +89,4 @@ class LogTimeEntry {
bool can_read_security_logs_;
};
typedef std::list<std::unique_ptr<LogTimeEntry>> LastLogTimes;
#endif // _LOGD_LOG_TIMES_H__
typedef std::list<std::unique_ptr<LogReaderThread>> LastLogTimes;

View File

@ -16,7 +16,7 @@
#include <string>
#include "../LogBuffer.h"
#include "../LogTimes.h"
#include "../LogReaderThread.h"
// We don't want to waste a lot of entropy on messages
#define MAX_MSG_LENGTH 5