remove eof whitespace lines
[folly.git] / folly / experimental / symbolizer / ElfCache.cpp
1 /*
2  * Copyright 2014 Facebook, Inc.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *   http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 #include <folly/experimental/symbolizer/ElfCache.h>
18
19 namespace folly { namespace symbolizer {
20
21 SignalSafeElfCache::SignalSafeElfCache(size_t capacity) {
22   map_.reserve(capacity);
23   slots_.reserve(capacity);
24
25   // Preallocate
26   for (size_t i = 0; i < capacity; ++i) {
27     slots_.push_back(std::make_shared<ElfFile>());
28   }
29 }
30
31 std::shared_ptr<ElfFile> SignalSafeElfCache::getFile(StringPiece p) {
32   if (p.size() > Path::kMaxSize) {
33     return nullptr;
34   }
35
36   Path path(p);
37   auto pos = map_.find(path);
38   if (pos != map_.end()) {
39     return slots_[pos->second];
40   }
41
42   size_t n = map_.size();
43   if (n >= slots_.size()) {
44     DCHECK_EQ(map_.size(), slots_.size());
45     return nullptr;
46   }
47
48   auto& f = slots_[n];
49
50   const char* msg = "";
51   int r = f->openNoThrow(path.data(), true, &msg);
52   if (r == ElfFile::kSystemError) {
53     return nullptr;
54   }
55   FOLLY_SAFE_CHECK(r == ElfFile::kSuccess, msg);
56
57   map_[path] = n;
58   return f;
59 }
60
61 ElfCache::ElfCache(size_t capacity) : capacity_(capacity) { }
62
63 std::shared_ptr<ElfFile> ElfCache::getFile(StringPiece p) {
64   std::lock_guard<std::mutex> lock(mutex_);
65
66   auto pos = files_.find(p);
67   if (pos != files_.end()) {
68     // Found, move to back (MRU)
69     auto& entry = pos->second;
70     lruList_.erase(lruList_.iterator_to(*entry));
71     lruList_.push_back(*entry);
72     return filePtr(entry);
73   }
74
75   auto entry = std::make_shared<Entry>();
76   entry->path = p.str();
77   auto& path = entry->path;
78
79   // No negative caching
80   const char* msg = "";
81   int r = entry->file.openNoThrow(path.c_str(), true, &msg);
82   if (r == ElfFile::kSystemError) {
83     return nullptr;
84   }
85   FOLLY_SAFE_CHECK(r == ElfFile::kSuccess, msg);
86
87   if (files_.size() == capacity_) {
88     auto& e = lruList_.front();
89     lruList_.pop_front();
90     files_.erase(e.path);
91   }
92
93   files_.emplace(entry->path, entry);
94   lruList_.push_back(*entry);
95
96   return filePtr(entry);
97 }
98
99 std::shared_ptr<ElfFile> ElfCache::filePtr(const std::shared_ptr<Entry>& e) {
100   // share ownership
101   return std::shared_ptr<ElfFile>(e, &e->file);
102 }
103
104 }}  // namespaces