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
00031
00032
00033 #include "HttpCacheSM.h"
00034 #include "HttpSM.h"
00035 #include "HttpDebugNames.h"
00036
00037 #define STATE_ENTER(state_name, event) { \
00038 REMEMBER(event, -1); \
00039 Debug("http_cache", "[%" PRId64 "] [%s, %s]", master_sm->sm_id, \
00040 #state_name, HttpDebugNames::get_event_name(event)); }
00041
00042 #define __REMEMBER(x) #x
00043 #define _REMEMBER(x) __REMEMBER(x)
00044
00045 #define REMEMBER(e,r) master_sm->add_history_entry(__FILE__ ":" _REMEMBER (__LINE__), e, r);
00046
00047
00048 HttpCacheAction::HttpCacheAction()
00049 : sm(NULL)
00050 {
00051 }
00052
00053 void
00054 HttpCacheAction::cancel(Continuation * c)
00055 {
00056 ink_assert(c == NULL || c == sm->master_sm);
00057 ink_assert(this->cancelled == 0);
00058
00059 this->cancelled = 1;
00060 if (sm->pending_action)
00061 sm->pending_action->cancel();
00062 }
00063
00064 HttpCacheSM::HttpCacheSM():
00065 Continuation(NULL),
00066 cache_read_vc(NULL), cache_write_vc(NULL),
00067 read_locked(false), write_locked(false),
00068 readwhilewrite_inprogress(false),
00069 master_sm(NULL), pending_action(NULL),
00070 captive_action(),
00071 open_read_cb(false), open_write_cb(false), open_read_tries(0),
00072 read_request_hdr(NULL), read_config(NULL),
00073 read_pin_in_cache(0), retry_write(true), open_write_tries(0),
00074 lookup_url(NULL), lookup_max_recursive(0), current_lookup_level(0)
00075 {
00076 }
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105 int
00106 HttpCacheSM::state_cache_open_read(int event, void *data)
00107 {
00108 STATE_ENTER(&HttpCacheSM::state_cache_open_read, event);
00109 ink_assert(captive_action.cancelled == 0);
00110 pending_action = NULL;
00111
00112 switch (event) {
00113 case CACHE_EVENT_OPEN_READ:
00114 HTTP_INCREMENT_DYN_STAT(http_current_cache_connections_stat);
00115 ink_assert(cache_read_vc == NULL);
00116 open_read_cb = true;
00117 cache_read_vc = (CacheVConnection *) data;
00118 master_sm->handleEvent(event, data);
00119 break;
00120
00121 case CACHE_EVENT_OPEN_READ_FAILED:
00122 if (data == (void *) -ECACHE_DOC_BUSY) {
00123
00124 if (open_read_tries <= master_sm->t_state.txn_conf->max_cache_open_read_retries) {
00125
00126 open_read_cb = false;
00127 do_schedule_in();
00128 } else {
00129
00130
00131 open_read_cb = true;
00132 master_sm->handleEvent(event, data);
00133 }
00134 } else {
00135
00136 open_read_cb = true;
00137 master_sm->handleEvent(event, data);
00138 }
00139 break;
00140
00141 case EVENT_INTERVAL:
00142
00143
00144
00145 ink_assert(open_read_tries <= master_sm->t_state.txn_conf->max_cache_open_read_retries || write_locked);
00146 Debug("http_cache", "[%" PRId64 "] [state_cache_open_read] cache open read failure %d. "
00147 "retrying cache open read...", master_sm->sm_id, open_read_tries);
00148
00149 do_cache_open_read();
00150 break;
00151
00152 default:
00153 ink_assert(0);
00154 }
00155
00156 return VC_EVENT_CONT;
00157 }
00158
00159 int
00160 HttpCacheSM::state_cache_open_write(int event, void *data)
00161 {
00162 STATE_ENTER(&HttpCacheSM::state_cache_open_write, event);
00163 ink_assert(captive_action.cancelled == 0);
00164 pending_action = NULL;
00165
00166 switch (event) {
00167 case CACHE_EVENT_OPEN_WRITE:
00168 HTTP_INCREMENT_DYN_STAT(http_current_cache_connections_stat);
00169 ink_assert(cache_write_vc == NULL);
00170 cache_write_vc = (CacheVConnection *) data;
00171 open_write_cb = true;
00172 master_sm->handleEvent(event, data);
00173 break;
00174
00175 case CACHE_EVENT_OPEN_WRITE_FAILED:
00176
00177
00178 open_write_cb = true;
00179 master_sm->handleEvent(event, data);
00180 break;
00181
00182 default:
00183 ink_release_assert(0);
00184 }
00185
00186 return VC_EVENT_CONT;
00187 }
00188
00189 void
00190 HttpCacheSM::do_schedule_in()
00191 {
00192 ink_assert(pending_action == NULL);
00193 Action *action_handle =
00194 mutex->thread_holding->schedule_in(this, HRTIME_MSECONDS(master_sm->t_state.txn_conf->cache_open_read_retry_time));
00195
00196 if (action_handle != ACTION_RESULT_DONE) {
00197 pending_action = action_handle;
00198 }
00199
00200 return;
00201 }
00202
00203 Action *
00204 HttpCacheSM::do_cache_open_read()
00205 {
00206 open_read_tries++;
00207 ink_assert(pending_action == NULL);
00208 if (write_locked) {
00209 open_read_cb = false;
00210 } else {
00211 ink_assert(open_read_cb == false);
00212 }
00213
00214 this->readwhilewrite_inprogress = false;
00215 Action *action_handle = cacheProcessor.open_read(this, this->lookup_url, master_sm->t_state.cache_control.cluster_cache_local, this->read_request_hdr, this->read_config,
00216 this->read_pin_in_cache);
00217
00218 if (action_handle != ACTION_RESULT_DONE) {
00219 pending_action = action_handle;
00220 }
00221
00222
00223
00224
00225 if (open_read_cb == true) {
00226 return ACTION_RESULT_DONE;
00227 } else {
00228 ink_assert(pending_action != NULL || write_locked == true);
00229 return &captive_action;
00230 }
00231 }
00232
00233 Action *
00234 HttpCacheSM::open_read(URL * url, HTTPHdr * hdr, CacheLookupHttpConfig * params, time_t pin_in_cache)
00235 {
00236 Action *act_return;
00237
00238 lookup_url = url;
00239 read_request_hdr = hdr;
00240 read_config = params;
00241 read_pin_in_cache = pin_in_cache;
00242 ink_assert(pending_action == NULL);
00243 SET_HANDLER(&HttpCacheSM::state_cache_open_read);
00244
00245 lookup_max_recursive++;
00246 current_lookup_level++;
00247 open_read_cb = false;
00248 act_return = do_cache_open_read();
00249
00250
00251
00252 if (current_lookup_level == lookup_max_recursive) {
00253 current_lookup_level--;
00254 ink_assert(current_lookup_level >= 0);
00255 if (current_lookup_level == 0) {
00256 lookup_max_recursive = 0;
00257 }
00258 return act_return;
00259 } else {
00260 ink_assert(current_lookup_level < lookup_max_recursive);
00261 current_lookup_level--;
00262
00263 if (current_lookup_level == 0)
00264 lookup_max_recursive = 0;
00265
00266 return ACTION_RESULT_DONE;
00267 }
00268 }
00269
00270 Action *
00271 HttpCacheSM::open_write(URL * url, HTTPHdr * request, CacheHTTPInfo * old_info, time_t pin_in_cache,
00272 bool retry, bool allow_multiple)
00273 {
00274 SET_HANDLER(&HttpCacheSM::state_cache_open_write);
00275 ink_assert(pending_action == NULL);
00276 ink_assert(cache_write_vc == NULL);
00277
00278 open_write_cb = false;
00279 open_write_tries++;
00280 this->retry_write = retry;
00281
00282
00283
00284
00285
00286 ink_assert(request == read_request_hdr || read_request_hdr == NULL);
00287 this->lookup_url = url;
00288 this->read_request_hdr = request;
00289
00290
00291
00292
00293
00294
00295 if (open_write_tries > master_sm->redirection_tries &&
00296 open_write_tries > master_sm->t_state.http_config_param->max_cache_open_write_retries) {
00297 master_sm->handleEvent(CACHE_EVENT_OPEN_WRITE_FAILED, (void *) -ECACHE_DOC_BUSY);
00298 return ACTION_RESULT_DONE;
00299 }
00300
00301 Action *action_handle = cacheProcessor.open_write(this,
00302 0,
00303 url,
00304 master_sm->t_state.cache_control.cluster_cache_local,
00305 request,
00306
00307 allow_multiple ? (CacheHTTPInfo *) CACHE_ALLOW_MULTIPLE_WRITES :
00308 old_info,
00309 pin_in_cache);
00310
00311 if (action_handle != ACTION_RESULT_DONE) {
00312 pending_action = action_handle;
00313 }
00314
00315
00316
00317
00318 if (open_write_cb == true) {
00319 return ACTION_RESULT_DONE;
00320 } else {
00321 ink_assert(pending_action != NULL);
00322 return &captive_action;
00323 }
00324 }