libosmscout 1.1.1
Loading...
Searching...
No Matches
SortDat.h
Go to the documentation of this file.
1#ifndef OSMSCOUT_IMPORT_SORTDAT_H
2#define OSMSCOUT_IMPORT_SORTDAT_H
3
4/*
5 This source is part of the libosmscout library
6 Copyright (C) 2013 Tim Teulings
7
8 This library is free software; you can redistribute it and/or
9 modify it under the terms of the GNU Lesser General Public
10 License as published by the Free Software Foundation; either
11 version 2.1 of the License, or (at your option) any later version.
12
13 This library is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Lesser General Public License for more details.
17
18 You should have received a copy of the GNU Lesser General Public
19 License along with this library; if not, write to the Free Software
20 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21*/
22
23#include <list>
24#include <map>
25#include <memory>
26
28
29#include <osmscout/ObjectRef.h>
30
33
35
36namespace osmscout {
37
38 template <class N>
40 {
41 private:
42 struct Source
43 {
44 std::string filename;
45 FileScanner scanner;
46 };
47
48 struct CellEntry
49 {
50 uint8_t type;
51 Id id;
52 Source &source;
53 FileOffset fileOffset;
54 Id sortId;
55
56 CellEntry(uint8_t type,
57 Id id,
58 Source& source,
59 FileOffset fileOffset,
60 Id sortId)
61 : type(type),
62 id(id),
63 source(source),
64 fileOffset(fileOffset),
65 sortId(sortId)
66 {
67 // no code
68 }
69
70 bool operator<(const CellEntry& other) const
71 {
72 return sortId<other.sortId;
73 }
74 };
75
76 public:
78 {
79 public:
81
82 virtual bool BeforeProcessingStart(const ImportParameter& /*parameter*/,
83 Progress& /*progress*/,
84 const TypeConfig& /*typeConfig*/)
85 {
86 return true;
87 }
88
89 virtual bool Process(Progress& progress,
90 const FileOffset& offset,
91 N& data,
92 bool& save) = 0;
93
94 virtual bool AfterProcessingEnd(const ImportParameter& /*parameter*/,
95 Progress& /*progress*/,
96 const TypeConfig& /*typeConfig*/)
97 {
98 return true;
99 }
100 };
101
102 using ProcessingFilterRef = std::shared_ptr<ProcessingFilter>;
103
104 private:
105 std::list<Source> sources;
106 std::string dataFilename;
107 std::string mapFilename;
108 std::list<ProcessingFilterRef> filters;
109
110 private:
111 bool ExecuteFilter(Progress& progress,
112 FileOffset fileOffset,
113 N& data,
114 bool& save);
115
116 bool Renumber(const TypeConfig& typeConfig,
117 const ImportParameter& parameter,
118 Progress& progress);
119
120 bool Copy(const TypeConfig& typeConfig,
121 const ImportParameter& parameter,
122 Progress& progress);
123
124 protected:
125 virtual void GetTopLeftCoordinate(const N& data,
126 GeoCoord& coord) = 0;
127
128 SortDataGenerator(const std::string& dataFilename,
129 const std::string& mapFilename);
130
131 void AddSource(const std::string& filename);
132
133 void AddFilter(const ProcessingFilterRef& filter);
134
135 public:
136 std::list<std::string> ProvidesFiles(const ImportParameter& parameter) const;
137
138 bool Import(const TypeConfigRef& typeConfig,
139 const ImportParameter& parameter,
140 Progress& progress) override;
141 };
142
143 template <class N>
145
146 template <class N>
147 SortDataGenerator<N>::SortDataGenerator(const std::string& dataFilename,
148 const std::string& mapFilename)
149 : dataFilename(dataFilename),
150 mapFilename(mapFilename)
151 {
152 // no code
153 }
154
155 template <class N>
156 std::list<std::string> SortDataGenerator<N>::ProvidesFiles(const ImportParameter& /*parameter*/) const
157 {
158 std::list<std::string> providedFiles={dataFilename, mapFilename};
159
160 return providedFiles;
161 }
162
163 template <class N>
164 void SortDataGenerator<N>::AddSource(const std::string& filename)
165 {
166 Source source;
167
168 source.filename=filename;
169
170 sources.push_back(source);
171 }
172
173 template <class N>
175 {
176 filters.push_back(filter);
177 }
178
179 template <class N>
180 bool SortDataGenerator<N>::ExecuteFilter(Progress& progress,
181 FileOffset fileOffset,
182 N& data,
183 bool& save)
184 {
185 save=true;
186
187 for (const auto& filter : filters) {
188 if (!filter->Process(progress,
189 fileOffset,
190 data,
191 save)) {
192 progress.Error(std::string("Error while processing data entry"));
193
194 return false;
195 }
196
197 if (!save) {
198 break;
199 }
200 }
201
202 return true;
203 }
204
205 template <class N>
206 bool SortDataGenerator<N>::Renumber(const TypeConfig& typeConfig,
207 const ImportParameter& parameter,
208 Progress& progress)
209 {
210 FileWriter dataWriter;
211 FileWriter mapWriter;
212 size_t zoomLevel=Pow(2,parameter.GetSortTileMag());
213 size_t cellCount=zoomLevel*zoomLevel;
214 size_t maxIndex=cellCount-1;
215
216 progress.SetAction("Sorting data");
217
218 try {
219 uint32_t overallDataCount=0;
220 uint32_t dataCopiedCount=0;
221 size_t minIndex=0;
222
223 for (auto& source : sources) {
224 std::string sourceFilename=AppendFileToDir(parameter.GetDestinationDirectory(),
225 source.filename);
226
227 progress.Info("Scanning file '"+sourceFilename+"'");
228
229 source.scanner.Open(sourceFilename,
230 FileScanner::Sequential,
231 parameter.GetWayDataMemoryMaped());
232
233 uint32_t dataCount=source.scanner.ReadUInt32();
234
235 progress.Info(std::to_string(dataCount)+" entries in file '"+source.scanner.GetFilename()+"'");
236
237 overallDataCount+=dataCount;
238 }
239
240 dataWriter.Open(AppendFileToDir(parameter.GetDestinationDirectory(),
241 dataFilename));
242
243 dataWriter.Write(overallDataCount);
244
245 mapWriter.Open(AppendFileToDir(parameter.GetDestinationDirectory(),
246 mapFilename));
247
248 mapWriter.Write(overallDataCount);
249
250 while (true) {
251 progress.Info("Reading objects in cell range "+std::to_string(minIndex)+ "-"+std::to_string(maxIndex));
252
253 size_t currentEntries=0;
254 std::map<size_t,std::list<CellEntry> > dataByCellMap;
255
256 for (auto& source :sources) {
257 progress.Info("Reading objects from file '"+source.scanner.GetFilename()+"'");
258
259 source.scanner.GotoBegin();
260
261 uint32_t dataCount=source.scanner.ReadUInt32();
262 uint32_t current=1;
263
264 while (current<=dataCount) {
265 N data;
266
267 progress.SetProgress(current,dataCount);
268
269 uint8_t type=source.scanner.ReadUInt8();
270 Id id=source.scanner.ReadUInt64();
271
272 data.Read(typeConfig,
273 source.scanner);
274
275 GeoCoord coord;
276
277 GetTopLeftCoordinate(data,
278 coord);
279
280 size_t cellY=(size_t)((coord.GetLat()+90.0)/180.0*zoomLevel);
281 size_t cellX=(size_t)((coord.GetLon()+180.0)/360.0*zoomLevel);
282 size_t cellIndex=cellY*zoomLevel+cellX;
283
284 if (cellIndex>=minIndex &&
285 cellIndex<=maxIndex) {
286 dataByCellMap[cellIndex].push_back(CellEntry(type,
287 id,
288 source,
289 data.GetFileOffset(),
290 coord.GetHash()));
291 currentEntries++;
292 }
293
294 // Reduce cell interval, deleting all already stored nodes beyond the new
295 // cell range end.
296 if (currentEntries>parameter.GetSortBlockSize() &&
297 dataByCellMap.size()>1) {
298 size_t count=0;
299 size_t cutLimit=parameter.GetSortBlockSize()*9/10;
300 typename std::map<size_t,std::list<CellEntry> >::iterator cutOff=dataByCellMap.end();
301
302 for (typename std::map<size_t,std::list<CellEntry> >::iterator iter=dataByCellMap.begin();
303 iter!=dataByCellMap.end();
304 ++iter) {
305 if (count<=cutLimit &&
306 count+iter->second.size()>cutLimit) {
307 cutOff=iter;
308 break;
309 }
310
311 maxIndex=iter->first;
312 count+=iter->second.size();
313 }
314
315 assert(cutOff!=dataByCellMap.end());
316
317 currentEntries=count;
318 dataByCellMap.erase(cutOff,dataByCellMap.end());
319 }
320
321 current++;
322 }
323 }
324
325 if (maxIndex<cellCount-1) {
326 progress.Info("Cell range was reduced to "+std::to_string(minIndex)+ "-"+std::to_string(maxIndex));
327 }
328
329 progress.Info(std::string("Copy renumbered data to '")+dataWriter.GetFilename()+"'");
330
331 size_t copyCount=0;
332 for (auto& cell : dataByCellMap) {
333 cell.second.sort();
334
335 for (auto& entry : cell.second) {
336 progress.SetProgress(copyCount,currentEntries);
337
338 copyCount++;
339
340 N data;
341
342 entry.source.scanner.SetPos(entry.fileOffset);
343
344 data.Read(typeConfig,
345 entry.source.scanner);
346
347 FileOffset fileOffset=dataWriter.GetPos();
348 bool save=true;
349
350 if (!ExecuteFilter(progress,
351 fileOffset,
352 data,
353 save)) {
354 return false;
355 }
356
357 if (!save) {
358 continue;
359 }
360
361 data.Write(typeConfig,
362 dataWriter);
363
364 mapWriter.Write(entry.id);
365 mapWriter.Write(entry.type);
366 mapWriter.WriteFileOffset(fileOffset);
367
368 dataCopiedCount++;
369 }
370 }
371
372 if (currentEntries==0) {
373 progress.Info("No more entries found");
374 break;
375 }
376
377 if (maxIndex==cellCount-1) {
378 // We are finished
379 break;
380 }
381
382 minIndex=maxIndex+1;
383 maxIndex=cellCount-1;
384 }
385
386 assert(overallDataCount>=dataCopiedCount);
387
388 for (auto& source : sources) {
389 source.scanner.Close();
390 }
391
392 progress.Info(std::to_string(dataCopiedCount)+" of " +std::to_string(overallDataCount) + " object(s) written to file '"+dataWriter.GetFilename()+"'");
393
394 dataWriter.SetPos(0);
395 dataWriter.Write(dataCopiedCount);
396
397 mapWriter.SetPos(0);
398 mapWriter.Write(dataCopiedCount);
399
400 dataWriter.Close();
401 mapWriter.Close();
402 }
403 catch (const IOException& e) {
404 progress.Error(e.GetDescription());
405
406 for (auto& source : sources) {
407 source.scanner.CloseFailsafe();
408 }
409
410 dataWriter.CloseFailsafe();
411 mapWriter.CloseFailsafe();
412
413 return false;
414 }
415
416 return true;
417 }
418
419 template <class N>
420 bool SortDataGenerator<N>::Copy(const TypeConfig& typeConfig,
421 const ImportParameter& parameter,
422 Progress& progress)
423 {
424 FileWriter dataWriter;
425 FileWriter mapWriter;
426
427 progress.SetAction("Copy data");
428
429 try {
430 uint32_t overallDataCount=0;
431 uint32_t dataCopiedCount=0;
432
433 dataWriter.Open(AppendFileToDir(parameter.GetDestinationDirectory(),
434 dataFilename));
435
436 dataWriter.Write(overallDataCount);
437
438 mapWriter.Open(AppendFileToDir(parameter.GetDestinationDirectory(),
439 mapFilename));
440
441 mapWriter.Write(overallDataCount);
442
443 for (auto& source : sources) {
444 std::string sourceFilename=AppendFileToDir(parameter.GetDestinationDirectory(),
445 source.filename);
446
447 progress.Info("Scanning file '"+sourceFilename+"'");
448
449 source.scanner.Open(sourceFilename,
450 FileScanner::Sequential,
451 parameter.GetWayDataMemoryMaped());
452
453 uint32_t dataCount=source.scanner.ReadUInt32();
454
455 progress.Info(std::to_string(dataCount)+" entries in file '"+source.scanner.GetFilename()+"'");
456
457 overallDataCount+=dataCount;
458
459 for (uint32_t current=1; current<=dataCount; current++) {
460 N data;
461
462 progress.SetProgress(current,dataCount);
463
464 uint8_t type=source.scanner.ReadUInt8();
465 Id id=source.scanner.ReadUInt64();
466
467 data.Read(typeConfig,
468 source.scanner);
469
470 FileOffset fileOffset=dataWriter.GetPos();
471 bool save=true;
472
473 if (!ExecuteFilter(progress,
474 fileOffset,
475 data,
476 save)) {
477 return false;
478 }
479
480 if (!save) {
481 continue;
482 }
483
484 data.Write(typeConfig,
485 dataWriter);
486
487 mapWriter.Write(id);
488 mapWriter.Write(type);
489 mapWriter.WriteFileOffset(fileOffset);
490
491 dataCopiedCount++;
492 }
493
494 source.scanner.Close();
495 }
496
497 assert(overallDataCount>=dataCopiedCount);
498
499 dataWriter.SetPos(0);
500 dataWriter.Write(dataCopiedCount);
501
502 mapWriter.SetPos(0);
503 mapWriter.Write(dataCopiedCount);
504
505 progress.Info(std::to_string(dataCopiedCount)+" of " +std::to_string(overallDataCount) + " object(s) written to file '"+dataWriter.GetFilename()+"'");
506
507 dataWriter.Close();
508 mapWriter.Close();
509 }
510 catch (const IOException& e) {
511 progress.Error(e.GetDescription());
512
513 for (auto& source : sources) {
514 source.scanner.CloseFailsafe();
515 }
516
517 dataWriter.CloseFailsafe();
518 mapWriter.CloseFailsafe();
519
520 return false;
521 }
522
523 return true;
524 }
525
526 template <class N>
528 const ImportParameter& parameter,
529 Progress& progress)
530 {
531 bool error=false;
532
533 for (auto& filter : filters) {
534 if (!filter->BeforeProcessingStart(parameter,
535 progress,
536 *typeConfig)) {
537 progress.Error("Cannot initialize processor filter");
538
539 error=true;
540 }
541 }
542
543 if (!error) {
544 if (parameter.GetSortObjects()) {
545 if (!Renumber(*typeConfig,
546 parameter,
547 progress)) {
548 error=true;
549 }
550 }
551 else {
552 if (!Copy(*typeConfig,
553 parameter,
554 progress)) {
555 error=true;
556 }
557 }
558 }
559
560 for (auto& filter : filters) {
561 if (!filter->AfterProcessingEnd(parameter,
562 progress,
563 *typeConfig)) {
564 progress.Error("Cannot deinitialize processor filter");
565
566 error=true;
567 }
568 }
569
570 return !error;
571 }
572}
573
574#endif
Definition Exception.h:73
Definition ImportModule.h:101
Definition Progress.h:34
virtual void Error(const std::string &text)
virtual bool BeforeProcessingStart(const ImportParameter &, Progress &, const TypeConfig &)
Definition SortDat.h:82
virtual bool Process(Progress &progress, const FileOffset &offset, N &data, bool &save)=0
virtual bool AfterProcessingEnd(const ImportParameter &, Progress &, const TypeConfig &)
Definition SortDat.h:94
std::shared_ptr< ProcessingFilter > ProcessingFilterRef
Definition SortDat.h:102
void AddFilter(const ProcessingFilterRef &filter)
Definition SortDat.h:174
bool Import(const TypeConfigRef &typeConfig, const ImportParameter &parameter, Progress &progress) override
Definition SortDat.h:527
virtual void GetTopLeftCoordinate(const N &data, GeoCoord &coord)=0
std::list< std::string > ProvidesFiles(const ImportParameter &parameter) const
Definition SortDat.h:156
SortDataGenerator(const std::string &dataFilename, const std::string &mapFilename)
Definition SortDat.h:147
void AddSource(const std::string &filename)
Definition SortDat.h:164
OSMSCOUT_API std::string AppendFileToDir(const std::string &dir, const std::string &file)
uint64_t Id
Definition OSMScoutTypes.h:40
uint64_t FileOffset
Definition OSMScoutTypes.h:46
std::shared_ptr< TypeConfig > TypeConfigRef
Definition TypeConfig.h:1396
Definition Area.h:39
OSMSCOUT_API size_t Pow(size_t a, size_t b)
bool operator<(const TileCacheKey &a, const TileCacheKey &b)