Page Speed Optimization Libraries  1.5.27.2
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 kClientPropertyCacheKeyPrefix[];
00182   static const char kDevicePropertyCacheKeyPrefix[];
00183 
00184   class CacheInterfaceCallback;
00185 
00192   class Cohort {
00193    public:
00195     Cohort(StringPiece name, CacheInterface* cache)
00196         : cache_(cache) {
00197       name.CopyToString(&name_);
00198     }
00199     const GoogleString& name() const { return name_; }
00200     CacheInterface* cache() const { return cache_.get(); }
00201 
00202    private:
00203     scoped_ptr<CacheInterface> cache_;
00204     GoogleString name_;
00205 
00206     DISALLOW_COPY_AND_ASSIGN(Cohort);
00207   };
00208 
00209   typedef std::vector<const Cohort*> CohortVector;
00210 
00212   PropertyCache(const GoogleString& cache_key_prefix,
00213                 CacheInterface* cache, Timer* timer,
00214                 Statistics* stats, ThreadSystem* threads);
00215   ~PropertyCache();
00216 
00220   void Read(PropertyPage* property_page) const;
00221 
00224   void ReadWithCohorts(const CohortVector& cohort_list,
00225                        PropertyPage* property_page) const;
00226 
00228   const CohortVector GetAllCohorts() const { return cohort_list_; }
00229 
00231   bool IsStable(const PropertyValue* property) const {
00232     return property->IsStable(mutations_per_1000_writes_threshold_);
00233   }
00234 
00243   bool IsExpired(const PropertyValue* property_value, int64 ttl_ms) const;
00244 
00245   void set_mutations_per_1000_writes_threshold(int x) {
00246     mutations_per_1000_writes_threshold_ = x;
00247   }
00248 
00252   const Cohort* AddCohort(const StringPiece& cohort_name);
00253 
00256   const Cohort* AddCohortWithCache(const StringPiece& cohort_name,
00257                                    CacheInterface* cache);
00258 
00262   const Cohort* GetCohort(const StringPiece& cohort_name) const;
00263 
00267   void set_enabled(bool x) { enabled_ = x; }
00268 
00270   bool enabled() const { return enabled_; }
00271 
00276   GoogleString CacheKey(const StringPiece& key, const Cohort* cohort) const;
00277 
00278   const CacheInterface* cache_backend() const { return cache_; }
00279 
00281   static void InitCohortStats(const GoogleString& cohort,
00282                               Statistics* statistics);
00283 
00285   Timer* timer() const { return timer_; }
00286 
00287   ThreadSystem* thread_system() const { return thread_system_; }
00288 
00290 
00291  private:
00292   GoogleString cache_key_prefix_;
00293   CacheInterface* cache_;
00294   Timer* timer_;
00295   Statistics* stats_;
00296   ThreadSystem* thread_system_;
00297 
00298   int mutations_per_1000_writes_threshold_;
00299   typedef std::map<GoogleString, Cohort*> CohortMap;
00300   CohortMap cohorts_;
00302   CohortVector cohort_list_;
00303   bool enabled_;
00304 
00305   DISALLOW_COPY_AND_ASSIGN(PropertyCache);
00306 };
00307 
00309 class AbstractPropertyPage {
00310  public:
00311   virtual ~AbstractPropertyPage();
00314   virtual PropertyValue* GetProperty(
00315       const PropertyCache::Cohort* cohort,
00316       const StringPiece& property_name) const = 0;
00317 
00320   virtual void UpdateValue(
00321      const PropertyCache::Cohort* cohort, const StringPiece& property_name,
00322      const StringPiece& value) = 0;
00323 
00327   virtual void WriteCohort(const PropertyCache::Cohort* cohort) = 0;
00328 
00330   virtual CacheInterface::KeyState GetCacheState(
00331      const PropertyCache::Cohort* cohort) = 0;
00332 
00334   virtual void DeleteProperty(const PropertyCache::Cohort* cohort,
00335                               const StringPiece& property_name) = 0;
00336 
00337   virtual const GoogleString& key() const = 0;
00338 };
00339 
00340 
00343 class PropertyPage : public AbstractPropertyPage {
00344  public:
00345   virtual ~PropertyPage();
00346 
00363   virtual PropertyValue* GetProperty(const PropertyCache::Cohort* cohort,
00364                                      const StringPiece& property_name) const;
00365 
00368   virtual void UpdateValue(
00369       const PropertyCache::Cohort* cohort, const StringPiece& property_name,
00370       const StringPiece& value);
00371 
00378   virtual void WriteCohort(const PropertyCache::Cohort* cohort);
00379 
00384   CacheInterface::KeyState GetCacheState(const PropertyCache::Cohort* cohort);
00385 
00392   void set_cache_state_for_tests(const PropertyCache::Cohort* cohort,
00393                                  CacheInterface::KeyState x);
00394 
00404   void DeleteProperty(const PropertyCache::Cohort* cohort,
00405                       const StringPiece& property_name);
00406 
00407   const GoogleString& key() const { return key_; }
00408 
00409   AbstractLogRecord* log_record() {
00410     return request_context_->log_record();
00411   }
00412 
00414   virtual void LogPageCohortInfo(AbstractLogRecord* log_record,
00415                                  int cohort_index) {}
00416 
00418   void Read(const PropertyCache::CohortVector& cohort_list);
00419 
00421   void Abort();
00422 
00423  protected:
00425   PropertyPage(const StringPiece& key,
00426                const RequestContextPtr& request_context,
00427                AbstractMutex* mutex,
00428                PropertyCache* property_cache);
00429 
00432   virtual bool IsCacheValid(int64 write_timestamp_ms) const { return true; }
00433 
00435   virtual void Done(bool success) = 0;
00436 
00437  private:
00438   class CallbackCollector;
00439   friend class CallbackCollector;
00440   friend class PropertyCache::CacheInterfaceCallback;
00441 
00442   void SetupCohorts(const PropertyCache::CohortVector& cohort_list);
00443 
00446   bool EncodeCacheEntry(const PropertyCache::Cohort* cohort,
00447                         GoogleString* value);
00448 
00450   bool HasPropertyValueDeleted(const PropertyCache::Cohort* cohort);
00451 
00452   void CallDone(bool success) {
00453     was_read_ = true;
00454     Done(success);
00455   }
00456 
00457   void AddValueFromProtobuf(const PropertyCache::Cohort* cohort,
00458                             const PropertyValueProtobuf& proto);
00459 
00460   typedef std::map<GoogleString, PropertyValue*> PropertyMap;
00461 
00462   struct PropertyMapStruct {
00463     PropertyMapStruct(AbstractLogRecord* log, int index)
00464         : has_deleted_property(false),
00465           log_record(log),
00466           cohort_index(index) {}
00467     PropertyMap pmap;
00468     bool has_deleted_property;
00469     AbstractLogRecord* log_record;
00470     int cohort_index;
00471     CacheInterface::KeyState cache_state;
00472   };
00473   typedef std::map<const PropertyCache::Cohort*, PropertyMapStruct*>
00474       CohortDataMap;
00475   CohortDataMap cohort_data_map_;
00476   scoped_ptr<AbstractMutex> mutex_;
00477   GoogleString key_;
00478   RequestContextPtr request_context_;
00479   bool was_read_;
00480   PropertyCache* property_cache_; 
00481 
00482   DISALLOW_COPY_AND_ASSIGN(PropertyPage);
00483 };
00484 
00485 }  
00486 
00487 #endif  ///< NET_INSTAWEB_UTIL_PUBLIC_PROPERTY_CACHE_H_
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines