1 #ifndef OSMSCOUT_NUMERICINDEX_H 2 #define OSMSCOUT_NUMERICINDEX_H 55 std::vector<Entry> entries;
57 inline bool IndexIsValid(
size_t index)
const 59 return index<entries.size();
63 using PageRef = std::shared_ptr<Page>;
65 using PageSimpleCache = std::unordered_map<N, PageRef>;
72 size_t GetSize(
const PageRef& value)
const 74 return sizeof(value)+
sizeof(Page)+
sizeof(Entry)*value->entries.size();
82 mutable FileScanner scanner;
87 std::vector<uint32_t> pageCounts;
91 size_t simpleCacheMaxLevel;
92 mutable std::vector<PageSimpleCache> simplePageCache;
93 mutable std::vector<PageCache> pageCaches;
95 mutable std::mutex accessMutex;
98 size_t GetPageIndex(
const Page& page, N
id)
const;
99 void ReadPage(
FileOffset offset, PageRef& page)
const;
100 void InitializeCache();
107 bool Open(
const std::string& path,
115 template<
typename IteratorIn>
119 std::vector<FileOffset>& offsets)
const;
127 : filepart(filename),
128 cacheSize(cacheSize),
150 size_t size=page.entries.size();
158 while (left<=right) {
159 size_t mid=(left+right)/2;
161 if (page.entries[mid].startId<=
id &&
162 (mid+1>=size || page.entries[mid+1].startId>
id)) {
166 if (page.entries[mid].startId<
id) {
183 inline void NumericIndex<N>::ReadPage(
FileOffset offset, PageRef& page)
const 186 page=std::make_shared<Page>();
189 page->entries.clear();
192 page->entries.reserve(pageSize/4);
194 scanner.SetPos(offset);
205 while (currentPos<pageSize &&
206 buffer[currentPos]!=0) {
207 unsigned int idBytes;
208 unsigned int fileOffsetBytes;
221 currentPos+=fileOffsetBytes;
223 entry.startId=prevId+curId;
224 entry.fileOffset=prefFileOffset+curFileOffset;
228 prevId=entry.startId;
229 prefFileOffset=entry.fileOffset;
231 page->entries.push_back(entry);
236 void NumericIndex<N>::InitializeCache()
238 size_t currentCacheSize=cacheSize;
239 size_t requiredCacheSize=0;
241 for (
const auto count : pageCounts) {
242 requiredCacheSize+=count;
245 if (requiredCacheSize>cacheSize) {
246 log.
Warn() <<
"Warning: Index " << filepart <<
" has cache size " << cacheSize<<
", but requires cache size " << requiredCacheSize <<
" to load index completely into cache!";
249 simpleCacheMaxLevel=0;
250 for (
size_t level=1; level<pageCounts.size(); level++) {
251 size_t resultingCacheSize;
253 simplePageCache.push_back(PageSimpleCache());
255 if (pageCounts[level]>currentCacheSize) {
256 resultingCacheSize=currentCacheSize;
259 pageCaches.push_back(PageCache(resultingCacheSize));
262 resultingCacheSize=pageCounts[level];
263 currentCacheSize-=pageCounts[level];
265 simpleCacheMaxLevel=level;
267 pageCaches.push_back(PageCache(0));
279 scanner.Open(filename,
280 FileScanner::FastRandom,
283 pageSize=scanner.ReadUInt32Number();
284 scanner.ReadUInt32Number();
286 levels=scanner.ReadUInt32();
287 pageCounts.resize(levels);
289 FileOffset lastLevelPageStart=scanner.ReadFileOffset();
290 FileOffset indexPageCountsOffset=scanner.ReadFileOffset();
292 scanner.SetPos(indexPageCountsOffset);
293 for (
size_t level=0; level<levels; level++) {
294 pageCounts[level]=scanner.ReadUInt32Number();
298 buffer=
new char[pageSize];
302 ReadPage(lastLevelPageStart,root);
308 scanner.CloseFailsafe();
312 return !scanner.HasError();
319 if (scanner.IsOpen()) {
325 scanner.CloseFailsafe();
349 std::lock_guard<std::mutex> lock(accessMutex);
353 size_t r=GetPageIndex(*root,
id);
356 if (!root->IndexIsValid(r)) {
361 const Entry& rootEntry=root->entries[r];
365 offset=rootEntry.fileOffset;
367 N startId=rootEntry.startId;
368 for (
size_t level=0; level+2<=levels; level++) {
370 if (level<=simpleCacheMaxLevel) {
371 auto cacheRef=simplePageCache[level].find(startId);
373 if (cacheRef==simplePageCache[level].end()) {
376 ReadPage(offset,pageRef);
378 simplePageCache[level].insert(std::make_pair(startId,pageRef));
381 pageRef=cacheRef->second;
387 if (!pageCaches[level].GetEntry(startId,cacheRef)) {
390 cacheRef=pageCaches[level].SetEntry(cacheEntry);
392 ReadPage(offset,cacheRef->value);
395 pageRef=cacheRef->value;
400 size_t i=GetPageIndex(page,
id);
402 if (!page.IndexIsValid(i)) {
407 const Entry& entry=page.entries[i];
411 startId=entry.startId;
412 offset=entry.fileOffset;
433 template<
typename IteratorIn>
437 std::vector<FileOffset>& offsets)
const 440 offsets.reserve(size);
442 for (IteratorIn idIter=begin; idIter!=end; ++idIter) {
445 if (GetOffset(*idIter,
447 offsets.push_back(offset);
461 memory+=root->entries.size()*
sizeof(Entry);
464 for (
size_t i=0; i<pageCaches.size(); i++) {
465 pages+=pageCaches[i].GetSize();
466 memory+=
sizeof(pageCaches[i])+pageCaches[i].GetMemory(NumericIndexCacheValueSizer());
469 log.
Info() <<
"Index " << filepart <<
": " << pages <<
" pages, memory " << memory;
bool GetOffset(const N &id, FileOffset &offset) const
Definition: NumericIndex.h:344
bool Open(const std::string &path, bool memoryMapped)
Definition: NumericIndex.h:273
bool Close()
Definition: NumericIndex.h:316
NumericIndex(const std::string &filename, size_t cacheSize)
Definition: NumericIndex.h:125
Definition: NumericIndex.h:41
Prints details for debugging, if debug flag (performance, data) is set in renderer parameter...
Definition: MapPainter.h:58
Log & Info(bool state)
Definition: Logger.h:455
Definition: Exception.h:72
virtual ~NumericIndex()
Definition: NumericIndex.h:137
Log & Error(bool state)
Definition: Logger.h:469
unsigned int DecodeNumber(const char *buffer, N &number)
Definition: Number.h:294
bool GetOffsets(IteratorIn begin, IteratorIn end, size_t size, std::vector< FileOffset > &offsets) const
Definition: NumericIndex.h:434
OSMSCOUT_API std::string AppendFileToDir(const std::string &dir, const std::string &file)
void DumpStatistics() const
Definition: NumericIndex.h:455
std::string GetDescription() const override
bool IsOpen() const
Definition: NumericIndex.h:333
uint64_t FileOffset
Definition: OSMScoutTypes.h:47
Log & Warn(bool state)
Definition: Logger.h:462
typename OrderList::iterator CacheRef
Definition: Cache.h:98