storj/satellite/satellitedb/irreparabledb.go
Egon Elbre 11a44cdd88 all: don't depend on gogo/proto directly
Change-Id: I8822dea0d1b7b99e0b828e0373a0308a42dde2be
2020-04-08 17:32:15 +00:00

122 lines
3.9 KiB
Go

// Copyright (C) 2019 Storj Labs, Inc.
// See LICENSE for copying information.
package satellitedb
import (
"context"
"database/sql"
"storj.io/common/pb"
"storj.io/storj/satellite/satellitedb/dbx"
)
type irreparableDB struct {
db *satelliteDB
}
// IncrementRepairAttempts a db entry for to increment the repair attempts field
func (db *irreparableDB) IncrementRepairAttempts(ctx context.Context, segmentInfo *pb.IrreparableSegment) (err error) {
defer mon.Task()(&ctx)(&err)
err = db.db.WithTx(ctx, func(ctx context.Context, tx *dbx.Tx) (err error) {
bytes, err := pb.Marshal(segmentInfo.SegmentDetail)
if err != nil {
return err
}
dbxInfo, err := tx.Get_Irreparabledb_By_Segmentpath(ctx, dbx.Irreparabledb_Segmentpath(segmentInfo.Path))
if err != nil {
if err == sql.ErrNoRows {
// no rows err, so create/insert an entry
return tx.CreateNoReturn_Irreparabledb(
ctx,
dbx.Irreparabledb_Segmentpath(segmentInfo.Path),
dbx.Irreparabledb_Segmentdetail(bytes),
dbx.Irreparabledb_PiecesLostCount(int64(segmentInfo.LostPieces)),
dbx.Irreparabledb_SegDamagedUnixSec(segmentInfo.LastRepairAttempt),
dbx.Irreparabledb_RepairAttemptCount(segmentInfo.RepairAttemptCount),
)
}
return err
}
// row exits increment the attempt counter
dbxInfo.RepairAttemptCount++
updateFields := dbx.Irreparabledb_Update_Fields{}
updateFields.RepairAttemptCount = dbx.Irreparabledb_RepairAttemptCount(dbxInfo.RepairAttemptCount)
updateFields.SegDamagedUnixSec = dbx.Irreparabledb_SegDamagedUnixSec(segmentInfo.LastRepairAttempt)
err = tx.UpdateNoReturn_Irreparabledb_By_Segmentpath(
ctx,
dbx.Irreparabledb_Segmentpath(dbxInfo.Segmentpath),
updateFields,
)
return err
})
return Error.Wrap(err)
}
// Get a irreparable's segment info from the db
func (db *irreparableDB) Get(ctx context.Context, segmentPath []byte) (resp *pb.IrreparableSegment, err error) {
defer mon.Task()(&ctx)(&err)
dbxInfo, err := db.db.Get_Irreparabledb_By_Segmentpath(ctx, dbx.Irreparabledb_Segmentpath(segmentPath))
if err != nil {
return nil, Error.Wrap(err)
}
p := &pb.Pointer{}
err = pb.Unmarshal(dbxInfo.Segmentdetail, p)
if err != nil {
return nil, Error.Wrap(err)
}
return &pb.IrreparableSegment{
Path: dbxInfo.Segmentpath,
SegmentDetail: p,
LostPieces: int32(dbxInfo.PiecesLostCount),
LastRepairAttempt: dbxInfo.SegDamagedUnixSec,
RepairAttemptCount: dbxInfo.RepairAttemptCount,
}, nil
}
// GetLimited returns a list of irreparable segment info starting after the last segment info we retrieved
func (db *irreparableDB) GetLimited(ctx context.Context, limit int, lastSeenSegmentPath []byte) (resp []*pb.IrreparableSegment, err error) {
defer mon.Task()(&ctx)(&err)
// the offset is hardcoded to 0 since we are using the lastSeenSegmentPath to
// indicate the item we last listed instead. In a perfect world this db query would
// not take an offset as an argument, but currently dbx only supports `limitoffset`
const offset = 0
rows, err := db.db.Limited_Irreparabledb_By_Segmentpath_Greater_OrderBy_Asc_Segmentpath(ctx,
dbx.Irreparabledb_Segmentpath(lastSeenSegmentPath),
limit, offset,
)
if err != nil {
return nil, err
}
for _, row := range rows {
p := &pb.Pointer{}
err = pb.Unmarshal(row.Segmentdetail, p)
if err != nil {
return nil, err
}
segment := &pb.IrreparableSegment{
Path: row.Segmentpath,
SegmentDetail: p,
LostPieces: int32(row.PiecesLostCount),
LastRepairAttempt: row.SegDamagedUnixSec,
RepairAttemptCount: row.RepairAttemptCount,
}
resp = append(resp, segment)
}
return resp, err
}
// Delete a irreparable's segment info from the db
func (db *irreparableDB) Delete(ctx context.Context, segmentPath []byte) (err error) {
defer mon.Task()(&ctx)(&err)
_, err = db.db.Delete_Irreparabledb_By_Segmentpath(ctx, dbx.Irreparabledb_Segmentpath(segmentPath))
return Error.Wrap(err)
}