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(&parameter_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(&parameter_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(&parameter_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(&parameter_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(&parameter_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(&parameter_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