17bdb5e9e5
Deprecate the pieceinfo database, and start storing piece info as a header to piece files. Institute a "storage format version" concept allowing us to handle pieces stored under multiple different types of storage. Add a piece_expirations table which will still be used to track expiration times, so we can query it, but which should be much smaller than the pieceinfo database would be for the same number of pieces. (Only pieces with expiration times need to be stored in piece_expirations, and we don't need to store large byte blobs like the serialized order limit, etc.) Use specialized names for accessing any functionality related only to dealing with V0 pieces (e.g., `store.V0PieceInfo()`). Move SpaceUsed- type functionality under the purview of the piece store. Add some generic interfaces for traversing all blobs or all pieces. Add lots of tests.
100 lines
3.0 KiB
Go
100 lines
3.0 KiB
Go
// Copyright (C) 2019 Storj Labs, Inc.
|
|
// See LICENSE for copying information.
|
|
|
|
package storagenodedb
|
|
|
|
import (
|
|
"context"
|
|
"time"
|
|
|
|
"github.com/zeebo/errs"
|
|
|
|
"storj.io/storj/pkg/storj"
|
|
"storj.io/storj/storagenode/pieces"
|
|
)
|
|
|
|
type pieceExpirationDB struct {
|
|
*InfoDB
|
|
}
|
|
|
|
// PieceExpirationDB returns database for storing piece expiration data
|
|
func (db *DB) PieceExpirationDB() pieces.PieceExpirationDB { return db.info.PieceExpirationDB() }
|
|
|
|
// PieceExpirationDB returns database for storing piece expiration data
|
|
func (db *InfoDB) PieceExpirationDB() pieces.PieceExpirationDB { return &db.pieceExpirationDB }
|
|
|
|
// GetExpired gets piece IDs that expire or have expired before the given time
|
|
func (db *pieceExpirationDB) GetExpired(ctx context.Context, expiresBefore time.Time, limit int64) (expiredPieceIDs []pieces.ExpiredInfo, err error) {
|
|
defer mon.Task()(&ctx)(&err)
|
|
|
|
rows, err := db.db.QueryContext(ctx, `
|
|
SELECT satellite_id, piece_id
|
|
FROM piece_expirations
|
|
WHERE piece_expiration < ?
|
|
AND ((deletion_failed_at IS NULL) OR deletion_failed_at <> ?)
|
|
LIMIT ?
|
|
`, expiresBefore.UTC(), expiresBefore.UTC(), limit)
|
|
if err != nil {
|
|
return nil, ErrInfo.Wrap(err)
|
|
}
|
|
defer func() { err = errs.Combine(err, rows.Close()) }()
|
|
|
|
for rows.Next() {
|
|
var satelliteID storj.NodeID
|
|
var pieceID storj.PieceID
|
|
err = rows.Scan(&satelliteID, &pieceID)
|
|
if err != nil {
|
|
return nil, ErrInfo.Wrap(err)
|
|
}
|
|
expiredPieceIDs = append(expiredPieceIDs, pieces.ExpiredInfo{
|
|
SatelliteID: satelliteID,
|
|
PieceID: pieceID,
|
|
InPieceInfo: false,
|
|
})
|
|
}
|
|
return expiredPieceIDs, nil
|
|
}
|
|
|
|
// SetExpiration sets an expiration time for the given piece ID on the given satellite
|
|
func (db *pieceExpirationDB) SetExpiration(ctx context.Context, satellite storj.NodeID, pieceID storj.PieceID, expiresAt time.Time) (err error) {
|
|
defer mon.Task()(&ctx)(&err)
|
|
|
|
_, err = db.db.ExecContext(ctx, `
|
|
INSERT INTO piece_expirations(satellite_id, piece_id, piece_expiration)
|
|
VALUES (?,?,?)
|
|
`, satellite, pieceID, expiresAt.UTC())
|
|
return ErrInfo.Wrap(err)
|
|
}
|
|
|
|
// DeleteExpiration removes an expiration record for the given piece ID on the given satellite
|
|
func (db *pieceExpirationDB) DeleteExpiration(ctx context.Context, satelliteID storj.NodeID, pieceID storj.PieceID) (found bool, err error) {
|
|
defer mon.Task()(&ctx)(&err)
|
|
|
|
result, err := db.db.ExecContext(ctx, `
|
|
DELETE FROM piece_expirations
|
|
WHERE satellite_id = ? AND piece_id = ?
|
|
`, satelliteID, pieceID)
|
|
if err != nil {
|
|
return false, err
|
|
}
|
|
numRows, err := result.RowsAffected()
|
|
if err != nil {
|
|
return false, err
|
|
}
|
|
return numRows > 0, nil
|
|
}
|
|
|
|
// DeleteFailed marks an expiration record as having experienced a failure in deleting the piece
|
|
// from the disk
|
|
func (db *pieceExpirationDB) DeleteFailed(ctx context.Context, satelliteID storj.NodeID, pieceID storj.PieceID, when time.Time) (err error) {
|
|
defer mon.Task()(&ctx)(&err)
|
|
|
|
_, err = db.db.ExecContext(ctx, `
|
|
UPDATE piece_expirations
|
|
SET deletion_failed_at = ?
|
|
WHERE satellite_id = ?
|
|
AND piece_id = ?
|
|
`, when.UTC(), satelliteID, pieceID)
|
|
return ErrInfo.Wrap(err)
|
|
}
|