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