Loading liblog/event_tag_map.cpp +19 −268 Original line number Original line Diff line number Diff line Loading @@ -31,84 +31,13 @@ #include <unordered_map> #include <unordered_map> #include <log/event_tag_map.h> #include <log/event_tag_map.h> #include <log/log_properties.h> #include <private/android_logger.h> #include <private/android_logger.h> #include <utils/FastStrcmp.h> #include <utils/FastStrcmp.h> #include <utils/RWLock.h> #include <utils/RWLock.h> #include "logd_reader.h" #define OUT_TAG "EventTagMap" #define OUT_TAG "EventTagMap" class MapString { typedef std::pair<std::string_view, std::string_view> TagFmt; private: const std::string* alloc; // HAS-AN const std::string_view str; // HAS-A public: operator const std::string_view() const { return str; } const char* data() const { return str.data(); } size_t length() const { return str.length(); } bool operator==(const MapString& rval) const { if (length() != rval.length()) return false; if (length() == 0) return true; return fastcmp<strncmp>(data(), rval.data(), length()) == 0; } bool operator!=(const MapString& rval) const { return !(*this == rval); } MapString(const char* str, size_t len) : alloc(NULL), str(str, len) { } explicit MapString(const std::string& str) : alloc(new std::string(str)), str(alloc->data(), alloc->length()) { } MapString(MapString&& rval) noexcept : alloc(rval.alloc), str(rval.data(), rval.length()) { rval.alloc = NULL; } explicit MapString(const MapString& rval) : alloc(rval.alloc ? new std::string(*rval.alloc) : NULL), str(alloc ? alloc->data() : rval.data(), rval.length()) { } ~MapString() { if (alloc) delete alloc; } }; // Hash for MapString template <> struct std::hash<MapString> : public std::unary_function<const MapString&, size_t> { size_t operator()(const MapString& __t) const noexcept { if (!__t.length()) return 0; return std::hash<std::string_view>()(std::string_view(__t)); } }; typedef std::pair<MapString, MapString> TagFmt; template <> struct std::hash<TagFmt> : public std::unary_function<const TagFmt&, size_t> { size_t operator()(const TagFmt& __t) const noexcept { // Tag is typically unique. Will cost us an extra 100ns for the // unordered_map lookup if we instead did a hash that combined // both of tag and fmt members, e.g.: // // return std::hash<MapString>()(__t.first) ^ // std::hash<MapString>()(__t.second); return std::hash<MapString>()(__t.first); } }; // Map // Map struct EventTagMap { struct EventTagMap { Loading @@ -119,8 +48,7 @@ struct EventTagMap { private: private: std::unordered_map<uint32_t, TagFmt> Idx2TagFmt; std::unordered_map<uint32_t, TagFmt> Idx2TagFmt; std::unordered_map<TagFmt, uint32_t> TagFmt2Idx; std::unordered_map<std::string_view, uint32_t> Tag2Idx; std::unordered_map<MapString, uint32_t> Tag2Idx; // protect unordered sets // protect unordered sets android::RWLock rwlock; android::RWLock rwlock; Loading @@ -132,7 +60,6 @@ struct EventTagMap { ~EventTagMap() { ~EventTagMap() { Idx2TagFmt.clear(); Idx2TagFmt.clear(); TagFmt2Idx.clear(); Tag2Idx.clear(); Tag2Idx.clear(); for (size_t which = 0; which < NUM_MAPS; ++which) { for (size_t which = 0; which < NUM_MAPS; ++which) { if (mapAddr[which]) { if (mapAddr[which]) { Loading @@ -144,8 +71,7 @@ struct EventTagMap { bool emplaceUnique(uint32_t tag, const TagFmt& tagfmt, bool verbose = false); bool emplaceUnique(uint32_t tag, const TagFmt& tagfmt, bool verbose = false); const TagFmt* find(uint32_t tag) const; const TagFmt* find(uint32_t tag) const; int find(TagFmt&& tagfmt) const; int find(std::string_view tag) const; int find(MapString&& tag) const; }; }; bool EventTagMap::emplaceUnique(uint32_t tag, const TagFmt& tagfmt, bool EventTagMap::emplaceUnique(uint32_t tag, const TagFmt& tagfmt, Loading @@ -156,8 +82,7 @@ bool EventTagMap::emplaceUnique(uint32_t tag, const TagFmt& tagfmt, ":%.*s:%.*s)\n"; ":%.*s:%.*s)\n"; android::RWLock::AutoWLock writeLock(rwlock); android::RWLock::AutoWLock writeLock(rwlock); { { std::unordered_map<uint32_t, TagFmt>::const_iterator it; auto it = Idx2TagFmt.find(tag); it = Idx2TagFmt.find(tag); if (it != Idx2TagFmt.end()) { if (it != Idx2TagFmt.end()) { if (verbose) { if (verbose) { fprintf(stderr, errorFormat, it->first, (int)it->second.first.length(), fprintf(stderr, errorFormat, it->first, (int)it->second.first.length(), Loading @@ -173,25 +98,7 @@ bool EventTagMap::emplaceUnique(uint32_t tag, const TagFmt& tagfmt, } } { { std::unordered_map<TagFmt, uint32_t>::const_iterator it; auto it = Tag2Idx.find(tagfmt.first); it = TagFmt2Idx.find(tagfmt); if (it != TagFmt2Idx.end()) { if (verbose) { fprintf(stderr, errorFormat, it->second, (int)it->first.first.length(), it->first.first.data(), (int)it->first.second.length(), it->first.second.data(), tag, (int)tagfmt.first.length(), tagfmt.first.data(), (int)tagfmt.second.length(), tagfmt.second.data()); } ret = false; } else { TagFmt2Idx.emplace(std::make_pair(tagfmt, tag)); } } { std::unordered_map<MapString, uint32_t>::const_iterator it; it = Tag2Idx.find(tagfmt.first); if (!tagfmt.second.length() && (it != Tag2Idx.end())) { if (!tagfmt.second.length() && (it != Tag2Idx.end())) { Tag2Idx.erase(it); Tag2Idx.erase(it); it = Tag2Idx.end(); it = Tag2Idx.end(); Loading @@ -205,25 +112,15 @@ bool EventTagMap::emplaceUnique(uint32_t tag, const TagFmt& tagfmt, } } const TagFmt* EventTagMap::find(uint32_t tag) const { const TagFmt* EventTagMap::find(uint32_t tag) const { std::unordered_map<uint32_t, TagFmt>::const_iterator it; android::RWLock::AutoRLock readLock(const_cast<android::RWLock&>(rwlock)); android::RWLock::AutoRLock readLock(const_cast<android::RWLock&>(rwlock)); it = Idx2TagFmt.find(tag); auto it = Idx2TagFmt.find(tag); if (it == Idx2TagFmt.end()) return NULL; if (it == Idx2TagFmt.end()) return NULL; return &(it->second); return &(it->second); } } int EventTagMap::find(TagFmt&& tagfmt) const { int EventTagMap::find(std::string_view tag) const { std::unordered_map<TagFmt, uint32_t>::const_iterator it; android::RWLock::AutoRLock readLock(const_cast<android::RWLock&>(rwlock)); android::RWLock::AutoRLock readLock(const_cast<android::RWLock&>(rwlock)); it = TagFmt2Idx.find(std::move(tagfmt)); auto it = Tag2Idx.find(std::move(tag)); if (it == TagFmt2Idx.end()) return -1; return it->second; } int EventTagMap::find(MapString&& tag) const { std::unordered_map<MapString, uint32_t>::const_iterator it; android::RWLock::AutoRLock readLock(const_cast<android::RWLock&>(rwlock)); it = Tag2Idx.find(std::move(tag)); if (it == Tag2Idx.end()) return -1; if (it == Tag2Idx.end()) return -1; return it->second; return it->second; } } Loading @@ -241,29 +138,20 @@ static const char* endOfTag(const char* cp) { // successful return, it will be pointing to the last character in the // successful return, it will be pointing to the last character in the // tag line (i.e. the character before the start of the next line). // tag line (i.e. the character before the start of the next line). // // // lineNum = 0 removes verbose comments and requires us to cache the // content rather than make direct raw references since the content // will disappear after the call. A non-zero lineNum means we own the // data and it will outlive the call. // // Returns 0 on success, nonzero on failure. // Returns 0 on success, nonzero on failure. static int scanTagLine(EventTagMap* map, const char*& pData, int lineNum) { static int scanTagLine(EventTagMap* map, const char*& pData, int line_num) { char* ep; char* ep; unsigned long val = strtoul(pData, &ep, 10); unsigned long val = strtoul(pData, &ep, 10); const char* cp = ep; const char* cp = ep; if (cp == pData) { if (cp == pData) { if (lineNum) { fprintf(stderr, OUT_TAG ": malformed tag number on line %d\n", line_num); fprintf(stderr, OUT_TAG ": malformed tag number on line %d\n", lineNum); } errno = EINVAL; errno = EINVAL; return -1; return -1; } } uint32_t tagIndex = val; uint32_t tagIndex = val; if (tagIndex != val) { if (tagIndex != val) { if (lineNum) { fprintf(stderr, OUT_TAG ": tag number too large on line %d\n", line_num); fprintf(stderr, OUT_TAG ": tag number too large on line %d\n", lineNum); } errno = ERANGE; errno = ERANGE; return -1; return -1; } } Loading @@ -272,9 +160,7 @@ static int scanTagLine(EventTagMap* map, const char*& pData, int lineNum) { } } if (*cp == '\n') { if (*cp == '\n') { if (lineNum) { fprintf(stderr, OUT_TAG ": missing tag string on line %d\n", line_num); fprintf(stderr, OUT_TAG ": missing tag string on line %d\n", lineNum); } errno = EINVAL; errno = EINVAL; return -1; return -1; } } Loading @@ -284,10 +170,7 @@ static int scanTagLine(EventTagMap* map, const char*& pData, int lineNum) { size_t tagLen = cp - tag; size_t tagLen = cp - tag; if (!isspace(*cp)) { if (!isspace(*cp)) { if (lineNum) { fprintf(stderr, OUT_TAG ": invalid tag char %c on line %d\n", *cp, line_num); fprintf(stderr, OUT_TAG ": invalid tag char %c on line %d\n", *cp, lineNum); } errno = EINVAL; errno = EINVAL; return -1; return -1; } } Loading Loading @@ -317,26 +200,16 @@ static int scanTagLine(EventTagMap* map, const char*& pData, int lineNum) { while (*cp && (*cp != '\n')) ++cp; while (*cp && (*cp != '\n')) ++cp; #ifdef DEBUG #ifdef DEBUG fprintf(stderr, "%d: %p: %.*s\n", lineNum, tag, (int)(cp - pData), pData); fprintf(stderr, "%d: %p: %.*s\n", line_num, tag, (int)(cp - pData), pData); #endif #endif pData = cp; pData = cp; if (lineNum) { if (map->emplaceUnique(tagIndex, TagFmt(std::make_pair(MapString(tag, tagLen), MapString(fmt, fmtLen))), verbose)) { return 0; } } else { // cache if (map->emplaceUnique( if (map->emplaceUnique( tagIndex, tagIndex, TagFmt(std::make_pair(MapString(std::string(tag, tagLen)), TagFmt(std::make_pair(std::string_view(tag, tagLen), std::string_view(fmt, fmtLen))), MapString(std::string(fmt, fmtLen)))))) { verbose)) { return 0; return 0; } } } errno = EMLINK; errno = EMLINK; return -1; return -1; } } Loading Loading @@ -491,57 +364,10 @@ void android_closeEventTagMap(EventTagMap* map) { if (map) delete map; if (map) delete map; } } // Cache miss, go to logd to acquire a public reference. // Because we lack access to a SHARED PUBLIC /dev/event-log-tags file map? static const TagFmt* __getEventTag([[maybe_unused]] EventTagMap* map, unsigned int tag) { // call event tag service to arrange for a new tag char* buf = NULL; // Can not use android::base::StringPrintf, asprintf + free instead. static const char command_template[] = "getEventTag id=%u"; int ret = asprintf(&buf, command_template, tag); if (ret > 0) { // Add some buffer margin for an estimate of the full return content. size_t size = ret - strlen(command_template) + strlen("65535\n4294967295\t?\t\t\t?\t# uid=32767\n\n\f?success?"); if (size > (size_t)ret) { char* np = static_cast<char*>(realloc(buf, size)); if (np) { buf = np; } else { size = ret; } } else { size = ret; } #ifdef __ANDROID__ // Ask event log tag service for an existing entry if (SendLogdControlMessage(buf, size) >= 0) { buf[size - 1] = '\0'; char* ep; unsigned long val = strtoul(buf, &ep, 10); // return size const char* cp = ep; if ((buf != cp) && (val > 0) && (*cp == '\n')) { // truncation OK ++cp; if (!scanTagLine(map, cp, 0)) { free(buf); return map->find(tag); } } } #endif free(buf); } return NULL; } // Look up an entry in the map. // Look up an entry in the map. const char* android_lookupEventTag_len(const EventTagMap* map, size_t* len, unsigned int tag) { const char* android_lookupEventTag_len(const EventTagMap* map, size_t* len, unsigned int tag) { if (len) *len = 0; if (len) *len = 0; const TagFmt* str = map->find(tag); const TagFmt* str = map->find(tag); if (!str) { str = __getEventTag(const_cast<EventTagMap*>(map), tag); } if (!str) return NULL; if (!str) return NULL; if (len) *len = str->first.length(); if (len) *len = str->first.length(); return str->first.data(); return str->first.data(); Loading @@ -551,83 +377,8 @@ const char* android_lookupEventTag_len(const EventTagMap* map, size_t* len, unsi const char* android_lookupEventFormat_len(const EventTagMap* map, size_t* len, unsigned int tag) { const char* android_lookupEventFormat_len(const EventTagMap* map, size_t* len, unsigned int tag) { if (len) *len = 0; if (len) *len = 0; const TagFmt* str = map->find(tag); const TagFmt* str = map->find(tag); if (!str) { str = __getEventTag(const_cast<EventTagMap*>(map), tag); } if (!str) return NULL; if (!str) return NULL; if (len) *len = str->second.length(); if (len) *len = str->second.length(); return str->second.data(); return str->second.data(); } } // Look up tagname, generate one if necessary, and return a tag int android_lookupEventTagNum(EventTagMap* map, const char* tagname, const char* format, int prio) { const char* ep = endOfTag(tagname); size_t len = ep - tagname; if (!len || *ep) { errno = EINVAL; return -1; } if ((prio != ANDROID_LOG_UNKNOWN) && (prio < ANDROID_LOG_SILENT) && !__android_log_is_loggable_len(prio, tagname, len, __android_log_is_debuggable() ? ANDROID_LOG_VERBOSE : ANDROID_LOG_DEBUG)) { errno = EPERM; return -1; } if (!format) format = ""; ssize_t fmtLen = strlen(format); int ret = map->find(TagFmt( std::make_pair(MapString(tagname, len), MapString(format, fmtLen)))); if (ret != -1) return ret; // call event tag service to arrange for a new tag char* buf = NULL; // Can not use android::base::StringPrintf, asprintf + free instead. static const char command_template[] = "getEventTag name=%s format=\"%s\""; ret = asprintf(&buf, command_template, tagname, format); if (ret > 0) { // Add some buffer margin for an estimate of the full return content. char* cp; size_t size = ret - strlen(command_template) + strlen("65535\n4294967295\t?\t\t\t?\t# uid=32767\n\n\f?success?"); if (size > (size_t)ret) { cp = static_cast<char*>(realloc(buf, size)); if (cp) { buf = cp; } else { size = ret; } } else { size = ret; } #ifdef __ANDROID__ // Ask event log tag service for an allocation if (SendLogdControlMessage(buf, size) >= 0) { buf[size - 1] = '\0'; unsigned long val = strtoul(buf, &cp, 10); // return size if ((buf != cp) && (val > 0) && (*cp == '\n')) { // truncation OK val = strtoul(cp + 1, &cp, 10); // allocated tag number if ((val > 0) && (val < UINT32_MAX) && (*cp == '\t')) { free(buf); ret = val; // cache map->emplaceUnique(ret, TagFmt(std::make_pair( MapString(std::string(tagname, len)), MapString(std::string(format, fmtLen))))); return ret; } } } #endif free(buf); } // Hail Mary ret = map->find(MapString(tagname, len)); if (ret == -1) errno = ESRCH; return ret; } liblog/include/log/event_tag_map.h +0 −6 Original line number Original line Diff line number Diff line Loading @@ -53,12 +53,6 @@ const char* android_lookupEventTag_len(const EventTagMap* map, size_t* len, const char* android_lookupEventFormat_len(const EventTagMap* map, size_t* len, const char* android_lookupEventFormat_len(const EventTagMap* map, size_t* len, unsigned int tag); unsigned int tag); /* * Look up tagname, generate one if necessary, and return a tag */ int android_lookupEventTagNum(EventTagMap* map, const char* tagname, const char* format, int prio); #ifdef __cplusplus #ifdef __cplusplus } } #endif #endif liblog/liblog.map.txt +0 −1 Original line number Original line Diff line number Diff line Loading @@ -89,6 +89,5 @@ LIBLOG_PRIVATE { android_log_processLogBuffer; android_log_processLogBuffer; android_log_read_next; android_log_read_next; android_log_write_list_buffer; android_log_write_list_buffer; android_lookupEventTagNum; create_android_log_parser; create_android_log_parser; }; }; liblog/tests/liblog_benchmark.cpp +0 −24 Original line number Original line Diff line number Diff line Loading @@ -879,30 +879,6 @@ static void BM_lookupEventFormat(benchmark::State& state) { } } BENCHMARK(BM_lookupEventFormat); BENCHMARK(BM_lookupEventFormat); /* * Measure the time it takes for android_lookupEventTagNum plus above */ static void BM_lookupEventTagNum(benchmark::State& state) { prechargeEventMap(); std::unordered_set<uint32_t>::const_iterator it = set.begin(); while (state.KeepRunning()) { size_t len; const char* name = android_lookupEventTag_len(map, &len, (*it)); std::string Name(name, len); const char* format = android_lookupEventFormat_len(map, &len, (*it)); std::string Format(format, len); state.ResumeTiming(); android_lookupEventTagNum(map, Name.c_str(), Format.c_str(), ANDROID_LOG_UNKNOWN); state.PauseTiming(); ++it; if (it == set.end()) it = set.begin(); } } BENCHMARK(BM_lookupEventTagNum); // Must be functionally identical to liblog internal SendLogdControlMessage() // Must be functionally identical to liblog internal SendLogdControlMessage() static void send_to_control(char* buf, size_t len) { static void send_to_control(char* buf, size_t len) { int sock = int sock = Loading liblog/tests/liblog_test.cpp +0 −17 Original line number Original line Diff line number Diff line Loading @@ -2768,20 +2768,3 @@ TEST(liblog, __android_log_pmsg_file_read) { #endif #endif } } #endif // ENABLE_FLAKY_TESTS #endif // ENABLE_FLAKY_TESTS TEST(liblog, android_lookupEventTagNum) { #ifdef __ANDROID__ EventTagMap* map = android_openEventTagMap(NULL); EXPECT_TRUE(NULL != map); std::string Name = android::base::StringPrintf("a%d", getpid()); int tag = android_lookupEventTagNum(map, Name.c_str(), "(new|1)", ANDROID_LOG_UNKNOWN); android_closeEventTagMap(map); if (tag == -1) system("tail -3 /dev/event-log-tags >&2"); EXPECT_NE(-1, tag); EXPECT_NE(0, tag); EXPECT_GT(UINT32_MAX, (unsigned)tag); #else GTEST_LOG_(INFO) << "This test does nothing.\n"; #endif } Loading
liblog/event_tag_map.cpp +19 −268 Original line number Original line Diff line number Diff line Loading @@ -31,84 +31,13 @@ #include <unordered_map> #include <unordered_map> #include <log/event_tag_map.h> #include <log/event_tag_map.h> #include <log/log_properties.h> #include <private/android_logger.h> #include <private/android_logger.h> #include <utils/FastStrcmp.h> #include <utils/FastStrcmp.h> #include <utils/RWLock.h> #include <utils/RWLock.h> #include "logd_reader.h" #define OUT_TAG "EventTagMap" #define OUT_TAG "EventTagMap" class MapString { typedef std::pair<std::string_view, std::string_view> TagFmt; private: const std::string* alloc; // HAS-AN const std::string_view str; // HAS-A public: operator const std::string_view() const { return str; } const char* data() const { return str.data(); } size_t length() const { return str.length(); } bool operator==(const MapString& rval) const { if (length() != rval.length()) return false; if (length() == 0) return true; return fastcmp<strncmp>(data(), rval.data(), length()) == 0; } bool operator!=(const MapString& rval) const { return !(*this == rval); } MapString(const char* str, size_t len) : alloc(NULL), str(str, len) { } explicit MapString(const std::string& str) : alloc(new std::string(str)), str(alloc->data(), alloc->length()) { } MapString(MapString&& rval) noexcept : alloc(rval.alloc), str(rval.data(), rval.length()) { rval.alloc = NULL; } explicit MapString(const MapString& rval) : alloc(rval.alloc ? new std::string(*rval.alloc) : NULL), str(alloc ? alloc->data() : rval.data(), rval.length()) { } ~MapString() { if (alloc) delete alloc; } }; // Hash for MapString template <> struct std::hash<MapString> : public std::unary_function<const MapString&, size_t> { size_t operator()(const MapString& __t) const noexcept { if (!__t.length()) return 0; return std::hash<std::string_view>()(std::string_view(__t)); } }; typedef std::pair<MapString, MapString> TagFmt; template <> struct std::hash<TagFmt> : public std::unary_function<const TagFmt&, size_t> { size_t operator()(const TagFmt& __t) const noexcept { // Tag is typically unique. Will cost us an extra 100ns for the // unordered_map lookup if we instead did a hash that combined // both of tag and fmt members, e.g.: // // return std::hash<MapString>()(__t.first) ^ // std::hash<MapString>()(__t.second); return std::hash<MapString>()(__t.first); } }; // Map // Map struct EventTagMap { struct EventTagMap { Loading @@ -119,8 +48,7 @@ struct EventTagMap { private: private: std::unordered_map<uint32_t, TagFmt> Idx2TagFmt; std::unordered_map<uint32_t, TagFmt> Idx2TagFmt; std::unordered_map<TagFmt, uint32_t> TagFmt2Idx; std::unordered_map<std::string_view, uint32_t> Tag2Idx; std::unordered_map<MapString, uint32_t> Tag2Idx; // protect unordered sets // protect unordered sets android::RWLock rwlock; android::RWLock rwlock; Loading @@ -132,7 +60,6 @@ struct EventTagMap { ~EventTagMap() { ~EventTagMap() { Idx2TagFmt.clear(); Idx2TagFmt.clear(); TagFmt2Idx.clear(); Tag2Idx.clear(); Tag2Idx.clear(); for (size_t which = 0; which < NUM_MAPS; ++which) { for (size_t which = 0; which < NUM_MAPS; ++which) { if (mapAddr[which]) { if (mapAddr[which]) { Loading @@ -144,8 +71,7 @@ struct EventTagMap { bool emplaceUnique(uint32_t tag, const TagFmt& tagfmt, bool verbose = false); bool emplaceUnique(uint32_t tag, const TagFmt& tagfmt, bool verbose = false); const TagFmt* find(uint32_t tag) const; const TagFmt* find(uint32_t tag) const; int find(TagFmt&& tagfmt) const; int find(std::string_view tag) const; int find(MapString&& tag) const; }; }; bool EventTagMap::emplaceUnique(uint32_t tag, const TagFmt& tagfmt, bool EventTagMap::emplaceUnique(uint32_t tag, const TagFmt& tagfmt, Loading @@ -156,8 +82,7 @@ bool EventTagMap::emplaceUnique(uint32_t tag, const TagFmt& tagfmt, ":%.*s:%.*s)\n"; ":%.*s:%.*s)\n"; android::RWLock::AutoWLock writeLock(rwlock); android::RWLock::AutoWLock writeLock(rwlock); { { std::unordered_map<uint32_t, TagFmt>::const_iterator it; auto it = Idx2TagFmt.find(tag); it = Idx2TagFmt.find(tag); if (it != Idx2TagFmt.end()) { if (it != Idx2TagFmt.end()) { if (verbose) { if (verbose) { fprintf(stderr, errorFormat, it->first, (int)it->second.first.length(), fprintf(stderr, errorFormat, it->first, (int)it->second.first.length(), Loading @@ -173,25 +98,7 @@ bool EventTagMap::emplaceUnique(uint32_t tag, const TagFmt& tagfmt, } } { { std::unordered_map<TagFmt, uint32_t>::const_iterator it; auto it = Tag2Idx.find(tagfmt.first); it = TagFmt2Idx.find(tagfmt); if (it != TagFmt2Idx.end()) { if (verbose) { fprintf(stderr, errorFormat, it->second, (int)it->first.first.length(), it->first.first.data(), (int)it->first.second.length(), it->first.second.data(), tag, (int)tagfmt.first.length(), tagfmt.first.data(), (int)tagfmt.second.length(), tagfmt.second.data()); } ret = false; } else { TagFmt2Idx.emplace(std::make_pair(tagfmt, tag)); } } { std::unordered_map<MapString, uint32_t>::const_iterator it; it = Tag2Idx.find(tagfmt.first); if (!tagfmt.second.length() && (it != Tag2Idx.end())) { if (!tagfmt.second.length() && (it != Tag2Idx.end())) { Tag2Idx.erase(it); Tag2Idx.erase(it); it = Tag2Idx.end(); it = Tag2Idx.end(); Loading @@ -205,25 +112,15 @@ bool EventTagMap::emplaceUnique(uint32_t tag, const TagFmt& tagfmt, } } const TagFmt* EventTagMap::find(uint32_t tag) const { const TagFmt* EventTagMap::find(uint32_t tag) const { std::unordered_map<uint32_t, TagFmt>::const_iterator it; android::RWLock::AutoRLock readLock(const_cast<android::RWLock&>(rwlock)); android::RWLock::AutoRLock readLock(const_cast<android::RWLock&>(rwlock)); it = Idx2TagFmt.find(tag); auto it = Idx2TagFmt.find(tag); if (it == Idx2TagFmt.end()) return NULL; if (it == Idx2TagFmt.end()) return NULL; return &(it->second); return &(it->second); } } int EventTagMap::find(TagFmt&& tagfmt) const { int EventTagMap::find(std::string_view tag) const { std::unordered_map<TagFmt, uint32_t>::const_iterator it; android::RWLock::AutoRLock readLock(const_cast<android::RWLock&>(rwlock)); android::RWLock::AutoRLock readLock(const_cast<android::RWLock&>(rwlock)); it = TagFmt2Idx.find(std::move(tagfmt)); auto it = Tag2Idx.find(std::move(tag)); if (it == TagFmt2Idx.end()) return -1; return it->second; } int EventTagMap::find(MapString&& tag) const { std::unordered_map<MapString, uint32_t>::const_iterator it; android::RWLock::AutoRLock readLock(const_cast<android::RWLock&>(rwlock)); it = Tag2Idx.find(std::move(tag)); if (it == Tag2Idx.end()) return -1; if (it == Tag2Idx.end()) return -1; return it->second; return it->second; } } Loading @@ -241,29 +138,20 @@ static const char* endOfTag(const char* cp) { // successful return, it will be pointing to the last character in the // successful return, it will be pointing to the last character in the // tag line (i.e. the character before the start of the next line). // tag line (i.e. the character before the start of the next line). // // // lineNum = 0 removes verbose comments and requires us to cache the // content rather than make direct raw references since the content // will disappear after the call. A non-zero lineNum means we own the // data and it will outlive the call. // // Returns 0 on success, nonzero on failure. // Returns 0 on success, nonzero on failure. static int scanTagLine(EventTagMap* map, const char*& pData, int lineNum) { static int scanTagLine(EventTagMap* map, const char*& pData, int line_num) { char* ep; char* ep; unsigned long val = strtoul(pData, &ep, 10); unsigned long val = strtoul(pData, &ep, 10); const char* cp = ep; const char* cp = ep; if (cp == pData) { if (cp == pData) { if (lineNum) { fprintf(stderr, OUT_TAG ": malformed tag number on line %d\n", line_num); fprintf(stderr, OUT_TAG ": malformed tag number on line %d\n", lineNum); } errno = EINVAL; errno = EINVAL; return -1; return -1; } } uint32_t tagIndex = val; uint32_t tagIndex = val; if (tagIndex != val) { if (tagIndex != val) { if (lineNum) { fprintf(stderr, OUT_TAG ": tag number too large on line %d\n", line_num); fprintf(stderr, OUT_TAG ": tag number too large on line %d\n", lineNum); } errno = ERANGE; errno = ERANGE; return -1; return -1; } } Loading @@ -272,9 +160,7 @@ static int scanTagLine(EventTagMap* map, const char*& pData, int lineNum) { } } if (*cp == '\n') { if (*cp == '\n') { if (lineNum) { fprintf(stderr, OUT_TAG ": missing tag string on line %d\n", line_num); fprintf(stderr, OUT_TAG ": missing tag string on line %d\n", lineNum); } errno = EINVAL; errno = EINVAL; return -1; return -1; } } Loading @@ -284,10 +170,7 @@ static int scanTagLine(EventTagMap* map, const char*& pData, int lineNum) { size_t tagLen = cp - tag; size_t tagLen = cp - tag; if (!isspace(*cp)) { if (!isspace(*cp)) { if (lineNum) { fprintf(stderr, OUT_TAG ": invalid tag char %c on line %d\n", *cp, line_num); fprintf(stderr, OUT_TAG ": invalid tag char %c on line %d\n", *cp, lineNum); } errno = EINVAL; errno = EINVAL; return -1; return -1; } } Loading Loading @@ -317,26 +200,16 @@ static int scanTagLine(EventTagMap* map, const char*& pData, int lineNum) { while (*cp && (*cp != '\n')) ++cp; while (*cp && (*cp != '\n')) ++cp; #ifdef DEBUG #ifdef DEBUG fprintf(stderr, "%d: %p: %.*s\n", lineNum, tag, (int)(cp - pData), pData); fprintf(stderr, "%d: %p: %.*s\n", line_num, tag, (int)(cp - pData), pData); #endif #endif pData = cp; pData = cp; if (lineNum) { if (map->emplaceUnique(tagIndex, TagFmt(std::make_pair(MapString(tag, tagLen), MapString(fmt, fmtLen))), verbose)) { return 0; } } else { // cache if (map->emplaceUnique( if (map->emplaceUnique( tagIndex, tagIndex, TagFmt(std::make_pair(MapString(std::string(tag, tagLen)), TagFmt(std::make_pair(std::string_view(tag, tagLen), std::string_view(fmt, fmtLen))), MapString(std::string(fmt, fmtLen)))))) { verbose)) { return 0; return 0; } } } errno = EMLINK; errno = EMLINK; return -1; return -1; } } Loading Loading @@ -491,57 +364,10 @@ void android_closeEventTagMap(EventTagMap* map) { if (map) delete map; if (map) delete map; } } // Cache miss, go to logd to acquire a public reference. // Because we lack access to a SHARED PUBLIC /dev/event-log-tags file map? static const TagFmt* __getEventTag([[maybe_unused]] EventTagMap* map, unsigned int tag) { // call event tag service to arrange for a new tag char* buf = NULL; // Can not use android::base::StringPrintf, asprintf + free instead. static const char command_template[] = "getEventTag id=%u"; int ret = asprintf(&buf, command_template, tag); if (ret > 0) { // Add some buffer margin for an estimate of the full return content. size_t size = ret - strlen(command_template) + strlen("65535\n4294967295\t?\t\t\t?\t# uid=32767\n\n\f?success?"); if (size > (size_t)ret) { char* np = static_cast<char*>(realloc(buf, size)); if (np) { buf = np; } else { size = ret; } } else { size = ret; } #ifdef __ANDROID__ // Ask event log tag service for an existing entry if (SendLogdControlMessage(buf, size) >= 0) { buf[size - 1] = '\0'; char* ep; unsigned long val = strtoul(buf, &ep, 10); // return size const char* cp = ep; if ((buf != cp) && (val > 0) && (*cp == '\n')) { // truncation OK ++cp; if (!scanTagLine(map, cp, 0)) { free(buf); return map->find(tag); } } } #endif free(buf); } return NULL; } // Look up an entry in the map. // Look up an entry in the map. const char* android_lookupEventTag_len(const EventTagMap* map, size_t* len, unsigned int tag) { const char* android_lookupEventTag_len(const EventTagMap* map, size_t* len, unsigned int tag) { if (len) *len = 0; if (len) *len = 0; const TagFmt* str = map->find(tag); const TagFmt* str = map->find(tag); if (!str) { str = __getEventTag(const_cast<EventTagMap*>(map), tag); } if (!str) return NULL; if (!str) return NULL; if (len) *len = str->first.length(); if (len) *len = str->first.length(); return str->first.data(); return str->first.data(); Loading @@ -551,83 +377,8 @@ const char* android_lookupEventTag_len(const EventTagMap* map, size_t* len, unsi const char* android_lookupEventFormat_len(const EventTagMap* map, size_t* len, unsigned int tag) { const char* android_lookupEventFormat_len(const EventTagMap* map, size_t* len, unsigned int tag) { if (len) *len = 0; if (len) *len = 0; const TagFmt* str = map->find(tag); const TagFmt* str = map->find(tag); if (!str) { str = __getEventTag(const_cast<EventTagMap*>(map), tag); } if (!str) return NULL; if (!str) return NULL; if (len) *len = str->second.length(); if (len) *len = str->second.length(); return str->second.data(); return str->second.data(); } } // Look up tagname, generate one if necessary, and return a tag int android_lookupEventTagNum(EventTagMap* map, const char* tagname, const char* format, int prio) { const char* ep = endOfTag(tagname); size_t len = ep - tagname; if (!len || *ep) { errno = EINVAL; return -1; } if ((prio != ANDROID_LOG_UNKNOWN) && (prio < ANDROID_LOG_SILENT) && !__android_log_is_loggable_len(prio, tagname, len, __android_log_is_debuggable() ? ANDROID_LOG_VERBOSE : ANDROID_LOG_DEBUG)) { errno = EPERM; return -1; } if (!format) format = ""; ssize_t fmtLen = strlen(format); int ret = map->find(TagFmt( std::make_pair(MapString(tagname, len), MapString(format, fmtLen)))); if (ret != -1) return ret; // call event tag service to arrange for a new tag char* buf = NULL; // Can not use android::base::StringPrintf, asprintf + free instead. static const char command_template[] = "getEventTag name=%s format=\"%s\""; ret = asprintf(&buf, command_template, tagname, format); if (ret > 0) { // Add some buffer margin for an estimate of the full return content. char* cp; size_t size = ret - strlen(command_template) + strlen("65535\n4294967295\t?\t\t\t?\t# uid=32767\n\n\f?success?"); if (size > (size_t)ret) { cp = static_cast<char*>(realloc(buf, size)); if (cp) { buf = cp; } else { size = ret; } } else { size = ret; } #ifdef __ANDROID__ // Ask event log tag service for an allocation if (SendLogdControlMessage(buf, size) >= 0) { buf[size - 1] = '\0'; unsigned long val = strtoul(buf, &cp, 10); // return size if ((buf != cp) && (val > 0) && (*cp == '\n')) { // truncation OK val = strtoul(cp + 1, &cp, 10); // allocated tag number if ((val > 0) && (val < UINT32_MAX) && (*cp == '\t')) { free(buf); ret = val; // cache map->emplaceUnique(ret, TagFmt(std::make_pair( MapString(std::string(tagname, len)), MapString(std::string(format, fmtLen))))); return ret; } } } #endif free(buf); } // Hail Mary ret = map->find(MapString(tagname, len)); if (ret == -1) errno = ESRCH; return ret; }
liblog/include/log/event_tag_map.h +0 −6 Original line number Original line Diff line number Diff line Loading @@ -53,12 +53,6 @@ const char* android_lookupEventTag_len(const EventTagMap* map, size_t* len, const char* android_lookupEventFormat_len(const EventTagMap* map, size_t* len, const char* android_lookupEventFormat_len(const EventTagMap* map, size_t* len, unsigned int tag); unsigned int tag); /* * Look up tagname, generate one if necessary, and return a tag */ int android_lookupEventTagNum(EventTagMap* map, const char* tagname, const char* format, int prio); #ifdef __cplusplus #ifdef __cplusplus } } #endif #endif
liblog/liblog.map.txt +0 −1 Original line number Original line Diff line number Diff line Loading @@ -89,6 +89,5 @@ LIBLOG_PRIVATE { android_log_processLogBuffer; android_log_processLogBuffer; android_log_read_next; android_log_read_next; android_log_write_list_buffer; android_log_write_list_buffer; android_lookupEventTagNum; create_android_log_parser; create_android_log_parser; }; };
liblog/tests/liblog_benchmark.cpp +0 −24 Original line number Original line Diff line number Diff line Loading @@ -879,30 +879,6 @@ static void BM_lookupEventFormat(benchmark::State& state) { } } BENCHMARK(BM_lookupEventFormat); BENCHMARK(BM_lookupEventFormat); /* * Measure the time it takes for android_lookupEventTagNum plus above */ static void BM_lookupEventTagNum(benchmark::State& state) { prechargeEventMap(); std::unordered_set<uint32_t>::const_iterator it = set.begin(); while (state.KeepRunning()) { size_t len; const char* name = android_lookupEventTag_len(map, &len, (*it)); std::string Name(name, len); const char* format = android_lookupEventFormat_len(map, &len, (*it)); std::string Format(format, len); state.ResumeTiming(); android_lookupEventTagNum(map, Name.c_str(), Format.c_str(), ANDROID_LOG_UNKNOWN); state.PauseTiming(); ++it; if (it == set.end()) it = set.begin(); } } BENCHMARK(BM_lookupEventTagNum); // Must be functionally identical to liblog internal SendLogdControlMessage() // Must be functionally identical to liblog internal SendLogdControlMessage() static void send_to_control(char* buf, size_t len) { static void send_to_control(char* buf, size_t len) { int sock = int sock = Loading
liblog/tests/liblog_test.cpp +0 −17 Original line number Original line Diff line number Diff line Loading @@ -2768,20 +2768,3 @@ TEST(liblog, __android_log_pmsg_file_read) { #endif #endif } } #endif // ENABLE_FLAKY_TESTS #endif // ENABLE_FLAKY_TESTS TEST(liblog, android_lookupEventTagNum) { #ifdef __ANDROID__ EventTagMap* map = android_openEventTagMap(NULL); EXPECT_TRUE(NULL != map); std::string Name = android::base::StringPrintf("a%d", getpid()); int tag = android_lookupEventTagNum(map, Name.c_str(), "(new|1)", ANDROID_LOG_UNKNOWN); android_closeEventTagMap(map); if (tag == -1) system("tail -3 /dev/event-log-tags >&2"); EXPECT_NE(-1, tag); EXPECT_NE(0, tag); EXPECT_GT(UINT32_MAX, (unsigned)tag); #else GTEST_LOG_(INFO) << "This test does nothing.\n"; #endif }