Panda3D
Loading...
Searching...
No Matches
bamCacheRecord.cxx
Go to the documentation of this file.
1/**
2 * PANDA 3D SOFTWARE
3 * Copyright (c) Carnegie Mellon University. All rights reserved.
4 *
5 * All use of this software is subject to the terms of the revised BSD
6 * license. You should have received a copy of this license along
7 * with this source code in a file named "LICENSE."
8 *
9 * @file bamCacheRecord.cxx
10 * @author drose
11 * @date 2006-06-09
12 */
13
14#include "bamCacheRecord.h"
15#include "bamReader.h"
16#include "bamWriter.h"
17#include "virtualFileSystem.h"
18#include "virtualFile.h"
19#include "indent.h"
20#include "config_putil.h" // util_cat
21
22TypeHandle BamCacheRecord::_type_handle;
23
24/**
25 * Used when reading from a bam file.
26 */
27BamCacheRecord::
28BamCacheRecord() :
29 _recorded_time(0),
30 _record_size(0),
31 _source_timestamp(0),
32 _ptr(nullptr),
33 _ref_ptr(nullptr),
34 _record_access_time(0)
35{
36}
37
38/**
39 * Use BamCache::lookup() to create one of these.
40 */
41BamCacheRecord::
42BamCacheRecord(const Filename &source_pathname,
43 const Filename &cache_filename) :
44 _source_pathname(source_pathname),
45 _cache_filename(cache_filename),
46 _recorded_time(0),
47 _record_size(0),
48 _source_timestamp(0),
49 _ptr(nullptr),
50 _ref_ptr(nullptr),
51 _record_access_time(0)
52{
53}
54
55/**
56 * Use make_copy() to make a copy. The copy does not share the data pointer.
57 */
58BamCacheRecord::
59BamCacheRecord(const BamCacheRecord &copy) :
60 _source_pathname(copy._source_pathname),
61 _cache_filename(copy._cache_filename),
62 _recorded_time(copy._recorded_time),
63 _record_size(copy._record_size),
64 _source_timestamp(copy._source_timestamp),
65 _ptr(nullptr),
66 _ref_ptr(nullptr),
67 _record_access_time(copy._record_access_time)
68{
69}
70
71/**
72 *
73 */
74BamCacheRecord::
75~BamCacheRecord() {
76 clear_data();
77}
78
79/**
80 * Returns true if all of the dependent files are still the same as when the
81 * cache was recorded, false otherwise.
82 */
86
87 if (util_cat.is_debug()) {
88 util_cat.debug()
89 << "Validating dependents for " << get_source_pathname() << "\n";
90 }
91
92 DependentFiles::const_iterator fi;
93 for (fi = _files.begin(); fi != _files.end(); ++fi) {
94 const DependentFile &dfile = (*fi);
95 PT(VirtualFile) file = vfs->get_file(dfile._pathname);
96 if (file == nullptr) {
97 // No such file.
98 if (dfile._timestamp != 0) {
99 if (util_cat.is_debug()) {
100 util_cat.debug()
101 << dfile._pathname << " does not exist.\n";
102 }
103 return false;
104 }
105 } else {
106 if (file->get_timestamp() != dfile._timestamp ||
107 file->get_file_size() != dfile._size) {
108 // File has changed timestamp or size.
109 if (util_cat.is_debug()) {
110 util_cat.debug()
111 << dfile._pathname << " has changed timestamp or size.\n";
112 }
113 return false;
114 }
115 }
116
117 // Presumably, the file is unchanged.
118 if (util_cat.is_debug()) {
119 util_cat.debug()
120 << dfile._pathname << " is unchanged.\n";
121 }
122 }
123
124 if (util_cat.is_debug()) {
125 util_cat.debug()
126 << "Dependents valid.\n";
127 }
128
129 return true;
130}
131
132
133/**
134 * Empties the list of files that contribute to the data in this record.
135 */
138 _files.clear();
139}
140
141/**
142 * Adds the indicated file to the list of files that will be loaded to
143 * generate the data in this record. This should be called once for the
144 * primary source file, and again for each secondary source file, if any.
145 */
147add_dependent_file(const Filename &pathname) {
149
150 _files.push_back(DependentFile());
151 DependentFile &dfile = _files.back();
152 dfile._pathname = pathname;
153 dfile._pathname.make_absolute();
154
155 PT(VirtualFile) file = vfs->get_file(dfile._pathname);
156 if (file == nullptr) {
157 // No such file.
158 dfile._timestamp = 0;
159 dfile._size = 0;
160
161 } else {
162 dfile._timestamp = file->get_timestamp();
163 dfile._size = file->get_file_size();
164
165 if (dfile._pathname == _source_pathname) {
166 _source_timestamp = dfile._timestamp;
167 }
168 }
169}
170
171/**
172 * Variant of add_dependent_file that takes an already opened VirtualFile.
173 */
175add_dependent_file(const VirtualFile *file) {
176 _files.push_back(DependentFile());
177 DependentFile &dfile = _files.back();
178 dfile._pathname = file->get_filename();
179 dfile._pathname.make_absolute();
180
181 dfile._timestamp = file->get_timestamp();
182 dfile._size = file->get_file_size();
183
184 if (dfile._pathname == _source_pathname) {
185 _source_timestamp = dfile._timestamp;
186 }
187}
188
189/**
190 *
191 */
192void BamCacheRecord::
193output(std::ostream &out) const {
194 out << "BamCacheRecord " << get_source_pathname();
195}
196
197/**
198 *
199 */
200void BamCacheRecord::
201write(std::ostream &out, int indent_level) const {
202 indent(out, indent_level)
203 << "BamCacheRecord " << get_source_pathname() << "\n";
204 indent(out, indent_level)
205 << "source " << format_timestamp(_source_timestamp) << "\n";
206 indent(out, indent_level)
207 << "recorded " << format_timestamp(_recorded_time) << "\n";
208
209 indent(out, indent_level)
210 << _files.size() << " dependent files.\n";
211 DependentFiles::const_iterator fi;
212 for (fi = _files.begin(); fi != _files.end(); ++fi) {
213 const DependentFile &dfile = (*fi);
214 indent(out, indent_level + 2)
215 << std::setw(10) << dfile._size << " "
216 << format_timestamp(dfile._timestamp) << " "
217 << dfile._pathname << "\n";
218 }
219}
220
221/**
222 * Returns a timestamp value formatted nicely for output.
223 */
224std::string BamCacheRecord::
225format_timestamp(time_t timestamp) {
226 static const size_t buffer_size = 512;
227 char buffer[buffer_size];
228
229 if (timestamp == 0) {
230 // A zero timestamp is a special case.
231 return " (no date) ";
232 }
233
234 time_t now = time(nullptr);
235 struct tm atm;
236#ifdef _WIN32
237 localtime_s(&atm, &timestamp);
238#else
239 localtime_r(&timestamp, &atm);
240#endif
241
242 if (timestamp > now || (now - timestamp > 86400 * 365)) {
243 // A timestamp in the future, or more than a year in the past, gets a year
244 // appended.
245 strftime(buffer, buffer_size, "%b %d %Y", &atm);
246 } else {
247 // Otherwise, within the past year, show the date and time.
248 strftime(buffer, buffer_size, "%b %d %H:%M", &atm);
249 }
250
251 return buffer;
252}
253
254/**
255 * Tells the BamReader how to create objects of type BamCacheRecord.
256 */
259 BamReader::get_factory()->register_factory(get_class_type(), make_from_bam);
260}
261
262/**
263 * Writes the contents of this object to the datagram for shipping out to a
264 * Bam file.
265 */
267write_datagram(BamWriter *manager, Datagram &dg) {
269 dg.add_string(_source_pathname);
270 dg.add_string(_cache_filename);
271 dg.add_uint32(_recorded_time);
272 dg.add_uint64(_record_size);
273
274 dg.add_uint16(_files.size());
275 DependentFiles::const_iterator fi;
276 for (fi = _files.begin(); fi != _files.end(); ++fi) {
277 const DependentFile &file = (*fi);
278 dg.add_string(file._pathname);
279 dg.add_uint32(file._timestamp);
280 dg.add_uint64(file._size);
281 }
282}
283
284/**
285 * This function is called by the BamReader's factory when a new object of
286 * type BamCacheRecord is encountered in the Bam file. It should create the
287 * BamCacheRecord and extract its information from the file.
288 */
289TypedWritable *BamCacheRecord::
290make_from_bam(const FactoryParams &params) {
291 BamCacheRecord *object = new BamCacheRecord;
292 DatagramIterator scan;
293 BamReader *manager;
294
295 parse_params(params, scan, manager);
296 object->fillin(scan, manager);
297
298 return object;
299}
300
301/**
302 * This internal function is called by make_from_bam to read in all of the
303 * relevant data from the BamFile for the new BamCacheRecord.
304 */
305void BamCacheRecord::
306fillin(DatagramIterator &scan, BamReader *manager) {
308
309 _source_pathname = scan.get_string();
310 _cache_filename = scan.get_string();
311 _recorded_time = scan.get_uint32();
312 _record_size = scan.get_uint64();
313
314 unsigned int num_files = scan.get_uint16();
315 _files.reserve(num_files);
316 for (unsigned int i = 0; i < num_files; ++i) {
317 _files.push_back(DependentFile());
318 DependentFile &file = _files.back();
319 file._pathname = scan.get_string();
320 file._timestamp = scan.get_uint32();
321 file._size = scan.get_uint64();
322
323 // If we come across the original source file (we normally expect to),
324 // record that as its timestamp.
325 if (file._pathname == _source_pathname) {
326 _source_timestamp = file._timestamp;
327 }
328 }
329}
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
void parse_params(const FactoryParams &params, DatagramIterator &scan, BamReader *&manager)
Takes in a FactoryParams, passed from a WritableFactory into any TypedWritable's make function,...
Definition bamReader.I:275
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
An instance of this class is written to the front of a Bam or Txo file to make the file a cached inst...
void add_dependent_file(const Filename &pathname)
Adds the indicated file to the list of files that will be loaded to generate the data in this record.
virtual void write_datagram(BamWriter *manager, Datagram &dg)
Writes the contents of this object to the datagram for shipping out to a Bam file.
static void register_with_read_factory()
Tells the BamReader how to create objects of type BamCacheRecord.
void clear_dependent_files()
Empties the list of files that contribute to the data in this record.
bool dependents_unchanged() const
Returns true if all of the dependent files are still the same as when the cache was recorded,...
This is the fundamental interface for extracting binary objects from a Bam file, as generated by a Ba...
Definition bamReader.h:110
static WritableFactory * get_factory()
Returns the global WritableFactory for generating TypedWritable objects.
Definition bamReader.I:177
This is the fundamental interface for writing binary objects to a Bam file, to be extracted later by ...
Definition bamWriter.h:63
A class to retrieve the individual data elements previously stored in a Datagram.
uint64_t get_uint64()
Extracts an unsigned 64-bit integer.
uint16_t get_uint16()
Extracts an unsigned 16-bit integer.
uint32_t get_uint32()
Extracts an unsigned 32-bit integer.
std::string get_string()
Extracts a variable-length string.
An ordered list of data elements, formatted in memory for transmission over a socket or writing to a ...
Definition datagram.h:38
void add_uint32(uint32_t value)
Adds an unsigned 32-bit integer to the datagram.
Definition datagram.I:94
void add_uint64(uint64_t value)
Adds an unsigned 64-bit integer to the datagram.
Definition datagram.I:103
void add_uint16(uint16_t value)
Adds an unsigned 16-bit integer to the datagram.
Definition datagram.I:85
void add_string(const std::string &str)
Adds a variable-length string to the datagram.
Definition datagram.I:219
An instance of this class is passed to the Factory when requesting it to do its business and construc...
void register_factory(TypeHandle handle, CreateFunc *func, void *user_data=nullptr)
Registers a new kind of thing the Factory will be able to create.
Definition factory.I:73
The name of a file, such as a texture file or an Egg file.
Definition filename.h:44
void make_absolute()
Converts the filename to a fully-qualified pathname from the root (if it is a relative pathname),...
Definition filename.cxx:968
TypeHandle is the identifier used to differentiate C++ class types.
Definition typeHandle.h:81
Base class for objects that can be written to and read from Bam files.
virtual void fillin(DatagramIterator &scan, BamReader *manager)
This internal function is intended to be called by each class's make_from_bam() method to read in all...
virtual void write_datagram(BamWriter *manager, Datagram &dg)
Writes the contents of this object to the datagram for shipping out to a Bam file.
A hierarchy of directories and files that appears to be one continuous file system,...
PointerTo< VirtualFile > get_file(const Filename &filename, bool status_only=false) const
Looks up the file by the indicated name in the file system.
static VirtualFileSystem * get_global_ptr()
Returns the default global VirtualFileSystem.
The abstract base class for a file or directory within the VirtualFileSystem.
Definition virtualFile.h:35
virtual std::streamsize get_file_size(std::istream *stream) const
Returns the current size on disk (or wherever it is) of the already-open file.
virtual time_t get_timestamp() const
Returns a time_t value that represents the time the file was last modified, to within whatever precis...
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
std::ostream & indent(std::ostream &out, int indent_level)
A handy function for doing text formatting.
Definition indent.cxx:20
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.