00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015 #include "pandabase.h"
00016 #include "pnotify.h"
00017
00018 #include "bam.h"
00019 #include "bamReader.h"
00020 #include "datagramIterator.h"
00021 #include "config_util.h"
00022 #include "pipelineCyclerBase.h"
00023
00024 TypeHandle BamReaderAuxData::_type_handle;
00025
00026 WritableFactory *BamReader::_factory = (WritableFactory*)0L;
00027 BamReader *const BamReader::Null = (BamReader*)0L;
00028 WritableFactory *const BamReader::NullFactory = (WritableFactory*)0L;
00029
00030 BamReader::NewTypes BamReader::_new_types;
00031
00032 const int BamReader::_cur_major = _bam_major_ver;
00033 const int BamReader::_cur_minor = _bam_minor_ver;
00034
00035
00036
00037
00038
00039
00040
00041 BamReader::
00042 BamReader(DatagramGenerator *source)
00043 : _source(source)
00044 {
00045 _needs_init = true;
00046 _num_extra_objects = 0;
00047 _nesting_level = 0;
00048 _now_creating = _created_objs.end();
00049 _reading_cycler = (PipelineCyclerBase *)NULL;
00050 _pta_id = -1;
00051 _long_object_id = false;
00052 _long_pta_id = false;
00053 }
00054
00055
00056
00057
00058
00059
00060
00061 BamReader::
00062 ~BamReader() {
00063 nassertv(_num_extra_objects == 0);
00064 nassertv(_nesting_level == 0);
00065 }
00066
00067
00068
00069
00070
00071
00072
00073
00074 void BamReader::
00075 set_source(DatagramGenerator *source) {
00076 _source = source;
00077 if (_needs_init && _source != NULL) {
00078 bool success = init();
00079 nassertv(success);
00080 }
00081 }
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093 bool BamReader::
00094 init() {
00095 nassertr(_source != NULL, false);
00096 nassertr(_needs_init, false);
00097 _needs_init = false;
00098 Datagram header;
00099
00100 if (_source->is_error()) {
00101 return false;
00102 }
00103
00104 if (!get_datagram(header)) {
00105 bam_cat.error()
00106 << "Unable to read Bam header.\n";
00107 return false;
00108 }
00109
00110 DatagramIterator scan(header);
00111
00112 _file_major = scan.get_uint16();
00113 _file_minor = scan.get_uint16();
00114
00115
00116
00117 if (_file_major != _bam_major_ver ||
00118 _file_minor < _bam_first_minor_ver ||
00119 _file_minor > _bam_minor_ver) {
00120 bam_cat.error()
00121 << "Bam file is version " << _file_major << "." << _file_minor
00122 << ".\n";
00123
00124 if (_bam_minor_ver == _bam_first_minor_ver) {
00125 bam_cat.error()
00126 << "This program can only load version "
00127 << _bam_major_ver << "." << _bam_first_minor_ver << " bams.\n";
00128 } else {
00129 bam_cat.error()
00130 << "This program can only load version "
00131 << _bam_major_ver << "." << _bam_first_minor_ver << " through "
00132 << _bam_major_ver << "." << _bam_minor_ver << " bams.\n";
00133 }
00134
00135 return false;
00136 }
00137
00138 _file_endian = (BamEndian)scan.get_uint8();
00139
00140 _file_stdfloat_double = false;
00141 if (_file_minor >= 27) {
00142 _file_stdfloat_double = scan.get_bool();
00143 }
00144
00145 return true;
00146 }
00147
00148
00149
00150
00151
00152
00153
00154
00155
00156
00157
00158
00159
00160
00161
00162
00163
00164
00165
00166
00167
00168
00169
00170
00171
00172
00173
00174
00175 void BamReader::
00176 set_aux_data(TypedWritable *obj, const string &name, BamReader::AuxData *data) {
00177 if (data == (void *)NULL) {
00178 AuxDataTable::iterator ti = _aux_data.find(obj);
00179 if (ti != _aux_data.end()) {
00180 AuxDataNames &names = (*ti).second;
00181 names.erase(name);
00182 if (names.empty()) {
00183 _aux_data.erase(ti);
00184 }
00185 }
00186
00187 } else {
00188 _aux_data[obj][name] = data;
00189 }
00190 }
00191
00192
00193
00194
00195
00196
00197
00198
00199 BamReader::AuxData *BamReader::
00200 get_aux_data(TypedWritable *obj, const string &name) const {
00201 AuxDataTable::const_iterator ti = _aux_data.find(obj);
00202 if (ti != _aux_data.end()) {
00203 const AuxDataNames &names = (*ti).second;
00204 AuxDataNames::const_iterator ni = names.find(name);
00205 if (ni != names.end()) {
00206 return (*ni).second;
00207 }
00208 }
00209
00210 return NULL;
00211 }
00212
00213
00214
00215
00216
00217
00218
00219
00220
00221
00222
00223
00224
00225
00226
00227
00228
00229
00230
00231
00232
00233
00234
00235
00236
00237
00238
00239
00240
00241
00242 TypedWritable *BamReader::
00243 read_object() {
00244 TypedWritable *ptr;
00245 ReferenceCount *ref_ptr;
00246
00247 if (!read_object(ptr, ref_ptr)) {
00248 return NULL;
00249 }
00250
00251 return ptr;
00252 }
00253
00254
00255
00256
00257
00258
00259
00260
00261
00262
00263
00264
00265
00266 bool BamReader::
00267 read_object(TypedWritable *&ptr, ReferenceCount *&ref_ptr) {
00268 ptr = NULL;
00269 ref_ptr = NULL;
00270 nassertr(_num_extra_objects == 0, false);
00271
00272 int start_level = _nesting_level;
00273
00274
00275 int object_id = p_read_object();
00276
00277
00278
00279
00280
00281
00282
00283
00284 while (_num_extra_objects > 0) {
00285 p_read_object();
00286 _num_extra_objects--;
00287 }
00288
00289
00290
00291 while (_nesting_level > start_level) {
00292 p_read_object();
00293 }
00294
00295
00296
00297 if (object_id == 0) {
00298 if (bam_cat.is_spam()) {
00299 bam_cat.spam()
00300 << "Returning false\n";
00301 }
00302 return false;
00303 }
00304
00305 CreatedObjs::iterator oi = _created_objs.find(object_id);
00306
00307 if (oi == _created_objs.end()) {
00308 bam_cat.error()
00309 << "Undefined object encountered!\n";
00310 return false;
00311
00312 } else {
00313 CreatedObj &created_obj = (*oi).second;
00314 ptr = created_obj._ptr;
00315 ref_ptr = created_obj._ref_ptr;
00316
00317 if (bam_cat.is_spam()) {
00318 if (ptr != (TypedWritable *)NULL) {
00319 bam_cat.spam()
00320 << "Returning object of type " << ptr->get_type() << "\n";
00321 }
00322 }
00323 if (created_obj._change_this != NULL ||
00324 created_obj._change_this_ref != NULL) {
00325 bam_cat.warning()
00326 << "Returning pointer to " << ptr->get_type()
00327 << " that might change.\n";
00328 }
00329
00330 return true;
00331 }
00332 }
00333
00334
00335
00336
00337
00338
00339
00340
00341
00342
00343
00344
00345
00346
00347
00348
00349
00350
00351
00352 bool BamReader::
00353 resolve() {
00354 bool all_completed;
00355 bool any_completed_this_pass;
00356
00357 do {
00358 if (bam_cat.is_spam()) {
00359 bam_cat.spam()
00360 << "resolve pass begin\n";
00361 }
00362 all_completed = true;
00363 any_completed_this_pass = false;
00364
00365 ObjectPointers::iterator oi;
00366 oi = _object_pointers.begin();
00367 while (oi != _object_pointers.end()) {
00368 int object_id = (*oi).first;
00369 PointerReference &pref = (*oi).second;
00370
00371 CreatedObjs::iterator ci = _created_objs.find(object_id);
00372 nassertr(ci != _created_objs.end(), false);
00373
00374 CreatedObj &created_obj = (*ci).second;
00375
00376 TypedWritable *object_ptr = created_obj._ptr;
00377
00378
00379
00380 CreatedObjs::iterator was_creating = _now_creating;
00381 _now_creating = ci;
00382
00383 if (resolve_object_pointers(object_ptr, pref)) {
00384
00385
00386
00387 ObjectPointers::iterator old = oi;
00388 ++oi;
00389 _object_pointers.erase(old);
00390 any_completed_this_pass = true;
00391
00392
00393 if (created_obj._change_this_ref != NULL) {
00394
00395 TypedWritableReferenceCount *object_ref_ptr = (TypedWritableReferenceCount *)object_ptr;
00396 nassertr(created_obj._ref_ptr == NULL || created_obj._ref_ptr == object_ref_ptr, false);
00397 PT(TypedWritableReferenceCount) new_ptr = created_obj._change_this_ref(object_ref_ptr, this);
00398 if (new_ptr != object_ref_ptr) {
00399
00400 vector_int &old_refs = _created_objs_by_pointer[object_ptr];
00401 vector_int &new_refs = _created_objs_by_pointer[new_ptr];
00402 for (vector_int::const_iterator oi = old_refs.begin();
00403 oi != old_refs.end();
00404 ++oi) {
00405 new_refs.push_back(*oi);
00406 }
00407 _created_objs_by_pointer.erase(object_ptr);
00408
00409
00410
00411 _finalize_list.erase(object_ptr);
00412 }
00413 created_obj.set_ptr(new_ptr, new_ptr);
00414 created_obj._change_this = NULL;
00415 created_obj._change_this_ref = NULL;
00416
00417 } else if (created_obj._change_this != NULL) {
00418
00419 TypedWritable *new_ptr = created_obj._change_this(object_ptr, this);
00420 if (new_ptr != object_ptr) {
00421
00422 vector_int &old_refs = _created_objs_by_pointer[object_ptr];
00423 vector_int &new_refs = _created_objs_by_pointer[new_ptr];
00424 for (vector_int::const_iterator oi = old_refs.begin();
00425 oi != old_refs.end();
00426 ++oi) {
00427 new_refs.push_back(*oi);
00428 }
00429 _created_objs_by_pointer.erase(object_ptr);
00430
00431
00432
00433 _finalize_list.erase(object_ptr);
00434 }
00435 created_obj.set_ptr(new_ptr, new_ptr->as_reference_count());
00436 created_obj._change_this = NULL;
00437 created_obj._change_this_ref = NULL;
00438 }
00439
00440 } else {
00441
00442 ++oi;
00443 all_completed = false;
00444 }
00445
00446 _now_creating = was_creating;
00447 }
00448
00449 if (bam_cat.is_spam()) {
00450 bam_cat.spam()
00451 << "resolve pass end: all_completed = " << all_completed
00452 << " any_completed_this_pass = " << any_completed_this_pass
00453 << "\n";
00454 }
00455 } while (!all_completed && any_completed_this_pass);
00456
00457 if (all_completed) {
00458 finalize();
00459 } else {
00460
00461
00462
00463
00464
00465 ObjectPointers::const_iterator oi;
00466 for (oi = _object_pointers.begin();
00467 oi != _object_pointers.end();
00468 ++oi) {
00469 int object_id = (*oi).first;
00470 CreatedObjs::iterator ci = _created_objs.find(object_id);
00471 nassertr(ci != _created_objs.end(), false);
00472 CreatedObj &created_obj = (*ci).second;
00473 TypedWritable *object_ptr = created_obj._ptr;
00474
00475 bam_cat.warning()
00476 << "Unable to complete " << object_ptr->get_type() << "\n";
00477 }
00478 }
00479
00480 return all_completed;
00481 }
00482
00483
00484
00485
00486
00487
00488
00489
00490
00491
00492
00493
00494
00495
00496 bool BamReader::
00497 change_pointer(const TypedWritable *orig_pointer, const TypedWritable *new_pointer) {
00498 if (orig_pointer == new_pointer) {
00499 return false;
00500 }
00501 CreatedObjsByPointer::iterator ci = _created_objs_by_pointer.find(orig_pointer);
00502 if (ci == _created_objs_by_pointer.end()) {
00503
00504 return false;
00505 }
00506
00507 if (bam_cat.is_spam()) {
00508 bam_cat.spam()
00509 << "change_pointer(" << (void *)orig_pointer << ", "
00510 << (void *)new_pointer << ") (" << new_pointer->get_type() << ")\n";
00511 }
00512
00513 const vector_int &old_refs = (*ci).second;
00514 vector_int &new_refs = _created_objs_by_pointer[new_pointer];
00515
00516 for (vector_int::const_iterator oi = old_refs.begin();
00517 oi != old_refs.end();
00518 ++oi) {
00519 int object_id = (*oi);
00520
00521 CreatedObjs::iterator ci = _created_objs.find(object_id);
00522 nassertr(ci != _created_objs.end(), false);
00523 nassertr((*ci).second._ptr == orig_pointer, false);
00524
00525 TypedWritable *ptr = (TypedWritable *)new_pointer;
00526 (*ci).second.set_ptr(ptr, ptr->as_reference_count());
00527 new_refs.push_back(object_id);
00528 }
00529
00530 _created_objs_by_pointer.erase(ci);
00531
00532
00533 Finalize::iterator fi = _finalize_list.find((TypedWritable *)orig_pointer);
00534 if (fi != _finalize_list.end()) {
00535 _finalize_list.insert((TypedWritable *)new_pointer);
00536 _finalize_list.erase(fi);
00537 }
00538
00539 return true;
00540 }
00541
00542
00543
00544
00545
00546
00547
00548 TypeHandle BamReader::
00549 read_handle(DatagramIterator &scan) {
00550
00551
00552
00553
00554
00555
00556
00557
00558
00559
00560
00561
00562 int id = scan.get_uint16();
00563
00564 if (id == 0) {
00565
00566 return TypeHandle::none();
00567 }
00568
00569 IndexMap::const_iterator mi = _index_map.find(id);
00570 if (mi != _index_map.end()) {
00571
00572
00573
00574 TypeHandle type = (*mi).second;
00575 return type;
00576 }
00577
00578
00579
00580
00581
00582
00583 string name = scan.get_string();
00584 bool new_type = false;
00585
00586 TypeHandle type = TypeRegistry::ptr()->find_type(name);
00587 if (type == TypeHandle::none()) {
00588
00589
00590
00591
00592 type = TypeRegistry::ptr()->register_dynamic_type(name);
00593 bam_cat.warning()
00594 << "Bam file '" << get_filename() << "' contains objects of unknown type: "
00595 << type << "\n";
00596 new_type = true;
00597 _new_types.insert(type);
00598 }
00599
00600
00601 int num_parent_classes = scan.get_uint8();
00602 for (int i = 0; i < num_parent_classes; i++) {
00603 TypeHandle parent_type = read_handle(scan);
00604 if (new_type) {
00605 TypeRegistry::ptr()->record_derivation(type, parent_type);
00606 } else {
00607 if (type.get_parent_towards(parent_type) != parent_type) {
00608 if (bam_cat.is_debug()) {
00609 bam_cat.debug()
00610 << "Bam file indicates a derivation of " << type
00611 << " from " << parent_type << " which is no longer true.\n";
00612 }
00613 }
00614 }
00615 }
00616
00617 bool inserted = _index_map.insert(IndexMap::value_type(id, type)).second;
00618 nassertr(inserted, type);
00619
00620 if (bam_cat.is_spam()) {
00621 bam_cat.spam()
00622 << "Read TypeHandle for " << type << ".\n";
00623 }
00624
00625 return type;
00626 }
00627
00628
00629
00630
00631
00632
00633
00634
00635
00636
00637
00638
00639
00640
00641
00642
00643
00644
00645
00646
00647
00648
00649
00650
00651 void BamReader::
00652 read_pointer(DatagramIterator &scan) {
00653 Thread::consider_yield();
00654
00655 nassertv(_now_creating != _created_objs.end());
00656 int requestor_id = (*_now_creating).first;
00657
00658
00659 int object_id = read_object_id(scan);
00660
00661 PointerReference &pref = _object_pointers[requestor_id];
00662 if (_reading_cycler == (PipelineCyclerBase *)NULL) {
00663
00664 pref._objects.push_back(object_id);
00665 } else {
00666
00667 pref._cycler_pointers[_reading_cycler].push_back(object_id);
00668 }
00669
00670
00671
00672 if (object_id != 0) {
00673
00674
00675
00676
00677
00678 if (get_file_minor_ver() < 21) {
00679
00680
00681 _num_extra_objects++;
00682 }
00683 }
00684 }
00685
00686
00687
00688
00689
00690
00691
00692
00693 void BamReader::
00694 read_pointers(DatagramIterator &scan, int count) {
00695 for (int i = 0; i < count; i++) {
00696 read_pointer(scan);
00697 }
00698 }
00699
00700
00701
00702
00703
00704
00705
00706
00707
00708 void BamReader::
00709 skip_pointer(DatagramIterator &scan) {
00710 read_object_id(scan);
00711 }
00712
00713
00714
00715
00716
00717
00718
00719
00720
00721
00722
00723
00724 void BamReader::
00725 read_file_data(SubfileInfo &info) {
00726
00727
00728
00729
00730
00731
00732 nassertv(!_file_data_records.empty());
00733 info = _file_data_records.front();
00734 _file_data_records.pop_front();
00735 }
00736
00737
00738
00739
00740
00741
00742
00743
00744
00745
00746 void BamReader::
00747 read_cdata(DatagramIterator &scan, PipelineCyclerBase &cycler) {
00748 PipelineCyclerBase *old_cycler = _reading_cycler;
00749 _reading_cycler = &cycler;
00750 CycleData *cdata = cycler.write(Thread::get_current_thread());
00751 cdata->fillin(scan, this);
00752 cycler.release_write(cdata);
00753 _reading_cycler = old_cycler;
00754 }
00755
00756
00757
00758
00759
00760
00761
00762 void BamReader::
00763 read_cdata(DatagramIterator &scan, PipelineCyclerBase &cycler,
00764 void *extra_data) {
00765 PipelineCyclerBase *old_cycler = _reading_cycler;
00766 _reading_cycler = &cycler;
00767 CycleData *cdata = cycler.write(Thread::get_current_thread());
00768 cdata->fillin(scan, this, extra_data);
00769 cycler.release_write(cdata);
00770 _reading_cycler = old_cycler;
00771 }
00772
00773
00774
00775
00776
00777
00778
00779
00780
00781
00782
00783
00784
00785
00786
00787
00788 void BamReader::
00789 set_int_tag(const string &tag, int value) {
00790 nassertv(_now_creating != _created_objs.end());
00791 int requestor_id = (*_now_creating).first;
00792
00793 PointerReference &pref = _object_pointers[requestor_id];
00794 pref._int_tags[tag] = value;
00795 }
00796
00797
00798
00799
00800
00801
00802
00803 int BamReader::
00804 get_int_tag(const string &tag) const {
00805 nassertr(_now_creating != _created_objs.end(), 0);
00806 int requestor_id = (*_now_creating).first;
00807
00808 ObjectPointers::const_iterator opi = _object_pointers.find(requestor_id);
00809 nassertr(opi != _object_pointers.end(), 0);
00810 const PointerReference &pref = (*opi).second;
00811
00812 IntTags::const_iterator iti = pref._int_tags.find(tag);
00813 nassertr(iti != pref._int_tags.end(), 0);
00814 return (*iti).second;
00815 }
00816
00817
00818
00819
00820
00821
00822
00823
00824
00825
00826
00827
00828
00829
00830
00831
00832
00833
00834
00835
00836
00837 void BamReader::
00838 set_aux_tag(const string &tag, BamReaderAuxData *value) {
00839 nassertv(_now_creating != _created_objs.end());
00840 int requestor_id = (*_now_creating).first;
00841
00842 PointerReference &pref = _object_pointers[requestor_id];
00843 pref._aux_tags[tag] = value;
00844 }
00845
00846
00847
00848
00849
00850
00851
00852 BamReaderAuxData *BamReader::
00853 get_aux_tag(const string &tag) const {
00854 nassertr(_now_creating != _created_objs.end(), NULL);
00855 int requestor_id = (*_now_creating).first;
00856
00857 ObjectPointers::const_iterator opi = _object_pointers.find(requestor_id);
00858 nassertr(opi != _object_pointers.end(), NULL);
00859 const PointerReference &pref = (*opi).second;
00860
00861 AuxTags::const_iterator ati = pref._aux_tags.find(tag);
00862 nassertr(ati != pref._aux_tags.end(), NULL);
00863 return (*ati).second;
00864 }
00865
00866
00867
00868
00869
00870
00871
00872
00873
00874
00875
00876
00877
00878
00879 void BamReader::
00880 register_finalize(TypedWritable *whom) {
00881 nassertv(whom != (TypedWritable *)NULL);
00882
00883 if (bam_cat.is_spam()) {
00884 bam_cat.spam()
00885 << "register_finalize(" << (void *)whom << ") (" << whom->get_type()
00886 << ")\n";
00887 }
00888
00889 _finalize_list.insert(whom);
00890 }
00891
00892
00893
00894
00895
00896
00897
00898
00899
00900
00901
00902
00903
00904
00905
00906
00907
00908
00909
00910 void BamReader::
00911 register_change_this(ChangeThisFunc func, TypedWritable *object) {
00912 nassertv(_now_creating != _created_objs.end());
00913 CreatedObj &created_obj = (*_now_creating).second;
00914
00915 #ifndef NDEBUG
00916
00917
00918 if (created_obj._ptr == (TypedWritable *)NULL) {
00919 created_obj.set_ptr(object, object->as_reference_count());
00920 } else {
00921
00922
00923 nassertv(created_obj._ptr == object);
00924 }
00925 #endif // NDEBUG
00926
00927 created_obj._change_this = func;
00928 created_obj._change_this_ref = NULL;
00929 }
00930
00931
00932
00933
00934
00935
00936
00937
00938
00939
00940
00941
00942
00943
00944
00945
00946
00947
00948
00949 void BamReader::
00950 register_change_this(ChangeThisRefFunc func, TypedWritableReferenceCount *object) {
00951 nassertv(_now_creating != _created_objs.end());
00952 CreatedObj &created_obj = (*_now_creating).second;
00953
00954 #ifndef NDEBUG
00955
00956
00957 if (created_obj._ptr == (TypedWritable *)NULL) {
00958 created_obj.set_ptr(object, object);
00959 } else {
00960
00961
00962 nassertv(created_obj._ptr == object);
00963 nassertv(created_obj._ref_ptr == object);
00964 }
00965 #endif // NDEBUG
00966
00967 created_obj._change_this = NULL;
00968 created_obj._change_this_ref = func;
00969 }
00970
00971
00972
00973
00974
00975
00976
00977
00978
00979 void BamReader::
00980 finalize_now(TypedWritable *whom) {
00981 if (whom == (TypedWritable *)NULL) {
00982 return;
00983 }
00984
00985 Finalize::iterator fi = _finalize_list.find(whom);
00986 if (fi != _finalize_list.end()) {
00987 _finalize_list.erase(fi);
00988 if (bam_cat.is_spam()) {
00989 bam_cat.spam()
00990 << "finalizing " << (void *)whom << " (" << whom->get_type()
00991 << ")\n";
00992 }
00993 whom->finalize(this);
00994 }
00995 }
00996
00997
00998
00999
01000
01001
01002
01003
01004
01005
01006
01007
01008
01009
01010
01011
01012
01013
01014
01015
01016
01017
01018 void *BamReader::
01019 get_pta(DatagramIterator &scan) {
01020 nassertr(_pta_id == -1, (void *)NULL);
01021 int id = read_pta_id(scan);
01022
01023 if (id == 0) {
01024
01025
01026
01027
01028
01029 return (void *)NULL;
01030 }
01031
01032 PTAMap::iterator pi = _pta_map.find(id);
01033 if (pi == _pta_map.end()) {
01034
01035
01036 _pta_id = id;
01037 return (void *)NULL;
01038 }
01039
01040 return (*pi).second;
01041 }
01042
01043
01044
01045
01046
01047
01048
01049
01050
01051
01052
01053
01054
01055
01056 void BamReader::
01057 register_pta(void *ptr) {
01058 if (_pta_id != -1) {
01059 bool inserted = _pta_map.insert(PTAMap::value_type(_pta_id, ptr)).second;
01060 _pta_id = -1;
01061 nassertv(inserted);
01062 }
01063 }
01064
01065
01066
01067
01068
01069
01070
01071
01072
01073 void BamReader::
01074 free_object_ids(DatagramIterator &scan) {
01075
01076
01077 resolve();
01078
01079 while (scan.get_remaining_size() > 0) {
01080 int object_id = read_object_id(scan);
01081
01082 CreatedObjs::iterator ci = _created_objs.find(object_id);
01083 if (ci == _created_objs.end()) {
01084 util_cat.warning()
01085 << "Bam file suggests eliminating object_id " << object_id
01086 << ", already gone.\n";
01087 } else {
01088
01089
01090 ObjectPointers::iterator oi = _object_pointers.find(object_id);
01091 if (oi != _object_pointers.end()) {
01092 util_cat.warning()
01093 << "Unable to resolve object " << object_id
01094 << " before removing from table.\n";
01095 }
01096
01097 _created_objs_by_pointer.erase((*ci).second._ptr);
01098 _created_objs.erase(ci);
01099 }
01100 }
01101 }
01102
01103
01104
01105
01106
01107
01108
01109 int BamReader::
01110 read_object_id(DatagramIterator &scan) {
01111 int object_id;
01112
01113 if (_long_object_id) {
01114 object_id = scan.get_uint32();
01115
01116 } else {
01117 object_id = scan.get_uint16();
01118 if (object_id == 0xffff) {
01119 _long_object_id = true;
01120 }
01121 }
01122
01123 return object_id;
01124 }
01125
01126
01127
01128
01129
01130
01131 int BamReader::
01132 read_pta_id(DatagramIterator &scan) {
01133 int pta_id;
01134
01135 if (_long_pta_id) {
01136 pta_id = scan.get_uint32();
01137
01138 } else {
01139 pta_id = scan.get_uint16();
01140 if (pta_id == 0xffff) {
01141 _long_pta_id = true;
01142 }
01143 }
01144
01145 return pta_id;
01146 }
01147
01148
01149
01150
01151
01152
01153
01154
01155 int BamReader::
01156 p_read_object() {
01157 Datagram dg;
01158
01159
01160 if (!get_datagram(dg)) {
01161
01162 if (bam_cat.is_debug()) {
01163 bam_cat.debug()
01164 << "Reached end of bam source.\n";
01165 }
01166 return 0;
01167 }
01168
01169
01170 DatagramIterator scan(dg);
01171
01172
01173
01174 BamObjectCode boc = BOC_adjunct;
01175 if (get_file_minor_ver() >= 21) {
01176 boc = (BamObjectCode)scan.get_uint8();
01177 }
01178 switch (boc) {
01179 case BOC_push:
01180 ++_nesting_level;
01181 break;
01182
01183 case BOC_pop:
01184 --_nesting_level;
01185 return 0;
01186
01187 case BOC_adjunct:
01188 break;
01189
01190 case BOC_remove:
01191
01192
01193
01194 free_object_ids(scan);
01195
01196
01197
01198
01199 return p_read_object();
01200
01201 case BOC_file_data:
01202
01203
01204
01205
01206 {
01207 SubfileInfo info;
01208 if (!_source->save_datagram(info)) {
01209 bam_cat.error()
01210 << "Failed to read file data.\n";
01211 return 0;
01212 }
01213 _file_data_records.push_back(info);
01214 }
01215
01216 return p_read_object();
01217 }
01218
01219
01220
01221
01222
01223
01224 TypeHandle type = read_handle(scan);
01225
01226 int object_id = read_object_id(scan);
01227
01228
01229
01230
01231
01232
01233
01234
01235
01236
01237
01238
01239
01240
01241
01242
01243 if (type != TypeHandle::none()) {
01244
01245
01246
01247
01248
01249
01250 CreatedObj new_created_obj;
01251 CreatedObjs::iterator oi =
01252 _created_objs.insert(CreatedObjs::value_type(object_id, new_created_obj)).first;
01253 CreatedObj &created_obj = (*oi).second;
01254
01255 if (created_obj._ptr != NULL) {
01256
01257
01258
01259
01260
01261
01262
01263
01264 CreatedObjs::iterator was_creating = _now_creating;
01265 _now_creating = oi;
01266 created_obj._ptr->fillin(scan, this);
01267 _now_creating = was_creating;
01268
01269 } else {
01270
01271
01272
01273
01274 FactoryParams fparams;
01275 fparams.add_param(new BamReaderParam(scan, this));
01276
01277
01278
01279 CreatedObjs::iterator was_creating = _now_creating;
01280 _now_creating = oi;
01281 TypedWritable *object =
01282 _factory->make_instance_more_general(type, fparams);
01283 _now_creating = was_creating;
01284
01285
01286 nassertr(created_obj._ptr == object || created_obj._ptr == NULL, object_id);
01287 if (object == NULL) {
01288 created_obj.set_ptr(NULL, NULL);
01289 } else {
01290 created_obj.set_ptr(object, object->as_reference_count());
01291 }
01292 created_obj._created = true;
01293
01294 if (created_obj._change_this_ref != NULL) {
01295
01296
01297
01298
01299
01300 ObjectPointers::const_iterator ri = _object_pointers.find(object_id);
01301 if (ri == _object_pointers.end()) {
01302 PT(TypedWritableReferenceCount) object_ref = (*created_obj._change_this_ref)((TypedWritableReferenceCount *)object, this);
01303 TypedWritable *new_ptr = object_ref;
01304 created_obj.set_ptr(object_ref, object_ref);
01305 created_obj._change_this = NULL;
01306 created_obj._change_this_ref = NULL;
01307
01308
01309
01310 if (new_ptr != object) {
01311 _finalize_list.erase(object);
01312 }
01313 object = new_ptr;
01314 }
01315
01316 } else if (created_obj._change_this != NULL) {
01317
01318 ObjectPointers::const_iterator ri = _object_pointers.find(object_id);
01319 if (ri == _object_pointers.end()) {
01320 TypedWritable *new_ptr = (*created_obj._change_this)(object, this);
01321 created_obj.set_ptr(new_ptr, new_ptr->as_reference_count());
01322 created_obj._change_this = NULL;
01323 created_obj._change_this_ref = NULL;
01324
01325 if (new_ptr != object) {
01326 _finalize_list.erase(object);
01327 }
01328 object = new_ptr;
01329 }
01330 }
01331
01332 _created_objs_by_pointer[created_obj._ptr].push_back(object_id);
01333
01334
01335 if (object == (TypedWritable *)NULL) {
01336 if (bam_cat.is_debug()) {
01337 bam_cat.debug()
01338 << "Unable to create an object of type " << type << endl;
01339 }
01340
01341 } else if (object->get_type() != type) {
01342 if (_new_types.find(type) != _new_types.end()) {
01343
01344
01345
01346 if (bam_cat.is_debug()) {
01347 bam_cat.warning()
01348 << "Attempted to create a " << type.get_name() \
01349 << " but a " << object->get_type() \
01350 << " was created instead." << endl;
01351 }
01352
01353 } else {
01354
01355
01356 bam_cat.warning()
01357 << "Attempted to create a " << type.get_name() \
01358 << " but a " << object->get_type() \
01359 << " was created instead." << endl;
01360 }
01361
01362 } else {
01363 if (bam_cat.is_spam()) {
01364 bam_cat.spam()
01365 << "Read a " << object->get_type() << ": " << (void *)object << "\n";
01366 }
01367 }
01368 }
01369 }
01370
01371 return object_id;
01372 }
01373
01374
01375
01376
01377
01378
01379
01380
01381
01382 bool BamReader::
01383 resolve_object_pointers(TypedWritable *object,
01384 BamReader::PointerReference &pref) {
01385
01386
01387
01388 bool require_fully_complete = object->require_fully_complete();
01389
01390
01391 CyclerPointers::iterator ci;
01392 ci = pref._cycler_pointers.begin();
01393 while (ci != pref._cycler_pointers.end()) {
01394 PipelineCyclerBase *cycler = (*ci).first;
01395 const vector_int &pointer_ids = (*ci).second;
01396
01397 if (resolve_cycler_pointers(cycler, pointer_ids, require_fully_complete)) {
01398
01399
01400
01401 CyclerPointers::iterator old = ci;
01402 ++ci;
01403 pref._cycler_pointers.erase(old);
01404
01405 } else {
01406
01407 ++ci;
01408 }
01409 }
01410
01411 if (!pref._cycler_pointers.empty()) {
01412
01413 if (bam_cat.is_spam()) {
01414 bam_cat.spam()
01415 << "some cyclers pending: complete_pointers for " << (void *)object
01416 << " (" << object->get_type() << ")\n";
01417 }
01418 return false;
01419 }
01420
01421
01422
01423
01424
01425
01426 bool is_complete = true;
01427
01428 vector_typedWritable references;
01429 references.reserve(pref._objects.size());
01430
01431 vector_int::const_iterator pi;
01432 for (pi = pref._objects.begin();
01433 pi != pref._objects.end() && is_complete;
01434 ++pi) {
01435 int child_id = (*pi);
01436 if (child_id == 0) {
01437
01438 references.push_back((TypedWritable *)NULL);
01439
01440 } else {
01441
01442 CreatedObjs::const_iterator oi = _created_objs.find(child_id);
01443 if (oi == _created_objs.end()) {
01444
01445 is_complete = false;
01446
01447 } else {
01448 const CreatedObj &child_obj = (*oi).second;
01449 if (!child_obj._created) {
01450
01451 is_complete = false;
01452 } else if (child_obj._change_this != NULL || child_obj._change_this_ref != NULL) {
01453
01454 is_complete = false;
01455 } else {
01456 if (require_fully_complete &&
01457 _object_pointers.find(child_id) != _object_pointers.end()) {
01458
01459 is_complete = false;
01460
01461 } else {
01462
01463 references.push_back(child_obj._ptr);
01464 }
01465 }
01466 }
01467 }
01468 }
01469
01470 if (is_complete) {
01471
01472 nassertr(references.size() == pref._objects.size(), false);
01473
01474 if (bam_cat.is_spam()) {
01475 bam_cat.spam()
01476 << "complete_pointers for " << (void *)object
01477 << " (" << object->get_type() << "), " << references.size()
01478 << " pointers.\n";
01479 }
01480 int num_completed = 0;
01481 if (!references.empty()) {
01482 num_completed = object->complete_pointers(&references[0], this);
01483 }
01484 if (num_completed != (int)references.size()) {
01485 bam_cat.warning()
01486 << object->get_type() << " completed " << num_completed
01487 << " of " << references.size() << " pointers.\n";
01488 nassertr(num_completed < (int)references.size(), true);
01489 }
01490 return true;
01491
01492 } else {
01493 if (bam_cat.is_spam()) {
01494 bam_cat.spam()
01495 << "not ready: complete_pointers for " << (void *)object
01496 << " (" << object->get_type() << ")\n";
01497 }
01498 }
01499
01500 return false;
01501 }
01502
01503
01504
01505
01506
01507
01508
01509
01510
01511 bool BamReader::
01512 resolve_cycler_pointers(PipelineCyclerBase *cycler,
01513 const vector_int &pointer_ids,
01514 bool require_fully_complete) {
01515
01516
01517
01518
01519
01520
01521 bool is_complete = true;
01522 vector_typedWritable references;
01523
01524 vector_int::const_iterator pi;
01525 for (pi = pointer_ids.begin(); pi != pointer_ids.end() && is_complete; ++pi) {
01526 int child_id = (*pi);
01527
01528 if (child_id == 0) {
01529
01530 references.push_back((TypedWritable *)NULL);
01531
01532 } else {
01533
01534 CreatedObjs::const_iterator oi = _created_objs.find(child_id);
01535 if (oi == _created_objs.end()) {
01536
01537 is_complete = false;
01538
01539 } else {
01540 const CreatedObj &child_obj = (*oi).second;
01541 if (child_obj._change_this != NULL || child_obj._change_this_ref != NULL) {
01542
01543 is_complete = false;
01544
01545 } else {
01546 if (require_fully_complete &&
01547 _object_pointers.find(child_id) != _object_pointers.end()) {
01548
01549 is_complete = false;
01550
01551 } else {
01552
01553 references.push_back(child_obj._ptr);
01554 }
01555 }
01556 }
01557 }
01558 }
01559
01560 if (is_complete) {
01561
01562 CycleData *cdata = cycler->write(Thread::get_current_thread());
01563 if (bam_cat.is_spam()) {
01564 bam_cat.spam()
01565 << "complete_pointers for CycleData object " << (void *)cdata
01566 << "\n";
01567 }
01568 int num_completed = cdata->complete_pointers(&references[0], this);
01569 cycler->release_write(cdata);
01570 if (num_completed != (int)references.size()) {
01571 bam_cat.warning()
01572 << "CycleData object completed " << num_completed
01573 << " of " << references.size() << " pointers.\n";
01574 nassertr(num_completed < (int)references.size(), true);
01575 }
01576 return true;
01577 }
01578
01579 return false;
01580 }
01581
01582
01583
01584
01585
01586
01587
01588
01589 void BamReader::
01590 finalize() {
01591 if (bam_cat.is_debug()) {
01592 bam_cat.debug()
01593 << "Finalizing bam source\n";
01594 }
01595
01596 Finalize::iterator fi = _finalize_list.begin();
01597 while (fi != _finalize_list.end()) {
01598 TypedWritable *object = (*fi);
01599 nassertv(object != (TypedWritable *)NULL);
01600 _finalize_list.erase(fi);
01601 if (bam_cat.is_spam()) {
01602 bam_cat.spam()
01603 << "finalizing " << (void *)object << " (" << object->get_type()
01604 << ")\n";
01605 }
01606 object->finalize(this);
01607 _aux_data.erase(object);
01608 fi = _finalize_list.begin();
01609 }
01610
01611
01612 if (!_aux_data.empty()) {
01613 AuxDataTable::iterator ti = _aux_data.find((TypedWritable *)NULL);
01614
01615 if (ti != _aux_data.end()) {
01616 if (_aux_data.size() > 1) {
01617
01618 AuxDataTable new_aux_data;
01619 AuxDataTable::iterator nti =
01620 new_aux_data.insert(AuxDataTable::value_type((TypedWritable *)NULL, AuxDataNames())).first;
01621 (*nti).second.swap((*ti).second);
01622 _aux_data.swap(new_aux_data);
01623 }
01624 } else {
01625
01626 _aux_data.clear();
01627 }
01628 }
01629 }
01630
01631
01632
01633
01634
01635
01636 BamReader::AuxData::
01637 ~AuxData() {
01638 }
01639