Merge branch 'master' into 9998-no-count-items-available
[arvados.git] / services / keepstore / volume.go
index 6e01e75b879b339232603d38f93cb040ecc6d86c..778f27fcde87cbc324a246aec571b3fe7a5c2b8a 100644 (file)
@@ -1,11 +1,24 @@
 package main
 
 import (
+       "context"
        "io"
        "sync/atomic"
        "time"
 )
 
+type BlockWriter interface {
+       // WriteBlock reads all data from r, writes it to a backing
+       // store as "loc", and returns the number of bytes written.
+       WriteBlock(ctx context.Context, loc string, r io.Reader) error
+}
+
+type BlockReader interface {
+       // ReadBlock retrieves data previously stored as "loc" and
+       // writes it to w.
+       ReadBlock(ctx context.Context, loc string, w io.Writer) error
+}
+
 // A Volume is an interface representing a Keep back-end storage unit:
 // for example, a single mounted disk, a RAID array, an Amazon S3 volume,
 // etc.
@@ -47,14 +60,14 @@ type Volume interface {
        // any of the data.
        //
        // len(buf) will not exceed BlockSize.
-       Get(loc string, buf []byte) (int, error)
+       Get(ctx context.Context, loc string, buf []byte) (int, error)
 
        // Compare the given data with the stored data (i.e., what Get
        // would return). If equal, return nil. If not, return
        // CollisionError or DiskHashError (depending on whether the
        // data on disk matches the expected hash), or whatever error
        // was encountered opening/reading the stored data.
-       Compare(loc string, data []byte) error
+       Compare(ctx context.Context, loc string, data []byte) error
 
        // Put writes a block to an underlying storage device.
        //
@@ -84,7 +97,7 @@ type Volume interface {
        //
        // Put should not verify that loc==hash(block): this is the
        // caller's responsibility.
-       Put(loc string, block []byte) error
+       Put(ctx context.Context, loc string, block []byte) error
 
        // Touch sets the timestamp for the given locator to the
        // current time.
@@ -242,6 +255,10 @@ type VolumeManager interface {
        // with more free space, etc.
        NextWritable() Volume
 
+       // VolumeStats returns the ioStats used for tracking stats for
+       // the given Volume.
+       VolumeStats(Volume) *ioStats
+
        // Close shuts down the volume manager cleanly.
        Close()
 }
@@ -253,12 +270,16 @@ type RRVolumeManager struct {
        readables []Volume
        writables []Volume
        counter   uint32
+       iostats   map[Volume]*ioStats
 }
 
 // MakeRRVolumeManager initializes RRVolumeManager
 func MakeRRVolumeManager(volumes []Volume) *RRVolumeManager {
-       vm := &RRVolumeManager{}
+       vm := &RRVolumeManager{
+               iostats: make(map[Volume]*ioStats),
+       }
        for _, v := range volumes {
+               vm.iostats[v] = &ioStats{}
                vm.readables = append(vm.readables, v)
                if v.Writable() {
                        vm.writables = append(vm.writables, v)
@@ -286,18 +307,35 @@ func (vm *RRVolumeManager) NextWritable() Volume {
        return vm.writables[i%uint32(len(vm.writables))]
 }
 
+// VolumeStats returns an ioStats for the given volume.
+func (vm *RRVolumeManager) VolumeStats(v Volume) *ioStats {
+       return vm.iostats[v]
+}
+
 // Close the RRVolumeManager
 func (vm *RRVolumeManager) Close() {
 }
 
-// VolumeStatus provides status information of the volume consisting of:
-//   * mount_point
-//   * device_num (an integer identifying the underlying storage system)
-//   * bytes_free
-//   * bytes_used
+// VolumeStatus describes the current condition of a volume
 type VolumeStatus struct {
-       MountPoint string `json:"mount_point"`
-       DeviceNum  uint64 `json:"device_num"`
-       BytesFree  uint64 `json:"bytes_free"`
-       BytesUsed  uint64 `json:"bytes_used"`
+       MountPoint string
+       DeviceNum  uint64
+       BytesFree  uint64
+       BytesUsed  uint64
+}
+
+// ioStats tracks I/O statistics for a volume or server
+type ioStats struct {
+       Errors     uint64
+       Ops        uint64
+       CompareOps uint64
+       GetOps     uint64
+       PutOps     uint64
+       TouchOps   uint64
+       InBytes    uint64
+       OutBytes   uint64
+}
+
+type InternalStatser interface {
+       InternalStats() interface{}
 }