chiark / gitweb /
New frequency test, fixed error accounting, added logging timestamps, and miscellaneo...
[stressapptest] / src / disk_blocks.h
index cb634c9135833d3ee780c1746ecac0e82e7d7b55..638ee9f34242592df73cf9aac7fc2043c373c877 100644 (file)
 #include <map>
 #include <vector>
 #include <string>
-// This file must work with autoconf on its public version,
-// so these includes are correct.
-#include "pattern.h"
+
+#include "sattypes.h"
+
+class Pattern;
 
 // Data about a block written to disk so that it can be verified later.
+// Thread-unsafe, must be used with locks on non-const methods,
+// except for initialized accessor/mutator, which are thread-safe
+// (and in fact, is the only method supposed to be accessed from
+// someone which is not the thread-safe DiskBlockTable).
 class BlockData {
  public:
   BlockData();
   ~BlockData();
-  void SetParameters(int64 address, int64 size);
-  void IncreaseReferenceCounter();
-  void DecreaseReferenceCounter();
-  int GetReferenceCounter();
-  void SetBlockAsInitialized();
-  bool BlockIsInitialized();
-  int64 GetAddress();
-  int64 GetSize();
-  void SetPattern(Pattern *p);
-  Pattern *GetPattern();
- protected:
-  int64 addr_;         // address of first sector in block
-  int64 size_;         // size of block
-  int references_;      // reference counter
-  bool initialized_;     // flag indicating the block was written on disk
+
+  // These are reference counters used to control how many
+  // threads currently have a copy of this particular block.
+  void IncreaseReferenceCounter() { references_++; }
+  void DecreaseReferenceCounter() { references_--; }
+  int GetReferenceCounter() const { return references_; }
+
+  // Controls whether the block was written on disk or not.
+  // Once written, you cannot "un-written" then without destroying
+  // this object.
+  void set_initialized();
+  bool initialized() const;
+
+  // Accessor methods for some data related to blocks.
+  void set_address(uint64 address) { address_ = address; }
+  uint64 address() const { return address_; }
+  void set_size(uint64 size) { size_ = size; }
+  uint64 size() const { return size_; }
+  void set_pattern(Pattern *p) { pattern_ = p; }
+  Pattern *pattern() { return pattern_; }
+ private:
+  uint64 address_;  // Address of first sector in block
+  uint64 size_;  // Size of block
+  int references_;  // Reference counter
+  bool initialized_;  // Flag indicating the block was written on disk
   Pattern *pattern_;
-  pthread_mutex_t data_mutex_;
+  mutable pthread_mutex_t data_mutex_;
   DISALLOW_COPY_AND_ASSIGN(BlockData);
 };
 
-// Disk Block table - store data from blocks to be write / read by
-// a DiskThread
+// A thread-safe table used to store block data and control access
+// to these blocks, letting several threads read and write blocks on
+// disk.
 class DiskBlockTable {
  public:
   DiskBlockTable();
   virtual ~DiskBlockTable();
 
-  // Get Number of elements stored on table
-  int64 NumElems();
-  // Clean all table data
-  void CleanTable();
-  // Get a random block from the list. Only returns if a element
-  // is available (consider that other thread must have added them.
-  BlockData *GetRandomBlock();
-  // Set all initial parameters. Assumes all existent data is
+  // Returns number of elements stored on table.
+  uint64 Size();
+
+  // Sets all initial parameters. Assumes all existent data is
   // invalid and, therefore, must be removed.
   void SetParameters(int sector_size, int write_block_size,
                      int64 device_sectors,
                      int64 segment_size,
-                     string device_name);
-  // Return a new block in a unused address.
+                     const string& device_name);
+
+  // During the regular execution, there will be 2 types of threads:
+  // - Write thread:  gets a large number of blocks using GetUnusedBlock,
+  //                  writes them on disk (if on destructive mode),
+  //                  reads block content ONCE from disk and them removes
+  //                  the block from queue with RemoveBlock. After a removal a
+  //                  block is not available for read threads, but it is
+  //                  only removed from memory if there is no reference for
+  //                  this block. Note that a write thread also counts as
+  //                  a reference.
+  // - Read threads:  get one block at a time (if available) with
+  //                  GetRandomBlock, reads its content from disk,
+  //                  checking whether it is correct or not, and releases
+  //                  (Using ReleaseBlock) the block to be erased by the
+  //                  write threads. Since several read threads are allowed
+  //                  to read the same block, a reference counter is used to
+  //                  control when the block can be REALLY erased from
+  //                  memory, and all memory management is made by a
+  //                  DiskBlockTable instance.
+
+  // Returns a new block in a unused address. Does not
+  // grant ownership of the pointer to the caller
+  // (use RemoveBlock to delete the block from memory instead).
   BlockData *GetUnusedBlock(int64 segment);
