1b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson// Copyright 2008 Google Inc. All Rights Reserved. 2b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 3b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson// Licensed under the Apache License, Version 2.0 (the "License"); 4b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson// you may not use this file except in compliance with the License. 5b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson// You may obtain a copy of the License at 6b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 7b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson// http://www.apache.org/licenses/LICENSE-2.0 8b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 9b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson// Unless required by applicable law or agreed to in writing, software 10b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson// distributed under the License is distributed on an "AS IS" BASIS, 11b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson// See the License for the specific language governing permissions and 13b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson// limitations under the License. 14b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 15b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson// Thread-safe container of disk blocks 16b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 17b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson#include <utility> 18b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 19b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson// This file must work with autoconf on its public version, 20b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson// so these includes are correct. 21b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson#include "disk_blocks.h" 22b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 23b0114cb9f332db144f65291211ae65f7f0e814e6Scott AndersonDiskBlockTable::DiskBlockTable() { 24b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson nelems_ = 0; 25b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson pthread_mutex_init(&data_mutex_, NULL); 26b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson pthread_mutex_init(¶meter_mutex_, NULL); 27b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson pthread_cond_init(&data_condition_, NULL); 28b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson} 29b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 30b0114cb9f332db144f65291211ae65f7f0e814e6Scott AndersonDiskBlockTable::~DiskBlockTable() { 31b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson CleanTable(); 32b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson pthread_mutex_destroy(&data_mutex_); 33b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson pthread_mutex_destroy(¶meter_mutex_); 34b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson pthread_cond_destroy(&data_condition_); 35b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson} 36b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 37b0114cb9f332db144f65291211ae65f7f0e814e6Scott Andersonvoid DiskBlockTable::CleanTable() { 38b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson pthread_mutex_lock(&data_mutex_); 39b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson for (map<int64, StorageData*>::iterator it = 40b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson addr_to_block_.begin(); it != addr_to_block_.end(); ++it) { 41b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson delete it->second; 42b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson } 43b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson addr_to_block_.erase(addr_to_block_.begin(), addr_to_block_.end()); 44b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson nelems_ = 0; 45b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson pthread_cond_broadcast(&data_condition_); 46b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson pthread_mutex_unlock(&data_mutex_); 47b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson} 48b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 49b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson// 64-bit non-negative random number generator. Stolen from 50b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson// depot/google3/base/tracecontext_unittest.cc. 51b0114cb9f332db144f65291211ae65f7f0e814e6Scott Andersonint64 DiskBlockTable::Random64() { 52b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson int64 x = random(); 53b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson x = (x << 30) ^ random(); 54b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson x = (x << 30) ^ random(); 55b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson if (x >= 0) 56b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson return x; 57b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson else 58b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson return -x; 59b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson} 60b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 61b0114cb9f332db144f65291211ae65f7f0e814e6Scott Andersonint64 DiskBlockTable::NumElems() { 62b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson unsigned int nelems; 63b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson pthread_mutex_lock(&data_mutex_); 64b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson nelems = nelems_; 65b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson pthread_mutex_unlock(&data_mutex_); 66b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson return nelems; 67b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson} 68b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 69b0114cb9f332db144f65291211ae65f7f0e814e6Scott Andersonvoid DiskBlockTable::InsertOnStructure(BlockData *block) { 70b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson int64 address = block->GetAddress(); 71b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson StorageData *sd = new StorageData(); 72b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson sd->block = block; 73b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson sd->pos = nelems_; 74b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // Creating new block ... 75b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson pthread_mutex_lock(&data_mutex_); 76b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson if (pos_to_addr_.size() <= nelems_) { 77b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson pos_to_addr_.insert(pos_to_addr_.end(), address); 78b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson } else { 79b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson pos_to_addr_[nelems_] = address; 80b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson } 81b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson addr_to_block_.insert(std::make_pair(address, sd)); 82b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson nelems_++; 83b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson pthread_cond_broadcast(&data_condition_); 84b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson pthread_mutex_unlock(&data_mutex_); 85b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson} 86b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 87b0114cb9f332db144f65291211ae65f7f0e814e6Scott Andersonint DiskBlockTable::RemoveBlock(BlockData *block) { 88b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // For write threads, check the reference counter and remove 89b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // it from the structure. 90b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson int64 address = block->GetAddress(); 91b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson AddrToBlockMap::iterator it = addr_to_block_.find(address); 92b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson int ret = 1; 93b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson if (it != addr_to_block_.end()) { 94b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson int curr_pos = it->second->pos; 95b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson int last_pos = nelems_ - 1; 96b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson AddrToBlockMap::iterator last_it = addr_to_block_.find( 97b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson pos_to_addr_[last_pos]); 98b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson sat_assert(nelems_ > 0); 99b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson sat_assert(last_it != addr_to_block_.end()); 100b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // Everything is fine, updating ... 101b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson pthread_mutex_lock(&data_mutex_); 102b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson pos_to_addr_[curr_pos] = pos_to_addr_[last_pos]; 103b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson last_it->second->pos = curr_pos; 104b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson delete it->second; 105b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson addr_to_block_.erase(it); 106b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson nelems_--; 107b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson block->DecreaseReferenceCounter(); 108b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson if (block->GetReferenceCounter() == 0) 109b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson delete block; 110b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson pthread_cond_broadcast(&data_condition_); 111b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson pthread_mutex_unlock(&data_mutex_); 112b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson } else { 113b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson ret = 0; 114b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson } 115b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson return ret; 116b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson} 117b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 118b0114cb9f332db144f65291211ae65f7f0e814e6Scott Andersonint DiskBlockTable::ReleaseBlock(BlockData *block) { 119b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // If is a random thread, just check the reference counter. 120b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson int ret = 1; 121b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson pthread_mutex_lock(&data_mutex_); 122b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson int references = block->GetReferenceCounter(); 123b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson if (references > 0) { 124b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson if (references == 1) 125b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson delete block; 126b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson else 127b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson block->DecreaseReferenceCounter(); 128b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson } else { 129b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson ret = 0; 130b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson } 131b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson pthread_mutex_unlock(&data_mutex_); 132b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson return ret; 133b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson} 134b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 135b0114cb9f332db144f65291211ae65f7f0e814e6Scott AndersonBlockData *DiskBlockTable::GetRandomBlock() { 136b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson struct timespec ts; 137b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson struct timeval tp; 138b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson int result = 0; 139b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson gettimeofday(&tp, NULL); 140b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson ts.tv_sec = tp.tv_sec; 141b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson ts.tv_nsec = tp.tv_usec * 1000; 142b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson ts.tv_sec += 2; // Wait for 2 seconds. 143b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson pthread_mutex_lock(&data_mutex_); 144b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson while (!nelems_ && result != ETIMEDOUT) { 145b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson result = pthread_cond_timedwait(&data_condition_, &data_mutex_, &ts); 146b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson } 147b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson if (result == ETIMEDOUT) { 148b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson pthread_mutex_unlock(&data_mutex_); 149b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson return NULL; 150b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson } else { 151b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson int64 random_number = Random64(); 152b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson int64 random_pos = random_number % nelems_; 153b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson int64 address = pos_to_addr_[random_pos]; 154b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson AddrToBlockMap::const_iterator it = addr_to_block_.find(address); 155b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson sat_assert(it != addr_to_block_.end()); 156b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson BlockData *b = it->second->block; 157b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // A block is returned only if its content is written on disk. 158b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson if (b->BlockIsInitialized()) { 159b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson b->IncreaseReferenceCounter(); 160b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson } else { 161b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson b = NULL; 162b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson } 163b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson pthread_mutex_unlock(&data_mutex_); 164b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson return b; 165b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson } 166b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson} 167b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 168b0114cb9f332db144f65291211ae65f7f0e814e6Scott Andersonvoid DiskBlockTable::SetParameters( 169b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson int sector_size, int write_block_size, int64 device_sectors, 170b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson int64 segment_size, string device_name) { 171b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson pthread_mutex_lock(¶meter_mutex_); 172b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson sector_size_ = sector_size; 173b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson write_block_size_ = write_block_size; 174b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson device_sectors_ = device_sectors; 175b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson segment_size_ = segment_size; 176b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson device_name_ = device_name; 177b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson CleanTable(); 178b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson pthread_mutex_unlock(¶meter_mutex_); 179b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson} 180b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 181b0114cb9f332db144f65291211ae65f7f0e814e6Scott AndersonBlockData *DiskBlockTable::GetUnusedBlock(int64 segment) { 182b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson int64 sector = 0; 183b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson BlockData *block = new BlockData(); 184b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 185b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson bool good_sequence = false; 186b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson int num_sectors; 187b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 188b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson if (block == NULL) { 189b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson logprintf(0, "Process Error: Unable to allocate memory " 190b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson "for sector data for disk %s.\n", device_name_.c_str()); 191b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson return NULL; 192b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson } 193b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 194b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson pthread_mutex_lock(¶meter_mutex_); 195b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 196b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson sat_assert(device_sectors_ != 0); 197b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 198b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // Align the first sector with the beginning of a write block 199b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson num_sectors = write_block_size_ / sector_size_; 200b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 201b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson for (int i = 0; i < kBlockRetry && !good_sequence; i++) { 202b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson good_sequence = true; 203b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 204b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // Use the entire disk or a small segment of the disk to allocate the first 205b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // sector in the block from. 206b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 207b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson if (segment_size_ == -1) { 208b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson sector = (Random64() & 0x7FFFFFFFFFFFFFFFLL) % ( 209b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson device_sectors_ / num_sectors); 210b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson sector *= num_sectors; 211b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson } else { 212b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson sector = (Random64() & 0x7FFFFFFFFFFFFFFFLL) % ( 213b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson segment_size_ / num_sectors); 214b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson sector *= num_sectors; 215b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson sector += segment * segment_size_; 216b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 217b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // Make sure the block is within the segment. 218b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson if (sector + num_sectors > (segment + 1) * segment_size_) { 219b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson good_sequence = false; 220b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson continue; 221b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson } 222b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson } 223b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // Make sure the entire block is in range. 224b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson if (sector + num_sectors > device_sectors_) { 225b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson good_sequence = false; 226b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson continue; 227b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson } 228b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // Check to see if the block is free. Since the blocks are 229b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // now aligned to the write_block_size, it is not necessary 230b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // to check each sector, just the first block (a sector 231b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // overlap will never occur). 232b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 233b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson pthread_mutex_lock(&data_mutex_); 234b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson if (addr_to_block_.find(sector) != addr_to_block_.end()) { 235b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson good_sequence = false; 236b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson } 237b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson pthread_mutex_unlock(&data_mutex_); 238b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson } 239b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 240b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson if (good_sequence) { 241b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson block->SetParameters(sector, write_block_size_); 242b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson block->IncreaseReferenceCounter(); 243b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson InsertOnStructure(block); 244b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson } else { 245b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // No contiguous sequence of num_sectors sectors was found within 246b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // kBlockRetry iterations so return an error value. 247b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson delete block; 248b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson block = NULL; 249b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson } 250b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson pthread_mutex_unlock(¶meter_mutex_); 251b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 252b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson return block; 253b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson} 254b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 255b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson// BlockData 256b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 257b0114cb9f332db144f65291211ae65f7f0e814e6Scott AndersonBlockData::BlockData() { 258b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson addr_ = 0; 259b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson size_ = 0; 260b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson references_ = 0; 261b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson initialized_ = false; 262b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson pthread_mutex_init(&data_mutex_, NULL); 263b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson} 264b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 265b0114cb9f332db144f65291211ae65f7f0e814e6Scott AndersonBlockData::~BlockData() { 266b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson pthread_mutex_destroy(&data_mutex_); 267b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson} 268b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 269b0114cb9f332db144f65291211ae65f7f0e814e6Scott Andersonvoid BlockData::SetParameters(int64 address, int64 size) { 270b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson addr_ = address; 271b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson size_ = size; 272b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson} 273b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 274b0114cb9f332db144f65291211ae65f7f0e814e6Scott Andersonvoid BlockData::IncreaseReferenceCounter() { 275b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson references_++; 276b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson} 277b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 278b0114cb9f332db144f65291211ae65f7f0e814e6Scott Andersonvoid BlockData::DecreaseReferenceCounter() { 279b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson references_--; 280b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson} 281b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 282b0114cb9f332db144f65291211ae65f7f0e814e6Scott Andersonint BlockData::GetReferenceCounter() { 283b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson return references_; 284b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson} 285b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 286b0114cb9f332db144f65291211ae65f7f0e814e6Scott Andersonvoid BlockData::SetBlockAsInitialized() { 287b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson pthread_mutex_lock(&data_mutex_); 288b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson initialized_ = true; 289b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson pthread_mutex_unlock(&data_mutex_); 290b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson} 291b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 292b0114cb9f332db144f65291211ae65f7f0e814e6Scott Andersonbool BlockData::BlockIsInitialized() { 293b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson pthread_mutex_lock(&data_mutex_); 294b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson bool initialized = initialized_; 295b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson pthread_mutex_unlock(&data_mutex_); 296b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson return initialized; 297b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson} 298b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 299b0114cb9f332db144f65291211ae65f7f0e814e6Scott Andersonint64 BlockData::GetAddress() { 300b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson return addr_; 301b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson} 302b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 303b0114cb9f332db144f65291211ae65f7f0e814e6Scott Andersonint64 BlockData::GetSize() { 304b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson return size_; 305b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson} 306b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 307b0114cb9f332db144f65291211ae65f7f0e814e6Scott AndersonPattern *BlockData::GetPattern() { 308b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson return pattern_; 309b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson} 310b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 311b0114cb9f332db144f65291211ae65f7f0e814e6Scott Andersonvoid BlockData::SetPattern(Pattern *p) { 312b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson pattern_ = p; 313b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson} 314