Home | History | Annotate | Download | only in common_time
      1 /*
      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 
     17 #define LOG_TAG "common_time"
     18 #include <utils/Log.h>
     19 
     20 #include "utils.h"
     21 
     22 namespace android {
     23 
     24 void 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 
     33 int 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 
     52 LogRing::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 
     62 LogRing::~LogRing() {
     63     if (NULL != mRingBuffer)
     64         delete[] mRingBuffer;
     65 }
     66 
     67 void 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 
     74 void 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 
     81 void 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 
    113 void 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 
    164 }  // namespace android
    165