~alinuxninja/nginx-edge/trunk

« back to all changes in this revision

Viewing changes to debian/modules/ngx_pagespeed/psol/include/pagespeed/kernel/cache/purge_context.h

  • Committer: Vivian
  • Date: 2015-12-04 18:20:11 UTC
  • Revision ID: git-v1:a36f2bc32e884f7473b3a47040e5411306144d7d
* Do not extract psol.tar.gz

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*
2
 
 * Copyright 2013 Google Inc.
3
 
 *
4
 
 * Licensed under the Apache License, Version 2.0 (the "License");
5
 
 * you may not use this file except in compliance with the License.
6
 
 * You may obtain a copy of the License at
7
 
 *
8
 
 *      http://www.apache.org/licenses/LICENSE-2.0
9
 
 *
10
 
 * Unless required by applicable law or agreed to in writing, software
11
 
 * distributed under the License is distributed on an "AS IS" BASIS,
12
 
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
 
 * See the License for the specific language governing permissions and
14
 
 * limitations under the License.
15
 
 */
16
 
 
17
 
// Author: jmarantz@google.com (Joshua Marantz)
18
 
 
19
 
#ifndef PAGESPEED_KERNEL_CACHE_PURGE_CONTEXT_H_
20
 
#define PAGESPEED_KERNEL_CACHE_PURGE_CONTEXT_H_
21
 
 
22
 
#include <vector>
23
 
 
24
 
#include "pagespeed/kernel/base/basictypes.h"
25
 
#include "pagespeed/kernel/base/callback.h"
26
 
#include "pagespeed/kernel/base/scoped_ptr.h"
27
 
#include "pagespeed/kernel/base/string.h"
28
 
#include "pagespeed/kernel/base/string_util.h"
29
 
#include "pagespeed/kernel/base/timer.h"
30
 
#include "pagespeed/kernel/cache/purge_set.h"
31
 
#include "pagespeed/kernel/util/copy_on_write.h"
32
 
 
33
 
namespace net_instaweb {
34
 
 
35
 
class AbstractMutex;
36
 
class FileSystem;
37
 
class MessageHandler;
38
 
class NamedLock;
39
 
class NamedLockManager;
40
 
class Scheduler;
41
 
class Statistics;
42
 
class ThreadSystem;
43
 
class UpDownCounter;
44
 
class Variable;
45
 
 
46
 
// Handles purging of URLs, atomically persisting them to disk, allowing
47
 
// multiple concurrent threads/processes to handle purge requests and
48
 
// propogate them to the other processes.
49
 
//
50
 
// All public methods in this class are thread-safe.
51
 
//
52
 
// This class depends on Statistics being functional.  If statistics are off,
53
 
// then cache purging may be slower, but it will still work.
54
 
class PurgeContext {
55
 
 public:
56
 
  typedef Callback2<bool, StringPiece> PurgeCallback;
57
 
  typedef Callback1<const CopyOnWrite<PurgeSet>&> PurgeSetCallback;
58
 
 
59
 
  // The source-of-truth of the purge data is kept in files.  These files
60
 
  // are checked for changes via stat every 5 seconds.
61
 
  //
62
 
  // TODO(jmarantz): make this settable.
63
 
  static const int kCheckCacheIntervalMs = 5 * Timer::kSecondMs;
64
 
 
65
 
  // Variable names.
66
 
  static const char kCancellations[];
67
 
  static const char kContentions[];
68
 
  static const char kFileParseFailures[];
69
 
  static const char kFileStats[];
70
 
  static const char kFileWriteFailures[];
71
 
  static const char kFileWrites[];
72
 
  static const char kPurgeIndex[];
73
 
  static const char kPurgePollTimestampMs[];
74
 
  static const char kStatCalls[];
75
 
 
76
 
  PurgeContext(StringPiece filename,
77
 
               FileSystem* file_system,
78
 
               Timer* timer,
79
 
               int max_bytes_in_cache,
80
 
               ThreadSystem* thread_system,
81
 
               NamedLockManager* lock_manager,
82
 
               Scheduler* scheduler,
83
 
               Statistics* statistics,
84
 
               MessageHandler* handler);
85
 
  ~PurgeContext();
86
 
 
87
 
  static void InitStats(Statistics* statistics);
88
 
 
89
 
  // By default, PurgeContext will try to acquire the lock and write the
90
 
  // cache.purge file as soon as it is called.  This may present a significant
91
 
  // load to the file system, causing delays.
92
 
  //
93
 
  // In a multi-threaded or asynchronous environment (e.g. any environment
94
 
