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 #include <sstream>
00027
00028 #include <Basics.H>
00029 #include <SRPC.H>
00030 #include <FP.H>
00031 #include <VestaConfig.H>
00032
00033
00034 #include <CacheArgs.H>
00035 #include <CacheIntf.H>
00036 #include <Model.H>
00037 #include <CacheIndex.H>
00038 #include <FV.H>
00039 #include <CompactFV.H>
00040 #include <VestaVal.H>
00041 #include <NewVal.H>
00042 #include <Debug.H>
00043
00044 #include "CacheC.H"
00045
00046 using std::ostringstream;
00047 using std::cout;
00048 using std::cerr;
00049 using std::endl;
00050
00051
00052 class FatalError {
00053 public: FatalError() { }
00054 };
00055
00056 struct ClientArgs {
00057 int id;
00058 int numReqs;
00059 int numAddOps;
00060 int numPKs;
00061 int minNames;
00062 int maxNames;
00063 int commonNames;
00064 bool kids;
00065 bool verbose;
00066 };
00067
00068 static void ExitClient() throw ()
00069 {
00070 cerr << "SYNTAX: TestCacheRandom ";
00071 cerr << "[-threads n] [-reqs numReqs] [-pks numPKs ] [-kids] [-quiet]";
00072 cerr << endl;
00073 exit(1);
00074 }
00075
00076 static FV::Epoch ClientFreeVarsCall(CacheC *client,
00077 int id, const FP::Tag& pk, int &numNames,
00078 bool &isEmpty) throw (SRPC::failure)
00079 {
00080 CompactFV::List names;
00081 FV::Epoch epoch;
00082
00083 epoch = client->FreeVariables(pk, names, isEmpty);
00084 numNames = names.num;
00085 return epoch;
00086 }
00087
00088 static CacheIntf::LookupRes
00089 ClientLookupCall(CacheC *client, int id, const FP::Tag& pk,
00090 FV::Epoch epoch, int numNames) throw (SRPC::failure)
00091 {
00092
00093 FP::List fps;
00094 if (numNames > 0) {
00095 NewVal::NewFPs(fps, numNames);
00096 }
00097
00098
00099 CacheEntry::Index ci;
00100 VestaVal::T value;
00101 CacheIntf::LookupRes res;
00102 res = client->Lookup(pk, epoch, fps, ci, value);
00103 return res;
00104 }
00105
00106 static void NewNames2( char* &types, FV2::List &names,
00107 int numCommon, unsigned int num) throw ()
00108 {
00109
00110 if (num < 1) num = Debug::MyRand(1, 5);
00111
00112
00113 num = max(num, numCommon);
00114 types = NEW_PTRFREE_ARRAY(char, num+1);
00115 int i;
00116 for (i = 0; i < numCommon; i++) {
00117 types[i] = 'A';
00118 }
00119 for (; i < num; i++) {
00120 types[i] = 'A' + Debug::MyRand(0,25);
00121 }
00122
00123 types[num] = '\0';
00124
00125
00126 names.len = num;
00127 names.name = NEW_ARRAY(FV2::TPtr, num);
00128 Text prefix("name");
00129 for (i=0; i < num; i++) {
00130 names.name[i] = NEW(FV2::T);
00131 names.name[i]->addhi(prefix);
00132 ostringstream oss; oss << i;
00133 names.name[i]->addhi(Text(oss.str()));
00134 }
00135 }
00136
00137 static const Text SourceFunc("TestCacheRandom source function location");
00138
00139 static void ClientAddEntry(CacheC *client, int id, const FP::Tag& pk,
00140 int minNames, int maxNames, int commonNames, bool genKids)
00141 throw (SRPC::failure)
00142 {
00143 int numNames;
00144 FV2::List names;
00145 char *types;
00146 FP::List fps;
00147 VestaVal::T value;
00148 Model::T model;
00149 CacheEntry::Indices kids;
00150 CacheEntry::Index ci;
00151 CacheIntf::AddEntryRes res;
00152
00153
00154 numNames = Debug::MyRand(minNames, maxNames);
00155 NewNames2( types, names, commonNames, numNames);
00156 NewVal::NewFPs( fps, numNames);
00157 NewVal::NewValue( value);
00158 NewVal::NewModel( model);
00159 if (genKids) NewVal::NewCIs( kids);
00160
00161
00162 res = client->AddEntry(pk, types, names, fps, value, model,
00163 kids, SourceFunc, ci);
00164 }
00165
00166 void *MainClientProc(void *ptr) throw ()
00167
00168
00169
00170
00171
00172 {
00173 ClientArgs *args = (ClientArgs *)ptr;
00174 FP::Tag pk;
00175 FV::Epoch epoch;
00176 int numNames;
00177 CacheIntf::LookupRes res;
00178
00179 Debug::Lock();
00180 cout << Debug::Timestamp() << "Starting client thread " << args->id <<endl;
00181 cout << endl;
00182 Debug::Unlock();
00183
00184 try {
00185 CacheC client( args->verbose
00186 ? CacheIntf::All
00187 : CacheIntf::None);
00188
00189 int addOps = 0;
00190 for (int i = 0;
00191 (args->numReqs < 0 || i < args->numReqs) &&
00192 (args->numAddOps < 0 || addOps < args->numAddOps);
00193 i++) {
00194 if (args->verbose) {
00195 Debug::Lock();
00196 cout << Debug::Timestamp() << "Client thread " << args->id;
00197 cout << " **** Round " << i << " ****" << endl;
00198 cout << endl;
00199 Debug::Unlock();
00200 }
00201 NewVal::NewFP( pk, args->numPKs);
00202 do {
00203 bool isEmpty;
00204 epoch = ClientFreeVarsCall(&client, args->id, pk,
00205 numNames, isEmpty);
00206 if (isEmpty) {
00207 res = CacheIntf::Miss;
00208 } else {
00209 res = ClientLookupCall(&client, args->id,
00210 pk, epoch, numNames);
00211 }
00212 } while (res == CacheIntf::FVMismatch);
00213 if (res == CacheIntf::Miss) {
00214 ClientAddEntry(&client, args->id, pk,
00215 args->minNames, args->maxNames, args->commonNames,
00216 args->kids);
00217 addOps++;
00218 }
00219 }
00220 } catch (SRPC::failure f) {
00221 Debug::Lock();
00222 cerr << "SRPC Failure: " << f.msg
00223 << " (code " << f.r << ")" << endl;
00224 cerr << endl;
00225 Debug::Unlock();
00226 }
00227
00228 Debug::Lock();
00229 cout << Debug::Timestamp() << "Exiting client thread " << args->id << endl;
00230 cout << endl;
00231 Debug::Unlock();
00232 return (void *)NULL;
00233 }
00234
00235 int main(int argc, char *argv[])
00236 {
00237 int numThreads = 1, numReqs = -1, numAddOps = -1, numPKs = 10;
00238 int minNames = 1, maxNames = 5, commonNames = 1;
00239 bool verbose = true;
00240 bool kids = false;
00241 int arg;
00242
00243
00244 if (argc < 1 || argc > 17) {
00245 cerr << "Error: Incorrect number of arguments" << endl;
00246 ExitClient();
00247 }
00248 for (arg = 1; arg < argc; arg++) {
00249 if (CacheArgs::StartsWith(argv[arg], "-threads")) {
00250 if (sscanf(argv[++arg], "%d", &numThreads) < 1 || numThreads < 1) {
00251 cerr <<"Error: -threads argument not a positive integer"<<endl;
00252 ExitClient();
00253 }
00254 } else if (CacheArgs::StartsWith(argv[arg], "-reqs")) {
00255 if (sscanf(argv[++arg], "%d", &numReqs) < 1) {
00256 cerr << "Error: -reqs argument must be an integer" << endl;
00257 ExitClient();
00258 }
00259 } else if (CacheArgs::StartsWith(argv[arg], "-addops")) {
00260 if (sscanf(argv[++arg], "%d", &numAddOps) < 1) {
00261 cerr << "Error: -addops argument must be an integer" << endl;
00262 ExitClient();
00263 }
00264 } else if (CacheArgs::StartsWith(argv[arg], "-commonNames")) {
00265 if (sscanf(argv[++arg], "%d", &commonNames) < 1) {
00266 cerr << "Error: -commonNames argument must be an integer"
00267 << endl;
00268 ExitClient();
00269 }
00270 } else if (CacheArgs::StartsWith(argv[arg], "-minNames", 3)) {
00271 if (sscanf(argv[++arg], "%d", &minNames) < 1) {
00272 cerr << "Error: -minNames argument must be an integer" << endl;
00273 ExitClient();
00274 }
00275 if (maxNames < minNames) maxNames = minNames;
00276 } else if (CacheArgs::StartsWith(argv[arg], "-maxNames", 3)) {
00277 if (sscanf(argv[++arg], "%d", &maxNames) < 1) {
00278 cerr << "Error: -maxNames argument must be an integer" << endl;
00279 ExitClient();
00280 }
00281 if (maxNames < minNames) minNames = maxNames;
00282 } else if (CacheArgs::StartsWith(argv[arg], "-pks")) {
00283 if (sscanf(argv[++arg], "%d", &numPKs) < 1) {
00284 cerr << "Error: -numPKs argument must be an integer" << endl;
00285 ExitClient();
00286 }
00287 } else if (CacheArgs::StartsWith(argv[arg], "-seed")) {
00288 int seed;
00289 if (sscanf(argv[++arg], "%d", &seed) < 1) {
00290 cerr << "Error: -seed argument must be an integer" << endl;
00291 ExitClient();
00292 }
00293 srand((unsigned int) seed);
00294 } else if (CacheArgs::StartsWith(argv[arg], "-kids")) {
00295 kids = true;
00296 } else if (CacheArgs::StartsWith(argv[arg], "-quiet")) {
00297 verbose = false;
00298 } else {
00299 cerr << "Error: argument " << arg << " is bad" << endl;
00300 ExitClient();
00301 }
00302 }
00303
00304
00305 Debug::Lock();
00306 cout << "Starting client:" << endl;
00307 cout << " Config: " << VestaConfig::get_location() << endl;
00308 cout << endl;
00309 Debug::Unlock();
00310
00311
00312 Debug::Lock();
00313 cout << Debug::Timestamp() <<"Forking "<< numThreads <<" thread(s)"<< endl;
00314 cout << endl;
00315 Debug::Unlock();
00316 Basics::thread *th = NEW_PTRFREE_ARRAY(Basics::thread, numThreads);
00317 int i;
00318 for (i = 0; i < numThreads; i++) {
00319 ClientArgs *args = NEW(ClientArgs);
00320 args->id = i + 1;
00321 args->numReqs = numReqs;
00322 args->numAddOps = numAddOps;
00323 args->numPKs = numPKs;
00324 args->minNames = minNames;
00325 args->maxNames = maxNames;
00326 args->commonNames = commonNames;
00327 args->kids = kids;
00328 args->verbose = verbose;
00329 th[i].fork(MainClientProc, (void *)args);
00330 }
00331
00332
00333 Debug::Lock();
00334 cout << Debug::Timestamp()
00335 << "Main client thread now waiting for threads to complete..." << endl;
00336 cout << endl;
00337 Debug::Unlock();
00338 for (i = 0; i < numThreads; i++) {
00339 (void) th[i].join();
00340 }
00341 }