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