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 }