134facab86b0fe7ec613de92b46b637f864fb0682Mark Salyzyn/*
234facab86b0fe7ec613de92b46b637f864fb0682Mark Salyzyn * Copyright (C) 2014 The Android Open Source Project
334facab86b0fe7ec613de92b46b637f864fb0682Mark Salyzyn *
434facab86b0fe7ec613de92b46b637f864fb0682Mark Salyzyn * Licensed under the Apache License, Version 2.0 (the "License");
534facab86b0fe7ec613de92b46b637f864fb0682Mark Salyzyn * you may not use this file except in compliance with the License.
634facab86b0fe7ec613de92b46b637f864fb0682Mark Salyzyn * You may obtain a copy of the License at
734facab86b0fe7ec613de92b46b637f864fb0682Mark Salyzyn *
834facab86b0fe7ec613de92b46b637f864fb0682Mark Salyzyn *      http://www.apache.org/licenses/LICENSE-2.0
934facab86b0fe7ec613de92b46b637f864fb0682Mark Salyzyn *
1034facab86b0fe7ec613de92b46b637f864fb0682Mark Salyzyn * Unless required by applicable law or agreed to in writing, software
1134facab86b0fe7ec613de92b46b637f864fb0682Mark Salyzyn * distributed under the License is distributed on an "AS IS" BASIS,
1234facab86b0fe7ec613de92b46b637f864fb0682Mark Salyzyn * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1334facab86b0fe7ec613de92b46b637f864fb0682Mark Salyzyn * See the License for the specific language governing permissions and
1434facab86b0fe7ec613de92b46b637f864fb0682Mark Salyzyn * limitations under the License.
1534facab86b0fe7ec613de92b46b637f864fb0682Mark Salyzyn */
1634facab86b0fe7ec613de92b46b637f864fb0682Mark Salyzyn
1734facab86b0fe7ec613de92b46b637f864fb0682Mark Salyzyn#ifndef _LOGD_LOG_STATISTICS_H__
1834facab86b0fe7ec613de92b46b637f864fb0682Mark Salyzyn#define _LOGD_LOG_STATISTICS_H__
1934facab86b0fe7ec613de92b46b637f864fb0682Mark Salyzyn
20b545e1c9e3d5989e2e889e65436524fdcfed930eMark Salyzyn#include <ctype.h>
21720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn#include <stdlib.h>
2234facab86b0fe7ec613de92b46b637f864fb0682Mark Salyzyn#include <sys/types.h>
2334facab86b0fe7ec613de92b46b637f864fb0682Mark Salyzyn
24501c373916e292764400dbae735f44b33378400fMark Salyzyn#include <algorithm>  // std::max
25b545e1c9e3d5989e2e889e65436524fdcfed930eMark Salyzyn#include <memory>
26501c373916e292764400dbae735f44b33378400fMark Salyzyn#include <string>  // std::string
27511338dd575572d567c04d69eaea60627b6c3452Mark Salyzyn#include <unordered_map>
28511338dd575572d567c04d69eaea60627b6c3452Mark Salyzyn
294f71319df011d796a60a43fc1bc68e16fbf7d321Elliott Hughes#include <android-base/stringprintf.h>
30501c373916e292764400dbae735f44b33378400fMark Salyzyn#include <android/log.h>
31758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn#include <private/android_filesystem_config.h>
3297c1c2beee2cbd8c67c1cd507367e5b084d853c8Mark Salyzyn
3397c1c2beee2cbd8c67c1cd507367e5b084d853c8Mark Salyzyn#include "LogBufferElement.h"
345ac5c6b19364b5b3061a59db796b2357c95c3b64Mark Salyzyn#include "LogUtils.h"
3534facab86b0fe7ec613de92b46b637f864fb0682Mark Salyzyn
3634facab86b0fe7ec613de92b46b637f864fb0682Mark Salyzyn#define log_id_for_each(i) \
37501c373916e292764400dbae735f44b33378400fMark Salyzyn    for (log_id_t i = LOG_ID_MIN; (i) < LOG_ID_MAX; (i) = (log_id_t)((i) + 1))
3834facab86b0fe7ec613de92b46b637f864fb0682Mark Salyzyn
39758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzynclass LogStatistics;
40758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn
41720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyntemplate <typename TKey, typename TEntry>
42511338dd575572d567c04d69eaea60627b6c3452Mark Salyzynclass LogHashtable {
43511338dd575572d567c04d69eaea60627b6c3452Mark Salyzyn    std::unordered_map<TKey, TEntry> map;
44511338dd575572d567c04d69eaea60627b6c3452Mark Salyzyn
456d981af12023bcaf22bfa0612a85ae4580ecb971Mark Salyzyn    size_t bucket_size() const {
466d981af12023bcaf22bfa0612a85ae4580ecb971Mark Salyzyn        size_t count = 0;
476d981af12023bcaf22bfa0612a85ae4580ecb971Mark Salyzyn        for (size_t idx = 0; idx < map.bucket_count(); ++idx) {
486d981af12023bcaf22bfa0612a85ae4580ecb971Mark Salyzyn            size_t bucket_size = map.bucket_size(idx);
496d981af12023bcaf22bfa0612a85ae4580ecb971Mark Salyzyn            if (bucket_size == 0) bucket_size = 1;
506d981af12023bcaf22bfa0612a85ae4580ecb971Mark Salyzyn            count += bucket_size;
516d981af12023bcaf22bfa0612a85ae4580ecb971Mark Salyzyn        }
526d981af12023bcaf22bfa0612a85ae4580ecb971Mark Salyzyn        float load_factor = map.max_load_factor();
536d981af12023bcaf22bfa0612a85ae4580ecb971Mark Salyzyn        if (load_factor < 1.0) return count;
546d981af12023bcaf22bfa0612a85ae4580ecb971Mark Salyzyn        return count * load_factor;
556d981af12023bcaf22bfa0612a85ae4580ecb971Mark Salyzyn    }
566d981af12023bcaf22bfa0612a85ae4580ecb971Mark Salyzyn
576d981af12023bcaf22bfa0612a85ae4580ecb971Mark Salyzyn    static const size_t unordered_map_per_entry_overhead = sizeof(void*);
586d981af12023bcaf22bfa0612a85ae4580ecb971Mark Salyzyn    static const size_t unordered_map_bucket_overhead = sizeof(void*);
596d981af12023bcaf22bfa0612a85ae4580ecb971Mark Salyzyn
60501c373916e292764400dbae735f44b33378400fMark Salyzyn   public:
61501c373916e292764400dbae735f44b33378400fMark Salyzyn    size_t size() const {
62501c373916e292764400dbae735f44b33378400fMark Salyzyn        return map.size();
63501c373916e292764400dbae735f44b33378400fMark Salyzyn    }
64b0672290e320113f4b6d8fc6bb2d1e0afe493c5cMark Salyzyn
656d981af12023bcaf22bfa0612a85ae4580ecb971Mark Salyzyn    // Estimate unordered_map memory usage.
666d981af12023bcaf22bfa0612a85ae4580ecb971Mark Salyzyn    size_t sizeOf() const {
676d981af12023bcaf22bfa0612a85ae4580ecb971Mark Salyzyn        return sizeof(*this) +
68b0672290e320113f4b6d8fc6bb2d1e0afe493c5cMark Salyzyn               (size() * (sizeof(TEntry) + unordered_map_per_entry_overhead)) +
696d981af12023bcaf22bfa0612a85ae4580ecb971Mark Salyzyn               (bucket_size() * sizeof(size_t) + unordered_map_bucket_overhead);
706d981af12023bcaf22bfa0612a85ae4580ecb971Mark Salyzyn    }
716d981af12023bcaf22bfa0612a85ae4580ecb971Mark Salyzyn
72511338dd575572d567c04d69eaea60627b6c3452Mark Salyzyn    typedef typename std::unordered_map<TKey, TEntry>::iterator iterator;
73501c373916e292764400dbae735f44b33378400fMark Salyzyn    typedef
74501c373916e292764400dbae735f44b33378400fMark Salyzyn        typename std::unordered_map<TKey, TEntry>::const_iterator const_iterator;
75511338dd575572d567c04d69eaea60627b6c3452Mark Salyzyn
76501c373916e292764400dbae735f44b33378400fMark Salyzyn    std::unique_ptr<const TEntry* []> sort(uid_t uid, pid_t pid,
77ee3b838e13dc2140ac2051c1012d471effd0fd5fMark Salyzyn                                           size_t len) const {
78758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn        if (!len) {
79501c373916e292764400dbae735f44b33378400fMark Salyzyn            std::unique_ptr<const TEntry* []> sorted(NULL);
80720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn            return sorted;
81720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn        }
82720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn
83501c373916e292764400dbae735f44b33378400fMark Salyzyn        const TEntry** retval = new const TEntry*[len];
84758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn        memset(retval, 0, sizeof(*retval) * len);
85720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn
86501c373916e292764400dbae735f44b33378400fMark Salyzyn        for (const_iterator it = map.begin(); it != map.end(); ++it) {
87501c373916e292764400dbae735f44b33378400fMark Salyzyn            const TEntry& entry = it->second;
88ee3b838e13dc2140ac2051c1012d471effd0fd5fMark Salyzyn
89ee3b838e13dc2140ac2051c1012d471effd0fd5fMark Salyzyn            if ((uid != AID_ROOT) && (uid != entry.getUid())) {
90ee3b838e13dc2140ac2051c1012d471effd0fd5fMark Salyzyn                continue;
91ee3b838e13dc2140ac2051c1012d471effd0fd5fMark Salyzyn            }
92ee3b838e13dc2140ac2051c1012d471effd0fd5fMark Salyzyn            if (pid && entry.getPid() && (pid != entry.getPid())) {
93ee3b838e13dc2140ac2051c1012d471effd0fd5fMark Salyzyn                continue;
94ee3b838e13dc2140ac2051c1012d471effd0fd5fMark Salyzyn            }
95ee3b838e13dc2140ac2051c1012d471effd0fd5fMark Salyzyn
96758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn            size_t sizes = entry.getSizes();
97758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn            ssize_t index = len - 1;
98501c373916e292764400dbae735f44b33378400fMark Salyzyn            while ((!retval[index] || (sizes > retval[index]->getSizes())) &&
99501c373916e292764400dbae735f44b33378400fMark Salyzyn                   (--index >= 0))
100720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn                ;
101758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn            if (++index < (ssize_t)len) {
102758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn                size_t num = len - index - 1;
103758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn                if (num) {
104758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn                    memmove(&retval[index + 1], &retval[index],
105758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn                            num * sizeof(retval[0]));
106720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn                }
107758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn                retval[index] = &entry;
108720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn            }
109720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn        }
110501c373916e292764400dbae735f44b33378400fMark Salyzyn        std::unique_ptr<const TEntry* []> sorted(retval);
111720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn        return sorted;
112720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn    }
113720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn
114501c373916e292764400dbae735f44b33378400fMark Salyzyn    inline iterator add(TKey key, LogBufferElement* element) {
115511338dd575572d567c04d69eaea60627b6c3452Mark Salyzyn        iterator it = map.find(key);
116511338dd575572d567c04d69eaea60627b6c3452Mark Salyzyn        if (it == map.end()) {
117758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn            it = map.insert(std::make_pair(key, TEntry(element))).first;
118511338dd575572d567c04d69eaea60627b6c3452Mark Salyzyn        } else {
119758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn            it->second.add(element);
12081b3eabc49736b89c4f99940f79785074955eaa5Mark Salyzyn        }
121511338dd575572d567c04d69eaea60627b6c3452Mark Salyzyn        return it;
12281b3eabc49736b89c4f99940f79785074955eaa5Mark Salyzyn    }
12381b3eabc49736b89c4f99940f79785074955eaa5Mark Salyzyn
124511338dd575572d567c04d69eaea60627b6c3452Mark Salyzyn    inline iterator add(TKey key) {
125511338dd575572d567c04d69eaea60627b6c3452Mark Salyzyn        iterator it = map.find(key);
126511338dd575572d567c04d69eaea60627b6c3452Mark Salyzyn        if (it == map.end()) {
127511338dd575572d567c04d69eaea60627b6c3452Mark Salyzyn            it = map.insert(std::make_pair(key, TEntry(key))).first;
128511338dd575572d567c04d69eaea60627b6c3452Mark Salyzyn        } else {
129511338dd575572d567c04d69eaea60627b6c3452Mark Salyzyn            it->second.add(key);
13081b3eabc49736b89c4f99940f79785074955eaa5Mark Salyzyn        }
131511338dd575572d567c04d69eaea60627b6c3452Mark Salyzyn        return it;
13281b3eabc49736b89c4f99940f79785074955eaa5Mark Salyzyn    }
13381b3eabc49736b89c4f99940f79785074955eaa5Mark Salyzyn
134501c373916e292764400dbae735f44b33378400fMark Salyzyn    void subtract(TKey key, LogBufferElement* element) {
135511338dd575572d567c04d69eaea60627b6c3452Mark Salyzyn        iterator it = map.find(key);
136758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn        if ((it != map.end()) && it->second.subtract(element)) {
137511338dd575572d567c04d69eaea60627b6c3452Mark Salyzyn            map.erase(it);
13881b3eabc49736b89c4f99940f79785074955eaa5Mark Salyzyn        }
13981b3eabc49736b89c4f99940f79785074955eaa5Mark Salyzyn    }
14081b3eabc49736b89c4f99940f79785074955eaa5Mark Salyzyn
141501c373916e292764400dbae735f44b33378400fMark Salyzyn    inline void drop(TKey key, LogBufferElement* element) {
142511338dd575572d567c04d69eaea60627b6c3452Mark Salyzyn        iterator it = map.find(key);
143511338dd575572d567c04d69eaea60627b6c3452Mark Salyzyn        if (it != map.end()) {
144758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn            it->second.drop(element);
14581b3eabc49736b89c4f99940f79785074955eaa5Mark Salyzyn        }
14681b3eabc49736b89c4f99940f79785074955eaa5Mark Salyzyn    }
14781b3eabc49736b89c4f99940f79785074955eaa5Mark Salyzyn
148501c373916e292764400dbae735f44b33378400fMark Salyzyn    inline iterator begin() {
149501c373916e292764400dbae735f44b33378400fMark Salyzyn        return map.begin();
150501c373916e292764400dbae735f44b33378400fMark Salyzyn    }
151501c373916e292764400dbae735f44b33378400fMark Salyzyn    inline const_iterator begin() const {
152501c373916e292764400dbae735f44b33378400fMark Salyzyn        return map.begin();
153501c373916e292764400dbae735f44b33378400fMark Salyzyn    }
154501c373916e292764400dbae735f44b33378400fMark Salyzyn    inline iterator end() {
155501c373916e292764400dbae735f44b33378400fMark Salyzyn        return map.end();
156501c373916e292764400dbae735f44b33378400fMark Salyzyn    }
157501c373916e292764400dbae735f44b33378400fMark Salyzyn    inline const_iterator end() const {
158501c373916e292764400dbae735f44b33378400fMark Salyzyn        return map.end();
159501c373916e292764400dbae735f44b33378400fMark Salyzyn    }
160758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn
161501c373916e292764400dbae735f44b33378400fMark Salyzyn    std::string format(const LogStatistics& stat, uid_t uid, pid_t pid,
162501c373916e292764400dbae735f44b33378400fMark Salyzyn                       const std::string& name = std::string(""),
163501c373916e292764400dbae735f44b33378400fMark Salyzyn                       log_id_t id = LOG_ID_MAX) const {
164758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn        static const size_t maximum_sorted_entries = 32;
165758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn        std::string output;
166501c373916e292764400dbae735f44b33378400fMark Salyzyn        std::unique_ptr<const TEntry* []> sorted =
167501c373916e292764400dbae735f44b33378400fMark Salyzyn            sort(uid, pid, maximum_sorted_entries);
168758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn        if (!sorted.get()) {
169758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn            return output;
170758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn        }
171758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn        bool headerPrinted = false;
172758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn        for (size_t index = 0; index < maximum_sorted_entries; ++index) {
173501c373916e292764400dbae735f44b33378400fMark Salyzyn            const TEntry* entry = sorted[index];
174758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn            if (!entry) {
175758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn                break;
176758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn            }
177758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn            if (entry->getSizes() <= (sorted[0]->getSizes() / 100)) {
178758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn                break;
179758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn            }
180758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn            if (!headerPrinted) {
181758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn                output += "\n\n";
182758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn                output += entry->formatHeader(name, id);
183758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn                headerPrinted = true;
184758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn            }
185758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn            output += entry->format(stat, id);
186758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn        }
187758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn        return output;
188758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn    }
189720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn};
190720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn
191758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzynnamespace EntryBaseConstants {
192501c373916e292764400dbae735f44b33378400fMark Salyzynstatic constexpr size_t pruned_len = 14;
193501c373916e292764400dbae735f44b33378400fMark Salyzynstatic constexpr size_t total_len = 80;
194758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn}
195758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn
19681b3eabc49736b89c4f99940f79785074955eaa5Mark Salyzynstruct EntryBase {
19797c1c2beee2cbd8c67c1cd507367e5b084d853c8Mark Salyzyn    size_t size;
19834facab86b0fe7ec613de92b46b637f864fb0682Mark Salyzyn
199501c373916e292764400dbae735f44b33378400fMark Salyzyn    EntryBase() : size(0) {
200501c373916e292764400dbae735f44b33378400fMark Salyzyn    }
201501c373916e292764400dbae735f44b33378400fMark Salyzyn    explicit EntryBase(LogBufferElement* element) : size(element->getMsgLen()) {
202501c373916e292764400dbae735f44b33378400fMark Salyzyn    }
20334facab86b0fe7ec613de92b46b637f864fb0682Mark Salyzyn
204501c373916e292764400dbae735f44b33378400fMark Salyzyn    size_t getSizes() const {
205501c373916e292764400dbae735f44b33378400fMark Salyzyn        return size;
206501c373916e292764400dbae735f44b33378400fMark Salyzyn    }
20781b3eabc49736b89c4f99940f79785074955eaa5Mark Salyzyn
208501c373916e292764400dbae735f44b33378400fMark Salyzyn    inline void add(LogBufferElement* element) {
209501c373916e292764400dbae735f44b33378400fMark Salyzyn        size += element->getMsgLen();
210501c373916e292764400dbae735f44b33378400fMark Salyzyn    }
211501c373916e292764400dbae735f44b33378400fMark Salyzyn    inline bool subtract(LogBufferElement* element) {
212758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn        size -= element->getMsgLen();
213758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn        return !size;
214758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn    }
215758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn
216501c373916e292764400dbae735f44b33378400fMark Salyzyn    static std::string formatLine(const std::string& name,
217501c373916e292764400dbae735f44b33378400fMark Salyzyn                                  const std::string& size,
218501c373916e292764400dbae735f44b33378400fMark Salyzyn                                  const std::string& pruned) {
219501c373916e292764400dbae735f44b33378400fMark Salyzyn        ssize_t drop_len =
220501c373916e292764400dbae735f44b33378400fMark Salyzyn            std::max(pruned.length() + 1, EntryBaseConstants::pruned_len);
221501c373916e292764400dbae735f44b33378400fMark Salyzyn        ssize_t size_len =
222501c373916e292764400dbae735f44b33378400fMark Salyzyn            std::max(size.length() + 1, EntryBaseConstants::total_len -
223501c373916e292764400dbae735f44b33378400fMark Salyzyn                                            name.length() - drop_len - 1);
224501c373916e292764400dbae735f44b33378400fMark Salyzyn
225501c373916e292764400dbae735f44b33378400fMark Salyzyn        std::string ret = android::base::StringPrintf(
226501c373916e292764400dbae735f44b33378400fMark Salyzyn            "%s%*s%*s", name.c_str(), (int)size_len, size.c_str(),
227501c373916e292764400dbae735f44b33378400fMark Salyzyn            (int)drop_len, pruned.c_str());
228b545e1c9e3d5989e2e889e65436524fdcfed930eMark Salyzyn        // remove any trailing spaces
229b545e1c9e3d5989e2e889e65436524fdcfed930eMark Salyzyn        size_t pos = ret.size();
230b545e1c9e3d5989e2e889e65436524fdcfed930eMark Salyzyn        size_t len = 0;
231b545e1c9e3d5989e2e889e65436524fdcfed930eMark Salyzyn        while (pos && isspace(ret[--pos])) ++len;
232b545e1c9e3d5989e2e889e65436524fdcfed930eMark Salyzyn        if (len) ret.erase(pos + 1, len);
233b545e1c9e3d5989e2e889e65436524fdcfed930eMark Salyzyn        return ret + "\n";
234758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn    }
23581b3eabc49736b89c4f99940f79785074955eaa5Mark Salyzyn};
23681b3eabc49736b89c4f99940f79785074955eaa5Mark Salyzyn
23781b3eabc49736b89c4f99940f79785074955eaa5Mark Salyzynstruct EntryBaseDropped : public EntryBase {
23881b3eabc49736b89c4f99940f79785074955eaa5Mark Salyzyn    size_t dropped;
23981b3eabc49736b89c4f99940f79785074955eaa5Mark Salyzyn
240501c373916e292764400dbae735f44b33378400fMark Salyzyn    EntryBaseDropped() : dropped(0) {
241501c373916e292764400dbae735f44b33378400fMark Salyzyn    }
242501c373916e292764400dbae735f44b33378400fMark Salyzyn    explicit EntryBaseDropped(LogBufferElement* element)
243501c373916e292764400dbae735f44b33378400fMark Salyzyn        : EntryBase(element), dropped(element->getDropped()) {
244758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn    }
24581b3eabc49736b89c4f99940f79785074955eaa5Mark Salyzyn
246501c373916e292764400dbae735f44b33378400fMark Salyzyn    size_t getDropped() const {
247501c373916e292764400dbae735f44b33378400fMark Salyzyn        return dropped;
248501c373916e292764400dbae735f44b33378400fMark Salyzyn    }
249ab0dcf682867bd7e1fdebfd8d8f9fafaccfad7f6Mark Salyzyn
250501c373916e292764400dbae735f44b33378400fMark Salyzyn    inline void add(LogBufferElement* element) {
251758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn        dropped += element->getDropped();
252758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn        EntryBase::add(element);
25381b3eabc49736b89c4f99940f79785074955eaa5Mark Salyzyn    }
254501c373916e292764400dbae735f44b33378400fMark Salyzyn    inline bool subtract(LogBufferElement* element) {
255758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn        dropped -= element->getDropped();
256758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn        return EntryBase::subtract(element) && !dropped;
25781b3eabc49736b89c4f99940f79785074955eaa5Mark Salyzyn    }
258501c373916e292764400dbae735f44b33378400fMark Salyzyn    inline void drop(LogBufferElement* element) {
25981b3eabc49736b89c4f99940f79785074955eaa5Mark Salyzyn        dropped += 1;
260758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn        EntryBase::subtract(element);
26181b3eabc49736b89c4f99940f79785074955eaa5Mark Salyzyn    }
26281b3eabc49736b89c4f99940f79785074955eaa5Mark Salyzyn};
26381b3eabc49736b89c4f99940f79785074955eaa5Mark Salyzyn
26481b3eabc49736b89c4f99940f79785074955eaa5Mark Salyzynstruct UidEntry : public EntryBaseDropped {
26581b3eabc49736b89c4f99940f79785074955eaa5Mark Salyzyn    const uid_t uid;
266ee3b838e13dc2140ac2051c1012d471effd0fd5fMark Salyzyn    pid_t pid;
26781b3eabc49736b89c4f99940f79785074955eaa5Mark Salyzyn
268501c373916e292764400dbae735f44b33378400fMark Salyzyn    explicit UidEntry(LogBufferElement* element)
269501c373916e292764400dbae735f44b33378400fMark Salyzyn        : EntryBaseDropped(element),
270501c373916e292764400dbae735f44b33378400fMark Salyzyn          uid(element->getUid()),
271501c373916e292764400dbae735f44b33378400fMark Salyzyn          pid(element->getPid()) {
272758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn    }
27381b3eabc49736b89c4f99940f79785074955eaa5Mark Salyzyn
274501c373916e292764400dbae735f44b33378400fMark Salyzyn    inline const uid_t& getKey() const {
275501c373916e292764400dbae735f44b33378400fMark Salyzyn        return uid;
276501c373916e292764400dbae735f44b33378400fMark Salyzyn    }
277501c373916e292764400dbae735f44b33378400fMark Salyzyn    inline const uid_t& getUid() const {
278501c373916e292764400dbae735f44b33378400fMark Salyzyn        return getKey();
279501c373916e292764400dbae735f44b33378400fMark Salyzyn    }
280501c373916e292764400dbae735f44b33378400fMark Salyzyn    inline const pid_t& getPid() const {
281501c373916e292764400dbae735f44b33378400fMark Salyzyn        return pid;
282501c373916e292764400dbae735f44b33378400fMark Salyzyn    }
283ee3b838e13dc2140ac2051c1012d471effd0fd5fMark Salyzyn
284501c373916e292764400dbae735f44b33378400fMark Salyzyn    inline void add(LogBufferElement* element) {
285ee3b838e13dc2140ac2051c1012d471effd0fd5fMark Salyzyn        if (pid != element->getPid()) {
286ee3b838e13dc2140ac2051c1012d471effd0fd5fMark Salyzyn            pid = -1;
287ee3b838e13dc2140ac2051c1012d471effd0fd5fMark Salyzyn        }
288a2c022257c5bed56fbc47de25c5d909bbe880f7bMark Salyzyn        EntryBaseDropped::add(element);
289ee3b838e13dc2140ac2051c1012d471effd0fd5fMark Salyzyn    }
290758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn
291501c373916e292764400dbae735f44b33378400fMark Salyzyn    std::string formatHeader(const std::string& name, log_id_t id) const;
292501c373916e292764400dbae735f44b33378400fMark Salyzyn    std::string format(const LogStatistics& stat, log_id_t id) const;
29334facab86b0fe7ec613de92b46b637f864fb0682Mark Salyzyn};
29434facab86b0fe7ec613de92b46b637f864fb0682Mark Salyzyn
29581b3eabc49736b89c4f99940f79785074955eaa5Mark Salyzynnamespace android {
29681b3eabc49736b89c4f99940f79785074955eaa5Mark Salyzynuid_t pidToUid(pid_t pid);
29781b3eabc49736b89c4f99940f79785074955eaa5Mark Salyzyn}
29881b3eabc49736b89c4f99940f79785074955eaa5Mark Salyzyn
29981b3eabc49736b89c4f99940f79785074955eaa5Mark Salyzynstruct PidEntry : public EntryBaseDropped {
300720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn    const pid_t pid;
301720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn    uid_t uid;
302501c373916e292764400dbae735f44b33378400fMark Salyzyn    char* name;
303720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn
304501c373916e292764400dbae735f44b33378400fMark Salyzyn    explicit PidEntry(pid_t pid)
305501c373916e292764400dbae735f44b33378400fMark Salyzyn        : EntryBaseDropped(),
306501c373916e292764400dbae735f44b33378400fMark Salyzyn          pid(pid),
307501c373916e292764400dbae735f44b33378400fMark Salyzyn          uid(android::pidToUid(pid)),
308501c373916e292764400dbae735f44b33378400fMark Salyzyn          name(android::pidToName(pid)) {
309501c373916e292764400dbae735f44b33378400fMark Salyzyn    }
310501c373916e292764400dbae735f44b33378400fMark Salyzyn    explicit PidEntry(LogBufferElement* element)
311501c373916e292764400dbae735f44b33378400fMark Salyzyn        : EntryBaseDropped(element),
312501c373916e292764400dbae735f44b33378400fMark Salyzyn          pid(element->getPid()),
313501c373916e292764400dbae735f44b33378400fMark Salyzyn          uid(element->getUid()),
314501c373916e292764400dbae735f44b33378400fMark Salyzyn          name(android::pidToName(pid)) {
315758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn    }
316501c373916e292764400dbae735f44b33378400fMark Salyzyn    PidEntry(const PidEntry& element)
317501c373916e292764400dbae735f44b33378400fMark Salyzyn        : EntryBaseDropped(element),
318501c373916e292764400dbae735f44b33378400fMark Salyzyn          pid(element.pid),
319501c373916e292764400dbae735f44b33378400fMark Salyzyn          uid(element.uid),
320501c373916e292764400dbae735f44b33378400fMark Salyzyn          name(element.name ? strdup(element.name) : NULL) {
321758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn    }
322501c373916e292764400dbae735f44b33378400fMark Salyzyn    ~PidEntry() {
323501c373916e292764400dbae735f44b33378400fMark Salyzyn        free(name);
324758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn    }
325720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn
326501c373916e292764400dbae735f44b33378400fMark Salyzyn    const pid_t& getKey() const {
327501c373916e292764400dbae735f44b33378400fMark Salyzyn        return pid;
328501c373916e292764400dbae735f44b33378400fMark Salyzyn    }
329501c373916e292764400dbae735f44b33378400fMark Salyzyn    const pid_t& getPid() const {
330501c373916e292764400dbae735f44b33378400fMark Salyzyn        return getKey();
331501c373916e292764400dbae735f44b33378400fMark Salyzyn    }
332501c373916e292764400dbae735f44b33378400fMark Salyzyn    const uid_t& getUid() const {
333501c373916e292764400dbae735f44b33378400fMark Salyzyn        return uid;
334501c373916e292764400dbae735f44b33378400fMark Salyzyn    }
335501c373916e292764400dbae735f44b33378400fMark Salyzyn    const char* getName() const {
336501c373916e292764400dbae735f44b33378400fMark Salyzyn        return name;
337501c373916e292764400dbae735f44b33378400fMark Salyzyn    }
33881b3eabc49736b89c4f99940f79785074955eaa5Mark Salyzyn
339758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn    inline void add(pid_t newPid) {
3400eeb06b932f185e10377e4494475d2cdd6adfa1bMark Salyzyn        if (name && !fastcmp<strncmp>(name, "zygote", 6)) {
341aa43ae2268076227e8b72ea095f8aeac439b3168Mark Salyzyn            free(name);
342aa43ae2268076227e8b72ea095f8aeac439b3168Mark Salyzyn            name = NULL;
343aa43ae2268076227e8b72ea095f8aeac439b3168Mark Salyzyn        }
34481b3eabc49736b89c4f99940f79785074955eaa5Mark Salyzyn        if (!name) {
345758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn            name = android::pidToName(newPid);
34681b3eabc49736b89c4f99940f79785074955eaa5Mark Salyzyn        }
34781b3eabc49736b89c4f99940f79785074955eaa5Mark Salyzyn    }
34881b3eabc49736b89c4f99940f79785074955eaa5Mark Salyzyn
349501c373916e292764400dbae735f44b33378400fMark Salyzyn    inline void add(LogBufferElement* element) {
350758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn        uid_t incomingUid = element->getUid();
351758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn        if (getUid() != incomingUid) {
352758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn            uid = incomingUid;
35381b3eabc49736b89c4f99940f79785074955eaa5Mark Salyzyn            free(name);
354758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn            name = android::pidToName(element->getPid());
35581b3eabc49736b89c4f99940f79785074955eaa5Mark Salyzyn        } else {
356758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn            add(element->getPid());
35781b3eabc49736b89c4f99940f79785074955eaa5Mark Salyzyn        }
358758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn        EntryBaseDropped::add(element);
35981b3eabc49736b89c4f99940f79785074955eaa5Mark Salyzyn    }
360758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn
361501c373916e292764400dbae735f44b33378400fMark Salyzyn    std::string formatHeader(const std::string& name, log_id_t id) const;
362501c373916e292764400dbae735f44b33378400fMark Salyzyn    std::string format(const LogStatistics& stat, log_id_t id) const;
363344bff4391dd434dda501e812f18f524290c5a7cMark Salyzyn};
364344bff4391dd434dda501e812f18f524290c5a7cMark Salyzyn
36517ed6797df722464eb5cc6dfc3e1e32aec284b70Mark Salyzynstruct TidEntry : public EntryBaseDropped {
36617ed6797df722464eb5cc6dfc3e1e32aec284b70Mark Salyzyn    const pid_t tid;
367ee3b838e13dc2140ac2051c1012d471effd0fd5fMark Salyzyn    pid_t pid;
36817ed6797df722464eb5cc6dfc3e1e32aec284b70Mark Salyzyn    uid_t uid;
369501c373916e292764400dbae735f44b33378400fMark Salyzyn    char* name;
370501c373916e292764400dbae735f44b33378400fMark Salyzyn
371501c373916e292764400dbae735f44b33378400fMark Salyzyn    TidEntry(pid_t tid, pid_t pid)
372501c373916e292764400dbae735f44b33378400fMark Salyzyn        : EntryBaseDropped(),
373501c373916e292764400dbae735f44b33378400fMark Salyzyn          tid(tid),
374501c373916e292764400dbae735f44b33378400fMark Salyzyn          pid(pid),
375501c373916e292764400dbae735f44b33378400fMark Salyzyn          uid(android::pidToUid(tid)),
376501c373916e292764400dbae735f44b33378400fMark Salyzyn          name(android::tidToName(tid)) {
377501c373916e292764400dbae735f44b33378400fMark Salyzyn    }
378501c373916e292764400dbae735f44b33378400fMark Salyzyn    explicit TidEntry(LogBufferElement* element)
379501c373916e292764400dbae735f44b33378400fMark Salyzyn        : EntryBaseDropped(element),
380501c373916e292764400dbae735f44b33378400fMark Salyzyn          tid(element->getTid()),
381501c373916e292764400dbae735f44b33378400fMark Salyzyn          pid(element->getPid()),
382501c373916e292764400dbae735f44b33378400fMark Salyzyn          uid(element->getUid()),
383501c373916e292764400dbae735f44b33378400fMark Salyzyn          name(android::tidToName(tid)) {
384501c373916e292764400dbae735f44b33378400fMark Salyzyn    }
385501c373916e292764400dbae735f44b33378400fMark Salyzyn    TidEntry(const TidEntry& element)
386501c373916e292764400dbae735f44b33378400fMark Salyzyn        : EntryBaseDropped(element),
387501c373916e292764400dbae735f44b33378400fMark Salyzyn          tid(element.tid),
388501c373916e292764400dbae735f44b33378400fMark Salyzyn          pid(element.pid),
389501c373916e292764400dbae735f44b33378400fMark Salyzyn          uid(element.uid),
390501c373916e292764400dbae735f44b33378400fMark Salyzyn          name(element.name ? strdup(element.name) : NULL) {
391501c373916e292764400dbae735f44b33378400fMark Salyzyn    }
392501c373916e292764400dbae735f44b33378400fMark Salyzyn    ~TidEntry() {
393501c373916e292764400dbae735f44b33378400fMark Salyzyn        free(name);
394501c373916e292764400dbae735f44b33378400fMark Salyzyn    }
395501c373916e292764400dbae735f44b33378400fMark Salyzyn
396501c373916e292764400dbae735f44b33378400fMark Salyzyn    const pid_t& getKey() const {
397501c373916e292764400dbae735f44b33378400fMark Salyzyn        return tid;
398501c373916e292764400dbae735f44b33378400fMark Salyzyn    }
399501c373916e292764400dbae735f44b33378400fMark Salyzyn    const pid_t& getTid() const {
400501c373916e292764400dbae735f44b33378400fMark Salyzyn        return getKey();
401501c373916e292764400dbae735f44b33378400fMark Salyzyn    }
402501c373916e292764400dbae735f44b33378400fMark Salyzyn    const pid_t& getPid() const {
403501c373916e292764400dbae735f44b33378400fMark Salyzyn        return pid;
404501c373916e292764400dbae735f44b33378400fMark Salyzyn    }
405501c373916e292764400dbae735f44b33378400fMark Salyzyn    const uid_t& getUid() const {
406501c373916e292764400dbae735f44b33378400fMark Salyzyn        return uid;
407501c373916e292764400dbae735f44b33378400fMark Salyzyn    }
408501c373916e292764400dbae735f44b33378400fMark Salyzyn    const char* getName() const {
409501c373916e292764400dbae735f44b33378400fMark Salyzyn        return name;
410501c373916e292764400dbae735f44b33378400fMark Salyzyn    }
41117ed6797df722464eb5cc6dfc3e1e32aec284b70Mark Salyzyn
412758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn    inline void add(pid_t incomingTid) {
4130eeb06b932f185e10377e4494475d2cdd6adfa1bMark Salyzyn        if (name && !fastcmp<strncmp>(name, "zygote", 6)) {
41417ed6797df722464eb5cc6dfc3e1e32aec284b70Mark Salyzyn            free(name);
41517ed6797df722464eb5cc6dfc3e1e32aec284b70Mark Salyzyn            name = NULL;
41617ed6797df722464eb5cc6dfc3e1e32aec284b70Mark Salyzyn        }
41717ed6797df722464eb5cc6dfc3e1e32aec284b70Mark Salyzyn        if (!name) {
418758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn            name = android::tidToName(incomingTid);
41917ed6797df722464eb5cc6dfc3e1e32aec284b70Mark Salyzyn        }
42017ed6797df722464eb5cc6dfc3e1e32aec284b70Mark Salyzyn    }
42117ed6797df722464eb5cc6dfc3e1e32aec284b70Mark Salyzyn
422501c373916e292764400dbae735f44b33378400fMark Salyzyn    inline void add(LogBufferElement* element) {
423758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn        uid_t incomingUid = element->getUid();
424ee3b838e13dc2140ac2051c1012d471effd0fd5fMark Salyzyn        pid_t incomingPid = element->getPid();
425ee3b838e13dc2140ac2051c1012d471effd0fd5fMark Salyzyn        if ((getUid() != incomingUid) || (getPid() != incomingPid)) {
426758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn            uid = incomingUid;
427ee3b838e13dc2140ac2051c1012d471effd0fd5fMark Salyzyn            pid = incomingPid;
42817ed6797df722464eb5cc6dfc3e1e32aec284b70Mark Salyzyn            free(name);
429758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn            name = android::tidToName(element->getTid());
43017ed6797df722464eb5cc6dfc3e1e32aec284b70Mark Salyzyn        } else {
431758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn            add(element->getTid());
43217ed6797df722464eb5cc6dfc3e1e32aec284b70Mark Salyzyn        }
433758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn        EntryBaseDropped::add(element);
43417ed6797df722464eb5cc6dfc3e1e32aec284b70Mark Salyzyn    }
435758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn
436501c373916e292764400dbae735f44b33378400fMark Salyzyn    std::string formatHeader(const std::string& name, log_id_t id) const;
437501c373916e292764400dbae735f44b33378400fMark Salyzyn    std::string format(const LogStatistics& stat, log_id_t id) const;
43817ed6797df722464eb5cc6dfc3e1e32aec284b70Mark Salyzyn};
43917ed6797df722464eb5cc6dfc3e1e32aec284b70Mark Salyzyn
4406a06694a610d103afdf424b0bb69dc8f7f2b8e5aMark Salyzynstruct TagEntry : public EntryBaseDropped {
441344bff4391dd434dda501e812f18f524290c5a7cMark Salyzyn    const uint32_t tag;
442ee3b838e13dc2140ac2051c1012d471effd0fd5fMark Salyzyn    pid_t pid;
443344bff4391dd434dda501e812f18f524290c5a7cMark Salyzyn    uid_t uid;
444344bff4391dd434dda501e812f18f524290c5a7cMark Salyzyn
445501c373916e292764400dbae735f44b33378400fMark Salyzyn    explicit TagEntry(LogBufferElement* element)
446501c373916e292764400dbae735f44b33378400fMark Salyzyn        : EntryBaseDropped(element),
447501c373916e292764400dbae735f44b33378400fMark Salyzyn          tag(element->getTag()),
448501c373916e292764400dbae735f44b33378400fMark Salyzyn          pid(element->getPid()),
449501c373916e292764400dbae735f44b33378400fMark Salyzyn          uid(element->getUid()) {
450758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn    }
451344bff4391dd434dda501e812f18f524290c5a7cMark Salyzyn
452501c373916e292764400dbae735f44b33378400fMark Salyzyn    const uint32_t& getKey() const {
453501c373916e292764400dbae735f44b33378400fMark Salyzyn        return tag;
454501c373916e292764400dbae735f44b33378400fMark Salyzyn    }
455501c373916e292764400dbae735f44b33378400fMark Salyzyn    const pid_t& getPid() const {
456501c373916e292764400dbae735f44b33378400fMark Salyzyn        return pid;
457501c373916e292764400dbae735f44b33378400fMark Salyzyn    }
458501c373916e292764400dbae735f44b33378400fMark Salyzyn    const uid_t& getUid() const {
459501c373916e292764400dbae735f44b33378400fMark Salyzyn        return uid;
460501c373916e292764400dbae735f44b33378400fMark Salyzyn    }
461501c373916e292764400dbae735f44b33378400fMark Salyzyn    const char* getName() const {
462501c373916e292764400dbae735f44b33378400fMark Salyzyn        return android::tagToName(tag);
463501c373916e292764400dbae735f44b33378400fMark Salyzyn    }
46481b3eabc49736b89c4f99940f79785074955eaa5Mark Salyzyn
465501c373916e292764400dbae735f44b33378400fMark Salyzyn    inline void add(LogBufferElement* element) {
466ee3b838e13dc2140ac2051c1012d471effd0fd5fMark Salyzyn        if (uid != element->getUid()) {
467344bff4391dd434dda501e812f18f524290c5a7cMark Salyzyn            uid = -1;
468344bff4391dd434dda501e812f18f524290c5a7cMark Salyzyn        }
469ee3b838e13dc2140ac2051c1012d471effd0fd5fMark Salyzyn        if (pid != element->getPid()) {
470ee3b838e13dc2140ac2051c1012d471effd0fd5fMark Salyzyn            pid = -1;
471ee3b838e13dc2140ac2051c1012d471effd0fd5fMark Salyzyn        }
472a2c022257c5bed56fbc47de25c5d909bbe880f7bMark Salyzyn        EntryBaseDropped::add(element);
473344bff4391dd434dda501e812f18f524290c5a7cMark Salyzyn    }
474758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn
475501c373916e292764400dbae735f44b33378400fMark Salyzyn    std::string formatHeader(const std::string& name, log_id_t id) const;
476501c373916e292764400dbae735f44b33378400fMark Salyzyn    std::string format(const LogStatistics& stat, log_id_t id) const;
477720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn};
478720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn
4796a06694a610d103afdf424b0bb69dc8f7f2b8e5aMark Salyzyntemplate <typename TEntry>
4806a06694a610d103afdf424b0bb69dc8f7f2b8e5aMark Salyzynclass LogFindWorst {
481501c373916e292764400dbae735f44b33378400fMark Salyzyn    std::unique_ptr<const TEntry* []> sorted;
4826a06694a610d103afdf424b0bb69dc8f7f2b8e5aMark Salyzyn
483501c373916e292764400dbae735f44b33378400fMark Salyzyn   public:
484501c373916e292764400dbae735f44b33378400fMark Salyzyn    explicit LogFindWorst(std::unique_ptr<const TEntry* []>&& sorted)
485501c373916e292764400dbae735f44b33378400fMark Salyzyn        : sorted(std::move(sorted)) {
486501c373916e292764400dbae735f44b33378400fMark Salyzyn    }
4876a06694a610d103afdf424b0bb69dc8f7f2b8e5aMark Salyzyn
488501c373916e292764400dbae735f44b33378400fMark Salyzyn    void findWorst(int& worst, size_t& worst_sizes, size_t& second_worst_sizes,
489501c373916e292764400dbae735f44b33378400fMark Salyzyn                   size_t threshold) {
4906a06694a610d103afdf424b0bb69dc8f7f2b8e5aMark Salyzyn        if (sorted.get() && sorted[0] && sorted[1]) {
4916a06694a610d103afdf424b0bb69dc8f7f2b8e5aMark Salyzyn            worst_sizes = sorted[0]->getSizes();
4926a06694a610d103afdf424b0bb69dc8f7f2b8e5aMark Salyzyn            if ((worst_sizes > threshold)
4936a06694a610d103afdf424b0bb69dc8f7f2b8e5aMark Salyzyn                // Allow time horizon to extend roughly tenfold, assume
4946a06694a610d103afdf424b0bb69dc8f7f2b8e5aMark Salyzyn                // average entry length is 100 characters.
495501c373916e292764400dbae735f44b33378400fMark Salyzyn                && (worst_sizes > (10 * sorted[0]->getDropped()))) {
4966a06694a610d103afdf424b0bb69dc8f7f2b8e5aMark Salyzyn                worst = sorted[0]->getKey();
4976a06694a610d103afdf424b0bb69dc8f7f2b8e5aMark Salyzyn                second_worst_sizes = sorted[1]->getSizes();
4986a06694a610d103afdf424b0bb69dc8f7f2b8e5aMark Salyzyn                if (second_worst_sizes < threshold) {
4996a06694a610d103afdf424b0bb69dc8f7f2b8e5aMark Salyzyn                    second_worst_sizes = threshold;
5006a06694a610d103afdf424b0bb69dc8f7f2b8e5aMark Salyzyn                }
5016a06694a610d103afdf424b0bb69dc8f7f2b8e5aMark Salyzyn            }
5026a06694a610d103afdf424b0bb69dc8f7f2b8e5aMark Salyzyn        }
5036a06694a610d103afdf424b0bb69dc8f7f2b8e5aMark Salyzyn    }
5046a06694a610d103afdf424b0bb69dc8f7f2b8e5aMark Salyzyn
505501c373916e292764400dbae735f44b33378400fMark Salyzyn    void findWorst(int& worst, size_t worst_sizes, size_t& second_worst_sizes) {
5066a06694a610d103afdf424b0bb69dc8f7f2b8e5aMark Salyzyn        if (sorted.get() && sorted[0] && sorted[1]) {
5076a06694a610d103afdf424b0bb69dc8f7f2b8e5aMark Salyzyn            worst = sorted[0]->getKey();
508501c373916e292764400dbae735f44b33378400fMark Salyzyn            second_worst_sizes =
509501c373916e292764400dbae735f44b33378400fMark Salyzyn                worst_sizes - sorted[0]->getSizes() + sorted[1]->getSizes();
5106a06694a610d103afdf424b0bb69dc8f7f2b8e5aMark Salyzyn        }
5116a06694a610d103afdf424b0bb69dc8f7f2b8e5aMark Salyzyn    }
5126a06694a610d103afdf424b0bb69dc8f7f2b8e5aMark Salyzyn};
5136a06694a610d103afdf424b0bb69dc8f7f2b8e5aMark Salyzyn
51434facab86b0fe7ec613de92b46b637f864fb0682Mark Salyzyn// Log Statistics
51534facab86b0fe7ec613de92b46b637f864fb0682Mark Salyzynclass LogStatistics {
516c723df805a1a3199577cac947cebf2ab53abdb34Mark Salyzyn    friend UidEntry;
517c723df805a1a3199577cac947cebf2ab53abdb34Mark Salyzyn
51834facab86b0fe7ec613de92b46b637f864fb0682Mark Salyzyn    size_t mSizes[LOG_ID_MAX];
51934facab86b0fe7ec613de92b46b637f864fb0682Mark Salyzyn    size_t mElements[LOG_ID_MAX];
52058b8be8906f903ac3d83c41bcb0fb9c7841945f0Mark Salyzyn    size_t mDroppedElements[LOG_ID_MAX];
52197c1c2beee2cbd8c67c1cd507367e5b084d853c8Mark Salyzyn    size_t mSizesTotal[LOG_ID_MAX];
52297c1c2beee2cbd8c67c1cd507367e5b084d853c8Mark Salyzyn    size_t mElementsTotal[LOG_ID_MAX];
5233296291cffd13af13ea9e60a8ac1138101cf8e4cMark Salyzyn    static size_t SizesTotal;
524720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn    bool enable;
52534facab86b0fe7ec613de92b46b637f864fb0682Mark Salyzyn
52697c1c2beee2cbd8c67c1cd507367e5b084d853c8Mark Salyzyn    // uid to size list
527720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn    typedef LogHashtable<uid_t, UidEntry> uidTable_t;
52897c1c2beee2cbd8c67c1cd507367e5b084d853c8Mark Salyzyn    uidTable_t uidTable[LOG_ID_MAX];
529e457b74ce6ee6d799812dc2ec5e4b8b18bcd3e91Mark Salyzyn
530bec3c3def945576d59d3344c16e149e6d9154e15Mark Salyzyn    // pid of system to size list
531bec3c3def945576d59d3344c16e149e6d9154e15Mark Salyzyn    typedef LogHashtable<pid_t, PidEntry> pidSystemTable_t;
532bec3c3def945576d59d3344c16e149e6d9154e15Mark Salyzyn    pidSystemTable_t pidSystemTable[LOG_ID_MAX];
533bec3c3def945576d59d3344c16e149e6d9154e15Mark Salyzyn
534720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn    // pid to uid list
535720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn    typedef LogHashtable<pid_t, PidEntry> pidTable_t;
536720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn    pidTable_t pidTable;
537720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn
53817ed6797df722464eb5cc6dfc3e1e32aec284b70Mark Salyzyn    // tid to uid list
53917ed6797df722464eb5cc6dfc3e1e32aec284b70Mark Salyzyn    typedef LogHashtable<pid_t, TidEntry> tidTable_t;
54017ed6797df722464eb5cc6dfc3e1e32aec284b70Mark Salyzyn    tidTable_t tidTable;
54117ed6797df722464eb5cc6dfc3e1e32aec284b70Mark Salyzyn
542344bff4391dd434dda501e812f18f524290c5a7cMark Salyzyn    // tag list
543344bff4391dd434dda501e812f18f524290c5a7cMark Salyzyn    typedef LogHashtable<uint32_t, TagEntry> tagTable_t;
544344bff4391dd434dda501e812f18f524290c5a7cMark Salyzyn    tagTable_t tagTable;
545344bff4391dd434dda501e812f18f524290c5a7cMark Salyzyn
546083b037c0740ca00f72429e4457bfdd4b4d4dfa7Mark Salyzyn    // security tag list
547083b037c0740ca00f72429e4457bfdd4b4d4dfa7Mark Salyzyn    tagTable_t securityTagTable;
548083b037c0740ca00f72429e4457bfdd4b4d4dfa7Mark Salyzyn
5496d981af12023bcaf22bfa0612a85ae4580ecb971Mark Salyzyn    size_t sizeOf() const {
5506d981af12023bcaf22bfa0612a85ae4580ecb971Mark Salyzyn        size_t size = sizeof(*this) + pidTable.sizeOf() + tidTable.sizeOf() +
551b0672290e320113f4b6d8fc6bb2d1e0afe493c5cMark Salyzyn                      tagTable.sizeOf() + securityTagTable.sizeOf() +
552b0672290e320113f4b6d8fc6bb2d1e0afe493c5cMark Salyzyn                      (pidTable.size() * sizeof(pidTable_t::iterator)) +
553b0672290e320113f4b6d8fc6bb2d1e0afe493c5cMark Salyzyn                      (tagTable.size() * sizeof(tagTable_t::iterator));
554501c373916e292764400dbae735f44b33378400fMark Salyzyn        for (auto it : pidTable) {
5556d981af12023bcaf22bfa0612a85ae4580ecb971Mark Salyzyn            const char* name = it.second.getName();
5566d981af12023bcaf22bfa0612a85ae4580ecb971Mark Salyzyn            if (name) size += strlen(name) + 1;
5576d981af12023bcaf22bfa0612a85ae4580ecb971Mark Salyzyn        }
558501c373916e292764400dbae735f44b33378400fMark Salyzyn        for (auto it : tidTable) {
5596d981af12023bcaf22bfa0612a85ae4580ecb971Mark Salyzyn            const char* name = it.second.getName();
5606d981af12023bcaf22bfa0612a85ae4580ecb971Mark Salyzyn            if (name) size += strlen(name) + 1;
5616d981af12023bcaf22bfa0612a85ae4580ecb971Mark Salyzyn        }
5626d981af12023bcaf22bfa0612a85ae4580ecb971Mark Salyzyn        log_id_for_each(id) {
5636d981af12023bcaf22bfa0612a85ae4580ecb971Mark Salyzyn            size += uidTable[id].sizeOf();
564b0672290e320113f4b6d8fc6bb2d1e0afe493c5cMark Salyzyn            size += uidTable[id].size() * sizeof(uidTable_t::iterator);
5656d981af12023bcaf22bfa0612a85ae4580ecb971Mark Salyzyn            size += pidSystemTable[id].sizeOf();
566501c373916e292764400dbae735f44b33378400fMark Salyzyn            size +=
567501c373916e292764400dbae735f44b33378400fMark Salyzyn                pidSystemTable[id].size() * sizeof(pidSystemTable_t::iterator);
5686d981af12023bcaf22bfa0612a85ae4580ecb971Mark Salyzyn        }
5696d981af12023bcaf22bfa0612a85ae4580ecb971Mark Salyzyn        return size;
5706d981af12023bcaf22bfa0612a85ae4580ecb971Mark Salyzyn    }
5716d981af12023bcaf22bfa0612a85ae4580ecb971Mark Salyzyn
572501c373916e292764400dbae735f44b33378400fMark Salyzyn   public:
57334facab86b0fe7ec613de92b46b637f864fb0682Mark Salyzyn    LogStatistics();
57434facab86b0fe7ec613de92b46b637f864fb0682Mark Salyzyn
575501c373916e292764400dbae735f44b33378400fMark Salyzyn    void enableStatistics() {
576501c373916e292764400dbae735f44b33378400fMark Salyzyn        enable = true;
577501c373916e292764400dbae735f44b33378400fMark Salyzyn    }
57834facab86b0fe7ec613de92b46b637f864fb0682Mark Salyzyn
579501c373916e292764400dbae735f44b33378400fMark Salyzyn    void add(LogBufferElement* entry);
580501c373916e292764400dbae735f44b33378400fMark Salyzyn    void subtract(LogBufferElement* entry);
581ab0dcf682867bd7e1fdebfd8d8f9fafaccfad7f6Mark Salyzyn    // entry->setDropped(1) must follow this call
582501c373916e292764400dbae735f44b33378400fMark Salyzyn    void drop(LogBufferElement* entry);
583aaad42f47c7363d68ddfb9ef8f1b51972c4d429dMark Salyzyn    // Correct for coalescing two entries referencing dropped content
584501c373916e292764400dbae735f44b33378400fMark Salyzyn    void erase(LogBufferElement* element) {
58558b8be8906f903ac3d83c41bcb0fb9c7841945f0Mark Salyzyn        log_id_t log_id = element->getLogId();
58658b8be8906f903ac3d83c41bcb0fb9c7841945f0Mark Salyzyn        --mElements[log_id];
58758b8be8906f903ac3d83c41bcb0fb9c7841945f0Mark Salyzyn        --mDroppedElements[log_id];
58858b8be8906f903ac3d83c41bcb0fb9c7841945f0Mark Salyzyn    }
589e457b74ce6ee6d799812dc2ec5e4b8b18bcd3e91Mark Salyzyn
5906a06694a610d103afdf424b0bb69dc8f7f2b8e5aMark Salyzyn    LogFindWorst<UidEntry> sort(uid_t uid, pid_t pid, size_t len, log_id id) {
5916a06694a610d103afdf424b0bb69dc8f7f2b8e5aMark Salyzyn        return LogFindWorst<UidEntry>(uidTable[id].sort(uid, pid, len));
5926a06694a610d103afdf424b0bb69dc8f7f2b8e5aMark Salyzyn    }
593501c373916e292764400dbae735f44b33378400fMark Salyzyn    LogFindWorst<PidEntry> sortPids(uid_t uid, pid_t pid, size_t len,
594501c373916e292764400dbae735f44b33378400fMark Salyzyn                                    log_id id) {
5956a06694a610d103afdf424b0bb69dc8f7f2b8e5aMark Salyzyn        return LogFindWorst<PidEntry>(pidSystemTable[id].sort(uid, pid, len));
596758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn    }
5976a06694a610d103afdf424b0bb69dc8f7f2b8e5aMark Salyzyn    LogFindWorst<TagEntry> sortTags(uid_t uid, pid_t pid, size_t len, log_id) {
5986a06694a610d103afdf424b0bb69dc8f7f2b8e5aMark Salyzyn        return LogFindWorst<TagEntry>(tagTable.sort(uid, pid, len));
599bec3c3def945576d59d3344c16e149e6d9154e15Mark Salyzyn    }
60034facab86b0fe7ec613de92b46b637f864fb0682Mark Salyzyn
60134facab86b0fe7ec613de92b46b637f864fb0682Mark Salyzyn    // fast track current value by id only
602501c373916e292764400dbae735f44b33378400fMark Salyzyn    size_t sizes(log_id_t id) const {
603501c373916e292764400dbae735f44b33378400fMark Salyzyn        return mSizes[id];
604501c373916e292764400dbae735f44b33378400fMark Salyzyn    }
605501c373916e292764400dbae735f44b33378400fMark Salyzyn    size_t elements(log_id_t id) const {
606501c373916e292764400dbae735f44b33378400fMark Salyzyn        return mElements[id];
607501c373916e292764400dbae735f44b33378400fMark Salyzyn    }
60858b8be8906f903ac3d83c41bcb0fb9c7841945f0Mark Salyzyn    size_t realElements(log_id_t id) const {
60958b8be8906f903ac3d83c41bcb0fb9c7841945f0Mark Salyzyn        return mElements[id] - mDroppedElements[id];
61058b8be8906f903ac3d83c41bcb0fb9c7841945f0Mark Salyzyn    }
611501c373916e292764400dbae735f44b33378400fMark Salyzyn    size_t sizesTotal(log_id_t id) const {
612501c373916e292764400dbae735f44b33378400fMark Salyzyn        return mSizesTotal[id];
613501c373916e292764400dbae735f44b33378400fMark Salyzyn    }
614501c373916e292764400dbae735f44b33378400fMark Salyzyn    size_t elementsTotal(log_id_t id) const {
615501c373916e292764400dbae735f44b33378400fMark Salyzyn        return mElementsTotal[id];
616501c373916e292764400dbae735f44b33378400fMark Salyzyn    }
617501c373916e292764400dbae735f44b33378400fMark Salyzyn    static size_t sizesTotal() {
618501c373916e292764400dbae735f44b33378400fMark Salyzyn        return SizesTotal;
619501c373916e292764400dbae735f44b33378400fMark Salyzyn    }
62034facab86b0fe7ec613de92b46b637f864fb0682Mark Salyzyn
621ee3b838e13dc2140ac2051c1012d471effd0fd5fMark Salyzyn    std::string format(uid_t uid, pid_t pid, unsigned int logMask) const;
6229a03863e88da99ba010342c874252089dd771f7fMark Salyzyn
623ed777e9eece54bf899f1a77a83f8b702970de686Mark Salyzyn    // helper (must be locked directly or implicitly by mLogElementsLock)
624501c373916e292764400dbae735f44b33378400fMark Salyzyn    const char* pidToName(pid_t pid) const;
6254ba0387af5acc52e43e4004ccb4c46b8bc700349Mark Salyzyn    uid_t pidToUid(pid_t pid);
626501c373916e292764400dbae735f44b33378400fMark Salyzyn    const char* uidToName(uid_t uid) const;
62734facab86b0fe7ec613de92b46b637f864fb0682Mark Salyzyn};
62834facab86b0fe7ec613de92b46b637f864fb0682Mark Salyzyn
629501c373916e292764400dbae735f44b33378400fMark Salyzyn#endif  // _LOGD_LOG_STATISTICS_H__
630