00001 
00002 
00003 
00004 
00005 
00006 
00007 
00008 
00009 
00010 
00011 
00012 
00013 
00014 
00015 
00016 
00017 
00018 
00019 
00020 
00021 
00022 
00023 
00024 
00025 
00026 #ifndef __PAR2REPAIRER_H__
00027 #define __PAR2REPAIRER_H__
00028 
00029 #include 
00030 #include "parheaders.h"
00031 
00032 #if WANT_CONCURRENT
00033 
00034  #include 
00035 
00036   struct u32_hasher {
00037     static  size_t  hash(u32 i) { return static_castsize_t> (i); }
00038     static  bool  equal( u32 x, u32 y ) { return x == y; }
00039   };
00040 
00041   struct string_hasher {
00042     static  size_t  hash(const std::string& x) {
00043       size_t h = 0;
00044       for (const char* s = x.c_str(); *s; ++s)
00045         h = (h*17)^*s;
00046       return h;
00047     }
00048     static  bool  equal( const std::string& x, const std::string& y ) { return x == y; }
00049   };
00050 
00051   struct istring_hasher {
00052     static  size_t  hash(const std::string& x) {
00053       size_t h = 0;
00054       for (const char* s = x.c_str(); *s; ++s)
00055         h = (h*17)^ tolower(*s);
00056       return h;
00057     }
00058     static  bool  equal( const std::string& x, const std::string& y )
00059     { return x.length() == y.length() && 0 == stricmp(x.c_str(), y.c_str()); }
00060   };
00061 
00062   template typename T>
00063   struct atomic_ptr : tbb::atomic {
00064     
00065     T  operator->(void) { return tbb::atomic::operator typename tbb::atomic::value_type(); }
00066     atomic_ptr&  operator=(T t) { tbb::atomic::operator=(t); return *this; }
00067   };
00068 
00069   class ConcurrentDiskFileMap {
00070   public:
00071  #if defined(WIN32) || defined(__APPLE_CC__)
00072     typedef tbb::concurrent_hash_map  map_type;
00073  #else
00074     typedef tbb::concurrent_hash_map  map_type;
00075  #endif
00076     ConcurrentDiskFileMap(void) {}
00077     ~ConcurrentDiskFileMap(void) {
00078       map_type::iterator fi;
00079       for (fi = _diskfilemap.begin(); fi != _diskfilemap.end(); ++fi)
00080         delete (*fi).second;
00081     }
00082 
00083     bool  Insert(DiskFile *diskfile) {
00084       assert(!diskfile->FileName().empty());
00085       map_type::accessor  a;
00086       (bool) _diskfilemap.insert(a, diskfile->FileName());
00087       a->second = diskfile;
00088       return true;
00089     }
00090     void Remove(DiskFile *diskfile) {
00091       assert(!diskfile->FileName().empty());
00092       (bool) _diskfilemap.erase(diskfile->FileName());
00093     }
00094     DiskFile* Find(string filename) const {
00095       assert(!filename.empty());
00096       map_type::const_accessor  a;
00097       return _diskfilemap.find(a, filename) ?  a->second : NULL;
00098     }
00099 
00100   protected:
00101     map_type _diskfilemap;             
00102   };
00103 
00104 #endif
00105 
00106 class Par2Repairer
00107 {
00108 public:
00109   Par2Repairer(void);
00110   ~Par2Repairer(void);
00111 
00112   Result Process(const CommandLine &commandline, bool dorepair);
00113 
00114   sigc::signal sig_filename;
00115   sigc::signal sig_progress;
00116   sigc::signal sig_headers;
00117   sigc::signal sig_done;
00118 
00119 protected:
00120   
00121 
00122 #if WANT_CONCURRENT
00123 public:
00124  #if WANT_CONCURRENT_SOURCE_VERIFICATION
00125   void VerifyOneSourceFile(Par2RepairerSourceFile *sourcefile, bool& finalresult);
00126  #endif
00127   void ProcessDataForOutputIndex(u32 outputstartindex, u32 outputendindex, size_t blocklength, u32 inputindex);
00128 #endif
00129   
00130   bool LoadPacketsFromFile(string filename);
00131 #if WANT_CONCURRENT
00132 protected:
00133 #endif
00134   
00135   bool LoadRecoveryPacket(DiskFile *diskfile, u64 offset, PACKET_HEADER &header);
00136   
00137   bool LoadDescriptionPacket(DiskFile *diskfile, u64 offset, PACKET_HEADER &header);
00138   
00139   bool LoadVerificationPacket(DiskFile *diskfile, u64 offset, PACKET_HEADER &header);
00140   
00141   bool LoadMainPacket(DiskFile *diskfile, u64 offset, PACKET_HEADER &header);
00142   
00143   bool LoadCreatorPacket(DiskFile *diskfile, u64 offset, PACKET_HEADER &header);
00144 
00145   
00146   bool LoadPacketsFromOtherFiles(string filename);
00147 
00148   
00149   bool LoadPacketsFromExtraFiles(const list<:extrafile> &extrafiles);
00150 
00151   
00152   bool CheckPacketConsistency(void);
00153 
00154   
00155   
00156   bool CreateSourceFileList(void);
00157 
00158   
00159   
00160   bool AllocateSourceBlocks(void);
00161 
00162   
00163   
00164   
00165   bool PrepareVerificationHashTable(void);
00166 
00167   
00168   bool ComputeWindowTable(void);
00169 
00170   
00171   bool VerifySourceFiles(void);
00172 
00173   
00174   bool VerifyExtraFiles(const list<:extrafile> &extrafiles);
00175 
00176   
00177   bool VerifyDataFile(DiskFile *diskfile, Par2RepairerSourceFile *sourcefile);
00178 
00179   
00180   
00181   
00182   
00183   
00184   bool ScanDataFile(DiskFile                *diskfile,   
00185                     Par2RepairerSourceFile* &sourcefile, 
00186                     MatchType               &matchtype,  
00187                     MD5Hash                 &hashfull,   
00188                     MD5Hash                 &hash16k,    
00189                     u32                     &count);     
00190 
00191   
00192   void UpdateVerificationResults(void);
00193 
00194   
00195   bool CheckVerificationResults(void);
00196 
00197   
00198   bool RenameTargetFiles(void);
00199 
00200   
00201   
00202   bool CreateTargetFiles(void);
00203 
00204   
00205   
00206   
00207   bool ComputeRSmatrix(void);
00208 
00209   
00210   bool AllocateBuffers(size_t memorylimit);
00211 
00212   
00213   bool ProcessData(u64 blockoffset, size_t blocklength);
00214 
00215   
00216   bool VerifyTargetFiles(void);
00217 
00218   
00219   bool DeleteIncompleteTargetFiles(void);
00220 
00221 protected:
00222   ParHeaders*               headers;                 
00223   CommandLine::NoiseLevel   noiselevel;              
00224 
00225   string                    searchpath;              
00226 
00227   bool                      firstpacket;             
00228   MD5Hash                   setid;                   
00229 #if WANT_CONCURRENT
00230   tbb::concurrent_hash_map recoverypacketmap;       
00231   ::atomic_ptr    mainpacket;           
00232   ::atomic_ptr creatorpacket;        
00233 
00234   ConcurrentDiskFileMap     diskFileMap;
00235 #else
00236   map recoverypacketmap;       
00237   MainPacket               *mainpacket;              
00238   CreatorPacket            *creatorpacket;           
00239 
00240   DiskFileMap               diskFileMap;
00241 #endif
00242 
00243   map sourcefilemap;
00244   vector      sourcefiles;  
00245   vector      verifylist;   
00246 
00247   u64                       blocksize;               
00248   u64                       chunksize;               
00249   u32                       sourceblockcount;        
00250   u32                       availableblockcount;     
00251   u32                       missingblockcount;       
00252 
00253   bool                      blocksallocated;         
00254   vector         sourceblocks;            
00255   vector         targetblocks;            
00256 
00257   u32                       windowtable[256];        
00258   u32                       windowmask;              
00259 
00260   bool                            blockverifiable;         
00261   VerificationHashTable           verificationhashtable;   
00262   list   unverifiablesourcefiles; 
00263 
00264   u32                       completefilecount;       
00265   u32                       renamedfilecount;        
00266   u32                       damagedfilecount;        
00267   u32                       missingfilecount;        
00268 
00269   vector        inputblocks;             
00270   vector        copyblocks;              
00271   vector        outputblocks;            
00272 
00273   ReedSolomon     rs;                      
00274 
00275   void                     *inputbuffer;             
00276   void                     *outputbuffer;            
00277 
00278 #if WANT_CONCURRENT
00279   tbb::atomic          progress;                
00280 #else
00281   u64                       progress;                
00282 #endif
00283   u64                       totaldata;               
00284   u64                       totalsize;               
00285 
00286 #if WANT_CONCURRENT
00287   unsigned                  concurrent_processing_level;
00288   tbb::mutex                cout_mutex;
00289   tbb::atomic          cout_in_use;             
00290   tbb::tick_count           last_cout;   
00291 #endif
00292 };
00293 
00294 #endif // __PAR2REPAIRER_H__