• Main Page
  • Related Pages
  • Namespaces
  • Data Structures
  • Files
  • File List
  • Globals

CacheTest.cc

Go to the documentation of this file.
00001 /** @file
00002 
00003   A brief file description
00004 
00005   @section license License
00006 
00007   Licensed to the Apache Software Foundation (ASF) under one
00008   or more contributor license agreements.  See the NOTICE file
00009   distributed with this work for additional information
00010   regarding copyright ownership.  The ASF licenses this file
00011   to you under the Apache License, Version 2.0 (the
00012   "License"); you may not use this file except in compliance
00013   with the License.  You may obtain a copy of the License at
00014 
00015       http://www.apache.org/licenses/LICENSE-2.0
00016 
00017   Unless required by applicable law or agreed to in writing, software
00018   distributed under the License is distributed on an "AS IS" BASIS,
00019   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00020   See the License for the specific language governing permissions and
00021   limitations under the License.
00022 
00023  */
00024 
00025 #include "P_Cache.h"
00026 #include "P_CacheTest.h"
00027 #include "api/ts/ts.h"
00028 
00029 CacheTestSM::CacheTestSM(RegressionTest *t) :
00030   RegressionSM(t),
00031   timeout(0),
00032   cache_action(0),
00033   start_time(0),
00034   cache_vc(0),
00035   cvio(0),
00036   buffer(0),
00037   buffer_reader(0),
00038   nbytes(-1),
00039   repeat_count(0),
00040   expect_event(EVENT_NONE),
00041   expect_initial_event(EVENT_NONE),
00042   initial_event(EVENT_NONE),
00043   content_salt(0)
00044 {
00045   SET_HANDLER(&CacheTestSM::event_handler);
00046 }
00047 
00048 CacheTestSM::~CacheTestSM() {
00049   ink_assert(!cache_action);
00050   ink_assert(!cache_vc);
00051   if (buffer_reader)
00052     buffer->dealloc_reader(buffer_reader);
00053   if (buffer)
00054     free_MIOBuffer(buffer);
00055 }
00056 
00057 int CacheTestSM::open_read_callout() {
00058   cvio = cache_vc->do_io_read(this, nbytes, buffer);
00059   return 1;
00060 }
00061 
00062 int CacheTestSM::open_write_callout() {
00063   cvio = cache_vc->do_io_write(this, nbytes, buffer_reader);
00064   return 1;
00065 }
00066 
00067 int CacheTestSM::event_handler(int event, void *data) {
00068 
00069   switch (event) {
00070 
00071     case EVENT_INTERVAL:
00072     case EVENT_IMMEDIATE:
00073       cancel_timeout();
00074       if (cache_action) {
00075         cache_action->cancel();
00076         cache_action = 0;
00077       }
00078       if (cache_vc) {
00079         cache_vc->do_io_close();
00080         cache_vc = 0;
00081       }
00082       cvio = 0;
00083       make_request();
00084       return EVENT_DONE;
00085 
00086     case CACHE_EVENT_LOOKUP_FAILED:
00087     case CACHE_EVENT_LOOKUP:
00088       goto Lcancel_next;
00089 
00090     case CACHE_EVENT_OPEN_READ:
00091       initial_event = event;
00092       cancel_timeout();
00093       cache_action = 0;
00094       cache_vc = (CacheVConnection*)data;
00095       buffer = new_empty_MIOBuffer();
00096       buffer_reader = buffer->alloc_reader();
00097       if (open_read_callout() < 0)
00098         goto Lclose_error_next;
00099       else
00100         return EVENT_DONE;
00101 
00102     case CACHE_EVENT_OPEN_READ_FAILED:
00103       goto Lcancel_next;
00104 
00105     case VC_EVENT_READ_READY:
00106       if (!check_buffer())
00107         goto Lclose_error_next;
00108       buffer_reader->consume(buffer_reader->read_avail());
00109       ((VIO*)data)->reenable();
00110       return EVENT_CONT;
00111 
00112     case VC_EVENT_READ_COMPLETE:
00113       if (!check_buffer())
00114         goto Lclose_error_next;
00115       goto Lclose_next;
00116 
00117     case VC_EVENT_ERROR:
00118     case VC_EVENT_EOS:
00119       goto Lclose_error_next;
00120 
00121     case CACHE_EVENT_OPEN_WRITE:
00122       initial_event = event;
00123       cancel_timeout();
00124       cache_action = 0;
00125       cache_vc = (CacheVConnection*)data;
00126       buffer = new_empty_MIOBuffer();
00127       buffer_reader = buffer->alloc_reader();
00128       if (open_write_callout() < 0)
00129         goto Lclose_error_next;
00130       else
00131         return EVENT_DONE;
00132 
00133     case CACHE_EVENT_OPEN_WRITE_FAILED:
00134       goto Lcancel_next;
00135 
00136     case VC_EVENT_WRITE_READY:
00137       fill_buffer();
00138       cvio->reenable();
00139       return EVENT_CONT;
00140 
00141     case VC_EVENT_WRITE_COMPLETE:
00142       if (nbytes != cvio->ndone)
00143         goto Lclose_error_next;
00144       goto Lclose_next;
00145 
00146     case CACHE_EVENT_REMOVE:
00147     case CACHE_EVENT_REMOVE_FAILED:
00148       goto Lcancel_next;
00149 
00150     case CACHE_EVENT_SCAN:
00151       initial_event = event;
00152       cache_vc = (CacheVConnection*)data;
00153       return EVENT_CONT;
00154 
00155     case CACHE_EVENT_SCAN_OBJECT:
00156       return CACHE_SCAN_RESULT_CONTINUE;
00157 
00158     case CACHE_EVENT_SCAN_OPERATION_FAILED:
00159       return CACHE_SCAN_RESULT_CONTINUE;
00160 
00161     case CACHE_EVENT_SCAN_OPERATION_BLOCKED:
00162       return CACHE_SCAN_RESULT_CONTINUE;
00163 
00164     case CACHE_EVENT_SCAN_DONE:
00165       return EVENT_CONT;
00166 
00167     case CACHE_EVENT_SCAN_FAILED:
00168       return EVENT_CONT;
00169 
00170     case AIO_EVENT_DONE:
00171       goto Lnext;
00172 
00173     default:
00174       ink_assert(!"case");
00175       break;
00176   }
00177   return EVENT_DONE;
00178 
00179 Lcancel_next:
00180   cancel_timeout();
00181   cache_action = 0;
00182   goto Lnext;
00183 Lclose_error_next:
00184   cache_vc->do_io_close(1);
00185   goto Lclose_next_internal;
00186 Lclose_next:
00187   cache_vc->do_io_close();
00188 Lclose_next_internal:
00189   cache_vc = 0;
00190   if (buffer_reader) {
00191     buffer->dealloc_reader(buffer_reader);
00192     buffer_reader = 0;
00193   }
00194   if (buffer) {
00195     free_MIOBuffer(buffer);
00196     buffer = 0;
00197   }
00198 Lnext:
00199   if (check_result(event) && repeat_count) {
00200     repeat_count--;
00201     timeout = eventProcessor.schedule_imm(this);
00202     return EVENT_DONE;
00203   } else
00204     return complete(event);
00205 }
00206 
00207 void CacheTestSM::fill_buffer() {
00208   int64_t avail = buffer->write_avail();
00209   CacheKey k = key;
00210   k.b[1] += content_salt;
00211   int64_t sk = (int64_t)sizeof(key);
00212   while (avail > 0) {
00213     int64_t l = avail;
00214     if (l > sk)
00215       l = sk;
00216 
00217     int64_t pos = cvio->ndone +  buffer_reader->read_avail();
00218     int64_t o = pos % sk;
00219 
00220     if (l > sk - o)
00221       l = sk - o;
00222     k.b[0] = pos / sk;
00223     char *x = ((char*)&k) + o;
00224     buffer->write(x, l);
00225     buffer->fill(l);
00226     avail -= l;
00227   }
00228 }
00229 
00230 int CacheTestSM::check_buffer() {
00231   int64_t avail = buffer_reader->read_avail();
00232   CacheKey k = key;
00233   k.b[1] += content_salt;
00234   char b[sizeof(key)];
00235   int64_t sk = (int64_t)sizeof(key);
00236   int64_t pos = cvio->ndone -  buffer_reader->read_avail();
00237   while (avail > 0) {
00238     int64_t l = avail;
00239     if (l > sk)
00240       l = sk;
00241     int64_t o = pos % sk;
00242     if (l > sk - o)
00243       l = sk - o;
00244     k.b[0] = pos / sk;
00245     char *x = ((char*)&k) + o;
00246     buffer_reader->read(&b[0], l);
00247     if (::memcmp(b, x, l))
00248       return 0;
00249     buffer_reader->consume(l);
00250     pos += l;
00251     avail -= l;
00252   }
00253   return 1;
00254 }
00255 
00256 int CacheTestSM::check_result(int event) {
00257   return
00258     initial_event == expect_initial_event &&
00259     event == expect_event;
00260 }
00261 
00262 int CacheTestSM::complete(int event) {
00263   if (!check_result(event))
00264     done(REGRESSION_TEST_FAILED);
00265   else
00266     done(REGRESSION_TEST_PASSED);
00267   delete this;
00268   return EVENT_DONE;
00269 }
00270 
00271 CacheTestSM::CacheTestSM(const CacheTestSM &ao) : RegressionSM(ao) {
00272   int o = (int)(((char*)&start_memcpy_on_clone) - ((char*)this));
00273   int s = (int)(((char*)&end_memcpy_on_clone) - ((char*)&start_memcpy_on_clone));
00274   memcpy(((char*)this)+o, ((char*)&ao)+o, s);
00275   SET_HANDLER(&CacheTestSM::event_handler);
00276 }
00277 
00278 EXCLUSIVE_REGRESSION_TEST(cache)(RegressionTest *t, int /* atype ATS_UNUSED */, int *pstatus) {
00279   if (cacheProcessor.IsCacheEnabled() != CACHE_INITIALIZED) {
00280     rprintf(t, "cache not initialized");
00281     *pstatus = REGRESSION_TEST_FAILED;
00282     return;
00283   }
00284 
00285   EThread *thread = this_ethread();
00286 
00287   CACHE_SM(t, write_test, { cacheProcessor.open_write(
00288         this, &key, false, CACHE_FRAG_TYPE_NONE, 100,
00289         CACHE_WRITE_OPT_SYNC); } );
00290   write_test.expect_initial_event = CACHE_EVENT_OPEN_WRITE;
00291   write_test.expect_event = VC_EVENT_WRITE_COMPLETE;
00292   write_test.nbytes = 100;
00293   rand_CacheKey(&write_test.key, thread->mutex);
00294 
00295   CACHE_SM(t, lookup_test, { cacheProcessor.lookup(this, &key, false); } );
00296   lookup_test.expect_event = CACHE_EVENT_LOOKUP;
00297   lookup_test.key = write_test.key;
00298 
00299   CACHE_SM(t, read_test, { cacheProcessor.open_read(this, &key, false); } );
00300   read_test.expect_initial_event = CACHE_EVENT_OPEN_READ;
00301   read_test.expect_event = VC_EVENT_READ_COMPLETE;
00302   read_test.nbytes = 100;
00303   read_test.key = write_test.key;
00304 
00305   CACHE_SM(t, remove_test, { cacheProcessor.remove(this, &key, false); } );
00306   remove_test.expect_event = CACHE_EVENT_REMOVE;
00307   remove_test.key = write_test.key;
00308 
00309   CACHE_SM(t, lookup_fail_test, { cacheProcessor.lookup(this, &key, false); } );
00310   lookup_fail_test.expect_event = CACHE_EVENT_LOOKUP_FAILED;
00311   lookup_fail_test.key = write_test.key;
00312 
00313   CACHE_SM(t, read_fail_test, { cacheProcessor.open_read(this, &key, false); } );
00314   read_fail_test.expect_event = CACHE_EVENT_OPEN_READ_FAILED;
00315   read_fail_test.key = write_test.key;
00316 
00317   CACHE_SM(t, remove_fail_test, { cacheProcessor.remove(this, &key, false); } );
00318   remove_fail_test.expect_event = CACHE_EVENT_REMOVE_FAILED;
00319   rand_CacheKey(&remove_fail_test.key, thread->mutex);
00320 
00321   CACHE_SM(t, replace_write_test, {
00322       cacheProcessor.open_write(this, &key, false, CACHE_FRAG_TYPE_NONE, 100,
00323                                 CACHE_WRITE_OPT_SYNC);
00324     }
00325     int open_write_callout() {
00326       header.serial = 10;
00327       cache_vc->set_header(&header, sizeof(header));
00328       cvio = cache_vc->do_io_write(this, nbytes, buffer_reader);
00329       return 1;
00330     });
00331   replace_write_test.expect_initial_event = CACHE_EVENT_OPEN_WRITE;
00332   replace_write_test.expect_event = VC_EVENT_WRITE_COMPLETE;
00333   replace_write_test.nbytes = 100;
00334   rand_CacheKey(&replace_write_test.key, thread->mutex);
00335 
00336   CACHE_SM(t, replace_test, {
00337       cacheProcessor.open_write(this, &key, false, CACHE_FRAG_TYPE_NONE, 100,
00338                                 CACHE_WRITE_OPT_OVERWRITE_SYNC);
00339     }
00340     int open_write_callout() {
00341       CacheTestHeader *h = 0;
00342       int hlen = 0;
00343       if (cache_vc->get_header((void**)&h, &hlen) < 0)
00344         return -1;
00345       if (h->serial != 10)
00346         return -1;
00347       header.serial = 11;
00348       cache_vc->set_header(&header, sizeof(header));
00349       cvio = cache_vc->do_io_write(this, nbytes, buffer_reader);
00350       return 1;
00351     });
00352   replace_test.expect_initial_event = CACHE_EVENT_OPEN_WRITE;
00353   replace_test.expect_event = VC_EVENT_WRITE_COMPLETE;
00354   replace_test.nbytes = 100;
00355   replace_test.key = replace_write_test.key;
00356   replace_test.content_salt = 1;
00357 
00358   CACHE_SM(t, replace_read_test, {
00359       cacheProcessor.open_read(this, &key, false);
00360     }
00361     int open_read_callout() {
00362       CacheTestHeader *h = 0;
00363       int hlen = 0;
00364       if (cache_vc->get_header((void**)&h, &hlen) < 0)
00365         return -1;
00366       if (h->serial != 11)
00367         return -1;
00368       cvio = cache_vc->do_io_read(this, nbytes, buffer);
00369       return 1;
00370     });
00371   replace_read_test.expect_initial_event = CACHE_EVENT_OPEN_READ;
00372   replace_read_test.expect_event = VC_EVENT_READ_COMPLETE;
00373   replace_read_test.nbytes = 100;
00374   replace_read_test.key = replace_test.key;
00375   replace_read_test.content_salt = 1;
00376 
00377   CACHE_SM(t, large_write_test, { cacheProcessor.open_write(
00378         this, &key, false, CACHE_FRAG_TYPE_NONE, 100,
00379         CACHE_WRITE_OPT_SYNC); } );
00380   large_write_test.expect_initial_event = CACHE_EVENT_OPEN_WRITE;
00381   large_write_test.expect_event = VC_EVENT_WRITE_COMPLETE;
00382   large_write_test.nbytes = 10000000;
00383   rand_CacheKey(&large_write_test.key, thread->mutex);
00384 
00385   CACHE_SM(t, pread_test, { 
00386       cacheProcessor.open_read(this, &key, false); 
00387     } 
00388     int open_read_callout() {
00389       cvio = cache_vc->do_io_pread(this, nbytes, buffer, 7000000);
00390       return 1;
00391     });
00392   pread_test.expect_initial_event = CACHE_EVENT_OPEN_READ;
00393   pread_test.expect_event = VC_EVENT_READ_COMPLETE;
00394   pread_test.nbytes = 100;
00395   pread_test.key = large_write_test.key;
00396 
00397   r_sequential(
00398     t,
00399     write_test.clone(),
00400     lookup_test.clone(),
00401     r_sequential(t, 10, read_test.clone()),
00402     remove_test.clone(),
00403     lookup_fail_test.clone(),
00404     read_fail_test.clone(),
00405     remove_fail_test.clone(),
00406     replace_write_test.clone(),
00407     replace_test.clone(),
00408     replace_read_test.clone(),
00409     large_write_test.clone(),
00410     pread_test.clone(),
00411     NULL_PTR
00412     )->run(pstatus);
00413   return;
00414 }
00415 
00416 void force_link_CacheTest() {
00417 }
00418 
00419 // run -R 3 -r cache_disk_replacement_stability
00420 
00421 REGRESSION_TEST(cache_disk_replacement_stability)(RegressionTest *t, int level, int *pstatus) {
00422   static int const MAX_VOLS = 26; // maximum values used in any test.
00423   static uint64_t DEFAULT_SKIP = 8192;
00424   static uint64_t DEFAULT_STRIPE_SIZE = 1024ULL * 1024 * 1024 * 911; // 911G
00425   CacheDisk disk; // Only need one because it's just checked for failure.
00426   CacheHostRecord hr1, hr2;
00427   Vol* sample;
00428   static int const sample_idx = 16;
00429   Vol vols[MAX_VOLS];
00430   Vol* vol_ptrs[MAX_VOLS]; // array of pointers.
00431   char buff[2048];
00432 
00433   // Only run at the highest levels.
00434   if (REGRESSION_TEST_EXTENDED > level) {
00435     *pstatus = REGRESSION_TEST_PASSED;
00436     return;
00437   }
00438 
00439   *pstatus = REGRESSION_TEST_INPROGRESS;
00440 
00441   disk.num_errors = 0;
00442 
00443   for ( int i = 0 ; i < MAX_VOLS ; ++i ) {
00444     vol_ptrs[i] = vols + i;
00445     vols[i].disk = &disk;
00446     vols[i].len = DEFAULT_STRIPE_SIZE;
00447     snprintf(buff, sizeof(buff), "/dev/sd%c %" PRIu64 ":%" PRIu64,
00448              'a' + i, DEFAULT_SKIP, vols[i].len);
00449     MD5Context().hash_immediate(vols[i].hash_id, buff, strlen(buff));
00450   }
00451 
00452   hr1.vol_hash_table = 0;
00453   hr1.vols = vol_ptrs;
00454   hr1.num_vols = MAX_VOLS;
00455   build_vol_hash_table(&hr1);
00456 
00457   hr2.vol_hash_table = 0;
00458   hr2.vols = vol_ptrs;
00459   hr2.num_vols = MAX_VOLS;
00460 
00461   sample = vols + sample_idx;
00462   sample->len = 1024ULL * 1024 * 1024 * (1024+128); // 1.1 TB
00463   snprintf(buff, sizeof(buff), "/dev/sd%c %" PRIu64 ":%" PRIu64,
00464            'a' + sample_idx, DEFAULT_SKIP, sample->len);
00465   MD5Context().hash_immediate(sample->hash_id, buff, strlen(buff));
00466   build_vol_hash_table(&hr2);
00467 
00468   // See what the difference is
00469   int to = 0, from = 0;
00470   int then = 0, now = 0;
00471   for ( int i = 0 ; i < VOL_HASH_TABLE_SIZE ; ++i ) {
00472     if (hr1.vol_hash_table[i] == sample_idx) ++then;
00473     if (hr2.vol_hash_table[i] == sample_idx) ++now;
00474     if (hr1.vol_hash_table[i] != hr2.vol_hash_table[i]) {
00475       if (hr1.vol_hash_table[i] == sample_idx)
00476         ++from;
00477       else
00478         ++to;
00479     }
00480   }
00481   rprintf(t, "Cache stability difference - "
00482           "delta = %d of %d : %d to, %d from, originally %d slots, now %d slots (net gain = %d/%d)\n"
00483           , to+from, VOL_HASH_TABLE_SIZE, to, from, then, now, now-then, to-from
00484     );
00485   *pstatus = REGRESSION_TEST_PASSED;
00486 
00487   hr1.vols = 0;
00488   hr2.vols = 0;
00489 }

Generated by  doxygen 1.7.1