Go to the documentation of this file.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
00034
00035
00036 #include "HttpUpdateSM.h"
00037 #include "HttpDebugNames.h"
00038
00039 ClassAllocator<HttpUpdateSM> httpUpdateSMAllocator("httpUpdateSMAllocator");
00040
00041 #define STATE_ENTER(state_name, event, vio) { \
00042 Debug("http", "[%" PRId64 "] [%s, %s]", sm_id, \
00043 #state_name, HttpDebugNames::get_event_name(event)); }
00044
00045 HttpUpdateSM::HttpUpdateSM():
00046 cb_occured(false), cb_cont(NULL), cb_action(), cb_event(HTTP_SCH_UPDATE_EVENT_ERROR)
00047 {
00048 }
00049
00050 void
00051 HttpUpdateSM::destroy()
00052 {
00053 cleanup();
00054 cb_action = NULL;
00055 httpUpdateSMAllocator.free(this);
00056 }
00057
00058 Action *
00059 HttpUpdateSM::start_scheduled_update(Continuation * cont, HTTPHdr * request)
00060 {
00061
00062
00063 this->mutex = cont->mutex;
00064 MUTEX_LOCK(lock, this->mutex, this_ethread());
00065
00066
00067 cb_cont = cont;
00068 cb_action = cont;
00069
00070 start_sub_sm();
00071
00072
00073 t_state.hdr_info.client_request.create(HTTP_TYPE_REQUEST);
00074 t_state.hdr_info.client_request.copy(request);
00075
00076
00077
00078 ats_ip4_set(&t_state.client_info.addr, htonl(INADDR_LOOPBACK), 0);
00079 t_state.backdoor_request = 0;
00080 t_state.client_info.port_attribute = HttpProxyPort::TRANSPORT_DEFAULT;
00081
00082 t_state.req_flavor = HttpTransact::REQ_FLAVOR_SCHEDULED_UPDATE;
00083
00084
00085 http_parser_init(&http_parser);
00086
00087
00088
00089
00090
00091 this->default_handler = &HttpUpdateSM::state_add_to_list;
00092 this->handleEvent(EVENT_NONE, NULL);
00093
00094 if (cb_occured == 0) {
00095 return &cb_action;
00096 } else {
00097 return ACTION_RESULT_DONE;
00098 }
00099 }
00100
00101 void
00102 HttpUpdateSM::handle_api_return()
00103 {
00104
00105 switch (t_state.api_next_action) {
00106 case HttpTransact::SM_ACTION_API_SM_START:
00107 call_transact_and_set_next_state(&HttpTransact::ModifyRequest);
00108 return;
00109 case HttpTransact::SM_ACTION_API_SEND_RESPONSE_HDR:
00110
00111
00112 break;
00113 default:
00114 HttpSM::handle_api_return();
00115 return;
00116 }
00117
00118 switch (t_state.next_action) {
00119 case HttpTransact::SM_ACTION_TRANSFORM_READ:
00120 {
00121 if (t_state.cache_info.transform_action == HttpTransact::CACHE_DO_WRITE) {
00122
00123
00124 HttpTunnelProducer *p = setup_transfer_from_transform_to_cache_only();
00125 tunnel.tunnel_run(p);
00126 } else {
00127
00128
00129
00130 Debug("http", "[%" PRId64 "] [HttpUpdateSM] aborting " "transform since result is not cached", sm_id);
00131 HttpTunnelConsumer *c = tunnel.get_consumer(transform_info.vc);
00132 ink_release_assert(c != NULL);
00133
00134 if (tunnel.is_tunnel_active()) {
00135 default_handler = &HttpUpdateSM::tunnel_handler;
00136 if (c->alive == true) {
00137
00138
00139 tunnel.handleEvent(VC_EVENT_ERROR, c->write_vio);
00140 } else {
00141
00142
00143
00144
00145 ink_assert(transform_info.entry->in_tunnel == false);
00146 }
00147 } else {
00148
00149
00150 ink_assert(transform_info.entry->in_tunnel == false);
00151 terminate_sm = true;
00152 }
00153 }
00154 break;
00155 }
00156 case HttpTransact::SM_ACTION_INTERNAL_CACHE_WRITE:
00157 case HttpTransact::SM_ACTION_SERVER_READ:
00158 case HttpTransact::SM_ACTION_INTERNAL_CACHE_NOOP:
00159 case HttpTransact::SM_ACTION_SEND_ERROR_CACHE_NOOP:
00160 case HttpTransact::SM_ACTION_SERVE_FROM_CACHE:
00161 {
00162 cb_event = HTTP_SCH_UPDATE_EVENT_NOT_CACHED;
00163 t_state.squid_codes.log_code = SQUID_LOG_TCP_MISS;
00164 terminate_sm = true;
00165 return;
00166 }
00167
00168 case HttpTransact::SM_ACTION_INTERNAL_CACHE_DELETE:
00169 case HttpTransact::SM_ACTION_INTERNAL_CACHE_UPDATE_HEADERS:
00170 {
00171 if (t_state.next_action == HttpTransact::SM_ACTION_INTERNAL_CACHE_DELETE) {
00172 cb_event = HTTP_SCH_UPDATE_EVENT_DELETED;
00173 } else {
00174 cb_event = HTTP_SCH_UPDATE_EVENT_UPDATED;
00175 }
00176
00177 perform_cache_write_action();
00178 terminate_sm = true;
00179 return;
00180 }
00181
00182 default:
00183 {
00184 ink_release_assert(!"Should not get here");
00185 }
00186 }
00187 }
00188
00189 void
00190 HttpUpdateSM::set_next_state()
00191 {
00192 if (t_state.cache_info.action == HttpTransact::CACHE_DO_NO_ACTION ||
00193 t_state.cache_info.action == HttpTransact::CACHE_DO_SERVE) {
00194
00195 if (t_state.next_action == HttpTransact::SM_ACTION_SERVE_FROM_CACHE) {
00196 cb_event = HTTP_SCH_UPDATE_EVENT_NO_ACTION;
00197 t_state.squid_codes.log_code = SQUID_LOG_TCP_HIT;
00198 } else {
00199 t_state.squid_codes.log_code = SQUID_LOG_TCP_MISS;
00200 }
00201
00202 terminate_sm = true;
00203 ink_assert(tunnel.is_tunnel_active() == false);
00204 return;
00205 }
00206
00207 HttpSM::set_next_state();
00208 }
00209
00210 int
00211 HttpUpdateSM::kill_this_async_hook(int event, void * )
00212 {
00213 STATE_ENTER(&HttpUpdateSM::user_cb_handler, event, data);
00214
00215 MUTEX_TRY_LOCK(lock, cb_action.mutex, this_ethread());
00216
00217 if (!lock) {
00218 default_handler = (HttpSMHandler) & HttpUpdateSM::kill_this_async_hook;
00219 eventProcessor.schedule_in(this, HRTIME_MSECONDS(10), ET_CALL);
00220 return EVENT_DONE;
00221 }
00222
00223 if (!cb_action.cancelled) {
00224 Debug("http", "[%" PRId64 "] [HttpUpdateSM] calling back user with event %s",
00225 sm_id, HttpDebugNames::get_event_name(cb_event));
00226 cb_cont->handleEvent(cb_event, NULL);
00227 }
00228
00229 cb_occured = true;
00230
00231 return HttpSM::kill_this_async_hook(EVENT_NONE, NULL);
00232 }