logd: initial checkin.
* Create a new userspace log daemon for handling logging messages.
Original-Change-Id: I75267df16359684490121e6c31cca48614d79856
Signed-off-by: Nick Kralevich <nnk@google.com>
* Merge conflicts
* rename new syslog daemon to logd to prevent confusion with bionic syslog
* replace racy getGroups call with KISS call to client->getGid()
* Timestamps are filed at logging source
* insert entries into list in timestamp order
* Added LogTimeEntry tail filtration handling
* Added region locking around LogWriter list
* separate threads for each writer
* /dev/socket/logd* permissions
Signed-off-by: Mark Salyzyn <salyzyn@google.com>
(cherry picked from commit 3e76e0a49760c4970b7cda6153e51026af98e4f3)
Author: Nick Kralevich <nnk@google.com>
Change-Id: Ice88b1412d8f9daa7f9119b2b5aaf684a5e28098
diff --git a/logd/FlushCommand.cpp b/logd/FlushCommand.cpp
new file mode 100644
index 0000000..b848fd0
--- /dev/null
+++ b/logd/FlushCommand.cpp
@@ -0,0 +1,86 @@
+/*
+ * Copyright (C) 2012-2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <stdlib.h>
+#include <private/android_filesystem_config.h>
+#include "FlushCommand.h"
+#include "LogBufferElement.h"
+#include "LogTimes.h"
+#include "LogReader.h"
+
+FlushCommand::FlushCommand(LogReader &reader,
+ bool nonBlock,
+ unsigned long tail,
+ unsigned int logMask,
+ pid_t pid)
+ : mReader(reader)
+ , mNonBlock(nonBlock)
+ , mTail(tail)
+ , mLogMask(logMask)
+ , mPid(pid)
+{ }
+
+// runSocketCommand is called once for every open client on the
+// log reader socket. Here we manage and associated the reader
+// client tracking and log region locks LastLogTimes list of
+// LogTimeEntrys, and spawn a transitory per-client thread to
+// work at filing data to the socket.
+//
+// global LogTimeEntry::lock() is used to protect access,
+// reference counts are used to ensure that individual
+// LogTimeEntry lifetime is managed when not protected.
+void FlushCommand::runSocketCommand(SocketClient *client) {
+ LogTimeEntry *entry = NULL;
+ LastLogTimes × = mReader.logbuf().mTimes;
+
+ LogTimeEntry::lock();
+ LastLogTimes::iterator it = times.begin();
+ while(it != times.end()) {
+ entry = (*it);
+ if (entry->mClient == client) {
+ entry->triggerReader_Locked();
+ if (entry->runningReader_Locked()) {
+ LogTimeEntry::unlock();
+ return;
+ }
+ entry->incRef_Locked();
+ break;
+ }
+ it++;
+ }
+
+ if (it == times.end()) {
+ /* Create LogTimeEntry in notifyNewLog() ? */
+ if (mTail == (unsigned long) -1) {
+ LogTimeEntry::unlock();
+ return;
+ }
+ entry = new LogTimeEntry(mReader, client, mNonBlock, mTail, mLogMask, mPid);
+ times.push_back(entry);
+ }
+
+ client->incRef();
+
+ /* release client and entry reference counts once done */
+ entry->startReader_Locked();
+ LogTimeEntry::unlock();
+}
+
+bool FlushCommand::hasReadLogs(SocketClient *client) {
+ return (client->getUid() == AID_ROOT)
+ || (client->getGid() == AID_ROOT)
+ || (client->getGid() == AID_LOG);
+}