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 "libts.h"
00031 #include <math.h>
00032 #include "Main.h"
00033 #include "CongestionDB.h"
00034 #include "Congestion.h"
00035 #include "Error.h"
00036
00037
00038
00039
00040
00041
00042
00043
00044 EXCLUSIVE_REGRESSION_TEST(Congestion_HashTable) (RegressionTest * t, int , int *pstatus)
00045 {
00046 MTHashTable<long, long>*htable = new MTHashTable<long, long>(4);
00047
00048 long i, count = 1 * 1024 * 1024;
00049 rprintf(t, "adding data into the hash table .", count);
00050 for (i = 1; i <= count; i++) {
00051 htable->insert_entry(i, i);
00052 if (i % (count / 50) == 0)
00053 fprintf(stderr, ".");
00054 }
00055 fprintf(stderr, "done\n");
00056 rprintf(t, "%d data added into the hash table\n", count);
00057 rprintf(t, "verifying the content");
00058 for (i = 1; i <= count; i++) {
00059 long data = htable->lookup_entry(i);
00060 if (i % (count / 50) == 0)
00061 fprintf(stderr, ".");
00062 if (data != i) {
00063 rprintf(t, "verify content failed: key(%d) data(%d)\n", i, data);
00064 *pstatus = REGRESSION_TEST_FAILED;
00065 return;
00066 }
00067 }
00068 fprintf(stderr, "done\n");
00069 long removed_count = 0;
00070
00071 rprintf(t, "removing data.");
00072 for (i = 1; i < count / 2; i++) {
00073 htable->remove_entry(i * 2);
00074 if (i % (count / 50) == 0)
00075 fprintf(stderr, ".");
00076 removed_count++;
00077 }
00078 fprintf(stderr, "done\n");
00079
00080 rprintf(t, "%d data entries are removed\n", removed_count);
00081 rprintf(t, "verify the content again");
00082 for (i = 1; i <= count; i++) {
00083 long data = htable->lookup_entry(i);
00084 if (i % 2 == 1 && data == 0) {
00085 rprintf(t, "verify content failed: key(%d) deleted\n", i);
00086 *pstatus = REGRESSION_TEST_FAILED;
00087 return;
00088 }
00089 if (data != 0 && data != i) {
00090 rprintf(t, "verify content failed: key(%d) data(%d)\n", i, data);
00091 *pstatus = REGRESSION_TEST_FAILED;
00092 return;
00093 }
00094 if (i % (count / 50) == 0)
00095 fprintf(stderr, ".");
00096 }
00097 fprintf(stderr, "done\n");
00098
00099 rprintf(t, "use iterator to list all the elements and delete half of them");
00100 HashTableIteratorState<long, long>it;
00101 int j, new_count = 0;
00102 for (j = 0; j < MT_HASHTABLE_PARTITIONS; j++) {
00103 int data = htable->first_entry(j, &it);
00104 while (data > 0) {
00105 new_count++;
00106 if (new_count % (count / 25) == 0)
00107 fprintf(stderr, ".");
00108
00109 if (new_count % 2 == 0) {
00110 htable->remove_entry(j, &it);
00111 data = htable->cur_entry(j, &it);
00112 removed_count++;
00113 } else
00114 data = htable->next_entry(j, &it);
00115 }
00116 }
00117 fprintf(stderr, "done\n");
00118
00119 rprintf(t, "verify the content once again");
00120 new_count = count - removed_count;
00121 for (j = 0; j < MT_HASHTABLE_PARTITIONS; j++) {
00122 int data = htable->first_entry(j, &it);
00123 while (data > 0) {
00124 new_count--;
00125 if (new_count % (count / 25) == 0)
00126 fprintf(stderr, ".");
00127 data = htable->next_entry(j, &it);
00128 if (data != htable->lookup_entry(data)) {
00129 rprintf(t, "verify content failed: key(%d) data(%d)\n", data, htable->lookup_entry(data));
00130 *pstatus = REGRESSION_TEST_FAILED;
00131 return;
00132 }
00133 }
00134 }
00135
00136 fprintf(stderr, "done\n");
00137 if (new_count != 0) {
00138 rprintf(t, "there are %d extra entries in the table\n", new_count);
00139 *pstatus = REGRESSION_TEST_FAILED;
00140 return;
00141 }
00142
00143 rprintf(t, "remove everything using iterator");
00144 new_count = count - removed_count;
00145 for (j = 0; j < MT_HASHTABLE_PARTITIONS; j++) {
00146 int data = htable->first_entry(j, &it);
00147 while (data > 0) {
00148 new_count--;
00149 if (new_count % (count / 25) == 0)
00150 fprintf(stderr, ".");
00151 htable->remove_entry(j, &it);
00152 data = htable->cur_entry(j, &it);
00153 }
00154 }
00155
00156 fprintf(stderr, "done\n");
00157 if (new_count != 0) {
00158 rprintf(t, "there are %d extra entries in the table\n", new_count);
00159 *pstatus = REGRESSION_TEST_FAILED;
00160 return;
00161 }
00162
00163 delete htable;
00164 *pstatus = REGRESSION_TEST_PASSED;
00165 }
00166
00167
00168
00169
00170
00171
00172
00173 struct CCFailHistoryTestCont: public Continuation
00174 {
00175 enum
00176 { FAIL_WINDOW = 300 };
00177 enum
00178 {
00179 SIMPLE_TEST,
00180 MULTIPLE_THREAD_TEST,
00181 ROTATING_TEST
00182 };
00183 int test_mode;
00184 int final_status;
00185 bool complete;
00186 RegressionTest *test;
00187 int mainEvent(int event, Event * e);
00188 CCFailHistoryTestCont()
00189 : Continuation(new_ProxyMutex()),
00190 test_mode(SIMPLE_TEST), final_status(0), complete(false), failEvents(NULL), entry(NULL)
00191 {
00192 }
00193
00194 CCFailHistoryTestCont(Ptr<ProxyMutex> _mutex, RegressionTest * _test)
00195 : Continuation(_mutex),
00196 test_mode(SIMPLE_TEST),
00197 final_status(REGRESSION_TEST_PASSED), complete(false), test(_test), failEvents(NULL), pending_action(NULL)
00198 {
00199 SET_HANDLER(&CCFailHistoryTestCont::mainEvent);
00200 rule = new CongestionControlRecord;
00201 rule->fail_window = FAIL_WINDOW;
00202 rule->max_connection_failures = 10;
00203 rule->pRecord = new CongestionControlRecord(*rule);
00204 entry = new CongestionEntry("dummy_host", 0, rule->pRecord, 0);
00205 }
00206
00207 ~CCFailHistoryTestCont() {
00208 if (pending_action) {
00209 pending_action->cancel();
00210 }
00211 entry->put();
00212 delete rule;
00213 clear_events();
00214 }
00215
00216 void init_events();
00217 void clear_events();
00218 int check_history(bool print);
00219 int schedule_event(int event, Event * e);
00220
00221 struct FailEvents
00222 {
00223 time_t time;
00224 Link<FailEvents> link;
00225 };
00226 InkAtomicList *failEvents;
00227 CongestionControlRecord *rule;
00228 CongestionEntry *entry;
00229 Action *pending_action;
00230
00231 };
00232
00233 void
00234 CCFailHistoryTestCont::clear_events()
00235 {
00236 if (failEvents) {
00237 CCFailHistoryTestCont::FailEvents * events =
00238 (CCFailHistoryTestCont::FailEvents *) ink_atomiclist_popall(failEvents);
00239 while (events != NULL) {
00240 CCFailHistoryTestCont::FailEvents * next = events->link.next;
00241 delete events;
00242 events = next;
00243 }
00244 delete failEvents;
00245 failEvents = NULL;
00246 }
00247 }
00248
00249 void
00250 CCFailHistoryTestCont::init_events()
00251 {
00252 clear_events();
00253
00254 failEvents = new InkAtomicList;
00255 ink_atomiclist_init(failEvents, "failEvents", (uintptr_t) &((CCFailHistoryTestCont::FailEvents *) 0)->link);
00256
00257 int i, j;
00258 CCFailHistoryTestCont::FailEvents * new_event = NULL;
00259
00260 switch (test_mode) {
00261 case CCFailHistoryTestCont::ROTATING_TEST:
00262 for (i = 0; i < 16384; i++) {
00263 for (j = 0; j < 10; j++) {
00264 new_event = new CCFailHistoryTestCont::FailEvents;
00265
00266 new_event->time = rand() % (FAIL_WINDOW) + j * FAIL_WINDOW;
00267 ink_atomiclist_push(failEvents, new_event);
00268 }
00269 }
00270 break;
00271 case CCFailHistoryTestCont::SIMPLE_TEST:
00272 default:
00273 for (i = 0; i < 65536; i++) {
00274 new_event = new CCFailHistoryTestCont::FailEvents;
00275
00276 new_event->time = rand() % FAIL_WINDOW;
00277 ink_atomiclist_push(failEvents, new_event);
00278 }
00279 }
00280 }
00281
00282 int
00283 CCFailHistoryTestCont::schedule_event(int , Event * )
00284 {
00285 if (failEvents == NULL)
00286 return EVENT_DONE;
00287 CCFailHistoryTestCont::FailEvents * f = (CCFailHistoryTestCont::FailEvents *) ink_atomiclist_pop(failEvents);
00288 if (f != NULL) {
00289 entry->failed_at(f->time);
00290 delete f;
00291 return EVENT_CONT;
00292 }
00293 return EVENT_DONE;
00294 }
00295
00296 int
00297 CCFailHistoryTestCont::check_history(bool print)
00298 {
00299 if (print) {
00300 rprintf(test, "Verify the result\n");
00301 rprintf(test, "Content of history\n");
00302 int e = 0;
00303 for (int i = 0; i < CONG_HIST_ENTRIES; i++) {
00304 e += entry->m_history.bins[i];
00305 rprintf(test, "bucket %d => events %d , sum = %d\n", i, entry->m_history.bins[i], e);
00306 }
00307 fprintf(stderr, "Events: %d, CurIndex: %d, LastEvent: %ld, HistLen: %d, BinLen: %d, Start: %ld\n",
00308 entry->m_history.events,
00309 entry->m_history.cur_index,
00310 entry->m_history.last_event, entry->m_history.length, entry->m_history.bin_len, entry->m_history.start);
00311 char buf[1024];
00312 entry->sprint(buf, 1024, 10);
00313 rprintf(test, "%s", buf);
00314 }
00315 if (test_mode == CCFailHistoryTestCont::SIMPLE_TEST && entry->m_history.events == 65536)
00316 return 0;
00317 return 0;
00318 }
00319
00320 int
00321 CCFailHistoryTestCont::mainEvent(int , Event * )
00322 {
00323 test_mode = CCFailHistoryTestCont::SIMPLE_TEST;
00324 init_events();
00325 entry->init(rule->pRecord);
00326 while (schedule_event(0, NULL) == EVENT_CONT);
00327 if (check_history(true) == 0) {
00328 final_status = REGRESSION_TEST_PASSED;
00329 } else {
00330 final_status = REGRESSION_TEST_FAILED;
00331 goto Ldone;
00332 }
00333
00334 test_mode = CCFailHistoryTestCont::ROTATING_TEST;
00335 init_events();
00336 entry->init(rule->pRecord);
00337 while (schedule_event(0, NULL) == EVENT_CONT);
00338 if (check_history(true) == 0) {
00339 final_status = REGRESSION_TEST_PASSED;
00340 } else {
00341 final_status = REGRESSION_TEST_FAILED;
00342 goto Ldone;
00343 }
00344
00345 Ldone:
00346 complete = true;
00347 if (complete) {
00348 test->status = final_status;
00349 delete this;
00350 return EVENT_DONE;
00351 }
00352 return EVENT_CONT;
00353 }
00354
00355 EXCLUSIVE_REGRESSION_TEST(Congestion_FailHistory) (RegressionTest * t, int , int *pstatus)
00356 {
00357 CCFailHistoryTestCont *test = new CCFailHistoryTestCont(make_ptr(new_ProxyMutex()), t);
00358 eventProcessor.schedule_in(test, HRTIME_SECONDS(1));
00359 *pstatus = REGRESSION_TEST_INPROGRESS;
00360 }
00361
00362
00363
00364
00365
00366
00367
00368
00369 struct CCCongestionDBTestCont: public Continuation
00370 {
00371 int final_status;
00372 bool complete;
00373 RegressionTest *test;
00374
00375 int mainEvent(int event, Event * e);
00376
00377 void init();
00378 int get_congest_list();
00379 CongestionControlRecord *rule;
00380 CongestionDB *db;
00381 int dbsize;
00382 CongestionEntry *gen_CongestionEntry(sockaddr const* ip, int congested = 0);
00383
00384
00385 CCCongestionDBTestCont(Ptr<ProxyMutex> _mutex, RegressionTest * _test):Continuation(_mutex),
00386 final_status(REGRESSION_TEST_PASSED), complete(false), test(_test), rule(NULL), db(NULL), dbsize(1024)
00387 {
00388 SET_HANDLER(&CCCongestionDBTestCont::mainEvent);
00389 }
00390 virtual ~ CCCongestionDBTestCont()
00391 {
00392 if (db) {
00393 db->removeAllRecords();
00394 delete db;
00395 }
00396 if (rule)
00397 delete rule;
00398 }
00399 };
00400
00401 CongestionEntry *
00402 CCCongestionDBTestCont::gen_CongestionEntry(sockaddr const* ip, int congested)
00403 {
00404 char hostname[INET6_ADDRSTRLEN];
00405 uint64_t key;
00406 ats_ip_ntop(ip, hostname, sizeof(hostname));
00407 key = make_key(hostname, strlen(hostname), ip, rule->pRecord);
00408 CongestionEntry *ret = new CongestionEntry(hostname,
00409 ip,
00410 rule->pRecord,
00411 key);
00412 ret->m_congested = congested;
00413 ret->m_ref_count = 0;
00414 return ret;
00415 }
00416
00417 void
00418 CCCongestionDBTestCont::init()
00419 {
00420
00421 if (!db)
00422 db = new CongestionDB(dbsize / MT_HASHTABLE_PARTITIONS);
00423 else
00424 db->removeAllRecords();
00425 if (!rule) {
00426 rule = new CongestionControlRecord;
00427 rule->fail_window = 300;
00428 rule->max_connection_failures = 10;
00429 rule->pRecord = new CongestionControlRecord(*rule);
00430 }
00431
00432 }
00433
00434 int
00435 CCCongestionDBTestCont::get_congest_list()
00436 {
00437 int cnt = 0;
00438 if (db == NULL)
00439 return 0;
00440 for (int i = 0; i < db->getSize(); i++) {
00441 db->RunTodoList(i);
00442 char buf[1024];
00443 Iter it;
00444
00445 CongestionEntry *pEntry = db->first_entry(i, &it);
00446 while (pEntry) {
00447 cnt++;
00448 if (cnt % 100 == 0) {
00449 pEntry->sprint(buf, 1024, 100);
00450 fprintf(stderr, "%s", buf);
00451 }
00452 pEntry = db->next_entry(i, &it);
00453 }
00454 }
00455 return cnt;
00456 }
00457
00458 int
00459 CCCongestionDBTestCont::mainEvent(int , Event * )
00460 {
00461 int to_add = 1 * 1024 * 1024;
00462 int i;
00463 int items[10] = { 0 };
00464 init();
00465 rprintf(test, "Add %d records into the db", dbsize);
00466
00467 for (i = 0; i < dbsize; i++) {
00468 if (i % (dbsize / 25) == 0)
00469 fprintf(stderr, ".");
00470
00471 IpEndpoint ip;
00472 ats_ip4_set(&ip, i + 255);
00473
00474 CongestionEntry *tmp = gen_CongestionEntry(&ip.sa);
00475 db->addRecord(tmp->m_key, tmp);
00476 }
00477 fprintf(stderr, "done\n");
00478
00479 items[0] = get_congest_list();
00480
00481 db->removeAllRecords();
00482
00483 rprintf(test, "There are %d records in the db\n", items[0]);
00484
00485
00486 rprintf(test, "Add %d records into the db", to_add);
00487 for (i = 0; i < to_add; i++) {
00488 if (i % (to_add / 25) == 0)
00489 fprintf(stderr, ".");
00490
00491 IpEndpoint ip;
00492 ats_ip4_set(&ip, i + 255);
00493 CongestionEntry *tmp = gen_CongestionEntry(&ip.sa);
00494 db->addRecord(tmp->m_key, tmp);
00495 }
00496
00497 items[1] = get_congest_list();
00498
00499 db->removeAllRecords();
00500
00501 rprintf(test, "There are %d records in the db\n", items[1]);
00502
00503 rprintf(test, "Add %d congested records into the db", to_add);
00504
00505 for (i = 0; i < to_add; i++) {
00506 if (i % (to_add / 25) == 0)
00507 fprintf(stderr, ".");
00508
00509 IpEndpoint ip;
00510 ats_ip4_set(&ip, i + 255);
00511
00512 CongestionEntry *tmp = gen_CongestionEntry(&ip.sa, 1);
00513 db->addRecord(tmp->m_key, tmp);
00514 }
00515 items[2] = get_congest_list();
00516 rprintf(test, "There are %d records in the db\n", items[2]);
00517
00518 db->removeAllRecords();
00519
00520 for (i = 0; i < 3; i++) {
00521 rprintf(test, "After test [%d] there are %d records in the db\n", i + 1, items[i]);
00522 }
00523
00524 complete = true;
00525 if (complete) {
00526 test->status = final_status;
00527 delete this;
00528 return EVENT_DONE;
00529 }
00530 return EVENT_CONT;
00531 }
00532
00533 EXCLUSIVE_REGRESSION_TEST(Congestion_CongestionDB) (RegressionTest * t, int , int *pstatus)
00534 {
00535 CCCongestionDBTestCont *test = new CCCongestionDBTestCont(make_ptr(new_ProxyMutex()), t);
00536 eventProcessor.schedule_in(test, HRTIME_SECONDS(1));
00537 *pstatus = REGRESSION_TEST_INPROGRESS;
00538 }
00539
00540
00541
00542
00543
00544
00545
00546
00547 void
00548 init_CongestionRegressionTest()
00549 {
00550 (void) regressionTest_Congestion_HashTable;
00551 (void) regressionTest_Congestion_FailHistory;
00552 (void) regressionTest_Congestion_CongestionDB;
00553 }