1c7f57c6f9289d0e3aaecc0bca4ae7b6eed1c93d7John Grossman/*
2c7f57c6f9289d0e3aaecc0bca4ae7b6eed1c93d7John Grossman * Copyright (C) 2012 The Android Open Source Project
3c7f57c6f9289d0e3aaecc0bca4ae7b6eed1c93d7John Grossman *
4c7f57c6f9289d0e3aaecc0bca4ae7b6eed1c93d7John Grossman * Licensed under the Apache License, Version 2.0 (the "License");
5c7f57c6f9289d0e3aaecc0bca4ae7b6eed1c93d7John Grossman * you may not use this file except in compliance with the License.
6c7f57c6f9289d0e3aaecc0bca4ae7b6eed1c93d7John Grossman * You may obtain a copy of the License at
7c7f57c6f9289d0e3aaecc0bca4ae7b6eed1c93d7John Grossman *
8c7f57c6f9289d0e3aaecc0bca4ae7b6eed1c93d7John Grossman *      http://www.apache.org/licenses/LICENSE-2.0
9c7f57c6f9289d0e3aaecc0bca4ae7b6eed1c93d7John Grossman *
10c7f57c6f9289d0e3aaecc0bca4ae7b6eed1c93d7John Grossman * Unless required by applicable law or agreed to in writing, software
11c7f57c6f9289d0e3aaecc0bca4ae7b6eed1c93d7John Grossman * distributed under the License is distributed on an "AS IS" BASIS,
12c7f57c6f9289d0e3aaecc0bca4ae7b6eed1c93d7John Grossman * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13c7f57c6f9289d0e3aaecc0bca4ae7b6eed1c93d7John Grossman * See the License for the specific language governing permissions and
14c7f57c6f9289d0e3aaecc0bca4ae7b6eed1c93d7John Grossman * limitations under the License.
15c7f57c6f9289d0e3aaecc0bca4ae7b6eed1c93d7John Grossman */
16c7f57c6f9289d0e3aaecc0bca4ae7b6eed1c93d7John Grossman
1779489c4c65d3c8e628991995b4a18f2a81802ee6John Grossman#define LOG_TAG "common_time"
1879489c4c65d3c8e628991995b4a18f2a81802ee6John Grossman#include <utils/Log.h>
1979489c4c65d3c8e628991995b4a18f2a81802ee6John Grossman
20c7f57c6f9289d0e3aaecc0bca4ae7b6eed1c93d7John Grossman#include "utils.h"
21c7f57c6f9289d0e3aaecc0bca4ae7b6eed1c93d7John Grossman
22c7f57c6f9289d0e3aaecc0bca4ae7b6eed1c93d7John Grossmannamespace android {
23c7f57c6f9289d0e3aaecc0bca4ae7b6eed1c93d7John Grossman
24c7f57c6f9289d0e3aaecc0bca4ae7b6eed1c93d7John Grossmanvoid Timeout::setTimeout(int msec) {
25c7f57c6f9289d0e3aaecc0bca4ae7b6eed1c93d7John Grossman    if (msec < 0) {
26c7f57c6f9289d0e3aaecc0bca4ae7b6eed1c93d7John Grossman        mSystemEndTime = 0;
27c7f57c6f9289d0e3aaecc0bca4ae7b6eed1c93d7John Grossman        return;
28c7f57c6f9289d0e3aaecc0bca4ae7b6eed1c93d7John Grossman    }
29c7f57c6f9289d0e3aaecc0bca4ae7b6eed1c93d7John Grossman
30c7f57c6f9289d0e3aaecc0bca4ae7b6eed1c93d7John Grossman    mSystemEndTime = systemTime() + (static_cast<nsecs_t>(msec) * 1000000);
31c7f57c6f9289d0e3aaecc0bca4ae7b6eed1c93d7John Grossman}
32c7f57c6f9289d0e3aaecc0bca4ae7b6eed1c93d7John Grossman
33c7f57c6f9289d0e3aaecc0bca4ae7b6eed1c93d7John Grossmanint Timeout::msecTillTimeout(nsecs_t nowTime) {
34c7f57c6f9289d0e3aaecc0bca4ae7b6eed1c93d7John Grossman    if (!mSystemEndTime) {
35c7f57c6f9289d0e3aaecc0bca4ae7b6eed1c93d7John Grossman        return -1;
36c7f57c6f9289d0e3aaecc0bca4ae7b6eed1c93d7John Grossman    }
37c7f57c6f9289d0e3aaecc0bca4ae7b6eed1c93d7John Grossman
38c7f57c6f9289d0e3aaecc0bca4ae7b6eed1c93d7John Grossman    if (mSystemEndTime < nowTime) {
39c7f57c6f9289d0e3aaecc0bca4ae7b6eed1c93d7John Grossman        return 0;
40c7f57c6f9289d0e3aaecc0bca4ae7b6eed1c93d7John Grossman    }
41c7f57c6f9289d0e3aaecc0bca4ae7b6eed1c93d7John Grossman
42c7f57c6f9289d0e3aaecc0bca4ae7b6eed1c93d7John Grossman    nsecs_t delta = mSystemEndTime - nowTime;
43c7f57c6f9289d0e3aaecc0bca4ae7b6eed1c93d7John Grossman    delta += 999999;
44c7f57c6f9289d0e3aaecc0bca4ae7b6eed1c93d7John Grossman    delta /= 1000000;
45c7f57c6f9289d0e3aaecc0bca4ae7b6eed1c93d7John Grossman    if (delta > 0x7FFFFFFF) {
46c7f57c6f9289d0e3aaecc0bca4ae7b6eed1c93d7John Grossman        return 0x7FFFFFFF;
47c7f57c6f9289d0e3aaecc0bca4ae7b6eed1c93d7John Grossman    }
48c7f57c6f9289d0e3aaecc0bca4ae7b6eed1c93d7John Grossman
49c7f57c6f9289d0e3aaecc0bca4ae7b6eed1c93d7John Grossman    return static_cast<int>(delta);
50c7f57c6f9289d0e3aaecc0bca4ae7b6eed1c93d7John Grossman}
51c7f57c6f9289d0e3aaecc0bca4ae7b6eed1c93d7John Grossman
5279489c4c65d3c8e628991995b4a18f2a81802ee6John GrossmanLogRing::LogRing(const char* header, size_t entries)
5379489c4c65d3c8e628991995b4a18f2a81802ee6John Grossman    : mSize(entries)
5479489c4c65d3c8e628991995b4a18f2a81802ee6John Grossman    , mWr(0)
5579489c4c65d3c8e628991995b4a18f2a81802ee6John Grossman    , mIsFull(false)
5679489c4c65d3c8e628991995b4a18f2a81802ee6John Grossman    , mHeader(header) {
5779489c4c65d3c8e628991995b4a18f2a81802ee6John Grossman    mRingBuffer = new Entry[mSize];
5879489c4c65d3c8e628991995b4a18f2a81802ee6John Grossman    if (NULL == mRingBuffer)
59f5df700e6ce056ebfa322314d970e52d6facc35aAshok Bhat        ALOGE("Failed to allocate log ring with %zu entries.", mSize);
6079489c4c65d3c8e628991995b4a18f2a81802ee6John Grossman}
6179489c4c65d3c8e628991995b4a18f2a81802ee6John Grossman
6279489c4c65d3c8e628991995b4a18f2a81802ee6John GrossmanLogRing::~LogRing() {
6379489c4c65d3c8e628991995b4a18f2a81802ee6John Grossman    if (NULL != mRingBuffer)
6479489c4c65d3c8e628991995b4a18f2a81802ee6John Grossman        delete[] mRingBuffer;
6579489c4c65d3c8e628991995b4a18f2a81802ee6John Grossman}
6679489c4c65d3c8e628991995b4a18f2a81802ee6John Grossman
6779489c4c65d3c8e628991995b4a18f2a81802ee6John Grossmanvoid LogRing::log(int prio, const char* tag, const char* fmt, ...) {
6879489c4c65d3c8e628991995b4a18f2a81802ee6John Grossman    va_list argp;
6979489c4c65d3c8e628991995b4a18f2a81802ee6John Grossman    va_start(argp, fmt);
7079489c4c65d3c8e628991995b4a18f2a81802ee6John Grossman    internalLog(prio, tag, fmt, argp);
7179489c4c65d3c8e628991995b4a18f2a81802ee6John Grossman    va_end(argp);
7279489c4c65d3c8e628991995b4a18f2a81802ee6John Grossman}
7379489c4c65d3c8e628991995b4a18f2a81802ee6John Grossman
7479489c4c65d3c8e628991995b4a18f2a81802ee6John Grossmanvoid LogRing::log(const char* fmt, ...) {
7579489c4c65d3c8e628991995b4a18f2a81802ee6John Grossman    va_list argp;
7679489c4c65d3c8e628991995b4a18f2a81802ee6John Grossman    va_start(argp, fmt);
7779489c4c65d3c8e628991995b4a18f2a81802ee6John Grossman    internalLog(0, NULL, fmt, argp);
7879489c4c65d3c8e628991995b4a18f2a81802ee6John Grossman    va_end(argp);
7979489c4c65d3c8e628991995b4a18f2a81802ee6John Grossman}
8079489c4c65d3c8e628991995b4a18f2a81802ee6John Grossman
8179489c4c65d3c8e628991995b4a18f2a81802ee6John Grossmanvoid LogRing::internalLog(int prio,
8279489c4c65d3c8e628991995b4a18f2a81802ee6John Grossman                          const char* tag,
8379489c4c65d3c8e628991995b4a18f2a81802ee6John Grossman                          const char* fmt,
8479489c4c65d3c8e628991995b4a18f2a81802ee6John Grossman                          va_list argp) {
8579489c4c65d3c8e628991995b4a18f2a81802ee6John Grossman    if (NULL != mRingBuffer) {
8679489c4c65d3c8e628991995b4a18f2a81802ee6John Grossman        Mutex::Autolock lock(&mLock);
8779489c4c65d3c8e628991995b4a18f2a81802ee6John Grossman        String8 s(String8::formatV(fmt, argp));
8879489c4c65d3c8e628991995b4a18f2a81802ee6John Grossman        Entry* last = NULL;
8979489c4c65d3c8e628991995b4a18f2a81802ee6John Grossman
9079489c4c65d3c8e628991995b4a18f2a81802ee6John Grossman        if (mIsFull || mWr)
9179489c4c65d3c8e628991995b4a18f2a81802ee6John Grossman            last = &(mRingBuffer[(mWr + mSize - 1) % mSize]);
9279489c4c65d3c8e628991995b4a18f2a81802ee6John Grossman
9379489c4c65d3c8e628991995b4a18f2a81802ee6John Grossman
9479489c4c65d3c8e628991995b4a18f2a81802ee6John Grossman        if ((NULL != last) && !last->s.compare(s)) {
9579489c4c65d3c8e628991995b4a18f2a81802ee6John Grossman            gettimeofday(&(last->last_ts), NULL);
9679489c4c65d3c8e628991995b4a18f2a81802ee6John Grossman            ++last->count;
9779489c4c65d3c8e628991995b4a18f2a81802ee6John Grossman        } else {
9879489c4c65d3c8e628991995b4a18f2a81802ee6John Grossman            gettimeofday(&mRingBuffer[mWr].first_ts, NULL);
9979489c4c65d3c8e628991995b4a18f2a81802ee6John Grossman            mRingBuffer[mWr].last_ts = mRingBuffer[mWr].first_ts;
10079489c4c65d3c8e628991995b4a18f2a81802ee6John Grossman            mRingBuffer[mWr].count = 1;
10179489c4c65d3c8e628991995b4a18f2a81802ee6John Grossman            mRingBuffer[mWr].s.setTo(s);
10279489c4c65d3c8e628991995b4a18f2a81802ee6John Grossman
10379489c4c65d3c8e628991995b4a18f2a81802ee6John Grossman            mWr = (mWr + 1) % mSize;
10479489c4c65d3c8e628991995b4a18f2a81802ee6John Grossman            if (!mWr)
10579489c4c65d3c8e628991995b4a18f2a81802ee6John Grossman                mIsFull = true;
10679489c4c65d3c8e628991995b4a18f2a81802ee6John Grossman        }
10779489c4c65d3c8e628991995b4a18f2a81802ee6John Grossman    }
10879489c4c65d3c8e628991995b4a18f2a81802ee6John Grossman
10979489c4c65d3c8e628991995b4a18f2a81802ee6John Grossman    if (NULL != tag)
11079489c4c65d3c8e628991995b4a18f2a81802ee6John Grossman        LOG_PRI_VA(prio, tag, fmt, argp);
11179489c4c65d3c8e628991995b4a18f2a81802ee6John Grossman}
11279489c4c65d3c8e628991995b4a18f2a81802ee6John Grossman
11379489c4c65d3c8e628991995b4a18f2a81802ee6John Grossmanvoid LogRing::dumpLog(int fd) {
11479489c4c65d3c8e628991995b4a18f2a81802ee6John Grossman    if (NULL == mRingBuffer)
11579489c4c65d3c8e628991995b4a18f2a81802ee6John Grossman        return;
11679489c4c65d3c8e628991995b4a18f2a81802ee6John Grossman
11779489c4c65d3c8e628991995b4a18f2a81802ee6John Grossman    Mutex::Autolock lock(&mLock);
11879489c4c65d3c8e628991995b4a18f2a81802ee6John Grossman
11979489c4c65d3c8e628991995b4a18f2a81802ee6John Grossman    if (!mWr && !mIsFull)
12079489c4c65d3c8e628991995b4a18f2a81802ee6John Grossman        return;
12179489c4c65d3c8e628991995b4a18f2a81802ee6John Grossman
12279489c4c65d3c8e628991995b4a18f2a81802ee6John Grossman    char buf[1024];
12379489c4c65d3c8e628991995b4a18f2a81802ee6John Grossman    int res;
12479489c4c65d3c8e628991995b4a18f2a81802ee6John Grossman    size_t start = mIsFull ? mWr : 0;
12579489c4c65d3c8e628991995b4a18f2a81802ee6John Grossman    size_t count = mIsFull ? mSize : mWr;
12679489c4c65d3c8e628991995b4a18f2a81802ee6John Grossman    static const char* kTimeFmt = "%a %b %d %Y %H:%M:%S";
12779489c4c65d3c8e628991995b4a18f2a81802ee6John Grossman
12879489c4c65d3c8e628991995b4a18f2a81802ee6John Grossman    res = snprintf(buf, sizeof(buf), "\n%s\n", mHeader);
12979489c4c65d3c8e628991995b4a18f2a81802ee6John Grossman    if (res > 0)
13079489c4c65d3c8e628991995b4a18f2a81802ee6John Grossman        write(fd, buf, res);
13179489c4c65d3c8e628991995b4a18f2a81802ee6John Grossman
13279489c4c65d3c8e628991995b4a18f2a81802ee6John Grossman    for (size_t i = 0; i < count; ++i) {
13379489c4c65d3c8e628991995b4a18f2a81802ee6John Grossman        struct tm t;
13479489c4c65d3c8e628991995b4a18f2a81802ee6John Grossman        char timebuf[64];
13579489c4c65d3c8e628991995b4a18f2a81802ee6John Grossman        char repbuf[96];
13679489c4c65d3c8e628991995b4a18f2a81802ee6John Grossman        size_t ndx = (start + i) % mSize;
13779489c4c65d3c8e628991995b4a18f2a81802ee6John Grossman
13879489c4c65d3c8e628991995b4a18f2a81802ee6John Grossman        if (1 != mRingBuffer[ndx].count) {
13979489c4c65d3c8e628991995b4a18f2a81802ee6John Grossman            localtime_r(&mRingBuffer[ndx].last_ts.tv_sec, &t);
14079489c4c65d3c8e628991995b4a18f2a81802ee6John Grossman            strftime(timebuf, sizeof(timebuf), kTimeFmt, &t);
14179489c4c65d3c8e628991995b4a18f2a81802ee6John Grossman            snprintf(repbuf, sizeof(repbuf),
14279489c4c65d3c8e628991995b4a18f2a81802ee6John Grossman                    " (repeated %d times, last was %s.%03ld)",
14379489c4c65d3c8e628991995b4a18f2a81802ee6John Grossman                     mRingBuffer[ndx].count,
14479489c4c65d3c8e628991995b4a18f2a81802ee6John Grossman                     timebuf,
14579489c4c65d3c8e628991995b4a18f2a81802ee6John Grossman                     mRingBuffer[ndx].last_ts.tv_usec / 1000);
14679489c4c65d3c8e628991995b4a18f2a81802ee6John Grossman            repbuf[sizeof(repbuf) - 1] = 0;
14779489c4c65d3c8e628991995b4a18f2a81802ee6John Grossman        } else {
14879489c4c65d3c8e628991995b4a18f2a81802ee6John Grossman            repbuf[0] = 0;
14979489c4c65d3c8e628991995b4a18f2a81802ee6John Grossman        }
15079489c4c65d3c8e628991995b4a18f2a81802ee6John Grossman
15179489c4c65d3c8e628991995b4a18f2a81802ee6John Grossman        localtime_r(&mRingBuffer[ndx].first_ts.tv_sec, &t);
15279489c4c65d3c8e628991995b4a18f2a81802ee6John Grossman        strftime(timebuf, sizeof(timebuf), kTimeFmt, &t);
153f5df700e6ce056ebfa322314d970e52d6facc35aAshok Bhat        res = snprintf(buf, sizeof(buf), "[%2zu] %s.%03ld :: %s%s\n",
15479489c4c65d3c8e628991995b4a18f2a81802ee6John Grossman                       i, timebuf,
15579489c4c65d3c8e628991995b4a18f2a81802ee6John Grossman                       mRingBuffer[ndx].first_ts.tv_usec / 1000,
15679489c4c65d3c8e628991995b4a18f2a81802ee6John Grossman                       mRingBuffer[ndx].s.string(),
15779489c4c65d3c8e628991995b4a18f2a81802ee6John Grossman                       repbuf);
15879489c4c65d3c8e628991995b4a18f2a81802ee6John Grossman
15979489c4c65d3c8e628991995b4a18f2a81802ee6John Grossman        if (res > 0)
16079489c4c65d3c8e628991995b4a18f2a81802ee6John Grossman            write(fd, buf, res);
16179489c4c65d3c8e628991995b4a18f2a81802ee6John Grossman    }
16279489c4c65d3c8e628991995b4a18f2a81802ee6John Grossman}
16379489c4c65d3c8e628991995b4a18f2a81802ee6John Grossman
164c7f57c6f9289d0e3aaecc0bca4ae7b6eed1c93d7John Grossman}  // namespace android
165