00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00091
00092 #ifndef NET_INSTAWEB_UTIL_PUBLIC_PROPERTY_CACHE_H_
00093 #define NET_INSTAWEB_UTIL_PUBLIC_PROPERTY_CACHE_H_
00094
00095 #include <map>
00096 #include <set>
00097
00098 #include "base/scoped_ptr.h"
00099 #include "net/instaweb/util/public/abstract_mutex.h"
00100 #include "net/instaweb/util/public/basictypes.h"
00101 #include "net/instaweb/util/public/string.h"
00102 #include "net/instaweb/util/public/string_util.h"
00103
00104 namespace net_instaweb {
00105
00106 class CacheInterface;
00107 class PropertyValueProtobuf;
00108 class PropertyPage;
00109 class ThreadSystem;
00110 class Timer;
00111
00113 class PropertyValue {
00114 public:
00115 StringPiece value() const;
00116 bool has_value() const { return valid_; }
00117
00120 int64 write_timestamp_ms() const;
00121
00124 bool was_read() { return was_read_; }
00125
00129 bool IsStable(int stable_hit_per_thousand_threshold) const;
00130
00131 private:
00132 friend class PropertyCache;
00133 friend class PropertyPage;
00134
00136 PropertyValue();
00137 ~PropertyValue();
00138
00139 void set_was_read(bool was_read) { was_read_ = was_read; }
00140
00142 void InitFromProtobuf(const PropertyValueProtobuf& value);
00143
00150 void SetValue(const StringPiece& value, int64 now_ms);
00151
00152 PropertyValueProtobuf* protobuf() { return proto_.get(); }
00153
00154 scoped_ptr<PropertyValueProtobuf> proto_;
00155 bool changed_;
00156 bool valid_;
00157 bool was_read_;
00158
00159 DISALLOW_COPY_AND_ASSIGN(PropertyValue);
00160 };
00161
00163 class PropertyCache {
00164 public:
00166 static const char kPagePropertyCacheKeyPrefix[];
00167 static const char kClientPropertyCacheKeyPrefix[];
00168
00169 class CacheInterfaceCallback;
00170
00182 class Cohort : public GoogleString {};
00183
00184 PropertyCache(const GoogleString& cache_key_prefix,
00185 CacheInterface* cache, Timer* timer, ThreadSystem* threads);
00186 ~PropertyCache();
00187
00191 void Read(PropertyPage* property_page) const;
00192
00199 void WriteCohort(const Cohort* cohort,
00200 PropertyPage* property_page) const;
00201
00203 bool IsStable(const PropertyValue* property) const {
00204 return property->IsStable(mutations_per_1000_writes_threshold_);
00205 }
00206
00215 bool IsExpired(const PropertyValue* property_value, int64 ttl_ms) const;
00216
00219 void UpdateValue(const StringPiece& value, PropertyValue* property) const;
00220
00221 void set_mutations_per_1000_writes_threshold(int x) {
00222 mutations_per_1000_writes_threshold_ = x;
00223 }
00224
00226 const Cohort* AddCohort(const StringPiece& cohort_name);
00227
00231 const Cohort* GetCohort(const StringPiece& cohort_name) const;
00232
00236 void set_enabled(bool x) { enabled_ = x; }
00237
00239 bool enabled() const { return enabled_; }
00240
00245 GoogleString CacheKey(const StringPiece& key, const Cohort* cohort) const;
00246
00247 const CacheInterface* cache_backend() const { return cache_; }
00248
00250
00251 private:
00252 GoogleString cache_key_prefix_;
00253 CacheInterface* cache_;
00254 Timer* timer_;
00255 ThreadSystem* thread_system_;
00256
00257 int mutations_per_1000_writes_threshold_;
00258 typedef std::set<Cohort> CohortSet;
00259 CohortSet cohorts_;
00260
00261 bool enabled_;
00262
00263 DISALLOW_COPY_AND_ASSIGN(PropertyCache);
00264 };
00265
00268 class PropertyPage {
00269 public:
00270 virtual ~PropertyPage();
00271
00288 PropertyValue* GetProperty(const PropertyCache::Cohort* cohort,
00289 const StringPiece& property_name);
00290
00300 void DeleteProperty(const PropertyCache::Cohort* cohort,
00301 const StringPiece& property_name);
00302
00303 const GoogleString& key() const { return key_; }
00304
00305 protected:
00307 explicit PropertyPage(AbstractMutex* mutex, const StringPiece& key)
00308 : mutex_(mutex),
00309 key_(key.as_string()),
00310 was_read_(false) {
00311 }
00312
00314 virtual void Done(bool success) = 0;
00315
00316 private:
00317 class CallbackCollector;
00318 friend class CallbackCollector;
00319 friend class PropertyCache::CacheInterfaceCallback;
00320 friend class PropertyCache;
00321
00324 bool EncodeCacheEntry(const PropertyCache::Cohort* cohort,
00325 GoogleString* value);
00326
00328 bool HasPropertyValueDeleted(const PropertyCache::Cohort* cohort);
00329
00330 void CallDone(bool success) {
00331 was_read_ = true;
00332 Done(success);
00333 }
00334
00335 void AddValueFromProtobuf(const PropertyCache::Cohort* cohort,
00336 const PropertyValueProtobuf& proto);
00337
00338 typedef std::map<GoogleString, PropertyValue*> PropertyMap;
00339
00340 struct PropertyMapStruct {
00341 PropertyMapStruct() {
00342 has_deleted_property = false;
00343 }
00344 PropertyMap pmap;
00345 bool has_deleted_property;
00346 };
00347 typedef std::map<const PropertyCache::Cohort*, PropertyMapStruct*>
00348 CohortDataMap;
00349 CohortDataMap cohort_data_map_;
00350 scoped_ptr<AbstractMutex> mutex_;
00351 GoogleString key_;
00352 bool was_read_;
00353
00354 DISALLOW_COPY_AND_ASSIGN(PropertyPage);
00355 };
00356
00357 }
00358
00359 #endif ///< NET_INSTAWEB_UTIL_PUBLIC_PROPERTY_CACHE_H_