Panda3D
|
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 ©) : 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 DependentFiles::const_iterator fi; 00095 for (fi = _files.begin(); fi != _files.end(); ++fi) { 00096 const DependentFile &dfile = (*fi); 00097 PT(VirtualFile) file = vfs->get_file(dfile._pathname); 00098 if (file == (VirtualFile *)NULL) { 00099 // No such file. 00100 if (dfile._timestamp != 0) { 00101 return false; 00102 } 00103 } else { 00104 if (file->get_timestamp() != dfile._timestamp || 00105 file->get_file_size() != dfile._size) { 00106 // File has changed timestamp or size. 00107 return false; 00108 } 00109 } 00110 00111 // Presumably, the file is unchanged. 00112 } 00113 00114 return true; 00115 } 00116 00117 00118 //////////////////////////////////////////////////////////////////// 00119 // Function: BamCacheRecord::clear_dependent_files 00120 // Access: Published 00121 // Description: Empties the list of files that contribute to the data 00122 // in this record. 00123 //////////////////////////////////////////////////////////////////// 00124 void BamCacheRecord:: 00125 clear_dependent_files() { 00126 _files.clear(); 00127 } 00128 00129 //////////////////////////////////////////////////////////////////// 00130 // Function: BamCacheRecord::add_dependent_file 00131 // Access: Published 00132 // Description: Adds the indicated file to the list of files that 00133 // will be loaded to generate the data in this record. 00134 // This should be called once for the primary source 00135 // file, and again for each secondary source file, if 00136 // any. 00137 //////////////////////////////////////////////////////////////////// 00138 void BamCacheRecord:: 00139 add_dependent_file(const Filename &pathname) { 00140 VirtualFileSystem *vfs = VirtualFileSystem::get_global_ptr(); 00141 00142 _files.push_back(DependentFile()); 00143 DependentFile &dfile = _files.back(); 00144 dfile._pathname = pathname; 00145 00146 PT(VirtualFile) file = vfs->get_file(pathname); 00147 if (file == (VirtualFile *)NULL) { 00148 // No such file. 00149 dfile._timestamp = 0; 00150 dfile._size = 0; 00151 00152 } else { 00153 dfile._timestamp = file->get_timestamp(); 00154 dfile._size = file->get_file_size(); 00155 } 00156 } 00157 00158 //////////////////////////////////////////////////////////////////// 00159 // Function: BamCacheRecord::output 00160 // Access: Published 00161 // Description: 00162 //////////////////////////////////////////////////////////////////// 00163 void BamCacheRecord:: 00164 output(ostream &out) const { 00165 out << "BamCacheRecord " << get_source_pathname(); 00166 } 00167 00168 //////////////////////////////////////////////////////////////////// 00169 // Function: BamCacheRecord::write 00170 // Access: Published 00171 // Description: 00172 //////////////////////////////////////////////////////////////////// 00173 void BamCacheRecord:: 00174 write(ostream &out, int indent_level) const { 00175 indent(out, indent_level) 00176 << "BamCacheRecord " << get_source_pathname() << "\n"; 00177 indent(out, indent_level) 00178 << "recorded " << format_timestamp(_recorded_time) << "\n"; 00179 00180 indent(out, indent_level) 00181 << _files.size() << " dependent files.\n"; 00182 DependentFiles::const_iterator fi; 00183 for (fi = _files.begin(); fi != _files.end(); ++fi) { 00184 const DependentFile &dfile = (*fi); 00185 indent(out, indent_level + 2) 00186 << setw(10) << dfile._size << " " 00187 << format_timestamp(dfile._timestamp) << " " 00188 << dfile._pathname << "\n"; 00189 } 00190 } 00191 00192 //////////////////////////////////////////////////////////////////// 00193 // Function: BamCacheRecord::format_timestamp 00194 // Access: Private, Static 00195 // Description: Returns a timestamp value formatted nicely for 00196 // output. 00197 //////////////////////////////////////////////////////////////////// 00198 string BamCacheRecord:: 00199 format_timestamp(time_t timestamp) { 00200 static const size_t buffer_size = 512; 00201 char buffer[buffer_size]; 00202 00203 if (timestamp == 0) { 00204 // A zero timestamp is a special case. 00205 return " (no date) "; 00206 } 00207 00208 time_t now = time(NULL); 00209 struct tm *tm_p = localtime(×tamp); 00210 00211 if (timestamp > now || (now - timestamp > 86400 * 365)) { 00212 // A timestamp in the future, or more than a year in the past, 00213 // gets a year appended. 00214 strftime(buffer, buffer_size, "%b %d %Y", tm_p); 00215 } else { 00216 // Otherwise, within the past year, show the date and time. 00217 strftime(buffer, buffer_size, "%b %d %H:%M", tm_p); 00218 } 00219 00220 return buffer; 00221 } 00222 00223 //////////////////////////////////////////////////////////////////// 00224 // Function: BamCacheRecord::register_with_read_factory 00225 // Access: Published, Static 00226 // Description: Tells the BamReader how to create objects of type 00227 // BamCacheRecord. 00228 //////////////////////////////////////////////////////////////////// 00229 void BamCacheRecord:: 00230 register_with_read_factory() { 00231 BamReader::get_factory()->register_factory(get_class_type(), make_from_bam); 00232 } 00233 00234 //////////////////////////////////////////////////////////////////// 00235 // Function: BamCacheRecord::write_datagram 00236 // Access: Published, Virtual 00237 // Description: Writes the contents of this object to the datagram 00238 // for shipping out to a Bam file. 00239 //////////////////////////////////////////////////////////////////// 00240 void BamCacheRecord:: 00241 write_datagram(BamWriter *manager, Datagram &dg) { 00242 TypedWritableReferenceCount::write_datagram(manager, dg); 00243 dg.add_string(_source_pathname); 00244 dg.add_string(_cache_filename); 00245 dg.add_uint32(_recorded_time); 00246 dg.add_uint64(_record_size); 00247 00248 dg.add_uint16(_files.size()); 00249 DependentFiles::const_iterator fi; 00250 for (fi = _files.begin(); fi != _files.end(); ++fi) { 00251 const DependentFile &file = (*fi); 00252 dg.add_string(file._pathname); 00253 dg.add_uint32(file._timestamp); 00254 dg.add_uint64(file._size); 00255 } 00256 } 00257 00258 //////////////////////////////////////////////////////////////////// 00259 // Function: BamCacheRecord::make_from_bam 00260 // Access: Protected, Static 00261 // Description: This function is called by the BamReader's factory 00262 // when a new object of type BamCacheRecord is encountered 00263 // in the Bam file. It should create the BamCacheRecord 00264 // and extract its information from the file. 00265 //////////////////////////////////////////////////////////////////// 00266 TypedWritable *BamCacheRecord:: 00267 make_from_bam(const FactoryParams ¶ms) { 00268 BamCacheRecord *object = new BamCacheRecord; 00269 DatagramIterator scan; 00270 BamReader *manager; 00271 00272 parse_params(params, scan, manager); 00273 object->fillin(scan, manager); 00274 00275 return object; 00276 } 00277 00278 //////////////////////////////////////////////////////////////////// 00279 // Function: BamCacheRecord::fillin 00280 // Access: Protected 00281 // Description: This internal function is called by make_from_bam to 00282 // read in all of the relevant data from the BamFile for 00283 // the new BamCacheRecord. 00284 //////////////////////////////////////////////////////////////////// 00285 void BamCacheRecord:: 00286 fillin(DatagramIterator &scan, BamReader *manager) { 00287 TypedWritableReferenceCount::fillin(scan, manager); 00288 00289 _source_pathname = scan.get_string(); 00290 _cache_filename = scan.get_string(); 00291 _recorded_time = scan.get_uint32(); 00292 _record_size = scan.get_uint64(); 00293 00294 unsigned int num_files = scan.get_uint16(); 00295 _files.reserve(num_files); 00296 for (unsigned int i = 0; i < num_files; ++i) { 00297 _files.push_back(DependentFile()); 00298 DependentFile &file = _files.back(); 00299 file._pathname = scan.get_string(); 00300 file._timestamp = scan.get_uint32(); 00301 file._size = scan.get_uint64(); 00302 } 00303 }