  // other than Apache HTTPD pre-fork MPM), it is desirable to batch up
95
 
  // requests for a time (e.g. 1 second) before writing the updated cache file.
96
 
  void set_request_batching_delay_ms(int64 delay_ms) {
97
 
    request_batching_delay_ms_ = delay_ms;
98
 
  }
99
 
 
100
 
  // Adds a URL to the purge-set, atomically updating the purge
101
 
  // file, and transmitting the results to the system, attempting
102
 
  // to do so within a bounded amount of time.
103
 
  //
104
 
  // Calls callback(true, "") if the invalidation succeeded (was able to grab
105
 
  // the global lock in a finite amount of time), and callback(false, "reason")
106
 
  // if it failed.  If we fail to take the lock then the invalidation is dropped
107
 
  // on the floor, and statistics "purge_cancellations" is bumped.
108
 
  void AddPurgeUrl(StringPiece url, int64 timestamp_ms,
109
 
                   PurgeCallback* callback);
110
 
 
111
 
  // Sets the global invalidation timestamp.
112
 
  //
113
 
  // Calls callback(true, "") if the invalidation succeeded (was able to grab
114
 
  // the global lock in a finite amount of time), and callback(false, "reason")
115
 
  // if it failed. If we fail to take the lock then the invalidation is dropped
116
 
  // on the floor, and statistics "purge_cancellations" is bumped.
117
 
  void SetCachePurgeGlobalTimestampMs(int64 timestamp_ms,
118
 
                                      PurgeCallback* callback);
119
 
 
120
 
  // Periodically updates the purge-set from disk if enough time has
121
 
  // expired.  This can be called on every request.
122
 
  void PollFileSystem();
123
 
 
124
 
  // To test whether URLs are purged, you must capture a PurgeSet by registering
125
 
  // a callback.  The PurgeSet is passed to the callback using a CopyOnWrite
126
 
  // wrapper so that the callback can efficiently share the storage.
127
 
  //
128
 
  // IsValid calls can then be made using the PurgeSet captured by the callback.
129
 
  void SetUpdateCallback(PurgeSetCallback* cb);
130
 
 
131
 
  // Indicates whether individual URL purging is supported.  If false,
132
 
  // then we only take the cache.flush file timestamp to do full cache
133
 
  // flushes.  If true, then we read and parse the contents of the file
134
 
  // to find the global invalidation time and cache-flush times for
135
 
  // the individual entries.
136
 
  void set_enable_purge(bool x) { enable_purge_ = x; }
137
 
 
138
 
 private:
139
 
  friend class PurgeContextTest;
140
 
 
141
 
  typedef std::vector<PurgeCallback*> PurgeCallbackVector;
142
 
 
143
 
  // Having acquired the lock, merges all sources of purge information and
144
 
  // write the purge file.  This must be called with interprocess_lock_
145
 
  // held.
146
 
  void UpdateCachePurgeFile();
147
 
 
148
 
  // Reads the contents of filename_ into *purges_from_file.  Any invalid
149
 
  // data in the file is ignored.
150
 
  //
151
 
  // This method doesn't read or write dynamic data from the class other
152
 
  // than statistics, so it's thread-safe.  Also it does not need to be
153
 
  // called with interprocess_lock_ held as the writes are made atomic
154
 
  // via write-to-temp + rename.
155
 
  void ReadPurgeFile(PurgeSet* purges_from_file);
156
 
  void ReadFileAndCallCallbackIfChanged(bool needs_update);
157
 
 
158
 
  // Combines the purges_from_file with pending_purges_ and purge_set_,
159
 
  // serializes the result into *buffer for writing back to the file.
160
 
  //
161
 
  // Note: this does *not* update purge_set_ (it treats it as read-only).
162
 
  // However, it bumps purge_index_ to induce a file-read on
163
 
  // the next call to PollFileSystem().
164
 
  //
165
 
  // This helper method is used as part of a read/modify/write/verify
166
 
  // sequence, and it returns the callbacks that must be called when
167
 
  // that sequence is done.  Similarly, this method transfers
168
 
  // num_consecutive_failures_ into *failures, zeroing the former.
169
 
  //
170
 
  // return_purges gets populated with pending_purges_ via swap.  It
171
 
  // can be used to replace pending_purges_ in the event of a write
172
 
  // failure so we don't lose that data.
173
 
  //
174
 
  // return_callbacks contains the callbacks to call when the
175
 
  // transaction is complete.
176
 
  //
177
 
  // TODO(jmarantz): the return values from this method comprise a
178
 
  // transaction which should be made an explicit class or struct.
179
 