-  // Remove block from structure (called by write threads)
+
+  // Removes block from structure (called by write threads). Returns
+  // 1 if successful, 0 otherwise.
   int RemoveBlock(BlockData *block);
-  // Release block to be erased (called by random threads)
-  int ReleaseBlock(BlockData *block);
 
- protected:
+  // Gets a random block from the list. Only returns if an element
+  // is available (a write thread has got this block, written it on disk,
+  // and set this block as initialized). Does not grant ownership of the
+  // pointer to the caller (use RemoveBlock to delete the block from
+  // memory instead).
+  BlockData *GetRandomBlock();
 
-  void InsertOnStructure(BlockData *block);
-  //  Generate a random 64-bit integer (virtual so it could be
-  //  override by the tests)
-  virtual int64 Random64();
+  // Releases block to be erased (called by random threads). Returns
+  // 1 if successful, 0 otherwise.
+  int ReleaseBlock(BlockData *block);
 
+ protected:
   struct StorageData {
     BlockData *block;
     int pos;
   };
-
-  static const int kBlockRetry = 100;       // Number of retries to allocate
-                                            // sectors.
-
   typedef map<int64, StorageData*> AddrToBlockMap;
   typedef vector<int64> PosToAddrVector;
+
+  // Inserts block in structure, used in tests and by other methods.
+  void InsertOnStructure(BlockData *block);
+
+  // Generates a random 64-bit integer.
+  // Virtual method so it can be overridden by the tests.
+  virtual int64 Random64();
+
+  // Accessor methods for testing.
+  const PosToAddrVector& pos_to_addr() const { return pos_to_addr_; }
+  const AddrToBlockMap& addr_to_block() const { return addr_to_block_; }
+
+  int sector_size() const { return sector_size_; }
+  int write_block_size() const { return write_block_size_; }
+  const string& device_name() const { return device_name_; }
+  int64 device_sectors() const { return device_sectors_; }
+  int64 segment_size() const { return segment_size_; }
+
+ private:
+  // Number of retries to allocate sectors.
+  static const int kBlockRetry = 100;
+  // Actual tables.
   PosToAddrVector pos_to_addr_;
   AddrToBlockMap addr_to_block_;
-  uint64 nelems_;
-  int sector_size_;          // Sector size, in bytes
-  int write_block_size_;     // Block size, in bytes
-  string device_name_;       // Device name
-  int64 device_sectors_;     // Number of sectors in device
-  int64 segment_size_;       // Segment size, in bytes
+
+  // Configuration parameters for block selection
+  int sector_size_;  // Sector size, in bytes
+  int write_block_size_;  // Block size, in bytes
+  string device_name_;  // Device name
+  int64 device_sectors_;  // Number of sectors in device
+  int64 segment_size_;  // Segment size in bytes
+  uint64 size_;  // Number of elements on table
   pthread_mutex_t data_mutex_;
   pthread_cond_t data_condition_;
   pthread_mutex_t parameter_mutex_;