78 lines
2.7 KiB
Go
78 lines
2.7 KiB
Go
// Copyright (C) 2019 Storj Labs, Inc.
|
|
// See LICENSE for copying information.
|
|
|
|
package live
|
|
|
|
import (
|
|
"context"
|
|
"sync"
|
|
|
|
"github.com/skyrings/skyring-common/tools/uuid"
|
|
"go.uber.org/zap"
|
|
)
|
|
|
|
// memoryLiveAccounting represents an accounting.Cache-implementing
|
|
// instance using plain memory (no coordination with other servers). It can be
|
|
// used to coordinate tracking of how much space a project has used.
|
|
//
|
|
// This should probably only be used at small scale or for testing areas where
|
|
// the accounting cache does not matter significantly. For production, an
|
|
// implementation that allows multiple servers to participate together would
|
|
// be preferable.
|
|
type memoryLiveAccounting struct {
|
|
log *zap.Logger
|
|
|
|
spaceMapLock sync.RWMutex
|
|
spaceDeltas map[uuid.UUID]int64
|
|
}
|
|
|
|
func newMemoryLiveAccounting(log *zap.Logger) (*memoryLiveAccounting, error) {
|
|
pmac := &memoryLiveAccounting{log: log}
|
|
pmac.spaceDeltas = make(map[uuid.UUID]int64)
|
|
return pmac, nil
|
|
}
|
|
|
|
// GetProjectStorageUsage gets inline and remote storage totals for a given
|
|
// project, back to the time of the last accounting tally.
|
|
func (mac *memoryLiveAccounting) GetProjectStorageUsage(ctx context.Context, projectID uuid.UUID) (totalUsed int64, err error) {
|
|
defer mon.Task()(&ctx, projectID)(&err)
|
|
mac.spaceMapLock.Lock()
|
|
defer mac.spaceMapLock.Unlock()
|
|
curVal, ok := mac.spaceDeltas[projectID]
|
|
if !ok {
|
|
return 0, nil
|
|
}
|
|
return curVal, nil
|
|
}
|
|
|
|
// AddProjectStorageUsage lets the live accounting know that the given
|
|
// project has just added inlineSpaceUsed bytes of inline space usage
|
|
// and remoteSpaceUsed bytes of remote space usage.
|
|
func (mac *memoryLiveAccounting) AddProjectStorageUsage(ctx context.Context, projectID uuid.UUID, inlineSpaceUsed, remoteSpaceUsed int64) (err error) {
|
|
defer mon.Task()(&ctx, projectID, inlineSpaceUsed, remoteSpaceUsed)(&err)
|
|
if inlineSpaceUsed < 0 || remoteSpaceUsed < 0 {
|
|
return Error.New("Used space amounts must be greater than 0. Inline: %d, Remote: %d", inlineSpaceUsed, remoteSpaceUsed)
|
|
}
|
|
mac.spaceMapLock.Lock()
|
|
defer mac.spaceMapLock.Unlock()
|
|
curVal := mac.spaceDeltas[projectID]
|
|
newTotal := curVal + inlineSpaceUsed + remoteSpaceUsed
|
|
mac.spaceDeltas[projectID] = newTotal
|
|
return nil
|
|
}
|
|
|
|
// ResetTotals reset all space-used totals for all projects back to zero. This
|
|
// would normally be done in concert with calculating new tally counts in the
|
|
// accountingDB.
|
|
func (mac *memoryLiveAccounting) ResetTotals(ctx context.Context) (err error) {
|
|
defer mon.Task()(&ctx)(&err)
|
|
mac.log.Debug("Resetting real-time accounting data")
|
|
mac.spaceMapLock.Lock()
|
|
mac.spaceDeltas = make(map[uuid.UUID]int64)
|
|
mac.spaceMapLock.Unlock()
|
|
return nil
|
|
}
|
|
|
|
// Close matches the accounting.LiveAccounting interface.
|
|
func (mac *memoryLiveAccounting) Close() error { return nil }
|