00001 
00002 
00003 
00004 
00005 
00006 
00007 
00008 
00009 
00010 
00011 
00012 
00013 
00014 
00015 
00016 
00017 
00018 
00019 
00020 
00021 
00022 
00023 
00024 #include "P_Cache.h"
00025 
00026 Action *
00027 Cache::link(Continuation * cont, CacheKey * from, CacheKey * to, CacheFragType type, char *hostname, int host_len)
00028 {
00029 
00030   if (!CacheProcessor::IsCacheReady(type)) {
00031     cont->handleEvent(CACHE_EVENT_LINK_FAILED, 0);
00032     return ACTION_RESULT_DONE;
00033   }
00034 
00035   ink_assert(caches[type] == this);
00036 
00037   CacheVC *c = new_CacheVC(cont);
00038   c->vol = key_to_vol(from, hostname, host_len);
00039   c->write_len = sizeof(*to);   
00040   c->f.use_first_key = 1;
00041   c->first_key = *from;
00042   c->earliest_key = *to;
00043 
00044   c->buf = new_IOBufferData(BUFFER_SIZE_INDEX_512);
00045 #ifdef DEBUG
00046   Doc *doc = (Doc *) c->buf->data();
00047   memcpy(doc->data(), to, sizeof(*to)); 
00048 #endif
00049 
00050   SET_CONTINUATION_HANDLER(c, &CacheVC::linkWrite);
00051 
00052   if (c->do_write_lock() == EVENT_DONE)
00053     return ACTION_RESULT_DONE;
00054   else
00055     return &c->_action;
00056 }
00057 
00058 int
00059 CacheVC::linkWrite(int event, Event * )
00060 {
00061   ink_assert(event == AIO_EVENT_DONE);
00062   set_io_not_in_progress();
00063   dir_insert(&first_key, vol, &dir);
00064   if (_action.cancelled)
00065     goto Ldone;
00066   if (io.ok())
00067     _action.continuation->handleEvent(CACHE_EVENT_LINK, NULL);
00068   else
00069     _action.continuation->handleEvent(CACHE_EVENT_LINK_FAILED, NULL);
00070 Ldone:
00071   return free_CacheVC(this);
00072 }
00073 
00074 Action *
00075 Cache::deref(Continuation * cont, CacheKey * key, CacheFragType type, char *hostname, int host_len)
00076 {
00077 
00078   if (!CacheProcessor::IsCacheReady(type)) {
00079     cont->handleEvent(CACHE_EVENT_DEREF_FAILED, 0);
00080     return ACTION_RESULT_DONE;
00081   }
00082 
00083   ink_assert(caches[type] == this);
00084 
00085   Vol *vol = key_to_vol(key, hostname, host_len);
00086   Dir result;
00087   Dir *last_collision = NULL;
00088   CacheVC *c = NULL;
00089   {
00090     MUTEX_TRY_LOCK(lock, vol->mutex, cont->mutex->thread_holding);
00091     if (lock) {
00092       if (!dir_probe(key, vol, &result, &last_collision)) {
00093         cont->handleEvent(CACHE_EVENT_DEREF_FAILED, (void *) -ECACHE_NO_DOC);
00094         return ACTION_RESULT_DONE;
00095       }
00096     }
00097     c = new_CacheVC(cont);
00098     SET_CONTINUATION_HANDLER(c, &CacheVC::derefRead);
00099     c->first_key = c->key = *key;
00100     c->vol = vol;
00101     c->dir = result;
00102     c->last_collision = last_collision;
00103 
00104     if (!lock) {
00105       c->mutex->thread_holding->schedule_in_local(c, HRTIME_MSECONDS(cache_config_mutex_retry_delay));
00106       return &c->_action;
00107     }
00108 
00109     switch (c->do_read_call(&c->key)) {
00110       case EVENT_DONE: return ACTION_RESULT_DONE;
00111       case EVENT_RETURN: goto Lcallreturn;
00112       default: return &c->_action;
00113     }
00114   }
00115 Lcallreturn:
00116   if (c->handleEvent(AIO_EVENT_DONE, 0) == EVENT_DONE)
00117     return ACTION_RESULT_DONE;
00118   else
00119     return &c->_action;
00120 }
00121 
00122 int
00123 CacheVC::derefRead(int , Event * )
00124 {
00125   Doc *doc = NULL;
00126 
00127   cancel_trigger();
00128   set_io_not_in_progress();
00129   if (_action.cancelled)
00130     return free_CacheVC(this);
00131   if (!buf)
00132     goto Lcollision;
00133   if ((int) io.aio_result != (int) io.aiocb.aio_nbytes)
00134     goto Ldone;
00135   if (!dir_agg_valid(vol, &dir)) {
00136     last_collision = NULL;
00137     goto Lcollision;
00138   }
00139   doc = (Doc *) buf->data();
00140   if (!(doc->first_key == key))
00141     goto Lcollision;
00142 #ifdef DEBUG
00143   ink_assert(!memcmp(doc->data(), &doc->key, sizeof(doc->key)));
00144 #endif
00145   _action.continuation->handleEvent(CACHE_EVENT_DEREF, (void *) &doc->key);
00146   return free_CacheVC(this);
00147 
00148 Lcollision:{
00149     CACHE_TRY_LOCK(lock, vol->mutex, mutex->thread_holding);
00150     if (!lock) {
00151       mutex->thread_holding->schedule_in_local(this, HRTIME_MSECONDS(cache_config_mutex_retry_delay));
00152       return EVENT_CONT;
00153     }
00154     if (dir_probe(&key, vol, &dir, &last_collision)) {
00155       int ret = do_read_call(&first_key);
00156       if (ret == EVENT_RETURN)
00157         goto Lcallreturn;
00158       return ret;
00159     }
00160   }
00161 Ldone:
00162   _action.continuation->handleEvent(CACHE_EVENT_DEREF_FAILED, (void *) -ECACHE_NO_DOC);
00163   return free_CacheVC(this);
00164 Lcallreturn:
00165   return handleEvent(AIO_EVENT_DONE, 0); 
00166 }