LogStatistics.h revision c723df805a1a3199577cac947cebf2ab53abdb34
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
20720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn#include <memory>
21720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn#include <stdlib.h>
2234facab86b0fe7ec613de92b46b637f864fb0682Mark Salyzyn#include <sys/types.h>
2334facab86b0fe7ec613de92b46b637f864fb0682Mark Salyzyn
24758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn#include <algorithm> // std::max
25758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn#include <string>    // std::string
26511338dd575572d567c04d69eaea60627b6c3452Mark Salyzyn#include <unordered_map>
27511338dd575572d567c04d69eaea60627b6c3452Mark Salyzyn
28758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn#include <base/stringprintf.h>
2934facab86b0fe7ec613de92b46b637f864fb0682Mark Salyzyn#include <log/log.h>
30758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn#include <private/android_filesystem_config.h>
3197c1c2beee2cbd8c67c1cd507367e5b084d853c8Mark Salyzyn
3297c1c2beee2cbd8c67c1cd507367e5b084d853c8Mark Salyzyn#include "LogBufferElement.h"
335ac5c6b19364b5b3061a59db796b2357c95c3b64Mark Salyzyn#include "LogUtils.h"
3434facab86b0fe7ec613de92b46b637f864fb0682Mark Salyzyn
3534facab86b0fe7ec613de92b46b637f864fb0682Mark Salyzyn#define log_id_for_each(i) \
3634facab86b0fe7ec613de92b46b637f864fb0682Mark Salyzyn    for (log_id_t i = LOG_ID_MIN; i < LOG_ID_MAX; i = (log_id_t) (i + 1))
3734facab86b0fe7ec613de92b46b637f864fb0682Mark Salyzyn
38758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzynclass LogStatistics;
39758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn
40720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyntemplate <typename TKey, typename TEntry>
41511338dd575572d567c04d69eaea60627b6c3452Mark Salyzynclass LogHashtable {
42511338dd575572d567c04d69eaea60627b6c3452Mark Salyzyn
43511338dd575572d567c04d69eaea60627b6c3452Mark Salyzyn    std::unordered_map<TKey, TEntry> map;
44511338dd575572d567c04d69eaea60627b6c3452Mark Salyzyn
45720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzynpublic:
46511338dd575572d567c04d69eaea60627b6c3452Mark Salyzyn
47511338dd575572d567c04d69eaea60627b6c3452Mark Salyzyn    typedef typename std::unordered_map<TKey, TEntry>::iterator iterator;
48758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn    typedef typename std::unordered_map<TKey, TEntry>::const_iterator const_iterator;
49511338dd575572d567c04d69eaea60627b6c3452Mark Salyzyn
50758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn    std::unique_ptr<const TEntry *[]> sort(size_t len) const {
51758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn        if (!len) {
52720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn            std::unique_ptr<const TEntry *[]> sorted(NULL);
53720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn            return sorted;
54720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn        }
55720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn
56758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn        const TEntry **retval = new const TEntry* [len];
57758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn        memset(retval, 0, sizeof(*retval) * len);
58720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn
59758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn        for(const_iterator it = map.begin(); it != map.end(); ++it) {
60511338dd575572d567c04d69eaea60627b6c3452Mark Salyzyn            const TEntry &entry = it->second;
61758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn            size_t sizes = entry.getSizes();
62758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn            ssize_t index = len - 1;
63758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn            while ((!retval[index] || (sizes > retval[index]->getSizes()))
64758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn                    && (--index >= 0))
65720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn                ;
66758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn            if (++index < (ssize_t)len) {
67758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn                size_t num = len - index - 1;
68758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn                if (num) {
69758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn                    memmove(&retval[index + 1], &retval[index],
70758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn                            num * sizeof(retval[0]));
71720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn                }
72758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn                retval[index] = &entry;
73720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn            }
74720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn        }
75720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn        std::unique_ptr<const TEntry *[]> sorted(retval);
76720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn        return sorted;
77720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn    }
78720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn
79758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn    inline iterator add(TKey key, LogBufferElement *element) {
80511338dd575572d567c04d69eaea60627b6c3452Mark Salyzyn        iterator it = map.find(key);
81511338dd575572d567c04d69eaea60627b6c3452Mark Salyzyn        if (it == map.end()) {
82758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn            it = map.insert(std::make_pair(key, TEntry(element))).first;
83511338dd575572d567c04d69eaea60627b6c3452Mark Salyzyn        } else {
84758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn            it->second.add(element);
8581b3eabc49736b89c4f99940f79785074955eaa5Mark Salyzyn        }
86511338dd575572d567c04d69eaea60627b6c3452Mark Salyzyn        return it;
8781b3eabc49736b89c4f99940f79785074955eaa5Mark Salyzyn    }
8881b3eabc49736b89c4f99940f79785074955eaa5Mark Salyzyn
89511338dd575572d567c04d69eaea60627b6c3452Mark Salyzyn    inline iterator add(TKey key) {
90511338dd575572d567c04d69eaea60627b6c3452Mark Salyzyn        iterator it = map.find(key);
91511338dd575572d567c04d69eaea60627b6c3452Mark Salyzyn        if (it == map.end()) {
92511338dd575572d567c04d69eaea60627b6c3452Mark Salyzyn            it = map.insert(std::make_pair(key, TEntry(key))).first;
93511338dd575572d567c04d69eaea60627b6c3452Mark Salyzyn        } else {
94511338dd575572d567c04d69eaea60627b6c3452Mark Salyzyn            it->second.add(key);
9581b3eabc49736b89c4f99940f79785074955eaa5Mark Salyzyn        }
96511338dd575572d567c04d69eaea60627b6c3452Mark Salyzyn        return it;
9781b3eabc49736b89c4f99940f79785074955eaa5Mark Salyzyn    }
9881b3eabc49736b89c4f99940f79785074955eaa5Mark Salyzyn
99758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn    void subtract(TKey key, LogBufferElement *element) {
100511338dd575572d567c04d69eaea60627b6c3452Mark Salyzyn        iterator it = map.find(key);
101758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn        if ((it != map.end()) && it->second.subtract(element)) {
102511338dd575572d567c04d69eaea60627b6c3452Mark Salyzyn            map.erase(it);
10381b3eabc49736b89c4f99940f79785074955eaa5Mark Salyzyn        }
10481b3eabc49736b89c4f99940f79785074955eaa5Mark Salyzyn    }
10581b3eabc49736b89c4f99940f79785074955eaa5Mark Salyzyn
106758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn    inline void drop(TKey key, LogBufferElement *element) {
107511338dd575572d567c04d69eaea60627b6c3452Mark Salyzyn        iterator it = map.find(key);
108511338dd575572d567c04d69eaea60627b6c3452Mark Salyzyn        if (it != map.end()) {
109758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn            it->second.drop(element);
11081b3eabc49736b89c4f99940f79785074955eaa5Mark Salyzyn        }
11181b3eabc49736b89c4f99940f79785074955eaa5Mark Salyzyn    }
11281b3eabc49736b89c4f99940f79785074955eaa5Mark Salyzyn
113511338dd575572d567c04d69eaea60627b6c3452Mark Salyzyn    inline iterator begin() { return map.begin(); }
114758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn    inline const_iterator begin() const { return map.begin(); }
115511338dd575572d567c04d69eaea60627b6c3452Mark Salyzyn    inline iterator end() { return map.end(); }
116758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn    inline const_iterator end() const { return map.end(); }
117758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn
118758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn    std::string format(
119758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn            const LogStatistics &stat,
120758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn            uid_t uid,
121758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn            const std::string &name = std::string(""),
122758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn            log_id_t id = LOG_ID_MAX) const {
123758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn        static const size_t maximum_sorted_entries = 32;
124758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn        std::string output;
125758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn        std::unique_ptr<const TEntry *[]> sorted = sort(maximum_sorted_entries);
126758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn
127758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn        if (!sorted.get()) {
128758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn            return output;
129758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn        }
130758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn        bool headerPrinted = false;
131758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn        for (size_t index = 0; index < maximum_sorted_entries; ++index) {
132758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn            const TEntry *entry = sorted[index];
133758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn            if (!entry) {
134758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn                break;
135758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn            }
136758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn            if (entry->getSizes() <= (sorted[0]->getSizes() / 100)) {
137758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn                break;
138758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn            }
139758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn            if ((uid != AID_ROOT) && (uid != entry->getUid())) {
140758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn                continue;
141758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn            }
142758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn            if (!headerPrinted) {
143758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn                output += "\n\n";
144758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn                output += entry->formatHeader(name, id);
145758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn                headerPrinted = true;
146758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn            }
147758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn            output += entry->format(stat, id);
148758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn        }
149758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn        return output;
150758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn    }
151720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn};
152720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn
153758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzynnamespace EntryBaseConstants {
154758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn    static constexpr size_t pruned_len = 14;
155758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn    static constexpr size_t total_len = 80;
156758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn}
157758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn
15881b3eabc49736b89c4f99940f79785074955eaa5Mark Salyzynstruct EntryBase {
15997c1c2beee2cbd8c67c1cd507367e5b084d853c8Mark Salyzyn    size_t size;
16034facab86b0fe7ec613de92b46b637f864fb0682Mark Salyzyn
16181b3eabc49736b89c4f99940f79785074955eaa5Mark Salyzyn    EntryBase():size(0) { }
162758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn    EntryBase(LogBufferElement *element):size(element->getMsgLen()) { }
16334facab86b0fe7ec613de92b46b637f864fb0682Mark Salyzyn
16497c1c2beee2cbd8c67c1cd507367e5b084d853c8Mark Salyzyn    size_t getSizes() const { return size; }
16581b3eabc49736b89c4f99940f79785074955eaa5Mark Salyzyn
166758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn    inline void add(LogBufferElement *element) { size += element->getMsgLen(); }
167758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn    inline bool subtract(LogBufferElement *element) {
168758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn        size -= element->getMsgLen();
169758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn        return !size;
170758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn    }
171758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn
172758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn    static std::string formatLine(
173758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn            const std::string &name,
174758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn            const std::string &size,
175758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn            const std::string &pruned) {
176758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn        ssize_t drop_len = std::max(pruned.length() + 1,
177758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn                                    EntryBaseConstants::pruned_len);
178758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn        ssize_t size_len = std::max(size.length() + 1,
179758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn                                    EntryBaseConstants::total_len
180758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn                                        - name.length() - drop_len - 1);
181758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn
182758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn        if (pruned.length()) {
183758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn            return android::base::StringPrintf("%s%*s%*s\n", name.c_str(),
184758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn                                               (int)size_len, size.c_str(),
185758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn                                               (int)drop_len, pruned.c_str());
186758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn        } else {
187758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn            return android::base::StringPrintf("%s%*s\n", name.c_str(),
188758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn                                               (int)size_len, size.c_str());
189758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn        }
190758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn    }
19181b3eabc49736b89c4f99940f79785074955eaa5Mark Salyzyn};
19281b3eabc49736b89c4f99940f79785074955eaa5Mark Salyzyn
19381b3eabc49736b89c4f99940f79785074955eaa5Mark Salyzynstruct EntryBaseDropped : public EntryBase {
19481b3eabc49736b89c4f99940f79785074955eaa5Mark Salyzyn    size_t dropped;
19581b3eabc49736b89c4f99940f79785074955eaa5Mark Salyzyn
19681b3eabc49736b89c4f99940f79785074955eaa5Mark Salyzyn    EntryBaseDropped():dropped(0) { }
197758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn    EntryBaseDropped(LogBufferElement *element):
198758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn            EntryBase(element),
199758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn            dropped(element->getDropped()){
200758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn    }
20181b3eabc49736b89c4f99940f79785074955eaa5Mark Salyzyn
202ab0dcf682867bd7e1fdebfd8d8f9fafaccfad7f6Mark Salyzyn    size_t getDropped() const { return dropped; }
203ab0dcf682867bd7e1fdebfd8d8f9fafaccfad7f6Mark Salyzyn
204758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn    inline void add(LogBufferElement *element) {
205758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn        dropped += element->getDropped();
206758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn        EntryBase::add(element);
20781b3eabc49736b89c4f99940f79785074955eaa5Mark Salyzyn    }
208758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn    inline bool subtract(LogBufferElement *element) {
209758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn        dropped -= element->getDropped();
210758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn        return EntryBase::subtract(element) && !dropped;
21181b3eabc49736b89c4f99940f79785074955eaa5Mark Salyzyn    }
212758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn    inline void drop(LogBufferElement *element) {
21381b3eabc49736b89c4f99940f79785074955eaa5Mark Salyzyn        dropped += 1;
214758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn        EntryBase::subtract(element);
21581b3eabc49736b89c4f99940f79785074955eaa5Mark Salyzyn    }
21681b3eabc49736b89c4f99940f79785074955eaa5Mark Salyzyn};
21781b3eabc49736b89c4f99940f79785074955eaa5Mark Salyzyn
21881b3eabc49736b89c4f99940f79785074955eaa5Mark Salyzynstruct UidEntry : public EntryBaseDropped {
21981b3eabc49736b89c4f99940f79785074955eaa5Mark Salyzyn    const uid_t uid;
22081b3eabc49736b89c4f99940f79785074955eaa5Mark Salyzyn
221758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn    UidEntry(LogBufferElement *element):
222758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn            EntryBaseDropped(element),
223758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn            uid(element->getUid()) {
224758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn    }
22581b3eabc49736b89c4f99940f79785074955eaa5Mark Salyzyn
22681b3eabc49736b89c4f99940f79785074955eaa5Mark Salyzyn    inline const uid_t&getKey() const { return uid; }
227758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn    inline const uid_t&getUid() const { return uid; }
228758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn
229758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn    std::string formatHeader(const std::string &name, log_id_t id) const;
230758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn    std::string format(const LogStatistics &stat, log_id_t id) const;
23134facab86b0fe7ec613de92b46b637f864fb0682Mark Salyzyn};
23234facab86b0fe7ec613de92b46b637f864fb0682Mark Salyzyn
23381b3eabc49736b89c4f99940f79785074955eaa5Mark Salyzynnamespace android {
23481b3eabc49736b89c4f99940f79785074955eaa5Mark Salyzynuid_t pidToUid(pid_t pid);
23581b3eabc49736b89c4f99940f79785074955eaa5Mark Salyzyn}
23681b3eabc49736b89c4f99940f79785074955eaa5Mark Salyzyn
23781b3eabc49736b89c4f99940f79785074955eaa5Mark Salyzynstruct PidEntry : public EntryBaseDropped {
238720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn    const pid_t pid;
239720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn    uid_t uid;
240720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn    char *name;
241720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn
242758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn    PidEntry(pid_t pid):
243758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn            EntryBaseDropped(),
244758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn            pid(pid),
245758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn            uid(android::pidToUid(pid)),
246758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn            name(android::pidToName(pid)) {
247758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn    }
248758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn    PidEntry(LogBufferElement *element):
249758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn            EntryBaseDropped(element),
250758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn            pid(element->getPid()),
251758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn            uid(element->getUid()),
252758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn            name(android::pidToName(pid)) {
253758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn    }
254758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn    PidEntry(const PidEntry &element):
255758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn            EntryBaseDropped(element),
256758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn            pid(element.pid),
257758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn            uid(element.uid),
258758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn            name(element.name ? strdup(element.name) : NULL) {
259758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn    }
260720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn    ~PidEntry() { free(name); }
261720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn
262720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn    const pid_t&getKey() const { return pid; }
263720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn    const uid_t&getUid() const { return uid; }
264720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn    const char*getName() const { return name; }
26581b3eabc49736b89c4f99940f79785074955eaa5Mark Salyzyn
266758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn    inline void add(pid_t newPid) {
267ddda212faa81d62f637926680cd8163345120f71Mark Salyzyn        if (name && !fast<strncmp>(name, "zygote", 6)) {
268aa43ae2268076227e8b72ea095f8aeac439b3168Mark Salyzyn            free(name);
269aa43ae2268076227e8b72ea095f8aeac439b3168Mark Salyzyn            name = NULL;
270aa43ae2268076227e8b72ea095f8aeac439b3168Mark Salyzyn        }
27181b3eabc49736b89c4f99940f79785074955eaa5Mark Salyzyn        if (!name) {
272758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn            name = android::pidToName(newPid);
27381b3eabc49736b89c4f99940f79785074955eaa5Mark Salyzyn        }
27481b3eabc49736b89c4f99940f79785074955eaa5Mark Salyzyn    }
27581b3eabc49736b89c4f99940f79785074955eaa5Mark Salyzyn
276758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn    inline void add(LogBufferElement *element) {
277758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn        uid_t incomingUid = element->getUid();
278758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn        if (getUid() != incomingUid) {
279758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn            uid = incomingUid;
28081b3eabc49736b89c4f99940f79785074955eaa5Mark Salyzyn            free(name);
281758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn            name = android::pidToName(element->getPid());
28281b3eabc49736b89c4f99940f79785074955eaa5Mark Salyzyn        } else {
283758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn            add(element->getPid());
28481b3eabc49736b89c4f99940f79785074955eaa5Mark Salyzyn        }
285758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn        EntryBaseDropped::add(element);
28681b3eabc49736b89c4f99940f79785074955eaa5Mark Salyzyn    }
287758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn
288758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn    std::string formatHeader(const std::string &name, log_id_t id) const;
289758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn    std::string format(const LogStatistics &stat, log_id_t id) const;
290344bff4391dd434dda501e812f18f524290c5a7cMark Salyzyn};
291344bff4391dd434dda501e812f18f524290c5a7cMark Salyzyn
29217ed6797df722464eb5cc6dfc3e1e32aec284b70Mark Salyzynstruct TidEntry : public EntryBaseDropped {
29317ed6797df722464eb5cc6dfc3e1e32aec284b70Mark Salyzyn    const pid_t tid;
29417ed6797df722464eb5cc6dfc3e1e32aec284b70Mark Salyzyn    uid_t uid;
29517ed6797df722464eb5cc6dfc3e1e32aec284b70Mark Salyzyn    char *name;
29617ed6797df722464eb5cc6dfc3e1e32aec284b70Mark Salyzyn
297758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn    TidEntry(pid_t tid):
298758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn            EntryBaseDropped(),
299758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn            tid(tid),
300758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn            uid(android::pidToUid(tid)),
301758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn            name(android::tidToName(tid)) {
302758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn    }
303758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn    TidEntry(LogBufferElement *element):
304758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn            EntryBaseDropped(element),
305758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn            tid(element->getTid()),
306758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn            uid(element->getUid()),
307758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn            name(android::tidToName(tid)) {
308758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn    }
309758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn    TidEntry(const TidEntry &element):
310758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn            EntryBaseDropped(element),
311758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn            tid(element.tid),
312758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn            uid(element.uid),
313758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn            name(element.name ? strdup(element.name) : NULL) {
314758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn    }
31517ed6797df722464eb5cc6dfc3e1e32aec284b70Mark Salyzyn    ~TidEntry() { free(name); }
31617ed6797df722464eb5cc6dfc3e1e32aec284b70Mark Salyzyn
31717ed6797df722464eb5cc6dfc3e1e32aec284b70Mark Salyzyn    const pid_t&getKey() const { return tid; }
31817ed6797df722464eb5cc6dfc3e1e32aec284b70Mark Salyzyn    const uid_t&getUid() const { return uid; }
31917ed6797df722464eb5cc6dfc3e1e32aec284b70Mark Salyzyn    const char*getName() const { return name; }
32017ed6797df722464eb5cc6dfc3e1e32aec284b70Mark Salyzyn
321758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn    inline void add(pid_t incomingTid) {
322ddda212faa81d62f637926680cd8163345120f71Mark Salyzyn        if (name && !fast<strncmp>(name, "zygote", 6)) {
32317ed6797df722464eb5cc6dfc3e1e32aec284b70Mark Salyzyn            free(name);
32417ed6797df722464eb5cc6dfc3e1e32aec284b70Mark Salyzyn            name = NULL;
32517ed6797df722464eb5cc6dfc3e1e32aec284b70Mark Salyzyn        }
32617ed6797df722464eb5cc6dfc3e1e32aec284b70Mark Salyzyn        if (!name) {
327758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn            name = android::tidToName(incomingTid);
32817ed6797df722464eb5cc6dfc3e1e32aec284b70Mark Salyzyn        }
32917ed6797df722464eb5cc6dfc3e1e32aec284b70Mark Salyzyn    }
33017ed6797df722464eb5cc6dfc3e1e32aec284b70Mark Salyzyn
331758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn    inline void add(LogBufferElement *element) {
332758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn        uid_t incomingUid = element->getUid();
333758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn        if (getUid() != incomingUid) {
334758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn            uid = incomingUid;
33517ed6797df722464eb5cc6dfc3e1e32aec284b70Mark Salyzyn            free(name);
336758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn            name = android::tidToName(element->getTid());
33717ed6797df722464eb5cc6dfc3e1e32aec284b70Mark Salyzyn        } else {
338758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn            add(element->getTid());
33917ed6797df722464eb5cc6dfc3e1e32aec284b70Mark Salyzyn        }
340758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn        EntryBaseDropped::add(element);
34117ed6797df722464eb5cc6dfc3e1e32aec284b70Mark Salyzyn    }
342758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn
343758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn    std::string formatHeader(const std::string &name, log_id_t id) const;
344758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn    std::string format(const LogStatistics &stat, log_id_t id) const;
34517ed6797df722464eb5cc6dfc3e1e32aec284b70Mark Salyzyn};
34617ed6797df722464eb5cc6dfc3e1e32aec284b70Mark Salyzyn
347344bff4391dd434dda501e812f18f524290c5a7cMark Salyzynstruct TagEntry : public EntryBase {
348344bff4391dd434dda501e812f18f524290c5a7cMark Salyzyn    const uint32_t tag;
349344bff4391dd434dda501e812f18f524290c5a7cMark Salyzyn    uid_t uid;
350344bff4391dd434dda501e812f18f524290c5a7cMark Salyzyn
351758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn    TagEntry(LogBufferElement *element):
352758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn            EntryBase(element),
353758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn            tag(element->getTag()),
354758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn            uid(element->getUid()) {
355758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn    }
356344bff4391dd434dda501e812f18f524290c5a7cMark Salyzyn
357344bff4391dd434dda501e812f18f524290c5a7cMark Salyzyn    const uint32_t&getKey() const { return tag; }
358344bff4391dd434dda501e812f18f524290c5a7cMark Salyzyn    const uid_t&getUid() const { return uid; }
359344bff4391dd434dda501e812f18f524290c5a7cMark Salyzyn    const char*getName() const { return android::tagToName(tag); }
36081b3eabc49736b89c4f99940f79785074955eaa5Mark Salyzyn
361758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn    inline void add(LogBufferElement *element) {
362758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn        uid_t incomingUid = element->getUid();
363758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn        if (uid != incomingUid) {
364344bff4391dd434dda501e812f18f524290c5a7cMark Salyzyn            uid = -1;
365344bff4391dd434dda501e812f18f524290c5a7cMark Salyzyn        }
366758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn        EntryBase::add(element);
367344bff4391dd434dda501e812f18f524290c5a7cMark Salyzyn    }
368758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn
369758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn    std::string formatHeader(const std::string &name, log_id_t id) const;
370758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn    std::string format(const LogStatistics &stat, log_id_t id) const;
371720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn};
372720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn
37334facab86b0fe7ec613de92b46b637f864fb0682Mark Salyzyn// Log Statistics
37434facab86b0fe7ec613de92b46b637f864fb0682Mark Salyzynclass LogStatistics {
375c723df805a1a3199577cac947cebf2ab53abdb34Mark Salyzyn    friend UidEntry;
376c723df805a1a3199577cac947cebf2ab53abdb34Mark Salyzyn
37734facab86b0fe7ec613de92b46b637f864fb0682Mark Salyzyn    size_t mSizes[LOG_ID_MAX];
37834facab86b0fe7ec613de92b46b637f864fb0682Mark Salyzyn    size_t mElements[LOG_ID_MAX];
37958b8be8906f903ac3d83c41bcb0fb9c7841945f0Mark Salyzyn    size_t mDroppedElements[LOG_ID_MAX];
38097c1c2beee2cbd8c67c1cd507367e5b084d853c8Mark Salyzyn    size_t mSizesTotal[LOG_ID_MAX];
38197c1c2beee2cbd8c67c1cd507367e5b084d853c8Mark Salyzyn    size_t mElementsTotal[LOG_ID_MAX];
382720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn    bool enable;
38334facab86b0fe7ec613de92b46b637f864fb0682Mark Salyzyn
38497c1c2beee2cbd8c67c1cd507367e5b084d853c8Mark Salyzyn    // uid to size list
385720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn    typedef LogHashtable<uid_t, UidEntry> uidTable_t;
38697c1c2beee2cbd8c67c1cd507367e5b084d853c8Mark Salyzyn    uidTable_t uidTable[LOG_ID_MAX];
387e457b74ce6ee6d799812dc2ec5e4b8b18bcd3e91Mark Salyzyn
388720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn    // pid to uid list
389720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn    typedef LogHashtable<pid_t, PidEntry> pidTable_t;
390720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn    pidTable_t pidTable;
391720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn
39217ed6797df722464eb5cc6dfc3e1e32aec284b70Mark Salyzyn    // tid to uid list
39317ed6797df722464eb5cc6dfc3e1e32aec284b70Mark Salyzyn    typedef LogHashtable<pid_t, TidEntry> tidTable_t;
39417ed6797df722464eb5cc6dfc3e1e32aec284b70Mark Salyzyn    tidTable_t tidTable;
39517ed6797df722464eb5cc6dfc3e1e32aec284b70Mark Salyzyn
396344bff4391dd434dda501e812f18f524290c5a7cMark Salyzyn    // tag list
397344bff4391dd434dda501e812f18f524290c5a7cMark Salyzyn    typedef LogHashtable<uint32_t, TagEntry> tagTable_t;
398344bff4391dd434dda501e812f18f524290c5a7cMark Salyzyn    tagTable_t tagTable;
399344bff4391dd434dda501e812f18f524290c5a7cMark Salyzyn
40034facab86b0fe7ec613de92b46b637f864fb0682Mark Salyzynpublic:
40134facab86b0fe7ec613de92b46b637f864fb0682Mark Salyzyn    LogStatistics();
40234facab86b0fe7ec613de92b46b637f864fb0682Mark Salyzyn
403720f6d1d55d936d98cc9752e96f479e03e6d5009Mark Salyzyn    void enableStatistics() { enable = true; }
40434facab86b0fe7ec613de92b46b637f864fb0682Mark Salyzyn
40597c1c2beee2cbd8c67c1cd507367e5b084d853c8Mark Salyzyn    void add(LogBufferElement *entry);
40697c1c2beee2cbd8c67c1cd507367e5b084d853c8Mark Salyzyn    void subtract(LogBufferElement *entry);
407ab0dcf682867bd7e1fdebfd8d8f9fafaccfad7f6Mark Salyzyn    // entry->setDropped(1) must follow this call
408ab0dcf682867bd7e1fdebfd8d8f9fafaccfad7f6Mark Salyzyn    void drop(LogBufferElement *entry);
409aaad42f47c7363d68ddfb9ef8f1b51972c4d429dMark Salyzyn    // Correct for coalescing two entries referencing dropped content
41058b8be8906f903ac3d83c41bcb0fb9c7841945f0Mark Salyzyn    void erase(LogBufferElement *element) {
41158b8be8906f903ac3d83c41bcb0fb9c7841945f0Mark Salyzyn        log_id_t log_id = element->getLogId();
41258b8be8906f903ac3d83c41bcb0fb9c7841945f0Mark Salyzyn        --mElements[log_id];
41358b8be8906f903ac3d83c41bcb0fb9c7841945f0Mark Salyzyn        --mDroppedElements[log_id];
41458b8be8906f903ac3d83c41bcb0fb9c7841945f0Mark Salyzyn    }
415e457b74ce6ee6d799812dc2ec5e4b8b18bcd3e91Mark Salyzyn
416758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn    std::unique_ptr<const UidEntry *[]> sort(size_t len, log_id id) {
417758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn        return uidTable[id].sort(len);
418758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn    }
41934facab86b0fe7ec613de92b46b637f864fb0682Mark Salyzyn
42034facab86b0fe7ec613de92b46b637f864fb0682Mark Salyzyn    // fast track current value by id only
42134facab86b0fe7ec613de92b46b637f864fb0682Mark Salyzyn    size_t sizes(log_id_t id) const { return mSizes[id]; }
42234facab86b0fe7ec613de92b46b637f864fb0682Mark Salyzyn    size_t elements(log_id_t id) const { return mElements[id]; }
42358b8be8906f903ac3d83c41bcb0fb9c7841945f0Mark Salyzyn    size_t realElements(log_id_t id) const {
42458b8be8906f903ac3d83c41bcb0fb9c7841945f0Mark Salyzyn        return mElements[id] - mDroppedElements[id];
42558b8be8906f903ac3d83c41bcb0fb9c7841945f0Mark Salyzyn    }
42697c1c2beee2cbd8c67c1cd507367e5b084d853c8Mark Salyzyn    size_t sizesTotal(log_id_t id) const { return mSizesTotal[id]; }
42797c1c2beee2cbd8c67c1cd507367e5b084d853c8Mark Salyzyn    size_t elementsTotal(log_id_t id) const { return mElementsTotal[id]; }
42834facab86b0fe7ec613de92b46b637f864fb0682Mark Salyzyn
429758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn    std::string format(uid_t uid, unsigned int logMask) const;
4309a03863e88da99ba010342c874252089dd771f7fMark Salyzyn
431ed777e9eece54bf899f1a77a83f8b702970de686Mark Salyzyn    // helper (must be locked directly or implicitly by mLogElementsLock)
432758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn    const char *pidToName(pid_t pid) const;
4334ba0387af5acc52e43e4004ccb4c46b8bc700349Mark Salyzyn    uid_t pidToUid(pid_t pid);
434758058ffd8820df71c27db7675c50a90a5fa02b4Mark Salyzyn    const char *uidToName(uid_t uid) const;
43534facab86b0fe7ec613de92b46b637f864fb0682Mark Salyzyn};
43634facab86b0fe7ec613de92b46b637f864fb0682Mark Salyzyn
43734facab86b0fe7ec613de92b46b637f864fb0682Mark Salyzyn#endif // _LOGD_LOG_STATISTICS_H__
438