Use generated locking database implementation (#947)
This commit is contained in:
parent
249244536a
commit
0ca03b41e2
6
go.mod
6
go.mod
@ -108,11 +108,13 @@ require (
|
||||
go.uber.org/multierr v1.1.0 // indirect
|
||||
go.uber.org/zap v1.9.1
|
||||
golang.org/x/crypto v0.0.0-20181009213950-7c1a557ab941
|
||||
golang.org/x/net v0.0.0-20181003013248-f5e5bdd77824
|
||||
golang.org/x/net v0.0.0-20181106065722-10aee1819953
|
||||
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f
|
||||
golang.org/x/sys v0.0.0-20181213081344-73d4af5aa059
|
||||
golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2 // indirect
|
||||
google.golang.org/grpc v1.15.0
|
||||
golang.org/x/tools v0.0.0-20181221235234-d00ac6d27372
|
||||
google.golang.org/genproto v0.0.0-20181221175505-bd9b4fb69e2f // indirect
|
||||
google.golang.org/grpc v1.16.0
|
||||
gopkg.in/Shopify/sarama.v1 v1.18.0 // indirect
|
||||
gopkg.in/cheggaaa/pb.v1 v1.0.25 // indirect
|
||||
gopkg.in/olivere/elastic.v5 v5.0.76 // indirect
|
||||
|
8
go.sum
8
go.sum
@ -346,6 +346,8 @@ golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73r
|
||||
golang.org/x/net v0.0.0-20180911220305-26e67e76b6c3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20181003013248-f5e5bdd77824 h1:MkjFNbaZJyH98M67Q3umtwZ+EdVdrNJLqSwZp5vcv60=
|
||||
golang.org/x/net v0.0.0-20181003013248-f5e5bdd77824/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20181106065722-10aee1819953 h1:LuZIitY8waaxUfNIdtajyE/YzA/zyf0YxXG27VpLrkg=
|
||||
golang.org/x/net v0.0.0-20181106065722-10aee1819953/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be h1:vEDujvNQGv4jgYKudGeI/+DAX4Jffq6hpD55MmoEvKs=
|
||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f h1:wMNYb4v58l5UBM7MYRLPG6ZhfOqbKu7X5eyFl8ZhKvA=
|
||||
@ -366,6 +368,8 @@ golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52 h1:JG/0uqcGdTNgq7FdU+61l5P
|
||||
golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20180911133044-677d2ff680c1 h1:dzEuQYa6+a3gROnSlgly5ERUm4SZKJt+dh+4iSbO+bI=
|
||||
golang.org/x/tools v0.0.0-20180911133044-677d2ff680c1/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20181221235234-d00ac6d27372 h1:zWPUEY/PjVHT+zO3L8OfkjrtIjf55joTxn/RQP/AjOI=
|
||||
golang.org/x/tools v0.0.0-20181221235234-d00ac6d27372/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
google.golang.org/api v0.0.0-20180818000503-e21acd801f91/go.mod h1:4mhQ8q/RsB7i+udVvVy5NUi08OU8ZlA0gRVgrF7VFY0=
|
||||
google.golang.org/api v0.0.0-20180826000528-7954115fcf34/go.mod h1:4mhQ8q/RsB7i+udVvVy5NUi08OU8ZlA0gRVgrF7VFY0=
|
||||
google.golang.org/api v0.0.0-20180910000450-7ca32eb868bf/go.mod h1:4mhQ8q/RsB7i+udVvVy5NUi08OU8ZlA0gRVgrF7VFY0=
|
||||
@ -375,9 +379,13 @@ google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8 h1:Nw54tB0rB7hY/N0
|
||||
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
|
||||
google.golang.org/genproto v0.0.0-20180912233945-5a2fd4cab2d6 h1:YN6g8chEdBTmaERxJzbJ6WKLrW3+Bf6rznOBkWNSQP0=
|
||||
google.golang.org/genproto v0.0.0-20180912233945-5a2fd4cab2d6/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
|
||||
google.golang.org/genproto v0.0.0-20181221175505-bd9b4fb69e2f h1:eT3B0O2ghdSPzjAOznr3oOLyN1HFeYUncYl7FRwg4VI=
|
||||
google.golang.org/genproto v0.0.0-20181221175505-bd9b4fb69e2f/go.mod h1:7Ep/1NZk928CDR8SjdVbjWNpdIf6nzjE3BTgJDr2Atg=
|
||||
google.golang.org/grpc v1.14.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw=
|
||||
google.golang.org/grpc v1.15.0 h1:Az/KuahOM4NAidTEuJCv/RonAA7rYsTPkqXVjr+8OOw=
|
||||
google.golang.org/grpc v1.15.0/go.mod h1:0JHn/cJsOMiMfNA9+DeHDlAU7KAAB5GDlYFpa9MZMio=
|
||||
google.golang.org/grpc v1.16.0 h1:dz5IJGuC2BB7qXR5AyHNwAUBhZscK2xVez7mznh72sY=
|
||||
google.golang.org/grpc v1.16.0/go.mod h1:0JHn/cJsOMiMfNA9+DeHDlAU7KAAB5GDlYFpa9MZMio=
|
||||
gopkg.in/Shopify/sarama.v1 v1.18.0 h1:f9aTXuIEFEjVvLG9p+kMSk01dMfFumHsySRk1okTdqU=
|
||||
gopkg.in/Shopify/sarama.v1 v1.18.0/go.mod h1:AxnvoaevB2nBjNK17cG61A3LleFcWFwVBHBt+cot4Oc=
|
||||
gopkg.in/airbrake/gobrake.v2 v2.0.9 h1:7z2uVWwn7oVeeugY1DtlPAy5H+KYgB1KeKTnqjNatLo=
|
||||
|
@ -10,13 +10,12 @@ import (
|
||||
"storj.io/storj/pkg/storj"
|
||||
)
|
||||
|
||||
//DB is an interface for interacting with accounting stuff
|
||||
// DB stores information about bandwidth usage
|
||||
type DB interface {
|
||||
// LastRawTime records the greatest last tallied time
|
||||
// LastRawTime records the latest last tallied time.
|
||||
LastRawTime(ctx context.Context, timestampType string) (time.Time, bool, error)
|
||||
// SaveBWRaw records raw sums of bw agreement values to the database
|
||||
// and updates the LastRawTime
|
||||
// SaveBWRaw records raw sums of agreement values to the database and updates the LastRawTime.
|
||||
SaveBWRaw(ctx context.Context, latestBwa time.Time, bwTotals map[string]int64) error
|
||||
// SaveAtRestRaw records raw tallies of at rest data to the database
|
||||
// SaveAtRestRaw records raw tallies of at-rest-data.
|
||||
SaveAtRestRaw(ctx context.Context, latestTally time.Time, nodeData map[storj.NodeID]int64) error
|
||||
}
|
||||
|
@ -18,13 +18,13 @@ import (
|
||||
"storj.io/storj/pkg/peertls"
|
||||
)
|
||||
|
||||
// DB interface for database operations
|
||||
// DB stores bandwidth agreements.
|
||||
type DB interface {
|
||||
// CreateAgreement creates bandwidth agreement in database
|
||||
// CreateAgreement adds a new bandwidth agreement.
|
||||
CreateAgreement(context.Context, Agreement) error
|
||||
// GetAgreements gets all bandwidth agreements
|
||||
// GetAgreements gets all bandwidth agreements.
|
||||
GetAgreements(context.Context) ([]Agreement, error)
|
||||
// GetAgreementsSince gets all bandwidth agreements since specific time
|
||||
// GetAgreementsSince gets all bandwidth agreements since specific time.
|
||||
GetAgreementsSince(context.Context, time.Time) ([]Agreement, error)
|
||||
}
|
||||
|
||||
|
@ -7,17 +7,17 @@ import (
|
||||
"context"
|
||||
)
|
||||
|
||||
// DB interface for database operations
|
||||
// DB stores information about repairs that have failed.
|
||||
type DB interface {
|
||||
// IncrementRepairAttempts increments the repair attempt
|
||||
// IncrementRepairAttempts increments the repair attempts.
|
||||
IncrementRepairAttempts(ctx context.Context, segmentInfo *RemoteSegmentInfo) error
|
||||
// Get a irreparable's segment info from the db
|
||||
// Get returns irreparable segment info based on segmentPath.
|
||||
Get(ctx context.Context, segmentPath []byte) (*RemoteSegmentInfo, error)
|
||||
// Delete a irreparable's segment info from the db
|
||||
// Delete removes irreparable segment info based on segmentPath.
|
||||
Delete(ctx context.Context, segmentPath []byte) error
|
||||
}
|
||||
|
||||
// RemoteSegmentInfo is info about a single entry stored in the irreparable
|
||||
// RemoteSegmentInfo is information about failed repairs.
|
||||
type RemoteSegmentInfo struct {
|
||||
EncryptedSegmentPath []byte
|
||||
EncryptedSegmentDetail []byte //contains marshaled info of pb.Pointer
|
||||
|
@ -13,10 +13,13 @@ import (
|
||||
"storj.io/storj/storage"
|
||||
)
|
||||
|
||||
// RepairQueue is the interface for the data repair queue
|
||||
// RepairQueue implements queueing for segments that need repairing.
|
||||
type RepairQueue interface {
|
||||
// Enqueue adds an injured segment.
|
||||
Enqueue(ctx context.Context, qi *pb.InjuredSegment) error
|
||||
// Dequeue removes an injured segment.
|
||||
Dequeue(ctx context.Context) (pb.InjuredSegment, error)
|
||||
// Peekqueue lists limit amount of injured segments.
|
||||
Peekqueue(ctx context.Context, limit int) ([]pb.InjuredSegment, error)
|
||||
}
|
||||
|
||||
|
@ -9,41 +9,34 @@ import (
|
||||
"storj.io/storj/pkg/storj"
|
||||
)
|
||||
|
||||
// DB interface for database operations
|
||||
// DB stores node statistics
|
||||
type DB interface {
|
||||
// Create a db entry for the provided storagenode
|
||||
Create(ctx context.Context, nodeID storj.NodeID, startingStats *NodeStats) (stats *NodeStats, err error)
|
||||
|
||||
// Get a storagenode's stats from the db
|
||||
// Create adds a new stats entry for node.
|
||||
Create(ctx context.Context, nodeID storj.NodeID, initial *NodeStats) (stats *NodeStats, err error)
|
||||
// Get returns node stats.
|
||||
Get(ctx context.Context, nodeID storj.NodeID) (stats *NodeStats, err error)
|
||||
|
||||
// FindInvalidNodes finds a subset of storagenodes that have stats below provided reputation requirements
|
||||
FindInvalidNodes(ctx context.Context, nodeIDs storj.NodeIDList, maxStats *NodeStats) (invalidIDs storj.NodeIDList, err error)
|
||||
|
||||
// Update all parts of single storagenode's stats in the db
|
||||
Update(ctx context.Context, updateReq *UpdateRequest) (stats *NodeStats, err error)
|
||||
|
||||
// UpdateUptime updates a single storagenode's uptime stats in the db
|
||||
// FindInvalidNodes finds a subset of storagenodes that have stats below provided reputation requirements.
|
||||
FindInvalidNodes(ctx context.Context, nodeIDs storj.NodeIDList, maxStats *NodeStats) (invalid storj.NodeIDList, err error)
|
||||
// Update all parts of single storagenode's stats.
|
||||
Update(ctx context.Context, request *UpdateRequest) (stats *NodeStats, err error)
|
||||
// UpdateUptime updates a single storagenode's uptime stats.
|
||||
UpdateUptime(ctx context.Context, nodeID storj.NodeID, isUp bool) (stats *NodeStats, err error)
|
||||
|
||||
// UpdateAuditSuccess updates a single storagenode's audit stats in the db
|
||||
// UpdateAuditSuccess updates a single storagenode's audit stats.
|
||||
UpdateAuditSuccess(ctx context.Context, nodeID storj.NodeID, auditSuccess bool) (stats *NodeStats, err error)
|
||||
|
||||
// UpdateBatch for updating multiple storage nodes' stats in the db
|
||||
UpdateBatch(ctx context.Context, updateReqList []*UpdateRequest) (statsList []*NodeStats, failedUpdateReqs []*UpdateRequest, err error)
|
||||
|
||||
// CreateEntryIfNotExists creates a statdb node entry and saves to statdb if it didn't already exist
|
||||
// UpdateBatch for updating multiple storage nodes' stats.
|
||||
UpdateBatch(ctx context.Context, requests []*UpdateRequest) (statslist []*NodeStats, failed []*UpdateRequest, err error)
|
||||
// CreateEntryIfNotExists creates a node stats entry if it didn't already exist.
|
||||
CreateEntryIfNotExists(ctx context.Context, nodeID storj.NodeID) (stats *NodeStats, err error)
|
||||
}
|
||||
|
||||
// UpdateRequest is a statdb update request message
|
||||
// UpdateRequest is used to update a node status.
|
||||
type UpdateRequest struct {
|
||||
NodeID storj.NodeID
|
||||
AuditSuccess bool
|
||||
IsUp bool
|
||||
}
|
||||
|
||||
// NodeStats is a statdb node stats message
|
||||
// NodeStats contains statistics abot a node.
|
||||
type NodeStats struct {
|
||||
NodeID storj.NodeID
|
||||
AuditSuccessRatio float64
|
||||
|
@ -14,14 +14,21 @@ import (
|
||||
|
||||
// DB is the master database for the satellite
|
||||
type DB interface {
|
||||
BandwidthAgreement() bwagreement.DB
|
||||
// PointerDB() pointerdb.DB
|
||||
StatDB() statdb.DB
|
||||
OverlayCache() storage.KeyValueStore
|
||||
RepairQueue() queue.RepairQueue
|
||||
Accounting() accounting.DB
|
||||
Irreparable() irreparable.DB
|
||||
|
||||
// CreateTables initializes the database
|
||||
CreateTables() error
|
||||
// Close closes the database
|
||||
Close() error
|
||||
|
||||
// BandwidthAgreement returns database for storing bandwidth agreements
|
||||
BandwidthAgreement() bwagreement.DB
|
||||
// StatDB returns database for storing node statistics
|
||||
StatDB() statdb.DB
|
||||
// OverlayCache returns database for caching overlay information
|
||||
OverlayCache() storage.KeyValueStore
|
||||
// Accounting returns database for storing information about data use
|
||||
Accounting() accounting.DB
|
||||
// RepairQueue returns queue for segments that need repairing
|
||||
RepairQueue() queue.RepairQueue
|
||||
// Irreparable returns database for failed repairs
|
||||
Irreparable() irreparable.DB
|
||||
}
|
||||
|
@ -23,6 +23,8 @@ var (
|
||||
Error = errs.Class("satellitedb")
|
||||
)
|
||||
|
||||
//go:generate go run lockedgen/main.go -o locked.go
|
||||
|
||||
// DB contains access to different database tables
|
||||
type DB struct {
|
||||
db *dbx.DB
|
||||
@ -43,7 +45,7 @@ func New(databaseURL string) (satellite.DB, error) {
|
||||
|
||||
core := &DB{db: db}
|
||||
if driver == "sqlite3" {
|
||||
return NewMutex(core), nil
|
||||
return newLocked(core), nil
|
||||
}
|
||||
return core, nil
|
||||
}
|
||||
|
@ -196,5 +196,4 @@ read first (
|
||||
read limitoffset (
|
||||
select injuredsegment
|
||||
)
|
||||
|
||||
delete injuredsegment ( where injuredsegment.id = ? )
|
||||
|
321
satellite/satellitedb/locked.go
Normal file
321
satellite/satellitedb/locked.go
Normal file
@ -0,0 +1,321 @@
|
||||
// Code generated by lockedgen using 'go generate'. DO NOT EDIT.
|
||||
|
||||
// Copyright (C) 2018 Storj Labs, Inc.
|
||||
// See LICENSE for copying information.
|
||||
|
||||
package satellitedb
|
||||
|
||||
import (
|
||||
"context"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"storj.io/storj/pkg/accounting"
|
||||
"storj.io/storj/pkg/bwagreement"
|
||||
"storj.io/storj/pkg/datarepair/irreparable"
|
||||
"storj.io/storj/pkg/datarepair/queue"
|
||||
"storj.io/storj/pkg/pb"
|
||||
"storj.io/storj/pkg/statdb"
|
||||
"storj.io/storj/pkg/storj"
|
||||
"storj.io/storj/satellite"
|
||||
"storj.io/storj/storage"
|
||||
)
|
||||
|
||||
// locked implements a locking wrapper around satellite.DB.
|
||||
type locked struct {
|
||||
sync.Locker
|
||||
db satellite.DB
|
||||
}
|
||||
|
||||
// newLocked returns database wrapped with locker.
|
||||
func newLocked(db satellite.DB) satellite.DB {
|
||||
return &locked{&sync.Mutex{}, db}
|
||||
}
|
||||
|
||||
// Accounting returns database for storing information about data use
|
||||
func (m *locked) Accounting() accounting.DB {
|
||||
m.Lock()
|
||||
defer m.Unlock()
|
||||
return &lockedAccounting{m.Locker, m.db.Accounting()}
|
||||
}
|
||||
|
||||
// BandwidthAgreement returns database for storing bandwidth agreements
|
||||
func (m *locked) BandwidthAgreement() bwagreement.DB {
|
||||
m.Lock()
|
||||
defer m.Unlock()
|
||||
return &lockedBandwidthAgreement{m.Locker, m.db.BandwidthAgreement()}
|
||||
}
|
||||
|
||||
// Close closes the database
|
||||
func (m *locked) Close() error {
|
||||
m.Lock()
|
||||
defer m.Unlock()
|
||||
return m.db.Close()
|
||||
}
|
||||
|
||||
// CreateTables initializes the database
|
||||
func (m *locked) CreateTables() error {
|
||||
m.Lock()
|
||||
defer m.Unlock()
|
||||
return m.db.CreateTables()
|
||||
}
|
||||
|
||||
// Irreparable returns database for failed repairs
|
||||
func (m *locked) Irreparable() irreparable.DB {
|
||||
m.Lock()
|
||||
defer m.Unlock()
|
||||
return &lockedIrreparable{m.Locker, m.db.Irreparable()}
|
||||
}
|
||||
|
||||
// OverlayCache returns database for caching overlay information
|
||||
func (m *locked) OverlayCache() storage.KeyValueStore {
|
||||
m.Lock()
|
||||
defer m.Unlock()
|
||||
return &lockedOverlayCache{m.Locker, m.db.OverlayCache()}
|
||||
}
|
||||
|
||||
// RepairQueue returns queue for segments that need repairing
|
||||
func (m *locked) RepairQueue() queue.RepairQueue {
|
||||
m.Lock()
|
||||
defer m.Unlock()
|
||||
return &lockedRepairQueue{m.Locker, m.db.RepairQueue()}
|
||||
}
|
||||
|
||||
// StatDB returns database for storing node statistics
|
||||
func (m *locked) StatDB() statdb.DB {
|
||||
m.Lock()
|
||||
defer m.Unlock()
|
||||
return &lockedStatDB{m.Locker, m.db.StatDB()}
|
||||
}
|
||||
|
||||
// lockedAccounting implements locking wrapper for accounting.DB
|
||||
type lockedAccounting struct {
|
||||
sync.Locker
|
||||
db accounting.DB
|
||||
}
|
||||
|
||||
// LastRawTime records the latest last tallied time.
|
||||
func (m *lockedAccounting) LastRawTime(ctx context.Context, timestampType string) (time.Time, bool, error) {
|
||||
m.Lock()
|
||||
defer m.Unlock()
|
||||
return m.db.LastRawTime(ctx, timestampType)
|
||||
}
|
||||
|
||||
// SaveAtRestRaw records raw tallies of at-rest-data.
|
||||
func (m *lockedAccounting) SaveAtRestRaw(ctx context.Context, latestTally time.Time, nodeData map[storj.NodeID]int64) error {
|
||||
m.Lock()
|
||||
defer m.Unlock()
|
||||
return m.db.SaveAtRestRaw(ctx, latestTally, nodeData)
|
||||
}
|
||||
|
||||
// SaveBWRaw records raw sums of agreement values to the database and updates the LastRawTime.
|
||||
func (m *lockedAccounting) SaveBWRaw(ctx context.Context, latestBwa time.Time, bwTotals map[string]int64) error {
|
||||
m.Lock()
|
||||
defer m.Unlock()
|
||||
return m.db.SaveBWRaw(ctx, latestBwa, bwTotals)
|
||||
}
|
||||
|
||||
// lockedBandwidthAgreement implements locking wrapper for bwagreement.DB
|
||||
type lockedBandwidthAgreement struct {
|
||||
sync.Locker
|
||||
db bwagreement.DB
|
||||
}
|
||||
|
||||
// CreateAgreement adds a new bandwidth agreement.
|
||||
func (m *lockedBandwidthAgreement) CreateAgreement(ctx context.Context, a1 bwagreement.Agreement) error {
|
||||
m.Lock()
|
||||
defer m.Unlock()
|
||||
return m.db.CreateAgreement(ctx, a1)
|
||||
}
|
||||
|
||||
// GetAgreements gets all bandwidth agreements.
|
||||
func (m *lockedBandwidthAgreement) GetAgreements(ctx context.Context) ([]bwagreement.Agreement, error) {
|
||||
m.Lock()
|
||||
defer m.Unlock()
|
||||
return m.db.GetAgreements(ctx)
|
||||
}
|
||||
|
||||
// GetAgreementsSince gets all bandwidth agreements since specific time.
|
||||
func (m *lockedBandwidthAgreement) GetAgreementsSince(ctx context.Context, a1 time.Time) ([]bwagreement.Agreement, error) {
|
||||
m.Lock()
|
||||
defer m.Unlock()
|
||||
return m.db.GetAgreementsSince(ctx, a1)
|
||||
}
|
||||
|
||||
// lockedIrreparable implements locking wrapper for irreparable.DB
|
||||
type lockedIrreparable struct {
|
||||
sync.Locker
|
||||
db irreparable.DB
|
||||
}
|
||||
|
||||
// Delete removes irreparable segment info based on segmentPath.
|
||||
func (m *lockedIrreparable) Delete(ctx context.Context, segmentPath []byte) error {
|
||||
m.Lock()
|
||||
defer m.Unlock()
|
||||
return m.db.Delete(ctx, segmentPath)
|
||||
}
|
||||
|
||||
// Get returns irreparable segment info based on segmentPath.
|
||||
func (m *lockedIrreparable) Get(ctx context.Context, segmentPath []byte) (*irreparable.RemoteSegmentInfo, error) {
|
||||
m.Lock()
|
||||
defer m.Unlock()
|
||||
return m.db.Get(ctx, segmentPath)
|
||||
}
|
||||
|
||||
// IncrementRepairAttempts increments the repair attempts.
|
||||
func (m *lockedIrreparable) IncrementRepairAttempts(ctx context.Context, segmentInfo *irreparable.RemoteSegmentInfo) error {
|
||||
m.Lock()
|
||||
defer m.Unlock()
|
||||
return m.db.IncrementRepairAttempts(ctx, segmentInfo)
|
||||
}
|
||||
|
||||
// lockedOverlayCache implements locking wrapper for storage.KeyValueStore
|
||||
type lockedOverlayCache struct {
|
||||
sync.Locker
|
||||
db storage.KeyValueStore
|
||||
}
|
||||
|
||||
// Close closes the store
|
||||
func (m *lockedOverlayCache) Close() error {
|
||||
m.Lock()
|
||||
defer m.Unlock()
|
||||
return m.db.Close()
|
||||
}
|
||||
|
||||
// Delete deletes key and the value
|
||||
func (m *lockedOverlayCache) Delete(a0 storage.Key) error {
|
||||
m.Lock()
|
||||
defer m.Unlock()
|
||||
return m.db.Delete(a0)
|
||||
}
|
||||
|
||||
// Get gets a value to store
|
||||
func (m *lockedOverlayCache) Get(a0 storage.Key) (storage.Value, error) {
|
||||
m.Lock()
|
||||
defer m.Unlock()
|
||||
return m.db.Get(a0)
|
||||
}
|
||||
|
||||
// GetAll gets all values from the store
|
||||
func (m *lockedOverlayCache) GetAll(a0 storage.Keys) (storage.Values, error) {
|
||||
m.Lock()
|
||||
defer m.Unlock()
|
||||
return m.db.GetAll(a0)
|
||||
}
|
||||
|
||||
// Iterate iterates over items based on opts
|
||||
func (m *lockedOverlayCache) Iterate(opts storage.IterateOptions, fn func(storage.Iterator) error) error {
|
||||
m.Lock()
|
||||
defer m.Unlock()
|
||||
return m.db.Iterate(opts, fn)
|
||||
}
|
||||
|
||||
// List lists all keys starting from start and upto limit items
|
||||
func (m *lockedOverlayCache) List(start storage.Key, limit int) (storage.Keys, error) {
|
||||
m.Lock()
|
||||
defer m.Unlock()
|
||||
return m.db.List(start, limit)
|
||||
}
|
||||
|
||||
// Put adds a value to store
|
||||
func (m *lockedOverlayCache) Put(a0 storage.Key, a1 storage.Value) error {
|
||||
m.Lock()
|
||||
defer m.Unlock()
|
||||
return m.db.Put(a0, a1)
|
||||
}
|
||||
|
||||
// ReverseList lists all keys in revers order
|
||||
func (m *lockedOverlayCache) ReverseList(a0 storage.Key, a1 int) (storage.Keys, error) {
|
||||
m.Lock()
|
||||
defer m.Unlock()
|
||||
return m.db.ReverseList(a0, a1)
|
||||
}
|
||||
|
||||
// lockedRepairQueue implements locking wrapper for queue.RepairQueue
|
||||
type lockedRepairQueue struct {
|
||||
sync.Locker
|
||||
db queue.RepairQueue
|
||||
}
|
||||
|
||||
// Dequeue removes an injured segment.
|
||||
func (m *lockedRepairQueue) Dequeue(ctx context.Context) (pb.InjuredSegment, error) {
|
||||
m.Lock()
|
||||
defer m.Unlock()
|
||||
return m.db.Dequeue(ctx)
|
||||
}
|
||||
|
||||
// Enqueue adds an injured segment.
|
||||
func (m *lockedRepairQueue) Enqueue(ctx context.Context, qi *pb.InjuredSegment) error {
|
||||
m.Lock()
|
||||
defer m.Unlock()
|
||||
return m.db.Enqueue(ctx, qi)
|
||||
}
|
||||
|
||||
// Peekqueue lists limit amount of injured segments.
|
||||
func (m *lockedRepairQueue) Peekqueue(ctx context.Context, limit int) ([]pb.InjuredSegment, error) {
|
||||
m.Lock()
|
||||
defer m.Unlock()
|
||||
return m.db.Peekqueue(ctx, limit)
|
||||
}
|
||||
|
||||
// lockedStatDB implements locking wrapper for statdb.DB
|
||||
type lockedStatDB struct {
|
||||
sync.Locker
|
||||
db statdb.DB
|
||||
}
|
||||
|
||||
// Create adds a new stats entry for node.
|
||||
func (m *lockedStatDB) Create(ctx context.Context, nodeID storj.NodeID, initial *statdb.NodeStats) (stats *statdb.NodeStats, err error) {
|
||||
m.Lock()
|
||||
defer m.Unlock()
|
||||
return m.db.Create(ctx, nodeID, initial)
|
||||
}
|
||||
|
||||
// CreateEntryIfNotExists creates a node stats entry if it didn't already exist.
|
||||
func (m *lockedStatDB) CreateEntryIfNotExists(ctx context.Context, nodeID storj.NodeID) (stats *statdb.NodeStats, err error) {
|
||||
m.Lock()
|
||||
defer m.Unlock()
|
||||
return m.db.CreateEntryIfNotExists(ctx, nodeID)
|
||||
}
|
||||
|
||||
// FindInvalidNodes finds a subset of storagenodes that have stats below provided reputation requirements.
|
||||
func (m *lockedStatDB) FindInvalidNodes(ctx context.Context, nodeIDs storj.NodeIDList, maxStats *statdb.NodeStats) (invalid storj.NodeIDList, err error) {
|
||||
m.Lock()
|
||||
defer m.Unlock()
|
||||
return m.db.FindInvalidNodes(ctx, nodeIDs, maxStats)
|
||||
}
|
||||
|
||||
// Get returns node stats.
|
||||
func (m *lockedStatDB) Get(ctx context.Context, nodeID storj.NodeID) (stats *statdb.NodeStats, err error) {
|
||||
m.Lock()
|
||||
defer m.Unlock()
|
||||
return m.db.Get(ctx, nodeID)
|
||||
}
|
||||
|
||||
// Update all parts of single storagenode's stats.
|
||||
func (m *lockedStatDB) Update(ctx context.Context, request *statdb.UpdateRequest) (stats *statdb.NodeStats, err error) {
|
||||
m.Lock()
|
||||
defer m.Unlock()
|
||||
return m.db.Update(ctx, request)
|
||||
}
|
||||
|
||||
// UpdateAuditSuccess updates a single storagenode's audit stats.
|
||||
func (m *lockedStatDB) UpdateAuditSuccess(ctx context.Context, nodeID storj.NodeID, auditSuccess bool) (stats *statdb.NodeStats, err error) {
|
||||
m.Lock()
|
||||
defer m.Unlock()
|
||||
return m.db.UpdateAuditSuccess(ctx, nodeID, auditSuccess)
|
||||
}
|
||||
|
||||
// UpdateBatch for updating multiple storagenodes stats.
|
||||
func (m *lockedStatDB) UpdateBatch(ctx context.Context, requests []*statdb.UpdateRequest) (statslist []*statdb.NodeStats, failed []*statdb.UpdateRequest, err error) {
|
||||
m.Lock()
|
||||
defer m.Unlock()
|
||||
return m.db.UpdateBatch(ctx, requests)
|
||||
}
|
||||
|
||||
// UpdateUptime updates a single storagenode's uptime stats.
|
||||
func (m *lockedStatDB) UpdateUptime(ctx context.Context, nodeID storj.NodeID, isUp bool) (stats *statdb.NodeStats, err error) {
|
||||
m.Lock()
|
||||
defer m.Unlock()
|
||||
return m.db.UpdateUptime(ctx, nodeID, isUp)
|
||||
}
|
343
satellite/satellitedb/lockedgen/main.go
Normal file
343
satellite/satellitedb/lockedgen/main.go
Normal file
@ -0,0 +1,343 @@
|
||||
// Copyright (C) 2018 Storj Labs, Inc.
|
||||
// See LICENSE for copying information.
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"flag"
|
||||
"fmt"
|
||||
"go/ast"
|
||||
"go/token"
|
||||
"go/types"
|
||||
"io/ioutil"
|
||||
"sort"
|
||||
|
||||
"golang.org/x/tools/go/ast/astutil"
|
||||
"golang.org/x/tools/go/packages"
|
||||
"golang.org/x/tools/imports"
|
||||
)
|
||||
|
||||
func main() {
|
||||
var outputPath string
|
||||
flag.StringVar(&outputPath, "o", "", "output file name")
|
||||
flag.Parse()
|
||||
|
||||
var code Code
|
||||
|
||||
code.Imports = map[string]bool{}
|
||||
code.Ignore = map[string]bool{
|
||||
"error": true,
|
||||
}
|
||||
|
||||
code.Config = &packages.Config{
|
||||
Mode: packages.LoadAllSyntax,
|
||||
}
|
||||
code.Package = "storj.io/storj/satellite"
|
||||
|
||||
var err error
|
||||
code.Roots, err = packages.Load(code.Config, code.Package)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
code.PrintLocked()
|
||||
code.PrintPreamble()
|
||||
|
||||
unformatted := code.Bytes()
|
||||
|
||||
imports.LocalPrefix = "storj.io"
|
||||
formatted, err := imports.Process(outputPath, unformatted, nil)
|
||||
if err != nil {
|
||||
fmt.Println(string(unformatted))
|
||||
panic(err)
|
||||
}
|
||||
|
||||
if outputPath == "" {
|
||||
fmt.Println(string(formatted))
|
||||
return
|
||||
}
|
||||
|
||||
err = ioutil.WriteFile(outputPath, formatted, 0644)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
||||
// Methods is the common interface for types having methods.
|
||||
type Methods interface {
|
||||
Method(i int) *types.Func
|
||||
NumMethods() int
|
||||
}
|
||||
|
||||
// Code is the information for generating the code.
|
||||
type Code struct {
|
||||
Config *packages.Config
|
||||
Package string
|
||||
Roots []*packages.Package
|
||||
|
||||
Imports map[string]bool
|
||||
Ignore map[string]bool
|
||||
|
||||
Preamble bytes.Buffer
|
||||
Source bytes.Buffer
|
||||
}
|
||||
|
||||
// Bytes returns all code merged together
|
||||
func (code *Code) Bytes() []byte {
|
||||
var all bytes.Buffer
|
||||
all.Write(code.Preamble.Bytes())
|
||||
all.Write(code.Source.Bytes())
|
||||
return all.Bytes()
|
||||
}
|
||||
|
||||
// PrintPreamble creates package header and imports.
|
||||
func (code *Code) PrintPreamble() {
|
||||
w := &code.Preamble
|
||||
fmt.Fprintf(w, "// Code generated by lockedgen using 'go generate'. DO NOT EDIT.\n\n")
|
||||
fmt.Fprintf(w, "// Copyright (C) 2018 Storj Labs, Inc.\n")
|
||||
fmt.Fprintf(w, "// See LICENSE for copying information.\n\n")
|
||||
fmt.Fprintf(w, "package satellitedb\n\n")
|
||||
fmt.Fprintf(w, "import (\n")
|
||||
|
||||
var imports []string
|
||||
for imp := range code.Imports {
|
||||
imports = append(imports, imp)
|
||||
}
|
||||
sort.Strings(imports)
|
||||
for _, imp := range imports {
|
||||
fmt.Fprintf(w, " %q\n", imp)
|
||||
}
|
||||
fmt.Fprintf(w, ")\n\n")
|
||||
}
|
||||
|
||||
// PrintLocked writes locked wrapper and methods.
|
||||
func (code *Code) PrintLocked() {
|
||||
code.Imports["sync"] = true
|
||||
code.Imports["storj.io/statellite"] = true
|
||||
|
||||
code.Printf("// locked implements a locking wrapper around satellite.DB.\n")
|
||||
code.Printf("type locked struct {\n")
|
||||
code.Printf(" sync.Locker\n")
|
||||
code.Printf(" db satellite.DB\n")
|
||||
code.Printf("}\n\n")
|
||||
|
||||
code.Printf("// newLocked returns database wrapped with locker.\n")
|
||||
code.Printf("func newLocked(db satellite.DB) satellite.DB {\n")
|
||||
code.Printf(" return &locked{&sync.Mutex{}, db}\n")
|
||||
code.Printf("}\n\n")
|
||||
|
||||
// find the satellite.DB type info
|
||||
dbObject := code.Roots[0].Types.Scope().Lookup("DB")
|
||||
methods := dbObject.Type().Underlying().(Methods)
|
||||
|
||||
for i := 0; i < methods.NumMethods(); i++ {
|
||||
code.PrintLockedFunc("locked", methods.Method(i), true)
|
||||
}
|
||||
|
||||
for i := 0; i < methods.NumMethods(); i++ {
|
||||
if !code.NeedsWrapper(methods.Method(i)) {
|
||||
continue
|
||||
}
|
||||
code.PrintWrapper(methods.Method(i))
|
||||
}
|
||||
}
|
||||
|
||||
// Printf writes formatted text to source.
|
||||
func (code *Code) Printf(format string, a ...interface{}) {
|
||||
fmt.Fprintf(&code.Source, format, a...)
|
||||
}
|
||||
|
||||
// PrintSignature prints method signature.
|
||||
func (code *Code) PrintSignature(sig *types.Signature) {
|
||||
code.PrintSignatureTuple(sig.Params(), true)
|
||||
if sig.Results().Len() > 0 {
|
||||
code.Printf(" ")
|
||||
code.PrintSignatureTuple(sig.Results(), false)
|
||||
}
|
||||
}
|
||||
|
||||
// PrintSignatureTuple prints method tuple, params or results.
|
||||
func (code *Code) PrintSignatureTuple(tuple *types.Tuple, needsNames bool) {
|
||||
code.Printf("(")
|
||||
defer code.Printf(")")
|
||||
|
||||
for i := 0; i < tuple.Len(); i++ {
|
||||
if i > 0 {
|
||||
code.Printf(", ")
|
||||
}
|
||||
|
||||
param := tuple.At(i)
|
||||
if code.PrintName(tuple.At(i), i, needsNames) {
|
||||
code.Printf(" ")
|
||||
}
|
||||
code.PrintType(param.Type())
|
||||
}
|
||||
}
|
||||
|
||||
// PrintCall prints a call using the specified signature.
|
||||
func (code *Code) PrintCall(sig *types.Signature) {
|
||||
code.Printf("(")
|
||||
defer code.Printf(")")
|
||||
|
||||
params := sig.Params()
|
||||
for i := 0; i < params.Len(); i++ {
|
||||
if i != 0 {
|
||||
code.Printf(", ")
|
||||
}
|
||||
code.PrintName(params.At(i), i, true)
|
||||
}
|
||||
}
|
||||
|
||||
// PrintName prints an appropriate name from signature tuple.
|
||||
func (code *Code) PrintName(v *types.Var, index int, needsNames bool) bool {
|
||||
name := v.Name()
|
||||
if needsNames && name == "" {
|
||||
if v.Type().String() == "context.Context" {
|
||||
code.Printf("ctx")
|
||||
return true
|
||||
}
|
||||
code.Printf("a%d", index)
|
||||
return true
|
||||
}
|
||||
code.Printf("%s", name)
|
||||
return name != ""
|
||||
}
|
||||
|
||||
// PrintType prints short form of type t.
|
||||
func (code *Code) PrintType(t types.Type) {
|
||||
types.WriteType(&code.Source, t, (*types.Package).Name)
|
||||
}
|
||||
|
||||
func typeName(typ types.Type) string {
|
||||
var body bytes.Buffer
|
||||
types.WriteType(&body, typ, (*types.Package).Name)
|
||||
return body.String()
|
||||
}
|
||||
|
||||
// IncludeImports imports all types referenced in the signature.
|
||||
func (code *Code) IncludeImports(sig *types.Signature) {
|
||||
var tmp bytes.Buffer
|
||||
types.WriteSignature(&tmp, sig, func(p *types.Package) string {
|
||||
code.Imports[p.Path()] = true
|
||||
return p.Name()
|
||||
})
|
||||
}
|
||||
|
||||
// NeedsWrapper checks whether method result needs a wrapper type.
|
||||
func (code *Code) NeedsWrapper(method *types.Func) bool {
|
||||
sig := method.Type().Underlying().(*types.Signature)
|
||||
return sig.Results().Len() == 1 && !code.Ignore[sig.Results().At(0).Type().String()]
|
||||
}
|
||||
|
||||
// WrapperTypeName returns an appropariate name for the wrapper type.
|
||||
func (code *Code) WrapperTypeName(method *types.Func) string {
|
||||
return "locked" + method.Name()
|
||||
}
|
||||
|
||||
// PrintLockedFunc prints a method with locking and defers the actual logic to method.
|
||||
func (code *Code) PrintLockedFunc(receiverType string, method *types.Func, allowNesting bool) {
|
||||
sig := method.Type().Underlying().(*types.Signature)
|
||||
code.IncludeImports(sig)
|
||||
|
||||
doc := code.MethodDoc(method)
|
||||
if doc != "" {
|
||||
code.Printf("// %s", code.MethodDoc(method))
|
||||
}
|
||||
code.Printf("func (m *%s) %s", receiverType, method.Name())
|
||||
code.PrintSignature(sig)
|
||||
code.Printf(" {\n")
|
||||
defer code.Printf("}\n\n")
|
||||
|
||||
code.Printf(" m.Lock(); defer m.Unlock()\n")
|
||||
if code.NeedsWrapper(method) {
|
||||
code.Printf(" return &%s{m.Locker, ", code.WrapperTypeName(method))
|
||||
code.Printf("m.db.%s", method.Name())
|
||||
code.PrintCall(sig)
|
||||
code.Printf("}\n")
|
||||
} else {
|
||||
code.Printf(" return m.db.%s", method.Name())
|
||||
code.PrintCall(sig)
|
||||
code.Printf("\n")
|
||||
}
|
||||
}
|
||||
|
||||
// PrintWrapper prints wrapper for the result type of method.
|
||||
func (code *Code) PrintWrapper(method *types.Func) {
|
||||
sig := method.Type().Underlying().(*types.Signature)
|
||||
results := sig.Results()
|
||||
result := results.At(0).Type()
|
||||
|
||||
receiverType := code.WrapperTypeName(method)
|
||||
code.Printf("// %s implements locking wrapper for %s\n", receiverType, typeName(result))
|
||||
code.Printf("type %s struct {\n", receiverType)
|
||||
code.Printf(" sync.Locker\n")
|
||||
code.Printf(" db %s\n", typeName(result))
|
||||
code.Printf("}\n\n")
|
||||
|
||||
methods := result.Underlying().(Methods)
|
||||
for i := 0; i < methods.NumMethods(); i++ {
|
||||
code.PrintLockedFunc(receiverType, methods.Method(i), false)
|
||||
}
|
||||
}
|
||||
|
||||
// MethodDoc finds documentation for the specified method.
|
||||
func (code *Code) MethodDoc(method *types.Func) string {
|
||||
file := code.FindASTFile(method.Pos())
|
||||
if file == nil {
|
||||
return ""
|
||||
}
|
||||
|
||||
path, exact := astutil.PathEnclosingInterval(file, method.Pos(), method.Pos())
|
||||
if !exact {
|
||||
return ""
|
||||
}
|
||||
|
||||
for _, p := range path {
|
||||
switch decl := p.(type) {
|
||||
case *ast.Field:
|
||||
return decl.Doc.Text()
|
||||
case *ast.GenDecl:
|
||||
return decl.Doc.Text()
|
||||
case *ast.FuncDecl:
|
||||
return decl.Doc.Text()
|
||||
}
|
||||
}
|
||||
|
||||
return ""
|
||||
}
|
||||
|
||||
// FindASTFile finds the *ast.File at the specified position.
|
||||
func (code *Code) FindASTFile(pos token.Pos) *ast.File {
|
||||
seen := map[*packages.Package]bool{}
|
||||
|
||||
// find searches pos recursively from p and its dependencies.
|
||||
var find func(p *packages.Package) *ast.File
|
||||
find = func(p *packages.Package) *ast.File {
|
||||
if seen[p] {
|
||||
return nil
|
||||
}
|
||||
seen[p] = true
|
||||
|
||||
for _, file := range p.Syntax {
|
||||
if file.Pos() <= pos && pos <= file.End() {
|
||||
return file
|
||||
}
|
||||
}
|
||||
|
||||
for _, dep := range p.Imports {
|
||||
if file := find(dep); file != nil {
|
||||
return file
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
for _, root := range code.Roots {
|
||||
if file := find(root); file != nil {
|
||||
return file
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
@ -1,267 +0,0 @@
|
||||
// Copyright (C) 2018 Storj Labs, Inc.
|
||||
// See LICENSE for copying information.
|
||||
|
||||
package satellitedb
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"storj.io/storj/pkg/accounting"
|
||||
"storj.io/storj/pkg/bwagreement"
|
||||
"storj.io/storj/pkg/datarepair/irreparable"
|
||||
"storj.io/storj/pkg/datarepair/queue"
|
||||
"storj.io/storj/pkg/pb"
|
||||
"storj.io/storj/pkg/statdb"
|
||||
"storj.io/storj/pkg/storj"
|
||||
"storj.io/storj/storage"
|
||||
)
|
||||
|
||||
// Mutex wraps DB in a mutex for non-concurrent databases
|
||||
type Mutex struct {
|
||||
mu sync.Mutex
|
||||
db *DB
|
||||
}
|
||||
|
||||
// NewMutex returns a mutex around DB
|
||||
func NewMutex(db *DB) *Mutex {
|
||||
return &Mutex{db: db}
|
||||
}
|
||||
|
||||
func (db *Mutex) locked() func() {
|
||||
db.mu.Lock()
|
||||
return db.mu.Unlock
|
||||
}
|
||||
|
||||
// BandwidthAgreement is a getter for bandwidth agreement repository
|
||||
func (db *Mutex) BandwidthAgreement() bwagreement.DB {
|
||||
return &muBandwidthAgreement{mu: db, bandwidth: db.db.BandwidthAgreement()}
|
||||
}
|
||||
|
||||
// // PointerDB is a getter for PointerDB repository
|
||||
// func (db *Mutex) PointerDB() pointerdb.DB {
|
||||
// return &pointerDB{db: db.db}
|
||||
// }
|
||||
|
||||
// StatDB is a getter for StatDB repository
|
||||
func (db *Mutex) StatDB() statdb.DB {
|
||||
return &muStatDB{mu: db, statdb: db.db.StatDB()}
|
||||
}
|
||||
|
||||
// OverlayCache is a getter for overlay cache repository
|
||||
func (db *Mutex) OverlayCache() storage.KeyValueStore {
|
||||
return &muOverlayCache{mu: db, overlay: db.db.OverlayCache()}
|
||||
}
|
||||
|
||||
// RepairQueue is a getter for RepairQueue repository
|
||||
func (db *Mutex) RepairQueue() queue.RepairQueue {
|
||||
return &muRepairQueue{mu: db, repair: db.db.RepairQueue()}
|
||||
}
|
||||
|
||||
// Accounting returns database for tracking bandwidth agreements over time
|
||||
func (db *Mutex) Accounting() accounting.DB {
|
||||
return &muAccounting{mu: db, accounting: db.db.Accounting()}
|
||||
}
|
||||
|
||||
// Irreparable returns database for storing segments that failed repair
|
||||
func (db *Mutex) Irreparable() irreparable.DB {
|
||||
return &muIrreparable{mu: db, irreparable: db.db.Irreparable()}
|
||||
}
|
||||
|
||||
// CreateTables is a method for creating all tables for database
|
||||
func (db *Mutex) CreateTables() error {
|
||||
return db.db.CreateTables()
|
||||
}
|
||||
|
||||
// Close is used to close db connection
|
||||
func (db *Mutex) Close() error {
|
||||
return db.db.Close()
|
||||
}
|
||||
|
||||
type muBandwidthAgreement struct {
|
||||
mu *Mutex
|
||||
bandwidth bwagreement.DB
|
||||
}
|
||||
|
||||
func (db *muBandwidthAgreement) CreateAgreement(ctx context.Context, agreement bwagreement.Agreement) error {
|
||||
defer db.mu.locked()()
|
||||
return db.bandwidth.CreateAgreement(ctx, agreement)
|
||||
}
|
||||
|
||||
func (db *muBandwidthAgreement) GetAgreements(ctx context.Context) ([]bwagreement.Agreement, error) {
|
||||
defer db.mu.locked()()
|
||||
return db.bandwidth.GetAgreements(ctx)
|
||||
}
|
||||
|
||||
func (db *muBandwidthAgreement) GetAgreementsSince(ctx context.Context, since time.Time) ([]bwagreement.Agreement, error) {
|
||||
defer db.mu.locked()()
|
||||
return db.bandwidth.GetAgreementsSince(ctx, since)
|
||||
}
|
||||
|
||||
// muStatDB implements mutex around statdb.DB
|
||||
type muStatDB struct {
|
||||
mu *Mutex
|
||||
statdb statdb.DB
|
||||
}
|
||||
|
||||
// Create a db entry for the provided storagenode
|
||||
func (db *muStatDB) Create(ctx context.Context, nodeID storj.NodeID, startingStats *statdb.NodeStats) (stats *statdb.NodeStats, err error) {
|
||||
defer db.mu.locked()()
|
||||
return db.statdb.Create(ctx, nodeID, startingStats)
|
||||
}
|
||||
|
||||
// Get a storagenode's stats from the db
|
||||
func (db *muStatDB) Get(ctx context.Context, nodeID storj.NodeID) (stats *statdb.NodeStats, err error) {
|
||||
defer db.mu.locked()()
|
||||
return db.statdb.Get(ctx, nodeID)
|
||||
}
|
||||
|
||||
// FindInvalidNodes finds a subset of storagenodes that have stats below provided reputation requirements
|
||||
func (db *muStatDB) FindInvalidNodes(ctx context.Context, nodeIDs storj.NodeIDList, maxStats *statdb.NodeStats) (invalidIDs storj.NodeIDList, err error) {
|
||||
defer db.mu.locked()()
|
||||
return db.statdb.FindInvalidNodes(ctx, nodeIDs, maxStats)
|
||||
}
|
||||
|
||||
// Update all parts of single storagenode's stats in the db
|
||||
func (db *muStatDB) Update(ctx context.Context, updateReq *statdb.UpdateRequest) (stats *statdb.NodeStats, err error) {
|
||||
defer db.mu.locked()()
|
||||
return db.statdb.Update(ctx, updateReq)
|
||||
}
|
||||
|
||||
// UpdateUptime updates a single storagenode's uptime stats in the db
|
||||
func (db *muStatDB) UpdateUptime(ctx context.Context, nodeID storj.NodeID, isUp bool) (stats *statdb.NodeStats, err error) {
|
||||
defer db.mu.locked()()
|
||||
return db.statdb.UpdateUptime(ctx, nodeID, isUp)
|
||||
}
|
||||
|
||||
// UpdateAuditSuccess updates a single storagenode's audit stats in the db
|
||||
func (db *muStatDB) UpdateAuditSuccess(ctx context.Context, nodeID storj.NodeID, auditSuccess bool) (stats *statdb.NodeStats, err error) {
|
||||
defer db.mu.locked()()
|
||||
return db.statdb.UpdateAuditSuccess(ctx, nodeID, auditSuccess)
|
||||
}
|
||||
|
||||
// UpdateBatch for updating multiple storage nodes' stats in the db
|
||||
func (db *muStatDB) UpdateBatch(ctx context.Context, updateReqList []*statdb.UpdateRequest) (statsList []*statdb.NodeStats, failedUpdateReqs []*statdb.UpdateRequest, err error) {
|
||||
defer db.mu.locked()()
|
||||
return db.statdb.UpdateBatch(ctx, updateReqList)
|
||||
}
|
||||
|
||||
// CreateEntryIfNotExists creates a statdb node entry and saves to statdb if it didn't already exist
|
||||
func (db *muStatDB) CreateEntryIfNotExists(ctx context.Context, nodeID storj.NodeID) (stats *statdb.NodeStats, err error) {
|
||||
defer db.mu.locked()()
|
||||
return db.statdb.CreateEntryIfNotExists(ctx, nodeID)
|
||||
}
|
||||
|
||||
// muOverlayCache implements a mutex around overlay cache
|
||||
type muOverlayCache struct {
|
||||
mu *Mutex
|
||||
overlay storage.KeyValueStore
|
||||
}
|
||||
|
||||
// Put adds a value to store
|
||||
func (db *muOverlayCache) Put(key storage.Key, value storage.Value) error {
|
||||
defer db.mu.locked()()
|
||||
return db.overlay.Put(key, value)
|
||||
}
|
||||
|
||||
// Get gets a value to store
|
||||
func (db *muOverlayCache) Get(key storage.Key) (storage.Value, error) {
|
||||
defer db.mu.locked()()
|
||||
return db.overlay.Get(key)
|
||||
}
|
||||
|
||||
// GetAll gets all values from the store
|
||||
func (db *muOverlayCache) GetAll(keys storage.Keys) (storage.Values, error) {
|
||||
defer db.mu.locked()()
|
||||
return db.overlay.GetAll(keys)
|
||||
}
|
||||
|
||||
// Delete deletes key and the value
|
||||
func (db *muOverlayCache) Delete(key storage.Key) error {
|
||||
defer db.mu.locked()()
|
||||
return db.overlay.Delete(key)
|
||||
}
|
||||
|
||||
// List lists all keys starting from start and upto limit items
|
||||
func (db *muOverlayCache) List(start storage.Key, limit int) (keys storage.Keys, err error) {
|
||||
defer db.mu.locked()()
|
||||
return db.overlay.List(start, limit)
|
||||
}
|
||||
|
||||
// ReverseList lists all keys in revers order
|
||||
func (db *muOverlayCache) ReverseList(start storage.Key, limit int) (storage.Keys, error) {
|
||||
defer db.mu.locked()()
|
||||
return db.overlay.ReverseList(start, limit)
|
||||
}
|
||||
|
||||
// Iterate iterates over items based on opts
|
||||
func (db *muOverlayCache) Iterate(opts storage.IterateOptions, fn func(storage.Iterator) error) error {
|
||||
return errors.New("not implemented")
|
||||
}
|
||||
|
||||
// Close closes the store
|
||||
func (db *muOverlayCache) Close() error {
|
||||
defer db.mu.locked()()
|
||||
return db.overlay.Close()
|
||||
}
|
||||
|
||||
// muRepairQueue implements mutex around repair queue
|
||||
type muRepairQueue struct {
|
||||
mu *Mutex
|
||||
repair queue.RepairQueue
|
||||
}
|
||||
|
||||
func (db *muRepairQueue) Enqueue(ctx context.Context, seg *pb.InjuredSegment) error {
|
||||
defer db.mu.locked()()
|
||||
return db.repair.Enqueue(ctx, seg)
|
||||
}
|
||||
func (db *muRepairQueue) Dequeue(ctx context.Context) (pb.InjuredSegment, error) {
|
||||
defer db.mu.locked()()
|
||||
return db.repair.Dequeue(ctx)
|
||||
}
|
||||
func (db *muRepairQueue) Peekqueue(ctx context.Context, limit int) ([]pb.InjuredSegment, error) {
|
||||
defer db.mu.locked()()
|
||||
return db.repair.Peekqueue(ctx, limit)
|
||||
}
|
||||
|
||||
type muAccounting struct {
|
||||
mu *Mutex
|
||||
accounting accounting.DB
|
||||
}
|
||||
|
||||
func (db *muAccounting) LastRawTime(ctx context.Context, timestampType string) (time.Time, bool, error) {
|
||||
defer db.mu.locked()()
|
||||
return db.accounting.LastRawTime(ctx, timestampType)
|
||||
}
|
||||
|
||||
func (db *muAccounting) SaveBWRaw(ctx context.Context, latestBwa time.Time, bwTotals map[string]int64) (err error) {
|
||||
defer db.mu.locked()()
|
||||
return db.accounting.SaveBWRaw(ctx, latestBwa, bwTotals)
|
||||
}
|
||||
|
||||
func (db *muAccounting) SaveAtRestRaw(ctx context.Context, latestTally time.Time, nodeData map[storj.NodeID]int64) error {
|
||||
defer db.mu.locked()()
|
||||
return db.accounting.SaveAtRestRaw(ctx, latestTally, nodeData)
|
||||
}
|
||||
|
||||
type muIrreparable struct {
|
||||
mu *Mutex
|
||||
irreparable irreparable.DB
|
||||
}
|
||||
|
||||
func (db *muIrreparable) IncrementRepairAttempts(ctx context.Context, segmentInfo *irreparable.RemoteSegmentInfo) (err error) {
|
||||
defer db.mu.locked()()
|
||||
return db.irreparable.IncrementRepairAttempts(ctx, segmentInfo)
|
||||
}
|
||||
|
||||
func (db *muIrreparable) Get(ctx context.Context, segmentPath []byte) (resp *irreparable.RemoteSegmentInfo, err error) {
|
||||
defer db.mu.locked()()
|
||||
return db.irreparable.Get(ctx, segmentPath)
|
||||
}
|
||||
|
||||
func (db *muIrreparable) Delete(ctx context.Context, segmentPath []byte) (err error) {
|
||||
defer db.mu.locked()()
|
||||
return db.irreparable.Delete(ctx, segmentPath)
|
||||
}
|
@ -50,7 +50,7 @@ type ListItem struct {
|
||||
IsPrefix bool
|
||||
}
|
||||
|
||||
// KeyValueStore is an interface describing key/value stores like redis and boltdb
|
||||
// KeyValueStore describes key/value stores like redis and boltdb
|
||||
type KeyValueStore interface {
|
||||
// Put adds a value to store
|
||||
Put(Key, Value) error
|
||||
|
Loading…
Reference in New Issue
Block a user