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

     1  package filesystem
     2  
     3  import (
     4  	"errors"
     5  	"io"
     6  	"os"
     7  	"path"
     8  
     9  	"github.com/Cloud-Foundations/Dominator/lib/fsutil"
    10  	"github.com/Cloud-Foundations/Dominator/lib/hash"
    11  	"github.com/Cloud-Foundations/Dominator/lib/objectcache"
    12  )
    13  
    14  var stashDirectory string = ".stash"
    15  
    16  func (objSrv *ObjectServer) commitObject(hashVal hash.Hash) error {
    17  	hashName := objectcache.HashToFilename(hashVal)
    18  	filename := path.Join(objSrv.BaseDirectory, hashName)
    19  	stashFilename := path.Join(objSrv.BaseDirectory, stashDirectory, hashName)
    20  	fi, err := os.Lstat(stashFilename)
    21  	if err != nil {
    22  		if length, _ := objSrv.checkObject(hashVal); length > 0 {
    23  			return nil // Previously committed: return success.
    24  		}
    25  		return err
    26  	}
    27  	if !fi.Mode().IsRegular() {
    28  		fsutil.ForceRemove(stashFilename)
    29  		return errors.New("existing non-file: " + stashFilename)
    30  	}
    31  	err = os.MkdirAll(path.Dir(filename), fsutil.PrivateDirPerms)
    32  	if err != nil {
    33  		return err
    34  	}
    35  	objSrv.rwLock.Lock()
    36  	defer objSrv.rwLock.Unlock()
    37  	if _, ok := objSrv.objects[hashVal]; ok {
    38  		fsutil.ForceRemove(stashFilename)
    39  		// Run in a goroutine to keep outside of the lock.
    40  		go objSrv.addCallback(hashVal, uint64(fi.Size()), false)
    41  		return nil
    42  	} else {
    43  		objSrv.add(&objectType{hash: hashVal, size: uint64(fi.Size())})
    44  		if objSrv.addCallback != nil {
    45  			// Run in a goroutine to keep outside of the lock.
    46  			go objSrv.addCallback(hashVal, uint64(fi.Size()), true)
    47  		}
    48  		return os.Rename(stashFilename, filename)
    49  	}
    50  }
    51  
    52  func (objSrv *ObjectServer) deleteStashedObject(hashVal hash.Hash) error {
    53  	filename := path.Join(objSrv.BaseDirectory, stashDirectory,
    54  		objectcache.HashToFilename(hashVal))
    55  	return os.Remove(filename)
    56  }
    57  
    58  func (objSrv *ObjectServer) stashOrVerifyObject(reader io.Reader,
    59  	length uint64, expectedHash *hash.Hash) (hash.Hash, []byte, error) {
    60  	hashVal, data, err := objectcache.ReadObject(reader, length, expectedHash)
    61  	if err != nil {
    62  		return hashVal, nil, err
    63  	}
    64  	hashName := objectcache.HashToFilename(hashVal)
    65  	filename := path.Join(objSrv.BaseDirectory, hashName)
    66  	// Check for existing object and collision.
    67  	if length, err := objSrv.checkObject(hashVal); err != nil {
    68  		return hashVal, nil, err
    69  	} else if length > 0 {
    70  		if err := collisionCheck(data, filename, int64(length)); err != nil {
    71  			return hashVal, nil, err
    72  		}
    73  		return hashVal, nil, nil
    74  	}
    75  	// Check for existing stashed object and collision.
    76  	stashFilename := path.Join(objSrv.BaseDirectory, stashDirectory, hashName)
    77  	if _, err := objSrv.addOrCompare(hashVal, data, stashFilename); err != nil {
    78  		return hashVal, nil, err
    79  	} else {
    80  		return hashVal, data, nil
    81  	}
    82  }