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 }