log_exceed.cpp

This example demonstrates the use of the ss_m::ss_m arguments. It is an extension of the create_rec::cpp example that generates enough log to run out of log space.

00001 /*<std-header orig-src='shore'>
00002 
00003  $Id: log_exceed.cpp,v 1.6 2010/09/21 14:26:28 nhall Exp $
00004 
00005 SHORE -- Scalable Heterogeneous Object REpository
00006 
00007 Copyright (c) 1994-99 Computer Sciences Department, University of
00008                       Wisconsin -- Madison
00009 All Rights Reserved.
00010 
00011 Permission to use, copy, modify and distribute this software and its
00012 documentation is hereby granted, provided that both the copyright
00013 notice and this permission notice appear in all copies of the
00014 software, derivative works or modified versions, and any portions
00015 thereof, and that both notices appear in supporting documentation.
00016 
00017 THE AUTHORS AND THE COMPUTER SCIENCES DEPARTMENT OF THE UNIVERSITY
00018 OF WISCONSIN - MADISON ALLOW FREE USE OF THIS SOFTWARE IN ITS
00019 "AS IS" CONDITION, AND THEY DISCLAIM ANY LIABILITY OF ANY KIND
00020 FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
00021 
00022 This software was developed with support by the Advanced Research
00023 Project Agency, ARPA order number 018 (formerly 8230), monitored by
00024 the U.S. Army Research Laboratory under contract DAAB07-91-C-Q518.
00025 Further funding for this work was provided by DARPA through
00026 Rome Research Laboratory Contract No. F30602-97-2-0247.
00027 
00028 */
00029 
00030 #include "w_defines.h"
00031 
00032 /*  -- do not edit anything above this line --   </std-header>*/
00033 
00034 /*
00035  * This program is a test of out-of-log-space-warning facilities
00036  * It requires access to xct_t, so the #include files are a bit different.
00037  * We have to pretend we are an internal part of the SM before we #include the world.
00038  */
00039 
00040 #define SM_LEVEL 1
00041 #define SM_SOURCE
00042 #define XCT_C
00043 #include "sm_int_1.h"
00044 #include "sm_vas.h"
00045 #define SUBSTITUTE_MAIN
00046 #include "create_rec.cpp"
00047 
00048 static option_t *logdir(NULL); // for use in dump() below.
00049 
00050 extern w_rc_t out_of_log_space (xct_i*, xct_t*&, ss_m::fileoff_t, 
00051                                  ss_m::fileoff_t, 
00052                                  const char *logfile
00053                                  );
00054 
00055 extern w_rc_t get_archived_log_file (const char *logfile, ss_m::partition_number_t);
00056 
00057 class smthread_user_t : public smthread_driver_t
00058 {
00059 
00060     void start_ssm(); //override the default
00061 public:
00062     smthread_user_t(int ac, char **av) 
00063                 : smthread_driver_t(ac, av) {}
00064 
00065     virtual ~smthread_user_t()  { }
00066 };
00067 
00068 void smthread_user_t::start_ssm()
00069 {
00070     // get the logdir option for use in dump()
00071     if(logdir==NULL) {
00072         W_COERCE(_options->lookup("sm_logdir", false, logdir));
00073         fprintf(stdout, "Found logdir %s\n", logdir->value());
00074     }
00075 
00076     // Now start a storage manager.
00077     cout << "Starting SSM (with out_of_log_space and get_archived_log_file) ..." << endl;
00078     ssm = new ss_m(out_of_log_space, get_archived_log_file);
00079 }
00080 
00081 int
00082 main(int argc, char* argv[])
00083 {
00084     smthread_user_t *smtu = new smthread_user_t(argc, argv);
00085     if (!smtu)
00086             W_FATAL(fcOUTOFMEMORY);
00087 
00088     w_rc_t e = smtu->fork();
00089     if(e.is_error()) {
00090         cerr << "error forking thread: " << e <<endl;
00091         return 1;
00092     }
00093     e = smtu->join();
00094     if(e.is_error()) {
00095         cerr << "error forking thread: " << e <<endl;
00096         return 1;
00097     }
00098 
00099     int        rv = smtu->return_value();
00100     delete smtu;
00101 
00102     return rv;
00103 }
00104 
00105 #include <os_interface.h>
00106 
00107 void dump()
00108 {
00109 
00110     os_dirent_t *dd = NULL;
00111     os_dir_t ldir = os_opendir(logdir->value());
00112     if(!ldir) {
00113         fprintf(stdout, "Could not open directory %s\n", logdir->value());
00114         return;
00115     }
00116     fprintf(stdout, "---------------------- %s {\n", logdir->value());
00117     while ((dd = os_readdir(ldir)))
00118     {
00119         fprintf(stdout, "%s\n", dd->d_name);
00120     }
00121     os_closedir(ldir);
00122     fprintf(stdout, "---------------------- %s }\n", logdir->value());
00123 }
00124 
00125 
00126 w_rc_t get_archived_log_file (
00127         const char *filename, 
00128         ss_m::partition_number_t num)
00129 {
00130     fprintf(stdout, 
00131             "\n**************************************** RECOVER %s : %d\n",
00132             filename, num
00133             );
00134     dump();
00135 
00136     w_rc_t rc;
00137 
00138     static char O[smlevel_0::max_devname<<1];
00139     strcat(O, filename);
00140     strcat(O, ".bak");
00141 
00142     static char N[smlevel_0::max_devname<<1];
00143     strcat(N, filename);
00144 
00145     int e = ::rename(O, N);
00146     if(e != 0) 
00147     {
00148         fprintf(stdout, "Could not move %s to %s: error : %d %s\n",
00149                 O, N, e, strerror(errno));
00150         rc = RC2(smlevel_0::eOUTOFLOGSPACE, errno); 
00151     }
00152     dump();
00153     fprintf(stdout, "recovered ... OK!\n\n");
00154     fprintf(stdout, 
00155         "This recovery of the log file will enable us to finish the abort.\n");
00156     fprintf(stdout, 
00157         "It will not continue the device/volume set up.\n");
00158     fprintf(stdout, 
00159         "Expect an error message and stack trace about that:\n\n");
00160     return rc;
00161 }
00162 w_rc_t out_of_log_space (
00163     xct_i* iter, 
00164     xct_t *& xd,
00165     smlevel_0::fileoff_t curr,
00166     smlevel_0::fileoff_t thresh,
00167     const char *filename
00168 )
00169 {
00170     static int calls=0;
00171 
00172     calls++;
00173 
00174     w_rc_t rc;
00175     fprintf(stdout, "\n**************************************** %d\n", calls);
00176     dump();
00177 
00178     fprintf(stdout, 
00179             "Called out_of_log_space with curr %lld thresh %lld, file %s\n",
00180             (long long) curr, (long long) thresh, filename);
00181     {
00182         w_ostrstream o;
00183         o << xd->tid() << endl;
00184         fprintf(stdout, "called with xct %s\n" , o.c_str()); 
00185     }
00186 
00187     xd->log_warn_disable();
00188     iter->never_mind(); // release the mutex
00189 
00190     {
00191         w_ostrstream o;
00192         static sm_stats_info_t curr;
00193 
00194         W_DO( ssm->gather_stats(curr));
00195 
00196         o << curr.sm.log_bytes_generated << ends;
00197         fprintf(stdout, "stats: log_bytes_generated %s\n" , o.c_str()); 
00198     }
00199     lsn_t target;
00200     {
00201         w_ostrstream o;
00202         o << "Active xcts: " << xct_t::num_active_xcts() << " ";
00203 
00204         tid_t old = xct_t::oldest_tid();
00205         o << "Oldest transaction: " << old;
00206 
00207         xct_t *x = xct_t::look_up(old);
00208         if(x==NULL) {
00209             fprintf(stdout, "Could not find %s\n", o.c_str());
00210             W_FATAL(fcINTERNAL);
00211         }
00212 
00213         target = x->first_lsn();
00214         o << "   First lsn: " << x->first_lsn();
00215         o << "   Last lsn: " << x->last_lsn();
00216 
00217         fprintf(stdout, "%s\n" , o.c_str()); 
00218 
00219     }
00220 
00221     if(calls > 3) {
00222         // See what happens...
00223         static tid_t aborted_tid;
00224         if(aborted_tid == xd->tid()) {
00225             w_ostrstream o;
00226             o << aborted_tid << endl;
00227             fprintf(stdout, 
00228                     "Multiple calls with same victim! : %s total calls %d\n",
00229                     o.c_str(), calls);
00230             W_FATAL(smlevel_0::eINTERNAL);
00231         }
00232         aborted_tid = xd->tid();
00233         fprintf(stdout, "\n\n******************************** ABORTING\n\n");
00234         return RC(smlevel_0::eUSERABORT); // sm will abort this guy
00235     }
00236 
00237     fprintf(stdout, "\n\n******************************** ARCHIVING \n\n");
00238     fprintf(stdout, "Move aside log file log.%d to log.%d.bak\n", 
00239             target.file(), target.file());
00240     static char O[smlevel_0::max_devname<<1];
00241     strcat(O, filename);
00242     static char N[smlevel_0::max_devname<<1];
00243     strcat(N, filename);
00244     strcat(N, ".bak");
00245 
00246     int e = ::rename(O, N);
00247     if(e != 0) {
00248         fprintf(stdout, "Could not move %s to %s: error : %d %s\n",
00249                 O, N, e, strerror(errno));
00250         if(errno == ENOENT) {
00251             fprintf(stdout, "Ignored error.\n\n");
00252             return RCOK; // just to ignore these.
00253         }
00254         fprintf(stdout, "Returning eOUTOFLOGSPACE.\n\n");
00255         rc = RC2(smlevel_0::eOUTOFLOGSPACE, errno); 
00256     } else {
00257         dump();
00258         fprintf(stdout, "archived ... OK\n\n");
00259         W_COERCE(ss_m::log_file_was_archived(filename));
00260     }
00261     return rc;
00262 }

Generated on Thu Dec 9 08:42:26 2010 for Shore Storage Manager by  doxygen 1.4.7