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