00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015 #include "config_downloader.h"
00016 #include "downloadDb.h"
00017 #include "streamReader.h"
00018 #include "streamWriter.h"
00019 #include "ramfile.h"
00020 #include "virtualFileSystem.h"
00021
00022 #include <algorithm>
00023
00024
00025
00026
00027
00028
00029 PN_uint32 DownloadDb::_magic_number = 0xfeedfeed;
00030
00031
00032
00033
00034
00035 PN_uint32 DownloadDb::_bogus_magic_number = 0x11111111;
00036
00037
00038 static string
00039 back_to_front_slash(const string &str) {
00040 string result = str;
00041 string::iterator si;
00042 for (si = result.begin(); si != result.end(); ++si) {
00043 if ((*si) == '\\') {
00044 (*si) = '/';
00045 }
00046 }
00047
00048 return result;
00049 }
00050
00051
00052
00053
00054
00055
00056
00057 DownloadDb::
00058 DownloadDb(Ramfile &server_file, Filename &client_file) {
00059 if (downloader_cat.is_debug())
00060 downloader_cat.debug()
00061 << "DownloadDb constructor called" << endl;
00062 _client_db = read_db(client_file, 0);
00063 _client_db._filename = client_file;
00064 _server_db = read_db(server_file, 1);
00065 }
00066
00067
00068
00069
00070
00071
00072 DownloadDb::
00073 DownloadDb(Filename &server_file, Filename &client_file) {
00074 if (downloader_cat.is_debug())
00075 downloader_cat.debug()
00076 << "DownloadDb constructor called" << endl;
00077 _client_db = read_db(client_file, 0);
00078 _client_db._filename = client_file;
00079 _server_db = read_db(server_file, 1);
00080 _server_db._filename = server_file;
00081 }
00082
00083
00084
00085
00086
00087
00088 DownloadDb::
00089 DownloadDb() {
00090 _client_db = Db();
00091 _server_db = Db();
00092 }
00093
00094
00095
00096
00097
00098
00099 DownloadDb::
00100 ~DownloadDb() {
00101 if (downloader_cat.is_debug())
00102 downloader_cat.debug()
00103 << "DownloadDb destructor called" << endl;
00104 }
00105
00106
00107
00108
00109
00110
00111
00112 void DownloadDb::
00113 output(ostream &out) const {
00114 out << "[" << _server_db._filename << " " << _client_db._filename << "]";
00115 }
00116
00117
00118
00119
00120
00121
00122 void DownloadDb::
00123 write(ostream &out) const {
00124 out << "DownloadDb" << endl;
00125 out << "============================================================" << endl;
00126 out << " Client DB file: " << _client_db._filename << endl;
00127 out << "============================================================" << endl;
00128 _client_db.write(out);
00129 out << endl;
00130 out << "============================================================" << endl;
00131 out << " Server DB file: " << _server_db._filename << endl;
00132 out << "============================================================" << endl;
00133 _server_db.write(out);
00134 write_version_map(out);
00135 out << endl;
00136 }
00137
00138
00139
00140
00141
00142
00143
00144 bool DownloadDb::
00145 write_client_db(Filename &file) {
00146 return write_db(file, _client_db, 0);
00147 }
00148
00149
00150
00151
00152
00153
00154
00155 bool DownloadDb::
00156 write_server_db(Filename &file) {
00157 return write_db(file, _server_db, 1);
00158 }
00159
00160
00161
00162
00163
00164
00165 bool DownloadDb::
00166 client_multifile_exists(string mfname) const {
00167 return (_client_db.multifile_exists(mfname));
00168 }
00169
00170
00171
00172
00173
00174
00175
00176
00177 bool DownloadDb::
00178 client_multifile_complete(string mfname) const {
00179 int client_status = _client_db.get_multifile_record_named(mfname)->_status;
00180 return (client_status >= Status_complete);
00181 }
00182
00183
00184
00185
00186
00187
00188 bool DownloadDb::
00189 client_multifile_decompressed(string mfname) const {
00190 int client_status = _client_db.get_multifile_record_named(mfname)->_status;
00191 return (client_status >= Status_decompressed);
00192 }
00193
00194
00195
00196
00197
00198
00199 bool DownloadDb::
00200 client_multifile_extracted(string mfname) const {
00201 int client_status = _client_db.get_multifile_record_named(mfname)->_status;
00202 return (client_status >= Status_extracted);
00203 }
00204
00205
00206
00207
00208
00209
00210
00211 HashVal DownloadDb::
00212 get_client_multifile_hash(string mfname) const {
00213 return _client_db.get_multifile_record_named(mfname)->_hash;
00214 }
00215
00216
00217
00218
00219
00220
00221
00222 HashVal DownloadDb::
00223 get_server_multifile_hash(string mfname) const {
00224 return _server_db.get_multifile_record_named(mfname)->_hash;
00225 }
00226
00227
00228
00229
00230
00231
00232
00233 void DownloadDb::
00234 set_client_multifile_hash(string mfname, HashVal val) {
00235 _client_db.get_multifile_record_named(mfname)->_hash = val;
00236 write_client_db(_client_db._filename);
00237 }
00238
00239
00240
00241
00242
00243
00244
00245 void DownloadDb::
00246 set_server_multifile_hash(string mfname, HashVal val) {
00247 _server_db.get_multifile_record_named(mfname)->_hash = val;
00248 }
00249
00250
00251
00252
00253
00254
00255
00256
00257 void DownloadDb::
00258 delete_client_multifile(string mfname) {
00259 }
00260
00261
00262
00263
00264
00265
00266 void DownloadDb::
00267 add_client_multifile(string server_mfname) {
00268 PT(MultifileRecord) server_mfr = _server_db.get_multifile_record_named(server_mfname);
00269 PT(MultifileRecord) client_mfr = new MultifileRecord;
00270 client_mfr->_name = server_mfr->_name;
00271 client_mfr->_phase = server_mfr->_phase;
00272 _client_db.add_multifile_record(client_mfr);
00273 }
00274
00275
00276
00277
00278
00279
00280
00281 void DownloadDb::
00282 expand_client_multifile(string mfname) {
00283 }
00284
00285
00286
00287
00288
00289
00290
00291 DownloadDb::Db DownloadDb::
00292 read_db(Filename &file, bool want_server_info) {
00293 VirtualFileSystem *vfs = VirtualFileSystem::get_global_ptr();
00294 Db db;
00295
00296
00297 file.set_binary();
00298 istream *read_stream = vfs->open_read_file(file, true);
00299
00300 if (read_stream == (istream *)NULL) {
00301 downloader_cat.error()
00302 << "failed to open input file: "
00303 << file << endl;
00304 return db;
00305 }
00306
00307 StreamReader sr(*read_stream);
00308 if (!db.read(sr, want_server_info)) {
00309 downloader_cat.error()
00310 << "read failed: "
00311 << file << endl;
00312 vfs->close_read_file(read_stream);
00313 return db;
00314 }
00315
00316 if (want_server_info) {
00317 if (!read_version_map(sr)) {
00318 downloader_cat.error()
00319 << "read_version_map() failed: "
00320 << file << endl;
00321 }
00322 }
00323
00324 vfs->close_read_file(read_stream);
00325
00326 return db;
00327 }
00328
00329
00330
00331
00332
00333
00334 DownloadDb::Db DownloadDb::
00335 read_db(Ramfile &file, bool want_server_info) {
00336
00337 istringstream read_stream(file._data);
00338 Db db;
00339
00340 StreamReader sr(read_stream);
00341
00342 if (!db.read(sr, want_server_info)) {
00343 downloader_cat.error()
00344 << "read failed" << endl;
00345 return db;
00346 }
00347 if (want_server_info) {
00348 if (!read_version_map(sr)) {
00349 downloader_cat.error()
00350 << "read_version_map() failed" << endl;
00351 }
00352 }
00353
00354 return db;
00355 }
00356
00357
00358
00359
00360
00361
00362
00363 bool DownloadDb::
00364 write_db(Filename &file, Db db, bool want_server_info) {
00365 pofstream write_stream;
00366 file.set_binary();
00367 if (!file.open_write(write_stream)) {
00368 downloader_cat.error()
00369 << "DownloadDb::write_db() - Failed to open output file: "
00370 << file << endl;
00371 return false;
00372 }
00373
00374 downloader_cat.spam()
00375 << "Writing to file: " << file << endl;
00376
00377 StreamWriter sw(write_stream);
00378
00379
00380 db.write_bogus_header(sw);
00381 db.write(sw, want_server_info);
00382 if (want_server_info) {
00383 write_version_map(sw);
00384 }
00385
00386 db.write_header(write_stream);
00387 write_stream.close();
00388 return true;
00389 }
00390
00391
00392
00393
00394
00395
00396
00397
00398 void DownloadDb::
00399 create_new_server_db() {
00400 _server_db = Db();
00401 }
00402
00403
00404
00405
00406
00407
00408
00409 void DownloadDb::
00410 server_add_multifile(string mfname, Phase phase, int size, int status) {
00411 PT(MultifileRecord) mfr = new MultifileRecord(mfname, phase, size, status);
00412 _server_db.add_multifile_record(mfr);
00413 }
00414
00415
00416
00417
00418
00419
00420
00421 void DownloadDb::
00422 server_add_file(string mfname, string fname) {
00423
00424 PT(FileRecord) fr = new FileRecord(fname);
00425
00426
00427 pvector< PT(MultifileRecord) >::iterator i = _server_db._mfile_records.begin();
00428 for (; i != _server_db._mfile_records.end(); ++i) {
00429 if (mfname == (*i)->_name) {
00430 (*i)->add_file_record(fr);
00431 return;
00432 }
00433 }
00434
00435
00436 downloader_cat.error() << "Could not find record named "
00437 << mfname << " in database " << endl;
00438 nassertv(false);
00439 return;
00440 }
00441
00442
00443
00444
00445
00446
00447
00448
00449
00450
00451
00452
00453 DownloadDb::MultifileRecord::
00454 MultifileRecord() {
00455 _name = "";
00456 _phase = 0;
00457 _size = 0;
00458 _status = Status_incomplete;
00459 }
00460
00461
00462
00463
00464
00465
00466
00467 DownloadDb::MultifileRecord::
00468 MultifileRecord(string name, Phase phase, int size, int status) {
00469 _name = name;
00470 _phase = phase;
00471 _size = size;
00472 _status = status;
00473 }
00474
00475
00476
00477
00478
00479
00480
00481 void DownloadDb::MultifileRecord::
00482 write(ostream &out) const {
00483 out << "==================================================" << endl;
00484 out << "MultifileRecord: " << _name << endl
00485 << " phase: " << _phase << endl
00486 << " size: " << _size << endl
00487 << " status: " << _status << endl
00488 << " hash: " << _hash.as_dec() << endl;
00489 out << "--------------------------------------------------" << endl;
00490 pvector< PT(FileRecord) >::const_iterator i = _file_records.begin();
00491 for(; i != _file_records.end(); ++i) {
00492 (*i)->write(out);
00493 }
00494 }
00495
00496
00497
00498
00499
00500
00501
00502
00503 int DownloadDb::MultifileRecord::
00504 get_num_files() const {
00505 return _file_records.size();
00506 }
00507
00508
00509
00510
00511
00512
00513 string DownloadDb::MultifileRecord::
00514 get_file_name(int index) const {
00515 return _file_records[index]->_name;
00516 }
00517
00518
00519
00520
00521
00522
00523
00524 bool DownloadDb::MultifileRecord::
00525 file_exists(string fname) const {
00526 pvector< PT(FileRecord) >::const_iterator i = _file_records.begin();
00527 for(; i != _file_records.end(); ++i) {
00528 if (fname == (*i)->_name) {
00529 return true;
00530 }
00531 }
00532 return false;
00533 }
00534
00535
00536
00537
00538
00539
00540
00541 PT(DownloadDb::FileRecord) DownloadDb::MultifileRecord::
00542 get_file_record_named(string fname) const {
00543 pvector< PT(FileRecord) >::const_iterator i = _file_records.begin();
00544 for(; i != _file_records.end(); ++i) {
00545 if (fname == (*i)->_name) {
00546 return (*i);
00547 }
00548 }
00549
00550 downloader_cat.error() << "Could not find record named "
00551 << fname << " in multifile " << _name << endl;
00552 PT(FileRecord) foo = new FileRecord;
00553 nassertr(false, foo);
00554 return foo;
00555 }
00556
00557
00558
00559
00560
00561
00562
00563 void DownloadDb::MultifileRecord::
00564 add_file_record(PT(FileRecord) fr) {
00565 _file_records.push_back(fr);
00566 }
00567
00568
00569
00570
00571
00572
00573
00574
00575
00576
00577
00578
00579
00580
00581
00582 DownloadDb::Db::
00583 Db() {
00584
00585 _header_length = sizeof(_magic_number) + sizeof(PN_int32);
00586 }
00587
00588
00589
00590
00591
00592
00593
00594 void DownloadDb::Db::
00595 write(ostream &out) const {
00596 pvector< PT(MultifileRecord) >::const_iterator i = _mfile_records.begin();
00597 for(; i != _mfile_records.end(); ++i) {
00598 (*i)->write(out);
00599 }
00600 }
00601
00602
00603
00604
00605
00606
00607
00608 int DownloadDb::Db::
00609 get_num_multifiles() const {
00610 return _mfile_records.size();
00611 }
00612
00613
00614
00615
00616
00617
00618 string DownloadDb::Db::
00619 get_multifile_name(int index) const {
00620 return _mfile_records[index]->_name;
00621 }
00622
00623
00624
00625
00626
00627
00628 bool DownloadDb::Db::
00629 multifile_exists(string mfname) const {
00630 pvector< PT(MultifileRecord) >::const_iterator i = _mfile_records.begin();
00631 for(; i != _mfile_records.end(); ++i) {
00632 if (mfname == (*i)->_name) {
00633 return true;
00634 }
00635 }
00636 return false;
00637 }
00638
00639
00640
00641
00642
00643
00644 PT(DownloadDb::MultifileRecord) DownloadDb::Db::
00645 get_multifile_record_named(string mfname) const {
00646 pvector< PT(MultifileRecord) >::const_iterator i = _mfile_records.begin();
00647 for(; i != _mfile_records.end(); ++i) {
00648 if (mfname == (*i)->_name) {
00649 return (*i);
00650 }
00651 }
00652
00653 downloader_cat.error() << "Could not find record named "
00654 << mfname << " in database " << endl;
00655 PT(MultifileRecord) foo = new MultifileRecord;
00656 nassertr(false, foo);
00657 return foo;
00658 }
00659
00660
00661
00662
00663
00664
00665 void DownloadDb::Db::
00666 add_multifile_record(PT(MultifileRecord) mfr) {
00667 _mfile_records.push_back(mfr);
00668 }
00669
00670
00671
00672
00673
00674
00675
00676
00677 int DownloadDb::Db::
00678 parse_header(const string &data) {
00679 Datagram dg(data);
00680
00681
00682 DatagramIterator di(dg);
00683 PN_uint32 magic_number = di.get_uint32();
00684 downloader_cat.debug()
00685 << "Parsed magic number: " << magic_number << endl;
00686
00687
00688 if (magic_number == _bogus_magic_number) {
00689 downloader_cat.error()
00690 << "DownloadDb::parse_header() - "
00691 << "Bogus magic number, previous write incomplete: "
00692 << magic_number << " expected: " << _magic_number << endl;
00693 return -1;
00694 }
00695
00696
00697 else if (magic_number != _magic_number) {
00698 downloader_cat.error()
00699 << "DownloadDb::parse_header() - Invalid magic number: "
00700 << magic_number << " expected: " << _magic_number << endl;
00701 return -1;
00702 }
00703
00704 PN_int32 num_multifiles = di.get_int32();
00705 downloader_cat.debug()
00706 << "Parsed number of multifiles: " << num_multifiles << endl;
00707
00708
00709 return num_multifiles;
00710 }
00711
00712
00713
00714
00715
00716
00717
00718
00719
00720 int DownloadDb::Db::
00721 parse_record_header(const string &data) {
00722 Datagram dg(data);
00723 DatagramIterator di(dg);
00724 PN_int32 record_length = di.get_int32();
00725 downloader_cat.spam()
00726 << "Parsed record header length: " << record_length << endl;
00727
00728
00729 return record_length;
00730 }
00731
00732
00733
00734
00735
00736
00737
00738 PT(DownloadDb::MultifileRecord) DownloadDb::Db::
00739 parse_mfr(const string &data) {
00740
00741 PT(DownloadDb::MultifileRecord) mfr = new DownloadDb::MultifileRecord;
00742
00743 Datagram dg(data);
00744 DatagramIterator di(dg);
00745 PN_int32 mfr_name_length = di.get_int32();
00746 mfr->_name = di.extract_bytes(mfr_name_length);
00747 mfr->_phase = di.get_float64();
00748 mfr->_size = di.get_int32();
00749 mfr->_status = di.get_int32();
00750 mfr->_num_files = di.get_int32();
00751
00752
00753
00754
00755 mfr->_name = back_to_front_slash(mfr->_name);
00756
00757
00758 mfr->_hash.read_datagram(di);
00759
00760 downloader_cat.debug()
00761 << "Parsed multifile record: " << mfr->_name << " phase: " << mfr->_phase
00762 << " size: " << mfr->_size
00763 << " status: " << mfr->_status << " num_files: " << mfr->_num_files << endl;
00764
00765
00766 return mfr;
00767 }
00768
00769
00770
00771
00772
00773
00774
00775
00776
00777 PT(DownloadDb::FileRecord) DownloadDb::Db::
00778 parse_fr(const string &data) {
00779
00780 PT(DownloadDb::FileRecord) fr = new DownloadDb::FileRecord;
00781
00782 Datagram dg(data);
00783 DatagramIterator di(dg);
00784 PN_int32 fr_name_length = di.get_int32();
00785 fr->_name = di.extract_bytes(fr_name_length);
00786
00787
00788
00789
00790 fr->_name = back_to_front_slash(fr->_name);
00791
00792 downloader_cat.spam()
00793 << "Parsed file record: " << fr->_name << endl;
00794
00795
00796 return fr;
00797 }
00798
00799
00800
00801
00802
00803
00804
00805
00806
00807 bool DownloadDb::Db::
00808 read(StreamReader &sr, bool want_server_info) {
00809
00810 string header;
00811 header = sr.extract_bytes(_header_length);
00812 if (header.size() != (size_t)_header_length) {
00813 downloader_cat.error() << "truncated db file" << endl;
00814 return false;
00815 }
00816
00817
00818 int num_multifiles = parse_header(header);
00819 if (num_multifiles < 0) {
00820 downloader_cat.error() << "invalid db header" << endl;
00821 return false;
00822 }
00823
00824
00825
00826 for (int i = 0; i < num_multifiles; i++) {
00827
00828
00829 int mfr_header_length = sizeof(PN_int32);
00830
00831 string mfr_header = sr.extract_bytes(mfr_header_length);
00832 if (mfr_header.size() != (size_t)mfr_header_length) {
00833 downloader_cat.error() << "invalid mfr header" << endl;
00834 return false;
00835 }
00836
00837
00838 int mfr_length = parse_record_header(mfr_header);
00839
00840
00841
00842
00843 int read_length = (mfr_length - mfr_header_length);
00844 string mfr_record = sr.extract_bytes(read_length);
00845 if (mfr_record.size() != (size_t)read_length) {
00846 downloader_cat.error() << "invalid mfr record" << endl;
00847 return false;
00848 }
00849
00850
00851 PT(DownloadDb::MultifileRecord) mfr = parse_mfr(mfr_record);
00852
00853
00854 if (want_server_info) {
00855
00856
00857 for (int j = 0; j < mfr->_num_files; j++) {
00858
00859
00860 int fr_header_length = sizeof(PN_int32);
00861
00862
00863 string fr_header = sr.extract_bytes(fr_header_length);
00864 if (fr_header.size() != (size_t)fr_header_length) {
00865 downloader_cat.error() << "invalid fr header" << endl;
00866 return false;
00867 }
00868
00869
00870 int fr_length = parse_record_header(fr_header);
00871
00872
00873
00874 int read_length = (fr_length - fr_header_length);
00875
00876 string fr_record = sr.extract_bytes(read_length);
00877 if (fr_record.size() != (size_t)read_length) {
00878 downloader_cat.error() << "invalid fr record" << endl;
00879 return false;
00880 }
00881
00882
00883 PT(DownloadDb::FileRecord) fr = parse_fr(fr_record);
00884
00885
00886 mfr->add_file_record(fr);
00887 }
00888 }
00889
00890
00891 add_multifile_record(mfr);
00892 }
00893
00894 return true;
00895 }
00896
00897
00898
00899
00900
00901
00902
00903
00904 bool DownloadDb::Db::
00905 write(StreamWriter &sw, bool want_server_info) {
00906
00907
00908 PN_float64 phase;
00909 PN_int32 size;
00910 PN_int32 status;
00911 PN_int32 num_files;
00912 PN_int32 name_length;
00913 PN_int32 header_length;
00914
00915
00916 pvector< PT(MultifileRecord) >::const_iterator i = _mfile_records.begin();
00917 for(; i != _mfile_records.end(); ++i) {
00918
00919 phase = (*i)->_phase;
00920 size = (*i)->_size;
00921 status = (*i)->_status;
00922 num_files = (*i)->get_num_files();
00923 name_length = (*i)->_name.length();
00924
00925
00926 header_length =
00927 sizeof(header_length) +
00928 sizeof(name_length) +
00929 (*i)->_name.length() +
00930 sizeof(phase) + sizeof(size) +
00931 sizeof(status) + sizeof(num_files) +
00932 sizeof(PN_uint32)*4;
00933
00934
00935 sw.add_int32(header_length);
00936
00937
00938 sw.add_int32(name_length);
00939
00940 sw.append_data((*i)->_name);
00941
00942
00943 sw.add_float64(phase);
00944 sw.add_int32(size);
00945 sw.add_int32(status);
00946 sw.add_int32(num_files);
00947
00948 (*i)->_hash.write_stream(sw);
00949
00950
00951 if (want_server_info) {
00952
00953
00954 pvector< PT(FileRecord) >::const_iterator j = (*i)->_file_records.begin();
00955 for(; j != (*i)->_file_records.end(); ++j) {
00956 name_length = (*j)->_name.length();
00957
00958
00959 header_length =
00960 sizeof(header_length) +
00961 sizeof(name_length) +
00962 (*j)->_name.length();
00963
00964
00965 sw.add_int32(header_length);
00966
00967
00968 sw.add_int32(name_length);
00969
00970 sw.append_data((*j)->_name);
00971 }
00972 }
00973 }
00974
00975 return true;
00976 }
00977
00978
00979
00980
00981
00982
00983
00984
00985
00986 bool DownloadDb::Db::
00987 write_bogus_header(StreamWriter &sw) {
00988
00989 sw.add_uint32(_bogus_magic_number);
00990
00991
00992 sw.add_int32(get_num_multifiles());
00993
00994 return true;
00995 }
00996
00997
00998
00999
01000
01001
01002
01003 bool DownloadDb::Db::
01004 write_header(ostream &write_stream) {
01005 Datagram dg;
01006
01007
01008 dg.add_uint32(_magic_number);
01009
01010
01011 dg.add_int32(get_num_multifiles());
01012
01013 string msg = dg.get_message();
01014
01015
01016 write_stream.seekp(0);
01017
01018 write_stream.write(msg.data(), msg.length());
01019 return true;
01020 }
01021
01022
01023
01024
01025
01026
01027
01028
01029
01030
01031
01032
01033
01034 DownloadDb::FileRecord::
01035 FileRecord() {
01036 _name = "";
01037 }
01038
01039
01040
01041
01042
01043
01044
01045 DownloadDb::FileRecord::
01046 FileRecord(string name) {
01047 _name = name;
01048 }
01049
01050
01051
01052
01053
01054
01055 void DownloadDb::FileRecord::
01056 write(ostream &out) const {
01057 out << " FileRecord: " << _name << endl;
01058 }
01059
01060
01061
01062
01063
01064
01065
01066
01067
01068
01069 void DownloadDb::
01070 add_version(const Filename &name, const HashVal &hash, int version) {
01071 nassertv(version >= 1);
01072
01073 VectorHash &vhash = _versions[name];
01074 int size = vhash.size();
01075
01076
01077 nassertv(version <= size+1);
01078
01079 if (version-1 < size) {
01080
01081 vhash[version-1] = hash;
01082
01083 } else {
01084
01085 vhash.push_back(hash);
01086 }
01087 }
01088
01089
01090
01091
01092
01093
01094
01095 void DownloadDb::
01096 insert_new_version(const Filename &name, const HashVal &hash) {
01097 VectorHash &vhash = _versions[name];
01098 vhash.insert(vhash.begin(), hash);
01099 }
01100
01101
01102
01103
01104
01105
01106
01107
01108 bool DownloadDb::
01109 has_version(const Filename &name) const {
01110 return (_versions.find(name) != _versions.end());
01111 }
01112
01113
01114
01115
01116
01117
01118
01119 int DownloadDb::
01120 get_num_versions(const Filename &name) const {
01121 VersionMap::const_iterator vmi = _versions.find(name);
01122 if (vmi == _versions.end()) {
01123 return 0;
01124 }
01125
01126 return (int)(*vmi).second.size();
01127 }
01128
01129
01130
01131
01132
01133
01134
01135
01136 void DownloadDb::
01137 set_num_versions(const Filename &name, int num_versions) {
01138 VersionMap::iterator vmi = _versions.find(name);
01139 if (vmi == _versions.end()) {
01140 nassertv(num_versions == 0);
01141 return;
01142 }
01143
01144 VectorHash &vhash = (*vmi).second;
01145
01146 nassertv(num_versions <= (int)vhash.size());
01147 vhash.erase(vhash.begin() + num_versions, vhash.end());
01148 }
01149
01150
01151
01152
01153
01154
01155
01156
01157
01158 int DownloadDb::
01159 get_version(const Filename &name, const HashVal &hash) const {
01160 VersionMap::const_iterator vmi = _versions.find(name);
01161 if (vmi == _versions.end()) {
01162 downloader_cat.debug()
01163 << "DownloadDb::get_version() - can't find: " << name << endl;
01164 return -1;
01165 }
01166 const VectorHash &vhash = (*vmi).second;
01167 VectorHash::const_iterator i = find(vhash.begin(), vhash.end(), hash);
01168 if (i != vhash.end())
01169 return (i - vhash.begin() + 1);
01170 downloader_cat.debug()
01171 << "DownloadDb::get_version() - can't find hash: " << hash << endl;
01172 return -1;
01173 }
01174
01175
01176
01177
01178
01179
01180
01181 const HashVal &DownloadDb::
01182 get_hash(const Filename &name, int version) const {
01183 static HashVal bogus_hash;
01184
01185 VersionMap::const_iterator vmi = _versions.find(name);
01186 if (vmi == _versions.end()) {
01187 downloader_cat.error()
01188 << "DownloadDb::get_hash() - can't find: " << name << endl;
01189 return bogus_hash;
01190 }
01191
01192 const VectorHash &vhash = (*vmi).second;
01193 if (version < 1 || version > (int)vhash.size()) {
01194 downloader_cat.error()
01195 << "DownloadDb::get_hash() - no version " << version
01196 << " for " << name << endl;
01197 return bogus_hash;
01198 }
01199 return vhash[version - 1];
01200 }
01201
01202
01203
01204
01205
01206
01207 void DownloadDb::
01208 write_version_map(StreamWriter &sw) {
01209 VersionMap::iterator vmi;
01210 VectorHash::iterator i;
01211 string name;
01212
01213 sw.add_int32(_versions.size());
01214 for (vmi = _versions.begin(); vmi != _versions.end(); ++vmi) {
01215 name = (*vmi).first;
01216 downloader_cat.spam()
01217 << "DownloadDb::write_version_map() - writing file: "
01218 << name << " of length: " << name.length() << endl;
01219 sw.add_int32(name.length());
01220 sw.append_data(name);
01221 sw.add_int32((*vmi).second.size());
01222 for (i = (*vmi).second.begin(); i != (*vmi).second.end(); ++i) {
01223
01224 (*i).write_stream(sw);
01225 }
01226 }
01227 }
01228
01229
01230
01231
01232
01233
01234 bool DownloadDb::
01235 read_version_map(StreamReader &sr) {
01236 int num_entries = sr.get_int32();
01237 if (sr.get_istream()->fail()) {
01238 return false;
01239 }
01240
01241 for (int i = 0; i < num_entries; i++) {
01242
01243
01244 int name_length = sr.get_int32();
01245 if (sr.get_istream()->fail()) {
01246 return false;
01247 }
01248 downloader_cat.spam()
01249 << "DownloadDb::read_version_map() - name length: " << name_length
01250 << endl;
01251
01252
01253 string name = sr.extract_bytes(name_length);
01254 downloader_cat.spam()
01255 << "DownloadDb::read_version_map() - name: " << name << endl;
01256
01257
01258 int length = sr.get_int32();
01259 if (sr.get_istream()->fail()) {
01260 return false;
01261 }
01262 downloader_cat.spam()
01263 << "DownloadDb::read_version_map() - number of values: " << length
01264 << endl;
01265
01266 for (int j = 0; j < length; j++) {
01267 HashVal hash;
01268 hash.read_stream(sr);
01269 if (sr.get_istream()->fail()) {
01270 return false;
01271 }
01272 add_version(name, hash, j + 1);
01273 }
01274 }
01275 return true;
01276 }
01277
01278
01279
01280
01281
01282
01283 void DownloadDb::
01284 write_version_map(ostream &out) const {
01285 out << "Version Map: " << endl;
01286 VersionMap::const_iterator vmi;
01287 VectorHash::const_iterator i;
01288 for (vmi = _versions.begin(); vmi != _versions.end(); ++vmi) {
01289 out << " " << (*vmi).first << endl;
01290 for (i = (*vmi).second.begin(); i != (*vmi).second.end(); ++i) {
01291 HashVal hash = *i;
01292 out << " " << hash.as_dec() << endl;
01293 }
01294 }
01295 out << endl;
01296 }