1 /* 2 * Copyright (C) 2010-2020 Codership Oy <info@codership.com> 3 */ 4 5 /*! @file ring buffer storage class */ 6 7 #ifndef _gcache_rb_store_hpp_ 8 #define _gcache_rb_store_hpp_ 9 10 #include "gcache_memops.hpp" 11 #include "gcache_bh.hpp" 12 #include "gcache_types.hpp" 13 14 #include <gu_fdesc.hpp> 15 #include <gu_mmap.hpp> 16 #include <gu_uuid.hpp> 17 18 #include <string> 19 20 namespace gcache 21 { 22 class RingBuffer : public MemOps 23 { 24 public: 25 26 RingBuffer (const std::string& name, 27 size_t size, 28 seqno2ptr_t& seqno2ptr, 29 gu::UUID& gid, 30 int dbg, 31 bool recover); 32 33 ~RingBuffer (); 34 35 void* malloc (size_type size); 36 37 void free (BufferHeader* bh); 38 39 void* realloc (void* ptr, size_type size); 40 discard(BufferHeader * const bh)41 void discard (BufferHeader* const bh) 42 { 43 assert (BH_is_released(bh)); 44 assert (SEQNO_ILL == bh->seqno_g); 45 size_free_ += bh->size; 46 assert (size_free_ <= size_cache_); 47 } 48 size() const49 size_t size () const { return size_cache_; } 50 rb_size() const51 size_t rb_size () const { return fd_.size(); } 52 rb_name() const53 const std::string& rb_name() const { return fd_.name(); } 54 55 void reset(); 56 57 void seqno_reset(); 58 59 /* returns true when successfully discards all seqnos in range */ 60 bool discard_seqnos(seqno2ptr_t::iterator i_begin, 61 seqno2ptr_t::iterator i_end); 62 63 /* returns true when successfully discards all seqnos up to s */ discard_seqno(seqno_t s)64 bool discard_seqno(seqno_t s) 65 { 66 return discard_seqnos(seqno2ptr_.begin(), seqno2ptr_.find(s + 1)); 67 } 68 69 void print (std::ostream& os) const; 70 pad_size()71 static size_t pad_size() 72 { 73 RingBuffer* rb(0); 74 // cppcheck-suppress nullPointer 75 return (PREAMBLE_LEN * sizeof(*(rb->preamble_)) + 76 // cppcheck-suppress nullPointer 77 HEADER_LEN * sizeof(*(rb->header_))); 78 } 79 assert_size_free() const80 void assert_size_free() const 81 { 82 #ifndef NDEBUG 83 if (next_ >= first_) 84 { 85 /* start_ first_ next_ end_ 86 * | |###########| | */ 87 assert(size_free_ >= (size_cache_ - (next_ - first_))); 88 } 89 else 90 { 91 /* start_ next_ first_ end_ 92 * |#######| |#####| | */ 93 assert(size_free_ >= size_t(first_ - next_)); 94 } 95 assert (size_free_ <= size_cache_); 96 #endif 97 } 98 assert_size_trail() const99 void assert_size_trail() const 100 { 101 #ifndef NDEBUG 102 if (next_ >= first_) 103 assert(0 == size_trail_); 104 else 105 assert(size_trail_ >= sizeof(BufferHeader)); 106 #endif 107 } 108 assert_sizes() const109 void assert_sizes() const 110 { 111 assert_size_trail(); 112 assert_size_free(); 113 } 114 set_debug(int const dbg)115 void set_debug(int const dbg) { debug_ = dbg & DEBUG; } 116 117 #ifdef GCACHE_RB_UNIT_TEST offset(const void * const ptr) const118 ptrdiff_t offset(const void* const ptr) const 119 { 120 return static_cast<const uint8_t*>(ptr) - start_; 121 } 122 #endif 123 124 private: 125 126 static size_t const PREAMBLE_LEN = 1024; 127 static size_t const HEADER_LEN = 32; 128 129 // 0 - undetermined version 130 // 1 - initial version, no buffer alignment 131 // 2 - buffer alignemnt to GU_WORD_BYTES 132 static int const VERSION = 2; 133 134 static int const DEBUG = 2; // debug flag 135 136 gu::FileDescriptor fd_; 137 gu::MMap mmap_; 138 char* const preamble_; // ASCII text preamble 139 int64_t* const header_; // cache binary header 140 uint8_t* const start_; // start of cache area 141 uint8_t* const end_; // first byte after cache area 142 uint8_t* first_; // pointer to the first (oldest) buffer 143 uint8_t* next_; // pointer to the next free space 144 145 seqno2ptr_t& seqno2ptr_; 146 gu::UUID& gid_; 147 148 size_t const size_cache_; 149 size_t size_free_; 150 size_t size_used_; 151 size_t size_trail_; 152 153 int debug_; 154 155 bool open_; 156 157 BufferHeader* get_new_buffer (size_type size); 158 159 void constructor_common(); 160 161 /* preamble fields */ 162 static std::string const PR_KEY_VERSION; 163 static std::string const PR_KEY_GID; 164 static std::string const PR_KEY_SEQNO_MAX; 165 static std::string const PR_KEY_SEQNO_MIN; 166 static std::string const PR_KEY_OFFSET; 167 static std::string const PR_KEY_SYNCED; 168 169 void write_preamble(bool synced); 170 void open_preamble(bool recover); 171 void close_preamble(); 172 173 // returns lower bound (not inclusive) of valid seqno range 174 seqno_t scan(off_t offset, int scan_step); 175 void recover(off_t offset, int version); 176 177 void estimate_space(); 178 179 RingBuffer(const gcache::RingBuffer&); 180 RingBuffer& operator=(const gcache::RingBuffer&); 181 182 #ifdef GCACHE_RB_UNIT_TEST 183 public: start() const184 uint8_t* start() const { return start_; } 185 #endif 186 }; 187 operator <<(std::ostream & os,const RingBuffer & rb)188 inline std::ostream& operator<< (std::ostream& os, const RingBuffer& rb) 189 { 190 rb.print(os); 191 return os; 192 } 193 194 } /* namespace gcache */ 195 196 #endif /* _gcache_rb_store_hpp_ */ 197