X-Git-Url: https://git.arvados.org/arvados.git/blobdiff_plain/e0632f47bb83bda5badccc47cc2d8dbb70d92678..02b35f7480e2792377e2ed23f740fff4b53badb9:/services/keepstore/handlers.go diff --git a/services/keepstore/handlers.go b/services/keepstore/handlers.go index 81f7fcd123..910033ebb1 100644 --- a/services/keepstore/handlers.go +++ b/services/keepstore/handlers.go @@ -837,7 +837,7 @@ func (pr *putProgress) Copy() *putProgress { return &cp } -func newPutResult(classes []string) putProgress { +func newPutProgress(classes []string) putProgress { pr := putProgress{ classNeeded: make(map[string]bool, len(classes)), classTodo: make(map[string]bool, len(classes)), @@ -853,33 +853,29 @@ func newPutResult(classes []string) putProgress { return pr } -// PutBlock Stores the BLOCK (identified by the content id HASH) in Keep. +// PutBlock stores the given block on one or more volumes. // -// PutBlock(ctx, block, hash) -// Stores the BLOCK (identified by the content id HASH) in Keep. +// The MD5 checksum of the block must match the given hash. // -// The MD5 checksum of the block must be identical to the content id HASH. -// If not, an error is returned. +// The block is written to each writable volume (ordered by priority +// and then UUID, see volume.go) until at least one replica has been +// stored in each of the requested storage classes. // -// PutBlock stores the BLOCK on the first Keep volume with free space. -// A failure code is returned to the user only if all volumes fail. -// -// On success, PutBlock returns nil. -// On failure, it returns a KeepError with one of the following codes: -// -// 500 Collision -// A different block with the same hash already exists on this -// Keep server. -// 422 MD5Fail -// The MD5 hash of the BLOCK does not match the argument HASH. -// 503 Full -// There was not enough space left in any Keep volume to store -// the object. -// 500 Fail -// The object could not be stored for some other reason (e.g. -// all writes failed). The text of the error message should -// provide as much detail as possible. +// The returned error, if any, is a KeepError with one of the +// following codes: // +// 500 Collision +// A different block with the same hash already exists on this +// Keep server. +// 422 MD5Fail +// The MD5 hash of the BLOCK does not match the argument HASH. +// 503 Full +// There was not enough space left in any Keep volume to store +// the object. +// 500 Fail +// The object could not be stored for some other reason (e.g. +// all writes failed). The text of the error message should +// provide as much detail as possible. func PutBlock(ctx context.Context, volmgr *RRVolumeManager, block []byte, hash string, wantStorageClasses []string) (putProgress, error) { log := ctxlog.FromContext(ctx) @@ -890,7 +886,7 @@ func PutBlock(ctx context.Context, volmgr *RRVolumeManager, block []byte, hash s return putProgress{}, RequestHashError } - result := newPutResult(wantStorageClasses) + result := newPutProgress(wantStorageClasses) // If we already have this data, it's intact on disk, and we // can update its timestamp, return success. If we have @@ -916,7 +912,11 @@ func PutBlock(ctx context.Context, volmgr *RRVolumeManager, block []byte, hash s pending := result.Copy() var allFull atomic.Value allFull.Store(true) + + // We hold the lock for the duration of the "each volume" loop + // below, except when it is released during cond.Wait(). mtx.Lock() + for _, mnt := range writables { // Wait until our decision to use this mount does not // depend on the outcome of pending writes.