00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015 #include "bamCacheIndex.h"
00016 #include "indent.h"
00017 #include <algorithm>
00018
00019 TypeHandle BamCacheIndex::_type_handle;
00020
00021
00022
00023
00024
00025
00026
00027 BamCacheIndex::
00028 ~BamCacheIndex() {
00029 #ifndef NDEBUG
00030
00031
00032 release_records();
00033 #endif
00034 }
00035
00036
00037
00038
00039
00040
00041 void BamCacheIndex::
00042 write(ostream &out, int indent_level) const {
00043 indent(out, indent_level)
00044 << "BamCacheIndex, " << _records.size() << " records:\n";
00045
00046 Records::const_iterator ri;
00047 for (ri = _records.begin(); ri != _records.end(); ++ri) {
00048 BamCacheRecord *record = (*ri).second;
00049 indent(out, indent_level + 2)
00050 << setw(10) << record->_record_size << " "
00051 << record->get_cache_filename() << " "
00052 << record->get_source_pathname() << "\n";
00053 }
00054 out << "\n";
00055 indent(out, indent_level)
00056 << setw(12) << _cache_size << " bytes total\n";
00057 }
00058
00059
00060
00061
00062
00063
00064
00065
00066 void BamCacheIndex::
00067 process_new_records() {
00068 nassertv(_cache_size == 0);
00069
00070
00071
00072 RecordVector rv;
00073 rv.reserve(_records.size());
00074
00075 Records::const_iterator ri;
00076 for (ri = _records.begin(); ri != _records.end(); ++ri) {
00077 BamCacheRecord *record = (*ri).second;
00078 _cache_size += record->_record_size;
00079 rv.push_back(record);
00080 }
00081
00082 sort(rv.begin(), rv.end(), BamCacheRecord::SortByAccessTime());
00083
00084
00085 RecordVector::const_iterator rvi;
00086 for (rvi = rv.begin(); rvi != rv.end(); ++rvi) {
00087 BamCacheRecord *record = *rvi;
00088 record->insert_before(this);
00089 }
00090 }
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101 void BamCacheIndex::
00102 release_records() {
00103 Records::const_iterator ri;
00104 for (ri = _records.begin(); ri != _records.end(); ++ri) {
00105 BamCacheRecord *record = (*ri).second;
00106 record->_next = NULL;
00107 record->_prev = NULL;
00108 }
00109 _next = this;
00110 _prev = this;
00111 _cache_size = 0;
00112 }
00113
00114
00115
00116
00117
00118
00119
00120 PT(BamCacheRecord) BamCacheIndex::
00121 evict_old_file() {
00122 if (_next == this) {
00123
00124 return NULL;
00125 }
00126
00127
00128
00129 PT(BamCacheRecord) record = (BamCacheRecord *)_next;
00130 bool removed = remove_record(record->get_source_pathname());
00131 nassertr(removed, NULL);
00132
00133 return record;
00134 }
00135
00136
00137
00138
00139
00140
00141
00142
00143
00144
00145 bool BamCacheIndex::
00146 add_record(BamCacheRecord *record) {
00147 pair<Records::iterator, bool> result =
00148 _records.insert(Records::value_type(record->get_source_pathname(), record));
00149 if (!result.second) {
00150
00151 BamCacheRecord *orig_record = (*result.first).second;
00152 orig_record->remove_from_list();
00153 if (*orig_record == *record) {
00154
00155 orig_record->insert_before(this);
00156 return false;
00157 }
00158
00159 _cache_size -= orig_record->_record_size;
00160 (*result.first).second = record;
00161 }
00162 record->insert_before(this);
00163
00164 _cache_size += record->_record_size;
00165 return true;
00166 }
00167
00168
00169
00170
00171
00172
00173
00174
00175
00176 bool BamCacheIndex::
00177 remove_record(const Filename &source_pathname) {
00178 Records::iterator ri = _records.find(source_pathname);
00179 if (ri == _records.end()) {
00180
00181 return false;
00182 }
00183
00184 BamCacheRecord *record = (*ri).second;
00185 record->remove_from_list();
00186 _cache_size -= record->_record_size;
00187 _records.erase(ri);
00188 return true;
00189 }
00190
00191
00192
00193
00194
00195
00196
00197 void BamCacheIndex::
00198 register_with_read_factory() {
00199 BamReader::get_factory()->register_factory(get_class_type(), make_from_bam);
00200 }
00201
00202
00203
00204
00205
00206
00207
00208 void BamCacheIndex::
00209 write_datagram(BamWriter *manager, Datagram &dg) {
00210 TypedWritable::write_datagram(manager, dg);
00211
00212 dg.add_uint32(_records.size());
00213 Records::const_iterator ri;
00214 for (ri = _records.begin(); ri != _records.end(); ++ri) {
00215 manager->write_pointer(dg, (*ri).second);
00216 }
00217 }
00218
00219
00220
00221
00222
00223
00224
00225
00226
00227 TypedWritable *BamCacheIndex::
00228 make_from_bam(const FactoryParams ¶ms) {
00229 BamCacheIndex *object = new BamCacheIndex;
00230 DatagramIterator scan;
00231 BamReader *manager;
00232
00233 parse_params(params, scan, manager);
00234 object->fillin(scan, manager);
00235
00236 return object;
00237 }
00238
00239
00240
00241
00242
00243
00244
00245
00246 int BamCacheIndex::
00247 complete_pointers(TypedWritable **p_list, BamReader *manager) {
00248 int pi = TypedWritable::complete_pointers(p_list, manager);
00249
00250 RecordVector::iterator vi;
00251 for (vi = _record_vector.begin(); vi != _record_vector.end(); ++vi) {
00252 PT(BamCacheRecord) record = DCAST(BamCacheRecord, p_list[pi++]);
00253 (*vi) = record;
00254
00255 bool inserted = _records.insert(Records::value_type(record->get_source_pathname(), record)).second;
00256 if (!inserted) {
00257 util_cat.info()
00258 << "Multiple cache files defining " << record->get_source_pathname()
00259 << " in index.\n";
00260 }
00261 }
00262
00263 _record_vector.clear();
00264
00265 process_new_records();
00266
00267 return pi;
00268 }
00269
00270
00271
00272
00273
00274
00275
00276
00277 void BamCacheIndex::
00278 fillin(DatagramIterator &scan, BamReader *manager) {
00279 TypedWritable::fillin(scan, manager);
00280
00281 int num_records = scan.get_uint32();
00282 _record_vector.reserve(num_records);
00283 for (int i = 0; i < num_records; ++i) {
00284 _record_vector.push_back(NULL);
00285 manager->read_pointer(scan);
00286 }
00287 }