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// Interface for a thread-safe container of disk blocks
16b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
17b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson#ifndef STRESSAPPTEST_DISK_BLOCKS_H_
18b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson#define STRESSAPPTEST_DISK_BLOCKS_H_
19b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
20b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson#include <sys/types.h>
21b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson#include <pthread.h>
22b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson#include <time.h>
23b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson#include <sys/time.h>
24b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson#include <errno.h>
25b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson#include <map>
26b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson#include <vector>
27b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson#include <string>
28b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson// This file must work with autoconf on its public version,
29b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson// so these includes are correct.
30b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson#include "pattern.h"
31b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
32b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson// Data about a block written to disk so that it can be verified later.
33b0114cb9f332db144f65291211ae65f7f0e814e6Scott Andersonclass BlockData {
34b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson public:
35b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  BlockData();
36b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  ~BlockData();
37b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  void SetParameters(int64 address, int64 size);
38b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  void IncreaseReferenceCounter();
39b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  void DecreaseReferenceCounter();
40b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  int GetReferenceCounter();
41b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  void SetBlockAsInitialized();
42b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  bool BlockIsInitialized();
43b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  int64 GetAddress();
44b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  int64 GetSize();
45b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  void SetPattern(Pattern *p);
46b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  Pattern *GetPattern();
47b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson protected:
48b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  int64 addr_;         // address of first sector in block
49b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  int64 size_;         // size of block
50b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  int references_;      // reference counter
51b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  bool initialized_;     // flag indicating the block was written on disk
52b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  Pattern *pattern_;
53b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  pthread_mutex_t data_mutex_;
54b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  DISALLOW_COPY_AND_ASSIGN(BlockData);
55b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson};
56b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
57b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson// Disk Block table - store data from blocks to be write / read by
58b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson// a DiskThread
59b0114cb9f332db144f65291211ae65f7f0e814e6Scott Andersonclass DiskBlockTable {
60b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson public:
61b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  DiskBlockTable();
62b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  virtual ~DiskBlockTable();
63b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
64b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  // Get Number of elements stored on table
65b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  int64 NumElems();
66b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  // Clean all table data
67b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  void CleanTable();
68b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  // Get a random block from the list. Only returns if a element
69b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  // is available (consider that other thread must have added them.
70b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  BlockData *GetRandomBlock();
71b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  // Set all initial parameters. Assumes all existent data is
72b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  // invalid and, therefore, must be removed.
73b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  void SetParameters(int sector_size, int write_block_size,
74b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson                     int64 device_sectors,
75b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson                     int64 segment_size,
76b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson                     string device_name);
77b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  // Return a new block in a unused address.
78b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  BlockData *GetUnusedBlock(int64 segment);
79b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  // Remove block from structure (called by write threads)
80b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  int RemoveBlock(BlockData *block);
81b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  // Release block to be erased (called by random threads)
82b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  int ReleaseBlock(BlockData *block);
83b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
84b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson protected:
85b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
86b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  void InsertOnStructure(BlockData *block);
87b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  //  Generate a random 64-bit integer (virtual so it could be
88b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  //  override by the tests)
89b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  virtual int64 Random64();
90b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
91b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  struct StorageData {
92b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    BlockData *block;
93b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    int pos;
94b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  };
95b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
96b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  static const int kBlockRetry = 100;       // Number of retries to allocate
97b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson                                            // sectors.
98b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
99b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  typedef map<int64, StorageData*> AddrToBlockMap;
100b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  typedef vector<int64> PosToAddrVector;
101b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  PosToAddrVector pos_to_addr_;
102b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  AddrToBlockMap addr_to_block_;
103b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  uint64 nelems_;
104b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  int sector_size_;          // Sector size, in bytes
105b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  int write_block_size_;     // Block size, in bytes
106b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  string device_name_;       // Device name
107b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  int64 device_sectors_;     // Number of sectors in device
108b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  int64 segment_size_;       // Segment size, in bytes
109b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  pthread_mutex_t data_mutex_;
110b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  pthread_cond_t data_condition_;
111b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  pthread_mutex_t parameter_mutex_;
112b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  DISALLOW_COPY_AND_ASSIGN(DiskBlockTable);
113b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson};
114b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
115b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson#endif  // STRESSAPPTEST_BLOCKS_H_
116