github.com/Cloud-Foundations/Dominator@v0.3.4/lib/objectserver/filesystem/api.go (about)

     1  package filesystem
     2  
     3  import (
     4  	"flag"
     5  	"io"
     6  	"sync"
     7  	"time"
     8  
     9  	"github.com/Cloud-Foundations/Dominator/lib/flagutil"
    10  	"github.com/Cloud-Foundations/Dominator/lib/hash"
    11  	"github.com/Cloud-Foundations/Dominator/lib/lockwatcher"
    12  	"github.com/Cloud-Foundations/Dominator/lib/log"
    13  	"github.com/Cloud-Foundations/Dominator/lib/log/debuglogger"
    14  	"github.com/Cloud-Foundations/Dominator/lib/objectserver"
    15  )
    16  
    17  var (
    18  	objectServerCleanupStartPercent = flag.Int(
    19  		"objectServerCleanupStartPercent", 95, "")
    20  	objectServerCleanupStartSize   flagutil.Size
    21  	objectServerCleanupStopPercent = flag.Int("objectServerCleanupStopPercent",
    22  		90, "")
    23  	objectServerCleanupStopSize flagutil.Size
    24  
    25  	// Interface check.
    26  	_ objectserver.FullObjectServer = (*ObjectServer)(nil)
    27  )
    28  
    29  func init() {
    30  	flag.Var(&objectServerCleanupStartSize, "objectServerCleanupStartSize", "")
    31  	flag.Var(&objectServerCleanupStopSize, "objectServerCleanupStopSize", "")
    32  }
    33  
    34  type objectType struct {
    35  	hash              hash.Hash
    36  	newerUnreferenced *objectType
    37  	olderUnreferenced *objectType
    38  	refcount          uint64
    39  	size              uint64
    40  }
    41  
    42  type Config struct {
    43  	BaseDirectory     string
    44  	LockCheckInterval time.Duration
    45  	LockLogTimeout    time.Duration
    46  }
    47  
    48  type ObjectServer struct {
    49  	addCallback objectserver.AddCallback
    50  	Config
    51  	gc          objectserver.GarbageCollector
    52  	lockWatcher *lockwatcher.LockWatcher
    53  	Params
    54  	rwLock                sync.RWMutex // Protect the following fields.
    55  	duplicatedBytes       uint64       // Sum of refcount*size for all objects.
    56  	lastGarbageCollection time.Time
    57  	lastMutationTime      time.Time
    58  	objects               map[hash.Hash]*objectType // Only set if object known.
    59  	newestUnreferenced    *objectType
    60  	numDuplicated         uint64 // Sum of refcount for all objects.
    61  	numReferenced         uint64
    62  	numUnreferenced       uint64
    63  	oldestUnreferenced    *objectType
    64  	referencedBytes       uint64
    65  	totalBytes            uint64
    66  	unreferencedBytes     uint64
    67  }
    68  
    69  type Params struct {
    70  	Logger log.DebugLogger
    71  }
    72  
    73  func NewObjectServer(baseDir string, logger log.Logger) (
    74  	*ObjectServer, error) {
    75  	return newObjectServer(
    76  		Config{BaseDirectory: baseDir},
    77  		Params{Logger: debuglogger.Upgrade(logger)},
    78  	)
    79  }
    80  
    81  func NewObjectServerWithConfigAndParams(config Config, params Params) (
    82  	*ObjectServer, error) {
    83  	return newObjectServer(config, params)
    84  }
    85  
    86  // AddObject will add an object. Object data are read from reader (length bytes
    87  // are read). The object hash is computed and compared with expectedHash if not
    88  // nil. The following are returned:
    89  //
    90  //	computed hash value
    91  //	a boolean which is true if the object is new
    92  //	an error or nil if no error.
    93  func (objSrv *ObjectServer) AddObject(reader io.Reader, length uint64,
    94  	expectedHash *hash.Hash) (hash.Hash, bool, error) {
    95  	return objSrv.addObject(reader, length, expectedHash)
    96  }
    97  
    98  // AdjustRefcounts will increment or decrement the refcounts for each object
    99  // yielded by the specified objects iterator. If there are missing objects or
   100  // the iterator returns an error, the adjustments are reverted and an error is
   101  // returned.
   102  func (objSrv *ObjectServer) AdjustRefcounts(increment bool,
   103  	iterator objectserver.ObjectsIterator) error {
   104  	return objSrv.adjustRefcounts(increment, iterator)
   105  }
   106  
   107  func (objSrv *ObjectServer) CheckObjects(hashes []hash.Hash) ([]uint64, error) {
   108  	return objSrv.checkObjects(hashes)
   109  }
   110  
   111  // CommitObject will commit (add) a previously stashed object.
   112  func (objSrv *ObjectServer) CommitObject(hashVal hash.Hash) error {
   113  	return objSrv.commitObject(hashVal)
   114  }
   115  
   116  func (objSrv *ObjectServer) DeleteObject(hashVal hash.Hash) error {
   117  	return objSrv.deleteObject(hashVal, false)
   118  }
   119  
   120  func (objSrv *ObjectServer) DeleteStashedObject(hashVal hash.Hash) error {
   121  	return objSrv.deleteStashedObject(hashVal)
   122  }
   123  
   124  // DeleteUnreferenced will delete some or all unreferenced objects.
   125  // The oldest unreferenced objects are deleted first, until both the percentage
   126  // and bytes thresholds are satisfied. The number of bytes and objects deleted
   127  // are returned.
   128  func (objSrv *ObjectServer) DeleteUnreferenced(percentage uint8,
   129  	bytes uint64) (uint64, uint64, error) {
   130  	return objSrv.deleteUnreferenced(percentage, bytes)
   131  }
   132  
   133  func (objSrv *ObjectServer) ListUnreferenced() map[hash.Hash]uint64 {
   134  	return objSrv.listUnreferenced()
   135  }
   136  
   137  func (objSrv *ObjectServer) SetAddCallback(callback objectserver.AddCallback) {
   138  	objSrv.addCallback = callback
   139  }
   140  
   141  // SetGarbageCollector is deprecated.
   142  func (objSrv *ObjectServer) SetGarbageCollector(
   143  	gc objectserver.GarbageCollector) {
   144  	objSrv.gc = gc
   145  }
   146  
   147  func (objSrv *ObjectServer) GetObject(hashVal hash.Hash) (
   148  	uint64, io.ReadCloser, error) {
   149  	return objectserver.GetObject(objSrv, hashVal)
   150  }
   151  
   152  func (objSrv *ObjectServer) GetObjects(hashes []hash.Hash) (
   153  	objectserver.ObjectsReader, error) {
   154  	return objSrv.getObjects(hashes)
   155  }
   156  
   157  func (objSrv *ObjectServer) LastMutationTime() time.Time {
   158  	objSrv.rwLock.RLock()
   159  	defer objSrv.rwLock.RUnlock()
   160  	return objSrv.lastMutationTime
   161  }
   162  
   163  func (objSrv *ObjectServer) ListObjectSizes() map[hash.Hash]uint64 {
   164  	return objSrv.listObjectSizes()
   165  }
   166  
   167  func (objSrv *ObjectServer) ListObjects() []hash.Hash {
   168  	return objSrv.listObjects()
   169  }
   170  
   171  func (objSrv *ObjectServer) NumObjects() uint64 {
   172  	objSrv.rwLock.RLock()
   173  	defer objSrv.rwLock.RUnlock()
   174  	return uint64(len(objSrv.objects))
   175  }
   176  
   177  // StashOrVerifyObject will stash an object if it is new or it will verify if it
   178  // already exists. Object data are read from reader (length bytes are read). The
   179  // object hash is computed and compared with expectedHash if not nil.
   180  // The following are returned:
   181  //
   182  //	computed hash value
   183  //	the object data if the object is new, otherwise nil
   184  //	an error or nil if no error.
   185  func (objSrv *ObjectServer) StashOrVerifyObject(reader io.Reader,
   186  	length uint64, expectedHash *hash.Hash) (hash.Hash, []byte, error) {
   187  	return objSrv.stashOrVerifyObject(reader, length, expectedHash)
   188  }
   189  
   190  func (objSrv *ObjectServer) WriteHtml(writer io.Writer) {
   191  	objSrv.writeHtml(writer)
   192  }
   193  
   194  type ObjectsReader struct {
   195  	objectServer *ObjectServer
   196  	hashes       []hash.Hash
   197  	nextIndex    int64
   198  	sizes        []uint64
   199  }
   200  
   201  func (or *ObjectsReader) Close() error {
   202  	return nil
   203  }
   204  
   205  func (or *ObjectsReader) NextObject() (uint64, io.ReadCloser, error) {
   206  	return or.nextObject()
   207  }
   208  
   209  func (or *ObjectsReader) ObjectSizes() []uint64 {
   210  	return or.sizes
   211  }