1 // Copyright 2008 Google Inc. All Rights Reserved.
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
7 // http://www.apache.org/licenses/LICENSE-2.0
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
15 // Interface for a thread-safe container of disk blocks
17 #ifndef STRESSAPPTEST_DISK_BLOCKS_H_
18 #define STRESSAPPTEST_DISK_BLOCKS_H_
20 #include <sys/types.h>
33 // Data about a block written to disk so that it can be verified later.
34 // Thread-unsafe, must be used with locks on non-const methods,
35 // except for initialized accessor/mutator, which are thread-safe
36 // (and in fact, is the only method supposed to be accessed from
37 // someone which is not the thread-safe DiskBlockTable).
43 // These are reference counters used to control how many
44 // threads currently have a copy of this particular block.
45 void IncreaseReferenceCounter() { references_++; }
46 void DecreaseReferenceCounter() { references_--; }
47 int GetReferenceCounter() const { return references_; }
49 // Controls whether the block was written on disk or not.
50 // Once written, you cannot "un-written" then without destroying
52 void set_initialized();
53 bool initialized() const;
55 // Accessor methods for some data related to blocks.
56 void set_address(uint64 address) { address_ = address; }
57 uint64 address() const { return address_; }
58 void set_size(uint64 size) { size_ = size; }
59 uint64 size() const { return size_; }
60 void set_pattern(Pattern *p) { pattern_ = p; }
61 Pattern *pattern() { return pattern_; }
63 uint64 address_; // Address of first sector in block
64 uint64 size_; // Size of block
65 int references_; // Reference counter
66 bool initialized_; // Flag indicating the block was written on disk
68 mutable pthread_mutex_t data_mutex_;
69 DISALLOW_COPY_AND_ASSIGN(BlockData);
72 // A thread-safe table used to store block data and control access
73 // to these blocks, letting several threads read and write blocks on
75 class DiskBlockTable {
78 virtual ~DiskBlockTable();
80 // Returns number of elements stored on table.
83 // Sets all initial parameters. Assumes all existent data is
84 // invalid and, therefore, must be removed.
85 void SetParameters(int sector_size, int write_block_size,
88 const string& device_name);
90 // During the regular execution, there will be 2 types of threads:
91 // - Write thread: gets a large number of blocks using GetUnusedBlock,
92 // writes them on disk (if on destructive mode),
93 // reads block content ONCE from disk and them removes
94 // the block from queue with RemoveBlock. After a removal a
95 // block is not available for read threads, but it is
96 // only removed from memory if there is no reference for
97 // this block. Note that a write thread also counts as
99 // - Read threads: get one block at a time (if available) with
100 // GetRandomBlock, reads its content from disk,
101 // checking whether it is correct or not, and releases
102 // (Using ReleaseBlock) the block to be erased by the
103 // write threads. Since several read threads are allowed
104 // to read the same block, a reference counter is used to
105 // control when the block can be REALLY erased from
106 // memory, and all memory management is made by a
107 // DiskBlockTable instance.
109 // Returns a new block in a unused address. Does not
110 // grant ownership of the pointer to the caller
111 // (use RemoveBlock to delete the block from memory instead).
112 BlockData *GetUnusedBlock(int64 segment);
114 // Removes block from structure (called by write threads). Returns
115 // 1 if successful, 0 otherwise.
116 int RemoveBlock(BlockData *block);
118 // Gets a random block from the list. Only returns if an element
119 // is available (a write thread has got this block, written it on disk,
120 // and set this block as initialized). Does not grant ownership of the
121 // pointer to the caller (use RemoveBlock to delete the block from
123 BlockData *GetRandomBlock();
125 // Releases block to be erased (called by random threads). Returns
126 // 1 if successful, 0 otherwise.
127 int ReleaseBlock(BlockData *block);
134 typedef map<int64, StorageData*> AddrToBlockMap;
135 typedef vector<int64> PosToAddrVector;
137 // Inserts block in structure, used in tests and by other methods.
138 void InsertOnStructure(BlockData *block);
140 // Generates a random 64-bit integer.
141 // Virtual method so it can be overridden by the tests.
142 virtual int64 Random64();
144 // Accessor methods for testing.
145 const PosToAddrVector& pos_to_addr() const { return pos_to_addr_; }
146 const AddrToBlockMap& addr_to_block() const { return addr_to_block_; }
148 int sector_size() const { return sector_size_; }
149 int write_block_size() const { return write_block_size_; }
150 const string& device_name() const { return device_name_; }
151 int64 device_sectors() const { return device_sectors_; }
152 int64 segment_size() const { return segment_size_; }
155 // Number of retries to allocate sectors.
156 static const int kBlockRetry = 100;
158 PosToAddrVector pos_to_addr_;
159 AddrToBlockMap addr_to_block_;
161 // Configuration parameters for block selection
162 int sector_size_; // Sector size, in bytes
163 int write_block_size_; // Block size, in bytes
164 string device_name_; // Device name
165 int64 device_sectors_; // Number of sectors in device
166 int64 segment_size_; // Segment size in bytes
167 uint64 size_; // Number of elements on table
168 pthread_mutex_t data_mutex_;
169 pthread_cond_t data_condition_;
170 pthread_mutex_t parameter_mutex_;
171 DISALLOW_COPY_AND_ASSIGN(DiskBlockTable);
174 #endif // STRESSAPPTEST_BLOCKS_H_