Page Speed Optimization Libraries  1.5.27.2
net/instaweb/util/shared_mem_cache_data.h
Go to the documentation of this file.
00001 /*
00002  * Copyright 2011 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 
00018 
00021 
00022 #ifndef NET_INSTAWEB_UTIL_SHARED_MEM_CACHE_DATA_H_
00023 #define NET_INSTAWEB_UTIL_SHARED_MEM_CACHE_DATA_H_
00024 
00025 #include <cstddef>                     
00026 
00027 #include "base/logging.h"
00028 #include "net/instaweb/util/public/basictypes.h"  
00029 #include "net/instaweb/util/public/scoped_ptr.h"
00030 #include "net/instaweb/util/public/shared_mem_cache.h"
00031 #include "net/instaweb/util/public/string.h"
00032 
00033 namespace net_instaweb {
00034 
00035 class AbstractMutex;
00036 class AbstractSharedMem;
00037 class AbstractSharedMemSegment;
00038 class MessageHandler;
00039 
00040 namespace SharedMemCacheData {
00041 
00042 const BlockNum kInvalidBlock = -1;
00043 const EntryNum kInvalidEntry = -1;
00044 const size_t kHashSize = 16;
00045 
00046 struct SectorStats {
00047   SectorStats();
00048 
00056   int64 num_put;
00057   int64 num_put_update; 
00058   int64 num_put_replace; 
00059   int64 num_put_concurrent_create;
00060   int64 num_put_concurrent_full_set;
00061   int64 num_put_spins; 
00062   int64 num_get; 
00063   int64 num_get_hit;
00064 
00066   int64 used_entries;
00067   int64 used_blocks;
00068 
00070   void Add(const SectorStats& other);
00071 
00073   GoogleString Dump(size_t total_entries, size_t total_blocks) const;
00074 };
00075 
00076 struct SectorHeader {
00077   BlockNum free_list_front;
00078   EntryNum lru_list_front;
00079   EntryNum lru_list_rear;
00080   int32 padding;
00081 
00082   SectorStats stats;
00083 
00085 };
00086 
00087 struct CacheEntry {
00088   char hash_bytes[kHashSize];
00089   int64 last_use_timestamp_ms;
00090   int32 byte_size;
00091 
00095   EntryNum lru_prev;
00096   EntryNum lru_next;
00097 
00098   BlockNum first_block;
00099 
00101   bool creating : 1;
00102 
00104   uint32 open_count : 31;
00105 
00106   uint32 padding; 
00107 };
00108 
00114 template<size_t kBlockSize>
00115 class Sector {
00116  public:
00126   Sector(AbstractSharedMemSegment* segment, size_t sector_offset,
00127          size_t cache_entries, size_t data_blocks);
00128 
00135   bool Attach(MessageHandler* handler);
00136 
00140   bool Initialize(MessageHandler* handler);
00141 
00144   static size_t RequiredSize(AbstractSharedMem* shmem_runtime,
00145                              size_t cache_entries, size_t data_blocks);
00146 
00148 
00150   void Lock();
00151   void Unlock();
00152 
00155   BlockNum GetBlockSuccessor(BlockNum block) {
00156     DCHECK_GE(block, 0);
00157     DCHECK_LT(block, static_cast<BlockNum>(data_blocks_));
00158     return block_successors_[block];
00159   }
00160 
00161   void SetBlockSuccessor(BlockNum block, BlockNum next) {
00162     DCHECK_GE(block, 0);
00163     DCHECK_LT(block, static_cast<BlockNum>(data_blocks_));
00164 
00165     DCHECK_GE(next, kInvalidBlock);
00166     DCHECK_LT(next, static_cast<BlockNum>(data_blocks_));
00167 
00168     block_successors_[block] = next;
00169   }
00170 
00173   void LinkBlockSuccessors(const BlockVector& blocks) {
00174     for (size_t pos = 0; pos < blocks.size(); ++pos) {
00175       if (pos == (blocks.size() - 1)) {
00176         SetBlockSuccessor(blocks[pos], kInvalidBlock);
00177       } else {
00178         SetBlockSuccessor(blocks[pos], blocks[pos + 1]);
00179       }
00180     }
00181   }
00182 
00185 
00194   int AllocBlocksFromFreeList(int goal, BlockVector* blocks);
00195 
00200   void ReturnBlocksToFreeList(const BlockVector& blocks);
00201 
00204 
00206   CacheEntry* EntryAt(EntryNum slot) {
00207     return reinterpret_cast<CacheEntry*>(directory_base_) + slot;
00208   }
00209 
00212   void InsertEntryIntoLRU(EntryNum entry_num);
00213 
00215   void UnlinkEntryFromLRU(EntryNum entry_num);
00216 
00217   EntryNum OldestEntryNum() {
00218     return sector_header_->lru_list_rear;
00219   }
00220 
00223 
00224   char* BlockBytes(BlockNum block_num) {
00225     return blocks_base_ + kBlockSize * block_num;
00226   }
00227 
00231 
00233   static size_t DataBlocksForSize(size_t size) {
00234     return NeededPieces(size, kBlockSize);
00235   }
00236 
00240   static size_t BytesInPortion(size_t total_bytes, size_t b, size_t total);
00241 
00246   int BlockListForEntry(CacheEntry* entry, BlockVector* out_blocks);
00247 
00250 
00251   SectorStats* sector_stats() { return &sector_header_->stats; }
00252 
00255   void DumpStats(MessageHandler* handler);
00256 
00257  private:
00259   struct MemLayout;
00260 
00262   static size_t NeededPieces(size_t total, size_t piece_size) {
00263     return (total + piece_size - 1) / piece_size;
00264   }
00265 
00267   size_t cache_entries_;
00268   size_t data_blocks_;
00269 
00271   AbstractSharedMemSegment* segment_;
00272   scoped_ptr<AbstractMutex> mutex_;
00273   SectorHeader* sector_header_;
00274   BlockNum* block_successors_;
00275   char* directory_base_;
00276   char* blocks_base_;
00277   size_t sector_offset_; 
00278 
00279   DISALLOW_COPY_AND_ASSIGN(Sector);
00280 };
00281 
00282 }  
00283 
00284 }  
00285 
00286 #endif  ///< NET_INSTAWEB_UTIL_SHARED_MEM_CACHE_DATA_H_
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines