1 /** @file
2 
3   A brief file description
4 
5   @section license License
6 
7   Licensed to the Apache Software Foundation (ASF) under one
8   or more contributor license agreements.  See the NOTICE file
9   distributed with this work for additional information
10   regarding copyright ownership.  The ASF licenses this file
11   to you under the Apache License, Version 2.0 (the
12   "License"); you may not use this file except in compliance
13   with the License.  You may obtain a copy of the License at
14 
15       http://www.apache.org/licenses/LICENSE-2.0
16 
17   Unless required by applicable law or agreed to in writing, software
18   distributed under the License is distributed on an "AS IS" BASIS,
19   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
20   See the License for the specific language governing permissions and
21   limitations under the License.
22  */
23 
24 /****************************************************************************
25 
26    HttpCacheSM.h
27 
28    Description:
29 
30 
31  ****************************************************************************/
32 
33 #pragma once
34 
35 #include "P_Cache.h"
36 #include "ProxyConfig.h"
37 #include "URL.h"
38 #include "HTTP.h"
39 #include "HttpConfig.h"
40 
41 class HttpSM;
42 class HttpCacheSM;
43 
44 struct HttpCacheAction : public Action {
45   HttpCacheAction();
46   void cancel(Continuation *c = nullptr) override;
47   void
initHttpCacheAction48   init(HttpCacheSM *sm_arg)
49   {
50     sm = sm_arg;
51   };
52   HttpCacheSM *sm = nullptr;
53 };
54 
55 class HttpCacheSM : public Continuation
56 {
57 public:
58   HttpCacheSM();
59 
60   void
init(HttpSM * sm_arg,Ptr<ProxyMutex> & amutex)61   init(HttpSM *sm_arg, Ptr<ProxyMutex> &amutex)
62   {
63     master_sm = sm_arg;
64     mutex     = amutex;
65     captive_action.init(this);
66   }
67 
68   Action *open_read(const HttpCacheKey *key, URL *url, HTTPHdr *hdr, const OverridableHttpConfigParams *params,
69                     time_t pin_in_cache);
70 
71   Action *open_write(const HttpCacheKey *key, URL *url, HTTPHdr *request, CacheHTTPInfo *old_info, time_t pin_in_cache, bool retry,
72                      bool allow_multiple);
73 
74   CacheVConnection *cache_read_vc  = nullptr;
75   CacheVConnection *cache_write_vc = nullptr;
76 
77   bool read_locked  = false;
78   bool write_locked = false;
79   // Flag to check whether read-while-write is in progress or not
80   bool readwhilewrite_inprogress = false;
81 
82   HttpSM *master_sm      = nullptr;
83   Action *pending_action = nullptr;
84 
85   // Function to set readwhilewrite_inprogress flag
86   inline void
set_readwhilewrite_inprogress(bool value)87   set_readwhilewrite_inprogress(bool value)
88   {
89     readwhilewrite_inprogress = value;
90   }
91 
92   // Function to get the readwhilewrite_inprogress flag
93   inline bool
is_readwhilewrite_inprogress()94   is_readwhilewrite_inprogress()
95   {
96     return readwhilewrite_inprogress;
97   }
98 
99   bool
is_ram_cache_hit()100   is_ram_cache_hit()
101   {
102     return cache_read_vc ? (cache_read_vc->is_ram_cache_hit()) : false;
103   }
104 
105   bool
is_compressed_in_ram()106   is_compressed_in_ram()
107   {
108     return cache_read_vc ? (cache_read_vc->is_compressed_in_ram()) : false;
109   }
110 
111   inline void
set_open_read_tries(int value)112   set_open_read_tries(int value)
113   {
114     open_read_tries = value;
115   }
116 
117   int
get_open_read_tries()118   get_open_read_tries()
119   {
120     return open_read_tries;
121   }
122 
123   inline void
set_open_write_tries(int value)124   set_open_write_tries(int value)
125   {
126     open_write_tries = value;
127   }
128 
129   int
get_open_write_tries()130   get_open_write_tries()
131   {
132     return open_write_tries;
133   }
134 
135   int
get_volume_number()136   get_volume_number()
137   {
138     if (cache_read_vc) {
139       return cache_read_vc->get_volume_number();
140     } else if (cache_write_vc) {
141       return cache_write_vc->get_volume_number();
142     }
143 
144     return -1;
145   }
146 
147   const char *
get_disk_path()148   get_disk_path()
149   {
150     if (cache_read_vc) {
151       return cache_read_vc->get_disk_path();
152     } else if (cache_write_vc) {
153       return cache_write_vc->get_disk_path();
154     }
155 
156     return nullptr;
157   }
158 
159   inline void
abort_read()160   abort_read()
161   {
162     if (cache_read_vc) {
163       HTTP_DECREMENT_DYN_STAT(http_current_cache_connections_stat);
164       cache_read_vc->do_io_close(0); // passing zero as aborting read is not an error
165       cache_read_vc = nullptr;
166     }
167   }
168   inline void
abort_write()169   abort_write()
170   {
171     if (cache_write_vc) {
172       HTTP_DECREMENT_DYN_STAT(http_current_cache_connections_stat);
173       cache_write_vc->do_io_close(0); // passing zero as aborting write is not an error
174       cache_write_vc = nullptr;
175     }
176   }
177   inline void
close_write()178   close_write()
179   {
180     if (cache_write_vc) {
181       HTTP_DECREMENT_DYN_STAT(http_current_cache_connections_stat);
182       cache_write_vc->do_io_close();
183       cache_write_vc = nullptr;
184     }
185   }
186   inline void
close_read()187   close_read()
188   {
189     if (cache_read_vc) {
190       HTTP_DECREMENT_DYN_STAT(http_current_cache_connections_stat);
191       cache_read_vc->do_io_close();
192       cache_read_vc = nullptr;
193     }
194   }
195   inline void
end_both()196   end_both()
197   {
198     // We close the read so that cache
199     //   records its stats
200     close_read();
201     abort_write();
202   }
203 
204   inline int
get_last_error()205   get_last_error() const
206   {
207     return err_code;
208   }
209 
210 private:
211   void do_schedule_in();
212   Action *do_cache_open_read(const HttpCacheKey &);
213 
214   int state_cache_open_read(int event, void *data);
215   int state_cache_open_write(int event, void *data);
216 
217   HttpCacheAction captive_action;
218   bool open_read_cb  = false;
219   bool open_write_cb = false;
220 
221   // Open read parameters
222   int open_read_tries                            = 0;
223   HTTPHdr *read_request_hdr                      = nullptr;
224   const OverridableHttpConfigParams *http_params = nullptr;
225   time_t read_pin_in_cache                       = 0;
226 
227   // Open write parameters
228   bool retry_write     = true;
229   int open_write_tries = 0;
230 
231   // Common parameters
232   URL *lookup_url = nullptr;
233   HttpCacheKey cache_key;
234 
235   // to keep track of multiple cache lookups
236   int lookup_max_recursive = 0;
237   int current_lookup_level = 0;
238 
239   // last error from the cache subsystem
240   int err_code = 0;
241 };
242