OSSIM - Open Source Software Image Map  Version 1.9.0 (20180803)
ossimFileWalker.cpp
Go to the documentation of this file.
1 //----------------------------------------------------------------------------
2 //
3 // File: ossimFileWalker.h
4 //
5 // License: LGPL
6 //
7 // See LICENSE.txt file in the top level directory for more details.
8 //
9 // Author: David Burken
10 //
11 // Description:
12 //
13 // Utility class to walk through directories and get a list of files to
14 // process.
15 //
16 //----------------------------------------------------------------------------
17 // $Id$
18 
22 #include <ossim/base/ossimTrace.h>
23 #include <ossim/base/Thread.h>
25 
26 static ossimTrace traceDebug(ossimString("ossimFileWalker:debug"));
27 
29  : m_fileProcessor(0),
30  m_jobQueue(std::make_shared<ossimJobMultiThreadQueue>(std::make_shared<ossimJobQueue>(), 1)),
31  m_filteredExtensions(0),
32  m_recurseFlag(true),
33  m_waitOnDirFlag(false),
34  m_abortFlag(false),
35  m_mutex()
36 {
37 }
38 
40 {
41  m_jobQueue = 0; // Not a leak, ref pointer.
42 }
43 
44 void ossimFileWalker::walk(const std::vector<ossimFilename>& files)
45 {
46  static const char M[] = "ossimFileWalker::walk";
47  if(traceDebug())
48  {
49  ossimNotify(ossimNotifyLevel_DEBUG) << M << " entered\n";
50  }
51 
52  if ( files.size() )
53  {
54  std::vector<ossimFilename>::const_iterator i = files.begin();
55  while ( i != files.end() )
56  {
57  // Must have call back set at this point.
58  if ( !m_abortFlag && m_fileProcessor )
59  {
60  ossimFilename file = (*i).expand();
61  if ( file.size() && file.exists() )
62  {
63  if ( file.isDir() ) // Directory:
64  {
65  walkDir(file);
66  }
67  else // File:
68  {
69  if ( isFiltered(file) == false )
70  {
71  if(traceDebug())
72  {
74  << "Making the job for: " << (*i) << std::endl;
75  }
76 
77  // Make the job:
78  std::shared_ptr<ossimFileWalkerJob> job =
79  std::make_shared<ossimFileWalkerJob>( m_fileProcessor, file );
80 
81  job->setName( ossimString( file.string() ) );
82 
83  job->setCallback( std::make_shared<ossimFileWalkerJobCallback>() );
84 
85  // Set the state to ready:
86  job->ready();
87 
88  // Add job to the queue:
89  m_jobQueue->getJobQueue()->add( job );
90 
91  m_mutex.lock();
92  if ( m_abortFlag )
93  {
94  // Clear out the queue.
95  m_jobQueue->getJobQueue()->clear();
96 
97  break; // Callee set our abort flag so break out of loop.
98  }
99  m_mutex.unlock();
100  }
101  }
102  }
103  else
104  {
106  << M << " WARNING: file: \""<< file << "\" does not exist" << std::endl;
107  }
108  }
109 
110  ++i;
111 
112  } // while ( i != files.end() )
113 
114  // FOREVER loop until all jobs are completed.
115  while (1)
116  {
118  if ( m_jobQueue->hasJobsToProcess() == false )
119  {
120  break;
121  }
122  }
123 
124  } // if ( files.size() )
125 
126  if(traceDebug())
127  {
128  ossimNotify(ossimNotifyLevel_DEBUG) << M << " exiting...\n";
129  }
130 }
131 
133 {
134  static const char M[] = "ossimFileWalker::walk";
135  if(traceDebug())
136  {
137  ossimNotify(ossimNotifyLevel_DEBUG) << M << " entered root=" << root << "\n";
138  }
139 
140  // Must have call back set at this point.
141  if ( !m_abortFlag && m_fileProcessor )
142  {
143  ossimFilename rootFile = root.expand();
144  if ( rootFile.size() && rootFile.exists() )
145  {
146  if ( rootFile.isDir() )
147  {
148  walkDir(rootFile);
149 
150  // FOREVER loop until all jobs are completed.
151  while (1)
152  {
154  if ( m_jobQueue->hasJobsToProcess() == false )
155  {
156  break;
157  }
158  }
159  }
160  else
161  {
162  // Single file no job queue needed.
163  if ( isFiltered( rootFile ) == false )
164  {
165  m_fileProcessor->processFile( rootFile );
166  }
167  }
168  }
169  else
170  {
172  << M << " WARNING: file: \""<< rootFile << "\" does not exist" << std::endl;
173  }
174  }
175 
176  if(traceDebug())
177  {
178  ossimNotify(ossimNotifyLevel_DEBUG) << M << " exiting...\n";
179  }
180 }
181 
183 {
184  static const char M[] = "ossimFileWalker::walkDir";
185  if(traceDebug())
186  {
188  << M << " entered...\n" << "processing dir: " << dir << "\n";
189  }
190 
191  // List of directories in this directory...
192  std::vector<ossimFilename> dirs;
193 
194  // List of files in this directory...
195  std::vector<ossimFilename> files;
196 
197  m_mutex.lock();
198  ossimDirectory d;
199  bool ossimDirectoryStatus = d.open(dir);
200  m_mutex.unlock();
201 
202  if ( ossimDirectoryStatus )
203  {
204  // Loop to get the list of files and directories in this directory.
205  m_mutex.lock();
206  ossimFilename f;
207  bool valid_file = d.getFirst(f);
208  while ( valid_file )
209  {
210  if ( isFiltered(f) == false )
211  {
212  if (f.isDir())
213  {
214  dirs.push_back(f);
215  }
216  else
217  {
218  files.push_back(f);
219  }
220  }
221  valid_file = d.getNext(f);
222  }
223  m_mutex.unlock();
224 
225  //---
226  // Process files first before recursing directories. If a file is a directory base image,
227  // e.g. RPF, then the callee should call ossimFileWalker::setRecurseFlag to false to
228  // stop us from going into sub directories.
229  //---
230  std::vector<ossimFilename>::const_iterator i = files.begin();
231  while (i != files.end())
232  {
233  if(traceDebug())
234  {
235  ossimNotify(ossimNotifyLevel_DEBUG) << "Making the job for: " << (*i) << std::endl;
236  }
237 
238  // Make the job:
239  std::shared_ptr<ossimFileWalkerJob> job =
240  std::make_shared<ossimFileWalkerJob>( m_fileProcessor, (*i) );
241 
242  job->setName( ossimString( (*i).string() ) );
243 
244  job->setCallback( std::make_shared<ossimFileWalkerJobCallback>() );
245 
246  // Set the state to ready:
247  job->ready();
248 
249  // Add job to the queue:
250  m_jobQueue->getJobQueue()->add( job );
251 
252  m_mutex.lock();
253  if ( m_abortFlag )
254  {
255  // Clear out the queue.
256  m_jobQueue->getJobQueue()->clear();
257 
258  break; // Callee set our abort flag so break out of loop.
259  }
260  m_mutex.unlock();
261 
262  ++i;
263  }
264 
265  if ( m_waitOnDirFlag )
266  {
267  // FOREVER loop until all jobs are completed.
268  while (1)
269  {
271  if ( m_jobQueue->hasJobsToProcess() == false )
272  {
273  break;
274  }
275  }
276  }
277 
278  m_mutex.lock();
279  if ( !m_abortFlag && m_recurseFlag )
280  {
281  // Process sub directories...
282  i = dirs.begin();
283  while (i != dirs.end())
284  {
285  m_mutex.unlock();
286  walkDir( (*i) );
287  m_mutex.lock();
288 
289  if ( m_abortFlag )
290  {
291  break; // Callee set our abort flag so break out of loop.
292  }
293  ++i;
294  }
295  }
296  m_mutex.unlock();
297 
298  } // if ( ossimDirectoryOpenStatus )
299 
300  // Reset the m_recurseFlag.
301  m_mutex.lock();
302  m_recurseFlag = true;
303  m_mutex.unlock();
304 
305  if(traceDebug())
306  {
307  ossimNotify(ossimNotifyLevel_DEBUG) << M << " exited...\n";
308  }
309 }
310 
312 {
313  bool result = false;
314  if ( file.size() )
315  {
316  if ( isDotFile(file) )
317  {
318  result = true;
319  }
320  else if ( file[file.size()-1] == '~' )
321  {
322  result = true;
323  }
324  else
325  {
326  std::string ext = file.ext().downcase().c_str();
327  if ( ext.size() )
328  {
329  std::vector<std::string>::const_iterator i = m_filteredExtensions.begin();
330  while ( i != m_filteredExtensions.end() )
331  {
332  if ( ext == (*i) )
333  {
334  result = true;
335  break;
336  }
337  ++i;
338  }
339  }
340  }
341  }
342 #if 0 /* Please leave for debug. (drb) */
343  if(traceDebug())
344  {
346  << "ossimFileWalker::isFiltered file " << (result?"filtered: ":"not filtered: ")
347  << file << "\n";
348  }
349 #endif
350 
351  return result;
352 }
353 
355 {
356  bool result = false;
357 
358  // Get the size in bytes.
359  if ( f.size() )
360  {
361  std::string::size_type firstDotPos = f.find('.');
362  if ( firstDotPos == 0 )
363  {
364  result = true;
365  }
366  else if ( firstDotPos != std::string::npos ) // Dot in file.
367  {
368  // Get the position of first dot from the end.
369  std::string::size_type lastDotPos = f.find_last_of('.');
370  if ( lastDotPos != std::string::npos )
371  {
372  // Make copy.
373  ossimFilename f2 = f;
374 
375  // Convert an '\'s to '/'s.
376  // f2.convertBackToForwardSlashes();
377 
378  // Find the first slash from end.
379  std::string::size_type lastSlashPos = f2.find_last_of('/');
380 
381  if (lastSlashPos != std::string::npos) // Found a slash.
382  {
383  if ( (lastSlashPos+1) == lastDotPos )
384  {
385  // dot in front of slash like /home/foo/.xemacs
386  result = true;
387  }
388  }
389  }
390  }
391  }
392 
393  return result;
394 }
395 
396 const std::vector<std::string>& ossimFileWalker::getFilteredExtensions() const
397 {
398  return m_filteredExtensions;
399 }
400 
401 std::vector<std::string>& ossimFileWalker::getFilteredExtensions()
402 {
403  return m_filteredExtensions;
404 }
405 
407 {
408  ossimNotify(ossimNotifyLevel_NOTICE) << "Filtered extension list:\n";
409  std::vector<std::string>::const_iterator i = m_filteredExtensions.begin();
410  while ( i != m_filteredExtensions.end() )
411  {
412  ossimNotify(ossimNotifyLevel_NOTICE) << (*i) << "\n";
413  ++i;
414  }
415  ossimNotify(ossimNotifyLevel_NOTICE) << std::endl;
416 }
417 
419 {
420  m_mutex.lock();
421 
422  // Common extensions to filter out, most common first.
423  m_filteredExtensions.push_back(std::string("ovr"));
424  m_filteredExtensions.push_back(std::string("omd"));
425  m_filteredExtensions.push_back(std::string("his"));
426  m_filteredExtensions.push_back(std::string("geom"));
427 
428  // The rest alphabetical.
429  m_filteredExtensions.push_back(std::string("aux"));
430  m_filteredExtensions.push_back(std::string("bin"));
431  m_filteredExtensions.push_back(std::string("dbf"));
432  m_filteredExtensions.push_back(std::string("h5"));
433  m_filteredExtensions.push_back(std::string("hdr"));
434  m_filteredExtensions.push_back(std::string("jgw"));
435  m_filteredExtensions.push_back(std::string("jpw"));
436  m_filteredExtensions.push_back(std::string("kwl"));
437  m_filteredExtensions.push_back(std::string("log"));
438  m_filteredExtensions.push_back(std::string("man"));
439  m_filteredExtensions.push_back(std::string("ocg"));
440  m_filteredExtensions.push_back(std::string("out"));
441  m_filteredExtensions.push_back(std::string("prj"));
442  m_filteredExtensions.push_back(std::string("save"));
443  m_filteredExtensions.push_back(std::string("sdw"));
444  m_filteredExtensions.push_back(std::string("sh"));
445  m_filteredExtensions.push_back(std::string("shp"));
446  m_filteredExtensions.push_back(std::string("shx"));
447  m_filteredExtensions.push_back(std::string("spec"));
448  m_filteredExtensions.push_back(std::string("statistics"));
449  m_filteredExtensions.push_back(std::string("tar"));
450  m_filteredExtensions.push_back(std::string("til"));
451  m_filteredExtensions.push_back(std::string("tfw"));
452  m_filteredExtensions.push_back(std::string("tgz"));
453  m_filteredExtensions.push_back(std::string("tmp"));
454  m_filteredExtensions.push_back(std::string("txt"));
455 
456  m_mutex.unlock();
457 }
458 
460 {
461  m_mutex.lock();
462  m_recurseFlag = flag;
463  m_mutex.unlock();
464 }
465 
467 {
468  m_mutex.lock();
469  m_waitOnDirFlag = flag;
470  m_mutex.unlock();
471 }
472 
474 {
475  m_mutex.lock();
476  m_abortFlag = flag;
477  m_mutex.unlock();
478 }
479 
481 {
482  m_mutex.lock();
483  m_jobQueue->setNumberOfThreads(nThreads);
484  m_mutex.unlock();
485 }
486 
488 {
489  m_mutex.lock();
490  m_fileProcessor = fpi;
491  m_mutex.unlock();
492 }
493 
496  const ossimFilename& file)
497  : m_fileProcessor( fpi ),
498  m_file( file )
499 {
500 }
501 
503 {
504  if ( m_fileProcessor && m_file.size() )
505  {
506  m_fileProcessor->processFile( m_file );
507  }
508 }
509 
511  : ossimJobCallback()
512 {
513 }
514 
515 void ossimFileWalker::ossimFileWalkerJobCallback::started(std::shared_ptr<ossimJob> job)
516 {
518 }
519 
520 void ossimFileWalker::ossimFileWalkerJobCallback::finished(std::shared_ptr<ossimJob> job)
521 {
523 }
524 
525 void ossimFileWalker::ossimFileWalkerJobCallback::canceled(std::shared_ptr<ossimJob> job)
526 {
528 }
void dumpFilteredExtensionList() const
Dumps filtered image extenstions to std out.
void setFileProcessor(ossimFileProcessorInterface *fpi)
Sets ossimFileProcessorInterfacecallback method to process files.
void setRecurseFlag(bool flag)
Sets recurse flag.
virtual void run()
Defines pure virtual ossimJob::start.
bool getFirst(ossimFilename &filename, int flags=OSSIM_DIR_DEFAULT)
ossimFilename expand() const
Method to do file name expansion.
ossimFileWalkerJob(ossimFileProcessorInterface *fpi, const ossimFilename &file)
Constructor that takes file processor pointer and file.
const std::vector< std::string > & getFilteredExtensions() const
ossimFileProcessorInterface * m_fileProcessor
Callback to method to process a file.
bool isDir() const
bool isFiltered(const ossimFilename &f) const
Convenience method for file walker code to check file to see is it should be processed.
static void sleepInMicroSeconds(ossim_uint64 micros)
Utility method to allow one to sleep in microseconds.
Definition: Thread.cpp:83
bool getNext(ossimFilename &filename) const
std::shared_ptr< ossimJobMultiThreadQueue > m_jobQueue
void walkDir(const ossimFilename &dir)
Processes files in directory.
std::mutex m_mutex
This allocates a thread pool used to listen on a shared job queue.
virtual void started(std::shared_ptr< ossimJob > job)
bool exists() const
std::string::size_type size() const
Definition: ossimString.h:405
virtual void canceled(std::shared_ptr< ossimJob > job)
unsigned int ossim_uint32
void setNumberOfThreads(ossim_uint32 nThreads)
Sets the max number of threads(jobs) to run at one time.
~ossimFileWalker()
destructor
static ossimString downcase(const ossimString &aString)
Definition: ossimString.cpp:48
virtual void finished(std::shared_ptr< ossimJob > job)
void initializeDefaultFilterList()
Initializes the filter list with a default set of filtered out file names.
bool open(const ossimFilename &dir)
bool isDotFile(const ossimFilename &f) const
isDotFile method.
ossimFileWalker()
default constructor
virtual void started(std::shared_ptr< ossimJob > job)
Definition: ossimJob.h:74
std::string::size_type find_last_of(char c, std::string::size_type pos=std::string::npos) const
Equivalent to rfind(c, pos).
Definition: ossimString.h:825
const char * c_str() const
Returns a pointer to a null-terminated array of characters representing the string&#39;s contents...
Definition: ossimString.h:396
This is the base implementation for the job queue.
Definition: ossimJobQueue.h:84
ossimString ext() const
void setWaitOnDirFlag(bool flag)
Sets waitOnDir flag.
virtual void canceled(std::shared_ptr< ossimJob > job)
Definition: ossimJob.h:76
std::string::size_type find(const std::string &s, std::string::size_type pos=0) const
Searches for s as a substring of *this, beginning at character pos of *this.
Definition: ossimString.h:753
virtual void finished(std::shared_ptr< ossimJob > job)
Definition: ossimJob.h:75
void walk(const std::vector< ossimFilename > &files)
Takes an array of files.
OSSIMDLLEXPORT std::ostream & ossimNotify(ossimNotifyLevel level=ossimNotifyLevel_WARN)
std::vector< std::string > m_filteredExtensions
This is the job callback interface It allows one to attach and listen for different states of the job...
Definition: ossimJob.h:68
virtual void processFile(const ossimFilename &file)=0
Pure virtual processFile method.
const std::string & string() const
Definition: ossimString.h:414
void setAbortFlag(bool flag)
If set to true this stops files walking (aborts).