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 }