Page Speed Optimization Libraries  1.6.29.3
net/instaweb/util/public/property_cache.h
Go to the documentation of this file.
00001 /*
00002  * Copyright 2012 Google Inc.
00003  *
00004  * Licensed under the Apache License, Version 2.0 (the "License");
00005  * you may not use this file except in compliance with the License.
00006  * You may obtain a copy of the License at
00007  *
00008  *      http:///www.apache.org/licenses/LICENSE-2.0
00009  *
00010  * Unless required by applicable law or agreed to in writing, software
00011  * distributed under the License is distributed on an "AS IS" BASIS,
00012  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00013  * See the License for the specific language governing permissions and
00014  * limitations under the License.
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 <vector>
00097 
00098 #include "net/instaweb/http/public/request_context.h"
00099 #include "net/instaweb/util/public/basictypes.h"
00100 #include "net/instaweb/util/public/cache_interface.h"
00101 #include "net/instaweb/util/public/ref_counted_ptr.h"
00102 #include "net/instaweb/util/public/scoped_ptr.h"
00103 #include "net/instaweb/util/public/string.h"
00104 #include "net/instaweb/util/public/string_util.h"
00105 
00106 namespace net_instaweb {
00107 
00108 class AbstractLogRecord;
00109 class AbstractMutex;
00110 class PropertyValueProtobuf;
00111 class PropertyPage;
00112 class Statistics;
00113 class ThreadSystem;
00114 class Timer;
00115 
00116 typedef std::vector<PropertyPage*> PropertyPageStarVector;
00117 
00119 class PropertyValue {
00120  public:
00121   StringPiece value() const;
00122   bool has_value() const { return valid_; }
00123 
00126   int64 write_timestamp_ms() const;
00127 
00130   bool was_read() { return was_read_; }
00131 
00135   bool IsStable(int stable_hit_per_thousand_threshold) const;
00136 
00139   bool IsRecentlyConstant(int num_writes_unchanged) const;
00140 
00143   static bool IsIndexOfLeastSetBitSmaller(uint64 value, int index);
00144 
00145  private:
00146   friend class PropertyCache;
00147   friend class PropertyPage;
00148 
00150   PropertyValue();
00151   ~PropertyValue();
00152 
00153   void set_was_read(bool was_read) { was_read_ = was_read; }
00154 
00156   void InitFromProtobuf(const PropertyValueProtobuf& value);
00157 
00164   void SetValue(const StringPiece& value, int64 now_ms);
00165 
00166   PropertyValueProtobuf* protobuf() { return proto_.get(); }
00167 
00168   scoped_ptr<PropertyValueProtobuf> proto_;
00169   bool changed_;
00170   bool valid_;
00171   bool was_read_;
00172 
00173   DISALLOW_COPY_AND_ASSIGN(PropertyValue);
00174 };
00175 
00177 class PropertyCache {
00178  public:
00180   static const char kPagePropertyCacheKeyPrefix[];
00181   static const char kDevicePropertyCacheKeyPrefix[];
00182 
00183   class CacheInterfaceCallback;
00184 
00191   class Cohort {
00192    public:
00194     Cohort(StringPiece name, CacheInterface* cache)
00195         : cache_(cache) {
00196       name.CopyToString(&name_);
00197     }
00198     const GoogleString& name() const { return name_; }
00199     CacheInterface* cache() const { return cache_.get(); }
00200 
00201    private:
00202     scoped_ptr<CacheInterface> cache_;
00203     GoogleString name_;
00204 
00205     DISALLOW_COPY_AND_ASSIGN(Cohort);
00206   };
00207 
00208   typedef std::vector<const Cohort*> CohortVector;
00209 
00211   PropertyCache(const GoogleString& cache_key_prefix,
00212                 CacheInterface* cache, Timer* timer,
00213                 Statistics* stats, ThreadSystem* threads);
00214   ~PropertyCache();
00215 
00219   void Read(PropertyPage* property_page) const;
00220 
00223   void ReadWithCohorts(const CohortVector& cohort_list,
00224                        PropertyPage* property_page) const;
00225 
00227   const CohortVector GetAllCohorts() const { return cohort_list_; }
00228 
00230   bool IsStable(const PropertyValue* property) const {
00231     return property->IsStable(mutations_per_1000_writes_threshold_);
00232   }
00233 
00242   bool IsExpired(const PropertyValue* property_value, int64 ttl_ms) const;
00243 
00244   void set_mutations_per_1000_writes_threshold(int x) {
00245     mutations_per_1000_writes_threshold_ = x;
00246   }
00247 
00251   const Cohort* AddCohort(const StringPiece& cohort_name);
00252 
00255   const Cohort* AddCohortWithCache(const StringPiece& cohort_name,
00256                                    CacheInterface* cache);
00257 
00261   const Cohort* GetCohort(const StringPiece& cohort_name) const;
00262 
00266   void set_enabled(bool x) { enabled_ = x; }
00267 
00269   bool enabled() const { return enabled_; }
00270 
00275   GoogleString CacheKey(const StringPiece& key, const Cohort* cohort) const;
00276 
00277   const CacheInterface* cache_backend() const { return cache_; }
00278 
00280   static void InitCohortStats(const GoogleString& cohort,
00281                               Statistics* statistics);
00282 
00284   Timer* timer() const { return timer_; }
00285 
00286   ThreadSystem* thread_system() const { return thread_system_; }
00287 
00289 
00290  private:
00291   GoogleString cache_key_prefix_;
00292   CacheInterface* cache_;
00293   Timer* timer_;
00294   Statistics* stats_;
00295   ThreadSystem* thread_system_;
00296 
00297   int mutations_per_1000_writes_threshold_;
00298   typedef std::map<GoogleString, Cohort*> CohortMap;
00299   CohortMap cohorts_;
00301   CohortVector cohort_list_;
00302   bool enabled_;
00303 
00304   DISALLOW_COPY_AND_ASSIGN(PropertyCache);
00305 };
00306 
00308 class AbstractPropertyPage {
00309  public:
00310   virtual ~AbstractPropertyPage();
00313   virtual PropertyValue* GetProperty(
00314       const PropertyCache::Cohort* cohort,
00315       const StringPiece& property_name) = 0;
00316 
00319   virtual void UpdateValue(
00320      const PropertyCache::Cohort* cohort, const StringPiece& property_name,
00321      const StringPiece& value) = 0;
00322 
00326   virtual void WriteCohort(const PropertyCache::Cohort* cohort) = 0;
00327 
00329   virtual CacheInterface::KeyState GetCacheState(
00330      const PropertyCache::Cohort* cohort) = 0;
00331 
00333   virtual void DeleteProperty(const PropertyCache::Cohort* cohort,
00334                               const StringPiece& property_name) = 0;
00335 
00336   virtual const GoogleString& key() const = 0;
00337 };
00338 
00339 
00342 class PropertyPage : public AbstractPropertyPage {
00343  public:
00345   enum PageType {
00346     kPropertyCachePage,
00347     kPropertyCacheFallbackPage,
00348     kDevicePropertyCachePage,
00349   };
00350 
00351   virtual ~PropertyPage();
00352 
00369   virtual PropertyValue* GetProperty(const PropertyCache::Cohort* cohort,
00370                                      const StringPiece& property_name);
00371 
00374   virtual void UpdateValue(
00375       const PropertyCache::Cohort* cohort, const StringPiece& property_name,
00376       const StringPiece& value);
00377 
00384   virtual void WriteCohort(const PropertyCache::Cohort* cohort);
00385 
00390   CacheInterface::KeyState GetCacheState(const PropertyCache::Cohort* cohort);
00391 
00398   void set_cache_state_for_tests(const PropertyCache::Cohort* cohort,
00399                                  CacheInterface::KeyState x);
00400 
00410   void DeleteProperty(const PropertyCache::Cohort* cohort,
00411                       const StringPiece& property_name);
00412 
00413   const GoogleString& key() const { return key_; }
00414 
00415   AbstractLogRecord* log_record() {
00416     return request_context_->log_record();
00417   }
00418 
00420   void Read(const PropertyCache::CohortVector& cohort_list);
00421 
00423   void Abort();
00424 
00425  protected:
00427   PropertyPage(PageType page_type,
00428                const StringPiece& key,
00429                const RequestContextPtr& request_context,
00430                AbstractMutex* mutex,
00431                PropertyCache* property_cache);
00432 
00435   virtual bool IsCacheValid(int64 write_timestamp_ms) const { return true; }
00436 
00438   virtual void Done(bool success) = 0;
00439 
00440  private:
00441   class CallbackCollector;
00442   friend class CallbackCollector;
00443   friend class PropertyCache::CacheInterfaceCallback;
00444 
00445   void SetupCohorts(const PropertyCache::CohortVector& cohort_list);
00446 
00449   bool EncodeCacheEntry(const PropertyCache::Cohort* cohort,
00450                         GoogleString* value);
00451 
00453   bool HasPropertyValueDeleted(const PropertyCache::Cohort* cohort);
00454 
00455   void CallDone(bool success) {
00456     was_read_ = true;
00457     Done(success);
00458   }
00459 
00460   void AddValueFromProtobuf(const PropertyCache::Cohort* cohort,
00461                             const PropertyValueProtobuf& proto);
00462 
00463   typedef std::map<GoogleString, PropertyValue*> PropertyMap;
00464 
00465   struct PropertyMapStruct {
00466     explicit PropertyMapStruct(AbstractLogRecord* log)
00467         : has_deleted_property(false),
00468           log_record(log) {}
00469     PropertyMap pmap;
00470     bool has_deleted_property;
00471     AbstractLogRecord* log_record;
00472     CacheInterface::KeyState cache_state;
00473   };
00474   typedef std::map<const PropertyCache::Cohort*, PropertyMapStruct*>
00475       CohortDataMap;
00476   CohortDataMap cohort_data_map_;
00477   scoped_ptr<AbstractMutex> mutex_;
00478   GoogleString key_;
00479   RequestContextPtr request_context_;
00480   bool was_read_;
00481   PropertyCache* property_cache_; 
00482   PageType page_type_;
00483 
00484   DISALLOW_COPY_AND_ASSIGN(PropertyPage);
00485 };
00486 
00487 }  
00488 
00489 #endif  ///< NET_INSTAWEB_UTIL_PUBLIC_PROPERTY_CACHE_H_
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines