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