  //
180
 
  // This method is thread-safe; it grabs mutex_.
181
 
  void ModifyPurgeSet(PurgeSet* purges_from_file, GoogleString* buffer,
182
 
                      PurgeCallbackVector* return_callbacks,
183
 
                      PurgeSet* return_purges,
184
 
                      int* failures);
185
 
 
186
 
  // When a write fails, we must do one of these:
187
 
  //  a) restore the pending purges & callbacks and try to re-take the lock.
188
 
  //  b) call the callbacks with 'false' and drop return_purges.
189
 
  void HandleWriteFailure(int failures,
190
 
                          PurgeCallbackVector* callbacks,
191
 
                          PurgeSet* return_purges,
192
 
                          bool* lock_and_update);
193
 
 
194
 
  // Writes the serialized purge data into filename_.  This method must
195
 
  // be called with the interprocess_lock_ held, but does not reference
196
 
  // or update dynamic data in this.
197
 
  bool WritePurgeFile(const GoogleString& buffer);
198
 
 
199
 
  // Returns true if the contents of filename_ matches the specified buffer.
200
 
  bool Verify(const GoogleString& expected_purge_file_contents);
201
 
 
202
 
  // Returns the name used to create a new lock.  Visible for testing
203
 
  // to aid in testing lock contention.
204
 
  GoogleString LockName() const { return StrCat(filename_, "-lock"); }
205
 
 
206
 
  // Initiates a scheduler-alarm to call GrabLockAndUpdate after a
207
 
  // small delay.  The delay is used to batch bursts of cache-purge
208
 
  // file updates, thereby rate-limiting disk-writes.
209
 
  void WaitForTimerAndGrabLock();
210
 
 
211
 
  // Attempts to grab a lock for the cache-purge file, calling
212
 
  // UpdateCachePurgeFile if successful, and CancelCachePurgeFile
213
 
  // if we failed to grab the lock.
214
 
  void GrabLockAndUpdate();
215
 
 
216
 
  // There is a non-zero chance that this thread will be unable to acquire the
217
 
  // named-lock in the given time-limit.  When this occurs, we'll fail the
218
 
  // requests, calling the callbacks with 'false'.
219
 
  void CancelCachePurgeFile();
220
 
 
221
 
  // Ensures a timestamp has reasonable syntax and is not (too far) in the
222
 
  // future.
223
 
  //
224
 
  // The parsed timestamp is placed in *timestamp_ms, and true/false is
225
 
  // used to indicate parsing & validation success.
226
 
  bool ParseAndValidateTimestamp(StringPiece time_string, int64 now_ms,
227
 
                                 int64* timestamp_ms);
228
 
 
229
 
  GoogleString filename_;
230
 
  scoped_ptr<NamedLock> interprocess_lock_;
231
 
  FileSystem* file_system_;
232
 
  Timer* timer_;
233
 
 
234
 
  Statistics* statistics_;
235
 
  scoped_ptr<AbstractMutex> mutex_;
236
 
  CopyOnWrite<PurgeSet> purge_set_;        // protected by mutex_
237
 
  PurgeSet pending_purges_;                // protected by mutex_
238
 
  PurgeCallbackVector pending_callbacks_;  // protected by mutex_
239
 
  int64 local_purge_index_;                // protected by mutex_
240
 
  int num_consecutive_failures_;           // protected_by mutex_
241
 
  bool waiting_for_interprocess_lock_;     // protected_by mutex_
242
 
  bool reading_;                           // protected_by mutex_
243
 
 
244
 
  bool enable_purge_;           // When false, can only flush entire cache.
245
 
  int max_bytes_in_cache_;
246
 
 
247
 
  int64 request_batching_delay_ms_;
248
 
 
249
 
  Variable* cancellations_;
250
 
  Variable* contentions_;
251
 
  Variable* file_parse_failures_;
252
 
  Variable* file_stats_;
253
 
  Variable* file_write_failures_;
254
 
  Variable* file_writes_;
255
 
  Variable* purge_index_;
256
 
  scoped_ptr<UpDownCounter> purge_poll_timestamp_ms_;
257
 
 
258
 
  Scheduler* scheduler_;
259
 
  MessageHandler* message_handler_;
260
 
 
261
 
  scoped_ptr<PurgeSetCallback> update_callback_;
262
 
 
263
 
  DISALLOW_COPY_AND_ASSIGN(PurgeContext);
264
 
};
265
 
 
266
 
}  // namespace net_instaweb
267
 
 
268
 
#endif  // PAGESPEED_KERNEL_CACHE_PURGE_CONTEXT_H_