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 #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);
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();
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
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
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();
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
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);
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;
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 }