Panda3D
 All Classes Functions Variables Enumerations
bamCacheRecord.cxx
00001 // Filename: bamCacheRecord.cxx
00002 // Created by:  drose (09Jun06)
00003 //
00004 ////////////////////////////////////////////////////////////////////
00005 //
00006 // PANDA 3D SOFTWARE
00007 // Copyright (c) Carnegie Mellon University.  All rights reserved.
00008 //
00009 // All use of this software is subject to the terms of the revised BSD
00010 // license.  You should have received a copy of this license along
00011 // with this source code in a file named "LICENSE."
00012 //
00013 ////////////////////////////////////////////////////////////////////
00014 
00015 #include "bamCacheRecord.h"
00016 #include "virtualFileSystem.h"
00017 #include "virtualFile.h"
00018 #include "indent.h"
00019 
00020 TypeHandle BamCacheRecord::_type_handle;
00021 
00022 ////////////////////////////////////////////////////////////////////
00023 //     Function: BamCacheRecord::Default Constructor
00024 //       Access: Private
00025 //  Description: Used when reading from a bam file.
00026 ////////////////////////////////////////////////////////////////////
00027 BamCacheRecord::
00028 BamCacheRecord() :
00029   _recorded_time(0),
00030   _record_size(0),
00031   _ptr(NULL),
00032   _ref_ptr(NULL),
00033   _record_access_time(0)
00034 {
00035 }
00036 
00037 ////////////////////////////////////////////////////////////////////
00038 //     Function: BamCacheRecord::Constructor
00039 //       Access: Private
00040 //  Description: Use BamCache::lookup() to create one of these.
00041 ////////////////////////////////////////////////////////////////////
00042 BamCacheRecord::
00043 BamCacheRecord(const Filename &source_pathname, 
00044                const Filename &cache_filename) :
00045   _source_pathname(source_pathname),
00046   _cache_filename(cache_filename),
00047   _recorded_time(0),
00048   _record_size(0),
00049   _ptr(NULL),
00050   _ref_ptr(NULL),
00051   _record_access_time(0)
00052 {
00053 }
00054 
00055 ////////////////////////////////////////////////////////////////////
00056 //     Function: BamCacheRecord::Copy Constructor
00057 //       Access: Private
00058 //  Description: Use make_copy() to make a copy.  The copy does not
00059 //               share the data pointer.
00060 ////////////////////////////////////////////////////////////////////
00061 BamCacheRecord::
00062 BamCacheRecord(const BamCacheRecord &copy) :
00063   _source_pathname(copy._source_pathname),
00064   _cache_filename(copy._cache_filename),
00065   _recorded_time(copy._recorded_time),
00066   _record_size(copy._record_size),
00067   _ptr(NULL),
00068   _ref_ptr(NULL),
00069   _record_access_time(copy._record_access_time)
00070 {
00071 }
00072 
00073 ////////////////////////////////////////////////////////////////////
00074 //     Function: BamCacheRecord::Destructor
00075 //       Access: Published, Virtual
00076 //  Description: 
00077 ////////////////////////////////////////////////////////////////////
00078 BamCacheRecord::
00079 ~BamCacheRecord() {
00080   clear_data();
00081 }
00082 
00083 ////////////////////////////////////////////////////////////////////
00084 //     Function: BamCacheRecord::dependents_unchanged
00085 //       Access: Published
00086 //  Description: Returns true if all of the dependent files are still
00087 //               the same as when the cache was recorded, false
00088 //               otherwise.
00089 ////////////////////////////////////////////////////////////////////
00090 bool BamCacheRecord::
00091 dependents_unchanged() const {
00092   VirtualFileSystem *vfs = VirtualFileSystem::get_global_ptr();
00093 
00094   if (util_cat.is_debug()) {
00095     util_cat.debug()
00096       << "Validating dependents for " << get_source_pathname() << "\n";
00097   }
00098 
00099   DependentFiles::const_iterator fi;
00100   for (fi = _files.begin(); fi != _files.end(); ++fi) {
00101     const DependentFile &dfile = (*fi);
00102     PT(VirtualFile) file = vfs->get_file(dfile._pathname);
00103     if (file == (VirtualFile *)NULL) {
00104       // No such file.
00105       if (dfile._timestamp != 0) {
00106         if (util_cat.is_debug()) {
00107           util_cat.debug()
00108             << dfile._pathname << " does not exist.\n";
00109         }
00110         return false;
00111       }
00112     } else {
00113       if (file->get_timestamp() != dfile._timestamp ||
00114           file->get_file_size() != dfile._size) {
00115         // File has changed timestamp or size.
00116         if (util_cat.is_debug()) {
00117           util_cat.debug()
00118             << dfile._pathname << " has changed timestamp or size.\n";
00119         }
00120         return false;
00121       }
00122     }
00123     
00124     // Presumably, the file is unchanged.
00125     if (util_cat.is_debug()) {
00126       util_cat.debug()
00127         << dfile._pathname << " is unchanged.\n";
00128     }
00129   }
00130 
00131   if (util_cat.is_debug()) {
00132     util_cat.debug()
00133       << "Dependents valid.\n";
00134   }
00135 
00136   return true;
00137 }
00138 
00139 
00140 ////////////////////////////////////////////////////////////////////
00141 //     Function: BamCacheRecord::clear_dependent_files
00142 //       Access: Published
00143 //  Description: Empties the list of files that contribute to the data
00144 //               in this record.
00145 ////////////////////////////////////////////////////////////////////
00146 void BamCacheRecord::
00147 clear_dependent_files() {
00148   _files.clear();
00149 }
00150 
00151 ////////////////////////////////////////////////////////////////////
00152 //     Function: BamCacheRecord::add_dependent_file
00153 //       Access: Published
00154 //  Description: Adds the indicated file to the list of files that
00155 //               will be loaded to generate the data in this record.
00156 //               This should be called once for the primary source
00157 //               file, and again for each secondary source file, if
00158 //               any.
00159 ////////////////////////////////////////////////////////////////////
00160 void BamCacheRecord::
00161 add_dependent_file(const Filename &pathname) {
00162   VirtualFileSystem *vfs = VirtualFileSystem::get_global_ptr();
00163 
00164   _files.push_back(DependentFile());
00165   DependentFile &dfile = _files.back();
00166   dfile._pathname = pathname;
00167   dfile._pathname.make_absolute();
00168 
00169   PT(VirtualFile) file = vfs->get_file(dfile._pathname);
00170   if (file == (VirtualFile *)NULL) {
00171     // No such file.
00172     dfile._timestamp = 0;
00173     dfile._size = 0;
00174 
00175   } else {
00176     dfile._timestamp = file->get_timestamp();
00177     dfile._size = file->get_file_size();
00178   }
00179 }
00180 
00181 ////////////////////////////////////////////////////////////////////
00182 //     Function: BamCacheRecord::output
00183 //       Access: Published
00184 //  Description: 
00185 ////////////////////////////////////////////////////////////////////
00186 void BamCacheRecord::
00187 output(ostream &out) const {
00188   out << "BamCacheRecord " << get_source_pathname();
00189 }
00190 
00191 ////////////////////////////////////////////////////////////////////
00192 //     Function: BamCacheRecord::write
00193 //       Access: Published
00194 //  Description: 
00195 ////////////////////////////////////////////////////////////////////
00196 void BamCacheRecord::
00197 write(ostream &out, int indent_level) const {
00198   indent(out, indent_level)
00199     << "BamCacheRecord " << get_source_pathname() << "\n";
00200   indent(out, indent_level)
00201     << "recorded " << format_timestamp(_recorded_time) << "\n";
00202 
00203   indent(out, indent_level)
00204     << _files.size() << " dependent files.\n";
00205   DependentFiles::const_iterator fi;
00206   for (fi = _files.begin(); fi != _files.end(); ++fi) {
00207     const DependentFile &dfile = (*fi);
00208     indent(out, indent_level + 2)
00209       << setw(10) << dfile._size << " "
00210       << format_timestamp(dfile._timestamp) << " "
00211       << dfile._pathname << "\n";
00212   }
00213 }
00214 
00215 ////////////////////////////////////////////////////////////////////
00216 //     Function: BamCacheRecord::format_timestamp
00217 //       Access: Private, Static
00218 //  Description: Returns a timestamp value formatted nicely for
00219 //               output.
00220 ////////////////////////////////////////////////////////////////////
00221 string BamCacheRecord::
00222 format_timestamp(time_t timestamp) {
00223   static const size_t buffer_size = 512;
00224   char buffer[buffer_size];
00225 
00226   if (timestamp == 0) {
00227     // A zero timestamp is a special case.
00228     return "  (no date) ";
00229   }
00230 
00231   time_t now = time(NULL);
00232   struct tm *tm_p = localtime(&timestamp);
00233 
00234   if (timestamp > now || (now - timestamp > 86400 * 365)) {
00235     // A timestamp in the future, or more than a year in the past,
00236     // gets a year appended.
00237     strftime(buffer, buffer_size, "%b %d  %Y", tm_p);
00238   } else {
00239     // Otherwise, within the past year, show the date and time.
00240     strftime(buffer, buffer_size, "%b %d %H:%M", tm_p);
00241   }
00242 
00243   return buffer;
00244 }
00245 
00246 ////////////////////////////////////////////////////////////////////
00247 //     Function: BamCacheRecord::register_with_read_factory
00248 //       Access: Published, Static
00249 //  Description: Tells the BamReader how to create objects of type
00250 //               BamCacheRecord.
00251 ////////////////////////////////////////////////////////////////////
00252 void BamCacheRecord::
00253 register_with_read_factory() {
00254   BamReader::get_factory()->register_factory(get_class_type(), make_from_bam);
00255 }
00256 
00257 ////////////////////////////////////////////////////////////////////
00258 //     Function: BamCacheRecord::write_datagram
00259 //       Access: Published, Virtual
00260 //  Description: Writes the contents of this object to the datagram
00261 //               for shipping out to a Bam file.
00262 ////////////////////////////////////////////////////////////////////
00263 void BamCacheRecord::
00264 write_datagram(BamWriter *manager, Datagram &dg) {
00265   TypedWritableReferenceCount::write_datagram(manager, dg);
00266   dg.add_string(_source_pathname);
00267   dg.add_string(_cache_filename);
00268   dg.add_uint32(_recorded_time);
00269   dg.add_uint64(_record_size);
00270 
00271   dg.add_uint16(_files.size());
00272   DependentFiles::const_iterator fi;
00273   for (fi = _files.begin(); fi != _files.end(); ++fi) {
00274     const DependentFile &file = (*fi);
00275     dg.add_string(file._pathname);
00276     dg.add_uint32(file._timestamp);
00277     dg.add_uint64(file._size);
00278   }
00279 }
00280 
00281 ////////////////////////////////////////////////////////////////////
00282 //     Function: BamCacheRecord::make_from_bam
00283 //       Access: Protected, Static
00284 //  Description: This function is called by the BamReader's factory
00285 //               when a new object of type BamCacheRecord is encountered
00286 //               in the Bam file.  It should create the BamCacheRecord
00287 //               and extract its information from the file.
00288 ////////////////////////////////////////////////////////////////////
00289 TypedWritable *BamCacheRecord::
00290 make_from_bam(const FactoryParams &params) {
00291   BamCacheRecord *object = new BamCacheRecord;
00292   DatagramIterator scan;
00293   BamReader *manager;
00294 
00295   parse_params(params, scan, manager);
00296   object->fillin(scan, manager);
00297 
00298   return object;
00299 }
00300 
00301 ////////////////////////////////////////////////////////////////////
00302 //     Function: BamCacheRecord::fillin
00303 //       Access: Protected
00304 //  Description: This internal function is called by make_from_bam to
00305 //               read in all of the relevant data from the BamFile for
00306 //               the new BamCacheRecord.
00307 ////////////////////////////////////////////////////////////////////
00308 void BamCacheRecord::
00309 fillin(DatagramIterator &scan, BamReader *manager) {
00310   TypedWritableReferenceCount::fillin(scan, manager);
00311 
00312   _source_pathname = scan.get_string();
00313   _cache_filename = scan.get_string();
00314   _recorded_time = scan.get_uint32();
00315   _record_size = scan.get_uint64();
00316 
00317   unsigned int num_files = scan.get_uint16();
00318   _files.reserve(num_files);
00319   for (unsigned int i = 0; i < num_files; ++i) {
00320     _files.push_back(DependentFile());
00321     DependentFile &file = _files.back();
00322     file._pathname = scan.get_string();
00323     file._timestamp = scan.get_uint32();
00324     file._size = scan.get_uint64();
00325   }
00326 }
 All Classes Functions Variables Enumerations