00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030 #include "w_defines.h"
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049 #include "sm_vas.h"
00050 ss_m* ssm = 0;
00051
00052
00053 typedef w_rc_t rc_t;
00054
00055
00056 w_rc_t init_config_options(option_group_t& options,
00057 const char* prog_type,
00058 int& argc, char** argv);
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071 struct file_info_t {
00072 static const char* key;
00073 stid_t fid;
00074 rid_t first_rid;
00075 int num_rec;
00076 int rec_size;
00077 };
00078 const char* file_info_t::key = "SCANFILE";
00079
00080 ostream &
00081 operator << (ostream &o, const file_info_t &info)
00082 {
00083 o << "key " << info.key
00084 << " fid " << info.fid
00085 << " first_rid " << info.first_rid
00086 << " num_rec " << info.num_rec
00087 << " rec_size " << info.rec_size ;
00088 return o;
00089 }
00090
00091 static char *argv0(NULL);
00092 void
00093 usage(option_group_t& options)
00094 {
00095 cerr << "Usage: " << argv0 << " [-h] [-i] [options]" << endl;
00096 cerr << " -i initialize device/volume and create file of records" << endl;
00097 cerr << "Valid options are: " << endl;
00098 options.print_usage(true, cerr);
00099 }
00100
00101
00102 class smthread_driver_t : public smthread_t {
00103 int _argc;
00104 char** _argv;
00105
00106 protected:
00107 const char *_device_name;
00108 smsize_t _quota;
00109 int _num_rec;
00110 smsize_t _rec_size;
00111 lvid_t _lvid;
00112 vid_t _vid;
00113 rid_t _start_rid;
00114 stid_t _fid;
00115 bool _initialize_device;
00116 option_group_t* _options;
00117 int _retval;
00118
00119
00120 virtual w_rc_t do_work() ;
00121 virtual void start_ssm() ;
00122 public:
00123
00124 smthread_driver_t(int ac, char **av)
00125 : smthread_t(t_regular, "smthread_driver_t"),
00126 _argc(ac), _argv(av),
00127 _device_name(NULL),
00128 _quota(0),
00129 _num_rec(0),
00130 _rec_size(0),
00131 _vid(1),
00132 _initialize_device(false),
00133 _options(NULL),
00134 _retval(0) { }
00135
00136 virtual ~smthread_driver_t() { if(_options) delete _options; }
00137
00138 virtual void run();
00139 void statistics() const;
00140 int return_value() const { return _retval; }
00141
00142
00143
00144 w_rc_t handle_options();
00145 w_rc_t find_file_info();
00146 w_rc_t create_the_file();
00147 w_rc_t scan_the_file();
00148 w_rc_t scan_the_root_index();
00149 w_rc_t do_init();
00150 w_rc_t no_init();
00151
00152 };
00153
00154 w_rc_t
00155 smthread_driver_t::handle_options()
00156 {
00157
00158
00159
00160
00161
00162
00163
00164
00165
00166
00167 const int option_level_cnt = 3;
00168
00169 _options = new option_group_t (option_level_cnt);
00170 if(!_options) {
00171 cerr << "Out of memory: could not allocate from heap." <<
00172 endl;
00173 _retval = 1;
00174 return RC(fcINTERNAL);
00175 }
00176 option_group_t &options(*_options);
00177
00178
00179
00180 option_t* opt_device_name = 0;
00181 W_DO(options.add_option(
00182 "device_name",
00183 "device/file name",
00184 NULL,
00185 "device containg volume holding file to scan",
00186 true,
00187 option_t::set_value_charstr,
00188 opt_device_name
00189 ));
00190
00191
00192 option_t* opt_device_quota = 0;
00193 W_DO(options.add_option(
00194 "device_quota",
00195 "# > 1000",
00196 "2000",
00197 "quota for device",
00198 false,
00199 option_t::set_value_long,
00200 opt_device_quota
00201 ));
00202
00203
00204
00205
00206 option_t* opt_num_rec = 0;
00207 W_DO(options.add_option(
00208 "num_rec",
00209 "# > 0",
00210 "100",
00211 "number of records in file",
00212 true,
00213 option_t::set_value_long,
00214 opt_num_rec
00215 ));
00216
00217
00218
00219
00220 W_DO(ss_m::setup_options(&options));
00221
00222
00223
00224
00225
00226 w_rc_t rc = init_config_options(options, "server", _argc, _argv);
00227 if (rc.is_error()) {
00228 usage(options);
00229 _retval = 1;
00230 return rc;
00231 }
00232
00233
00234
00235
00236
00237
00238 int option;
00239 while ((option = getopt(_argc, _argv, "hi")) != -1) {
00240 switch (option) {
00241 case 'i' :
00242 _initialize_device = true;
00243 break;
00244
00245 case 'h' :
00246 usage(options);
00247 break;
00248
00249 default:
00250 usage(options);
00251 _retval = 1;
00252 return RC(fcNOTIMPLEMENTED);
00253 break;
00254 }
00255 }
00256
00257
00258 _device_name = opt_device_name->value();
00259 _quota = strtol(opt_device_quota->value(), 0, 0);
00260 _num_rec = strtol(opt_num_rec->value(), 0, 0);
00261
00262 return RCOK;
00263 }
00264
00265 void
00266 smthread_driver_t::statistics() const
00267 {
00268 sm_stats_info_t stats;
00269 W_COERCE(ss_m::gather_stats(stats));
00270 cout << " SM Statistics : " << endl
00271 << stats << endl;
00272 }
00273
00274
00275
00276
00277 w_rc_t
00278 smthread_driver_t::find_file_info()
00279 {
00280 file_info_t info;
00281
00282
00283 W_DO(ssm->begin_xct());
00284
00285
00286
00287
00288 stid_t root_iid;
00289 W_DO(ss_m::vol_root_index(_vid, root_iid));
00290
00291
00292
00293
00294 const vec_t key_vec_tmp(file_info_t::key, strlen(file_info_t::key));
00295
00296
00297 smsize_t info_len = sizeof(info);
00298
00299
00300
00301
00302
00303
00304
00305 bool found;
00306 W_DO(ss_m::find_assoc(root_iid,
00307 key_vec_tmp,
00308 &info, info_len, found));
00309 if (!found) {
00310 cerr << "No file information found" <<endl;
00311 return RC(fcASSERT);
00312 } else {
00313
00314
00315
00316 cout << "Found assoc "
00317 << file_info_t::key << " --> " << info << endl;
00318
00319 _fid = info.fid;
00320 _start_rid = info.first_rid;
00321 _rec_size = info.rec_size;
00322 _num_rec = info.num_rec;
00323 }
00324
00325
00326 W_DO(ssm->commit_xct());
00327
00328 return RCOK;
00329 }
00330
00331 rc_t
00332 smthread_driver_t::create_the_file()
00333 {
00334 file_info_t info;
00335
00336
00337 W_DO(ssm->begin_xct());
00338
00339
00340
00341
00342
00343
00344
00345
00346 W_DO(ssm->create_file(_vid, _fid, smlevel_3::t_regular));
00347 info.fid = _fid;
00348
00349
00350 W_DO(ssm->commit_xct());
00351
00352
00353
00354
00355
00356
00357
00358
00359
00360
00361
00362
00363 _rec_size -= align(sizeof(int));
00364
00365 char* dummy = new char[_rec_size];
00366 memset(dummy, '\0', _rec_size);
00367
00368
00369
00370 vec_t data(dummy, _rec_size);
00371
00372
00373 W_DO(ssm->begin_xct());
00374
00375
00376 for(int j=0; j < _num_rec; j++)
00377 {
00378
00379
00380
00381 const vec_t hdr(&j, sizeof(j));
00382 rid_t rid;
00383
00384 W_DO(ssm->create_rec(
00385 info.fid,
00386 hdr,
00387 _rec_size,
00388 data,
00389 rid
00390 ));
00391 if (j == 0) {
00392 info.first_rid = rid;
00393 }
00394 cout << "Record number " << j << " " << rid << endl;
00395
00396 }
00397 delete [] dummy;
00398 cout << "Created all."
00399 << endl
00400 << " First rid " << info.first_rid << endl;
00401
00402
00403
00404
00405
00406 info.num_rec = _num_rec;
00407 info.rec_size = _rec_size;
00408
00409
00410 stid_t _root_iid;
00411 W_DO(ss_m::vol_root_index(_vid, _root_iid));
00412
00413
00414
00415
00416 const vec_t key_vec_tmp(file_info_t::key, strlen(file_info_t::key));
00417
00418 const vec_t info_vec_tmp(&info, sizeof(info));
00419
00420 W_DO(ss_m::create_assoc(_root_iid,
00421 key_vec_tmp,
00422 info_vec_tmp));
00423 cout << "Creating assoc "
00424 << file_info_t::key << " --> " << info << endl;
00425
00426 W_DO(ssm->commit_xct());
00427 return RCOK;
00428 }
00429
00430 rc_t
00431 smthread_driver_t::scan_the_root_index()
00432 {
00433 W_DO(ssm->begin_xct());
00434 stid_t _root_iid;
00435 W_DO(ss_m::vol_root_index(_vid, _root_iid));
00436 cout << "Scanning index " << _root_iid << endl;
00437 scan_index_i scan(_root_iid,
00438 scan_index_i::ge, vec_t::neg_inf,
00439 scan_index_i::le, vec_t::pos_inf, false,
00440 ss_m::t_cc_kvl);
00441 bool eof(false);
00442 int i(0);
00443 smsize_t klen(0);
00444 smsize_t elen(0);
00445 #define MAXKEYSIZE 100
00446 char keybuf[MAXKEYSIZE];
00447 file_info_t info;
00448
00449 do {
00450 w_rc_t rc = scan.next(eof);
00451 if(rc.is_error()) {
00452 cerr << "Error getting next: " << rc << endl;
00453 _retval = rc.err_num();
00454 return rc;
00455 }
00456 if(eof) break;
00457
00458
00459 W_DO(scan.curr(NULL, klen, NULL, elen));
00460
00461 vec_t key(&keybuf[0], klen);
00462 vec_t elem(&info, elen);
00463
00464 W_DO(scan.curr(&key, klen, &elem, elen));
00465 keybuf[klen] = '\0';
00466 cout << "Key " << (const char *)keybuf << endl;
00467 cout << "Value "
00468 << " { fid " << info.fid
00469 << " first_rid " << info.first_rid
00470 << " #rec " << info.num_rec
00471 << " rec size " << info.rec_size << " }"
00472 << endl;
00473 i++;
00474 } while (!eof);
00475 W_DO(ssm->commit_xct());
00476 return RCOK;
00477 }
00478
00479 rc_t
00480 smthread_driver_t::scan_the_file()
00481 {
00482 cout << "Scanning file " << _fid << endl;
00483 W_DO(ssm->begin_xct());
00484
00485 scan_file_i scan(_fid);
00486 pin_i* cursor(NULL);
00487 bool eof(false);
00488 int i(0);
00489
00490 do {
00491 w_rc_t rc = scan.next(cursor, 0, eof);
00492 if(rc.is_error()) {
00493 cerr << "Error getting next: " << rc << endl;
00494 _retval = rc.err_num();
00495 return rc;
00496 }
00497 if(eof) break;
00498
00499 cout << "Record " << i
00500 << " Rid " << cursor->rid() ;
00501 vec_t header (cursor->hdr(), cursor->hdr_size());
00502 int hdrcontents;
00503 header.copy_to(&hdrcontents, sizeof(hdrcontents));
00504 cout << " Hdr {" << hdrcontents << "}";
00505
00506 const char *body = cursor->body();
00507 w_assert0(cursor->body_size() == _rec_size);
00508 cout << " Body {" << body << "}";
00509 cout << endl;
00510 i++;
00511 } while (!eof);
00512 w_assert1(i == _num_rec);
00513
00514 W_DO(ssm->commit_xct());
00515 return RCOK;
00516 }
00517
00518 rc_t
00519 smthread_driver_t::do_init()
00520 {
00521 cout << "-i: Initialize " << endl;
00522
00523 {
00524 devid_t devid;
00525 cout << "Formatting device: " << _device_name
00526 << " with a " << _quota << "KB quota ..." << endl;
00527 W_DO(ssm->format_dev(_device_name, _quota, true));
00528
00529 cout << "Mounting device: " << _device_name << endl;
00530
00531 u_int vol_cnt;
00532 W_DO(ssm->mount_dev(_device_name, vol_cnt, devid));
00533
00534 cout << "Mounted device: " << _device_name
00535 << " volume count " << vol_cnt
00536 << " device " << devid
00537 << endl;
00538
00539
00540
00541 cout << "Generating new lvid: " << endl;
00542 W_DO(ssm->generate_new_lvid(_lvid));
00543 cout << "Generated lvid " << _lvid << endl;
00544
00545
00546 cout << "Creating a new volume on the device" << endl;
00547 cout << " with a " << _quota << "KB quota ..." << endl;
00548
00549 W_DO(ssm->create_vol(_device_name, _lvid, _quota, false, _vid));
00550 cout << " with local handle(phys volid) " << _vid << endl;
00551
00552 }
00553
00554 W_DO(create_the_file());
00555 return RCOK;
00556 }
00557
00558 rc_t
00559 smthread_driver_t::no_init()
00560 {
00561 cout << "Using already-existing device: " << _device_name << endl;
00562
00563 devid_t devid;
00564 u_int vol_cnt;
00565 w_rc_t rc = ssm->mount_dev(_device_name, vol_cnt, devid);
00566 if (rc.is_error()) {
00567 cerr << "Error: could not mount device: "
00568 << _device_name << endl;
00569 cerr << " Did you forget to run the server with -i?"
00570 << endl;
00571 return rc;
00572 }
00573
00574
00575 lvid_t* lvid_list;
00576 u_int lvid_cnt;
00577 W_DO(ssm->list_volumes(_device_name, lvid_list, lvid_cnt));
00578 if (lvid_cnt == 0) {
00579 cerr << "Error, device has no volumes" << endl;
00580 exit(1);
00581 }
00582 _lvid = lvid_list[0];
00583 delete [] lvid_list;
00584
00585 W_DO(find_file_info());
00586 W_DO(scan_the_root_index());
00587 W_DO(scan_the_file());
00588 return RCOK;
00589 }
00590
00591
00592 rc_t
00593 smthread_driver_t::do_work()
00594 {
00595 if (_initialize_device) W_DO(do_init());
00596 else W_DO(no_init());
00597 statistics();
00598 return RCOK;
00599 }
00600
00601 void
00602 smthread_driver_t::start_ssm()
00603 {
00604
00605 cout << "Starting SSM and performing recovery ..." << endl;
00606 ssm = new ss_m();
00607 }
00608
00609
00610 void smthread_driver_t::run()
00611 {
00612
00613 w_rc_t rc = handle_options();
00614 if(rc.is_error()) {
00615 _retval = 1;
00616 return;
00617 }
00618
00619
00620 start_ssm();
00621 if (!ssm) {
00622 cerr << "Error: Out of memory for ss_m" << endl;
00623 _retval = 1;
00624 return;
00625 }
00626
00627
00628
00629
00630
00631
00632
00633
00634
00635
00636
00637
00638
00639
00640 sm_config_info_t config_info;
00641 rc = ss_m::config_info(config_info);
00642 if(rc.is_error()) {
00643 cerr << "Could not get storage manager configuration info: " << rc << endl;
00644 _retval = 1;
00645 return;
00646 }
00647 _rec_size = config_info.max_small_rec;
00648
00649 _rec_size += config_info.small_rec_overhead;
00650 _rec_size /= 2;
00651 _rec_size -= config_info.small_rec_overhead;
00652
00653 rc = do_work();
00654 if(rc.is_error()) {
00655 cerr << "Failure: " << rc << endl;
00656 _retval = 1;
00657 }
00658
00659
00660 cout << "\nShutting down SSM ..." << endl;
00661 delete ssm;
00662 cout << "Finished!" << endl;
00663
00664 return;
00665 }
00666
00667
00668
00669
00670 #ifndef SUBSTITUTE_MAIN
00671 int
00672 main(int argc, char* argv[])
00673 {
00674
00675
00676 argv0 = argv[0];
00677
00678
00679 smthread_driver_t *smtu = new smthread_driver_t(argc, argv);
00680 if (!smtu)
00681 W_FATAL(fcOUTOFMEMORY);
00682
00683
00684 w_rc_t e = smtu->fork();
00685 if(e.is_error()) {
00686 cerr << "Error forking thread: " << e <<endl;
00687 return 1;
00688 }
00689
00690
00691 e = smtu->join();
00692 if(e.is_error()) {
00693 cerr << "Error joining thread: " << e <<endl;
00694 return 1;
00695 }
00696
00697
00698 int rv = smtu->return_value();
00699
00700
00701 delete smtu;
00702
00703 return rv;
00704 }
00705 #endif
00706