X-Git-Url: https://git.arvados.org/arvados.git/blobdiff_plain/0a98952530fb465fa31566fa5e0192bea9fc16e4..816764a283c2cbf2d41b4582113065922b99bd52:/services/keep-balance/block_state.go diff --git a/services/keep-balance/block_state.go b/services/keep-balance/block_state.go index d60738613d..22e89c019a 100644 --- a/services/keep-balance/block_state.go +++ b/services/keep-balance/block_state.go @@ -1,3 +1,7 @@ +// Copyright (C) The Arvados Authors. All rights reserved. +// +// SPDX-License-Identifier: AGPL-3.0 + package main import ( @@ -10,25 +14,43 @@ import ( // Azure storage container, etc.) as reported in a keepstore index // response. type Replica struct { - *KeepService + *KeepMount Mtime int64 } -// BlockState indicates the number of desired replicas (according to -// the collections we know about) and the replicas actually stored -// (according to the keepstore indexes we know about). +// BlockState indicates the desired storage class and number of +// replicas (according to the collections we know about) and the +// replicas actually stored (according to the keepstore indexes we +// know about). type BlockState struct { Replicas []Replica - Desired int + Desired map[string]int + // TODO: Support combinations of classes ("private + durable") + // by replacing the map[string]int with a map[*[]string]int + // here, where the map keys come from a pool of semantically + // distinct class combinations. + // + // TODO: Use a pool of semantically distinct Desired maps to + // conserve memory (typically there are far more BlockState + // objects in memory than distinct Desired profiles). } +var defaultClasses = []string{"default"} + func (bs *BlockState) addReplica(r Replica) { bs.Replicas = append(bs.Replicas, r) } -func (bs *BlockState) increaseDesired(n int) { - if bs.Desired < n { - bs.Desired = n +func (bs *BlockState) increaseDesired(classes []string, n int) { + if len(classes) == 0 { + classes = defaultClasses + } + for _, class := range classes { + if bs.Desired == nil { + bs.Desired = map[string]int{class: n} + } else if d, ok := bs.Desired[class]; !ok || d < n { + bs.Desired[class] = n + } } } @@ -69,27 +91,27 @@ func (bsm *BlockStateMap) Apply(f func(arvados.SizedDigest, *BlockState)) { } } -// AddReplicas updates the map to indicate srv has a replica of each -// block in idx. -func (bsm *BlockStateMap) AddReplicas(srv *KeepService, idx []arvados.KeepServiceIndexEntry) { +// AddReplicas updates the map to indicate that mnt has a replica of +// each block in idx. +func (bsm *BlockStateMap) AddReplicas(mnt *KeepMount, idx []arvados.KeepServiceIndexEntry) { bsm.mutex.Lock() defer bsm.mutex.Unlock() for _, ent := range idx { bsm.get(ent.SizedDigest).addReplica(Replica{ - KeepService: srv, - Mtime: ent.Mtime, + KeepMount: mnt, + Mtime: ent.Mtime, }) } } // IncreaseDesired updates the map to indicate the desired replication -// for the given blocks is at least n. -func (bsm *BlockStateMap) IncreaseDesired(n int, blocks []arvados.SizedDigest) { +// for the given blocks in the given storage class is at least n. +func (bsm *BlockStateMap) IncreaseDesired(classes []string, n int, blocks []arvados.SizedDigest) { bsm.mutex.Lock() defer bsm.mutex.Unlock() for _, blkid := range blocks { - bsm.get(blkid).increaseDesired(n) + bsm.get(blkid).increaseDesired(classes, n) } }