blob: ed2c77ddb3a54d98f0ebf9bb0080de2e2a8f187f [file] [log] [blame]
John Grossmanc7f57c62012-06-26 12:50:28 -07001/*
2 * Copyright (C) 2012 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
John Grossman79489c42012-07-20 10:17:26 -070017#define LOG_TAG "common_time"
18#include <utils/Log.h>
19
John Grossmanc7f57c62012-06-26 12:50:28 -070020#include "utils.h"
21
22namespace android {
23
24void Timeout::setTimeout(int msec) {
25 if (msec < 0) {
26 mSystemEndTime = 0;
27 return;
28 }
29
30 mSystemEndTime = systemTime() + (static_cast<nsecs_t>(msec) * 1000000);
31}
32
33int Timeout::msecTillTimeout(nsecs_t nowTime) {
34 if (!mSystemEndTime) {
35 return -1;
36 }
37
38 if (mSystemEndTime < nowTime) {
39 return 0;
40 }
41
42 nsecs_t delta = mSystemEndTime - nowTime;
43 delta += 999999;
44 delta /= 1000000;
45 if (delta > 0x7FFFFFFF) {
46 return 0x7FFFFFFF;
47 }
48
49 return static_cast<int>(delta);
50}
51
John Grossman79489c42012-07-20 10:17:26 -070052LogRing::LogRing(const char* header, size_t entries)
53 : mSize(entries)
54 , mWr(0)
55 , mIsFull(false)
56 , mHeader(header) {
57 mRingBuffer = new Entry[mSize];
58 if (NULL == mRingBuffer)
59 ALOGE("Failed to allocate log ring with %u entries.", mSize);
60}
61
62LogRing::~LogRing() {
63 if (NULL != mRingBuffer)
64 delete[] mRingBuffer;
65}
66
67void LogRing::log(int prio, const char* tag, const char* fmt, ...) {
68 va_list argp;
69 va_start(argp, fmt);
70 internalLog(prio, tag, fmt, argp);
71 va_end(argp);
72}
73
74void LogRing::log(const char* fmt, ...) {
75 va_list argp;
76 va_start(argp, fmt);
77 internalLog(0, NULL, fmt, argp);
78 va_end(argp);
79}
80
81void LogRing::internalLog(int prio,
82 const char* tag,
83 const char* fmt,
84 va_list argp) {
85 if (NULL != mRingBuffer) {
86 Mutex::Autolock lock(&mLock);
87 String8 s(String8::formatV(fmt, argp));
88 Entry* last = NULL;
89
90 if (mIsFull || mWr)
91 last = &(mRingBuffer[(mWr + mSize - 1) % mSize]);
92
93
94 if ((NULL != last) && !last->s.compare(s)) {
95 gettimeofday(&(last->last_ts), NULL);
96 ++last->count;
97 } else {
98 gettimeofday(&mRingBuffer[mWr].first_ts, NULL);
99 mRingBuffer[mWr].last_ts = mRingBuffer[mWr].first_ts;
100 mRingBuffer[mWr].count = 1;
101 mRingBuffer[mWr].s.setTo(s);
102
103 mWr = (mWr + 1) % mSize;
104 if (!mWr)
105 mIsFull = true;
106 }
107 }
108
109 if (NULL != tag)
110 LOG_PRI_VA(prio, tag, fmt, argp);
111}
112
113void LogRing::dumpLog(int fd) {
114 if (NULL == mRingBuffer)
115 return;
116
117 Mutex::Autolock lock(&mLock);
118
119 if (!mWr && !mIsFull)
120 return;
121
122 char buf[1024];
123 int res;
124 size_t start = mIsFull ? mWr : 0;
125 size_t count = mIsFull ? mSize : mWr;
126 static const char* kTimeFmt = "%a %b %d %Y %H:%M:%S";
127
128 res = snprintf(buf, sizeof(buf), "\n%s\n", mHeader);
129 if (res > 0)
130 write(fd, buf, res);
131
132 for (size_t i = 0; i < count; ++i) {
133 struct tm t;
134 char timebuf[64];
135 char repbuf[96];
136 size_t ndx = (start + i) % mSize;
137
138 if (1 != mRingBuffer[ndx].count) {
139 localtime_r(&mRingBuffer[ndx].last_ts.tv_sec, &t);
140 strftime(timebuf, sizeof(timebuf), kTimeFmt, &t);
141 snprintf(repbuf, sizeof(repbuf),
142 " (repeated %d times, last was %s.%03ld)",
143 mRingBuffer[ndx].count,
144 timebuf,
145 mRingBuffer[ndx].last_ts.tv_usec / 1000);
146 repbuf[sizeof(repbuf) - 1] = 0;
147 } else {
148 repbuf[0] = 0;
149 }
150
151 localtime_r(&mRingBuffer[ndx].first_ts.tv_sec, &t);
152 strftime(timebuf, sizeof(timebuf), kTimeFmt, &t);
153 res = snprintf(buf, sizeof(buf), "[%2d] %s.%03ld :: %s%s\n",
154 i, timebuf,
155 mRingBuffer[ndx].first_ts.tv_usec / 1000,
156 mRingBuffer[ndx].s.string(),
157 repbuf);
158
159 if (res > 0)
160 write(fd, buf, res);
161 }
162}
163
John Grossmanc7f57c62012-06-26 12:50:28 -0700164} // namespace android