2019-09-16 18:54:53 +01:00
// Copyright (C) 2019 Storj Labs, Inc.
// See LICENSE for copying information.
package storagenodedb
import (
2019-10-01 15:34:03 +01:00
"context"
"time"
2019-09-16 18:54:53 +01:00
"github.com/zeebo/errs"
2019-10-01 15:34:03 +01:00
2019-12-27 11:48:47 +00:00
"storj.io/common/storj"
2021-04-23 10:52:40 +01:00
"storj.io/private/tagsql"
2019-10-01 15:34:03 +01:00
"storj.io/storj/storagenode/satellites"
2019-09-16 18:54:53 +01:00
)
// ErrSatellitesDB represents errors from the satellites database.
2021-04-28 09:06:17 +01:00
var ErrSatellitesDB = errs . Class ( "satellitesdb" )
2019-09-16 18:54:53 +01:00
2019-09-18 17:17:28 +01:00
// SatellitesDBName represents the database name.
const SatellitesDBName = "satellites"
2020-07-16 15:18:02 +01:00
// reputation works with node reputation DB.
2019-09-16 18:54:53 +01:00
type satellitesDB struct {
2019-11-13 16:49:22 +00:00
dbContainerImpl
2019-09-16 18:54:53 +01:00
}
2019-10-01 15:34:03 +01:00
2021-07-08 10:14:15 +01:00
// SetAddress inserts into satellite's db id, address, added time.
func ( db * satellitesDB ) SetAddress ( ctx context . Context , satelliteID storj . NodeID , address string ) ( err error ) {
defer mon . Task ( ) ( & ctx ) ( & err )
_ , err = db . ExecContext ( ctx ,
` INSERT INTO satellites (node_id, address, added_at, status) VALUES(?,?,?,?) ON CONFLICT (node_id) DO UPDATE SET address = EXCLUDED.address ` ,
satelliteID ,
address ,
time . Now ( ) . UTC ( ) ,
satellites . Normal ,
)
return ErrSatellitesDB . Wrap ( err )
}
2023-08-01 10:46:55 +01:00
// SetAddressAndStatus inserts into satellite's db id, address, added time and status.
func ( db * satellitesDB ) SetAddressAndStatus ( ctx context . Context , satelliteID storj . NodeID , address string , status satellites . Status ) ( err error ) {
defer mon . Task ( ) ( & ctx ) ( & err )
_ , err = db . ExecContext ( ctx ,
` INSERT INTO satellites (node_id, address, added_at, status) VALUES(?,?,?,?) ON CONFLICT (node_id) DO UPDATE SET address = EXCLUDED.address, status = EXCLUDED.status ` ,
satelliteID ,
address ,
time . Now ( ) . UTC ( ) ,
status ,
)
return ErrSatellitesDB . Wrap ( err )
}
2020-07-16 15:18:02 +01:00
// GetSatellite retrieves that satellite by ID.
2019-10-28 17:59:45 +00:00
func ( db * satellitesDB ) GetSatellite ( ctx context . Context , satelliteID storj . NodeID ) ( satellite satellites . Satellite , err error ) {
defer mon . Task ( ) ( & ctx ) ( & err )
2022-02-22 14:41:20 +00:00
rows , err := db . QueryContext ( ctx , "SELECT node_id, added_at, status FROM satellites WHERE node_id = ?" , satelliteID )
2019-10-28 17:59:45 +00:00
if err != nil {
return satellite , err
}
defer func ( ) { err = errs . Combine ( err , rows . Close ( ) ) } ( )
if rows . Next ( ) {
err := rows . Scan ( & satellite . SatelliteID , & satellite . AddedAt , & satellite . Status )
if err != nil {
return satellite , err
}
}
2020-01-16 14:36:50 +00:00
return satellite , rows . Err ( )
2019-10-28 17:59:45 +00:00
}
2023-08-01 10:46:55 +01:00
// GetSatellites retrieves all satellites.
func ( db * satellitesDB ) GetSatellites ( ctx context . Context ) ( sats [ ] satellites . Satellite , err error ) {
defer mon . Task ( ) ( & ctx ) ( & err )
rows , err := db . QueryContext ( ctx , "SELECT node_id, added_at, status FROM satellites" )
if err != nil {
return nil , err
}
defer func ( ) { err = errs . Combine ( err , rows . Close ( ) ) } ( )
for rows . Next ( ) {
var satellite satellites . Satellite
err := rows . Scan ( & satellite . SatelliteID , & satellite . AddedAt , & satellite . Status )
if err != nil {
return nil , err
}
sats = append ( sats , satellite )
}
return sats , rows . Err ( )
}
2021-07-29 15:30:57 +01:00
// GetSatellitesUrls retrieves all satellite's id and urls.
func ( db * satellitesDB ) GetSatellitesUrls ( ctx context . Context ) ( satelliteURLs [ ] storj . NodeURL , err error ) {
2021-07-08 10:14:15 +01:00
defer mon . Task ( ) ( & ctx ) ( & err )
query := ` SELECT
node_id ,
address
FROM satellites `
rows , err := db . QueryContext ( ctx , query )
if err != nil {
return nil , err
}
defer func ( ) { err = errs . Combine ( err , rows . Close ( ) ) } ( )
var urls [ ] storj . NodeURL
for rows . Next ( ) {
var url storj . NodeURL
err := rows . Scan ( & url . ID , & url . Address )
if err != nil {
return nil , ErrPayout . Wrap ( err )
}
urls = append ( urls , url )
}
if err = rows . Err ( ) ; err != nil {
return nil , ErrPayout . Wrap ( err )
}
return urls , nil
}
2023-08-01 10:46:55 +01:00
// UpdateSatelliteStatus updates satellite status.
func ( db * satellitesDB ) UpdateSatelliteStatus ( ctx context . Context , satelliteID storj . NodeID , status satellites . Status ) ( err error ) {
defer mon . Task ( ) ( & ctx ) ( & err )
_ , err = db . ExecContext ( ctx , "UPDATE satellites SET status = ? WHERE node_id = ?" , status , satelliteID )
return ErrSatellitesDB . Wrap ( err )
}
2020-07-16 15:18:02 +01:00
// InitiateGracefulExit updates the database to reflect the beginning of a graceful exit.
2019-10-01 15:34:03 +01:00
func ( db * satellitesDB ) InitiateGracefulExit ( ctx context . Context , satelliteID storj . NodeID , intitiatedAt time . Time , startingDiskUsage int64 ) ( err error ) {
defer mon . Task ( ) ( & ctx ) ( & err )
2020-01-17 19:08:29 +00:00
return ErrSatellitesDB . Wrap ( withTx ( ctx , db . GetDB ( ) , func ( tx tagsql . Tx ) error {
2019-10-01 15:34:03 +01:00
query := ` INSERT OR REPLACE INTO satellites (node_id, status, added_at) VALUES (?,?, COALESCE((SELECT added_at FROM satellites WHERE node_id = ?), ?)) `
_ , err = tx . ExecContext ( ctx , query , satelliteID , satellites . Exiting , satelliteID , intitiatedAt . UTC ( ) ) // assume intitiatedAt < time.Now()
if err != nil {
return err
}
query = ` INSERT INTO satellite_exit_progress (satellite_id, initiated_at, starting_disk_usage, bytes_deleted) VALUES (?,?,?,0) `
_ , err = tx . ExecContext ( ctx , query , satelliteID , intitiatedAt . UTC ( ) , startingDiskUsage )
return err
} ) )
2020-01-08 02:33:41 +00:00
}
2020-07-16 15:18:02 +01:00
// CancelGracefulExit delete an entry by satellite ID.
2020-01-08 02:33:41 +00:00
func ( db * satellitesDB ) CancelGracefulExit ( ctx context . Context , satelliteID storj . NodeID ) ( err error ) {
defer mon . Task ( ) ( & ctx ) ( & err )
_ , err = db . ExecContext ( ctx , "DELETE FROM satellite_exit_progress WHERE satellite_id = ?" , satelliteID )
return ErrSatellitesDB . Wrap ( err )
2019-10-01 15:34:03 +01:00
}
2020-07-16 15:18:02 +01:00
// UpdateGracefulExit increments the total bytes deleted during a graceful exit.
2019-10-01 15:34:03 +01:00
func ( db * satellitesDB ) UpdateGracefulExit ( ctx context . Context , satelliteID storj . NodeID , addToBytesDeleted int64 ) ( err error ) {
defer mon . Task ( ) ( & ctx ) ( & err )
query := ` UPDATE satellite_exit_progress SET bytes_deleted = bytes_deleted + ? WHERE satellite_id = ? `
_ , err = db . ExecContext ( ctx , query , addToBytesDeleted , satelliteID )
return ErrSatellitesDB . Wrap ( err )
}
2020-07-16 15:18:02 +01:00
// CompleteGracefulExit updates the database when a graceful exit is completed or failed.
2019-10-01 15:34:03 +01:00
func ( db * satellitesDB ) CompleteGracefulExit ( ctx context . Context , satelliteID storj . NodeID , finishedAt time . Time , exitStatus satellites . Status , completionReceipt [ ] byte ) ( err error ) {
defer mon . Task ( ) ( & ctx ) ( & err )
2020-01-17 19:08:29 +00:00
return ErrSatellitesDB . Wrap ( withTx ( ctx , db . GetDB ( ) , func ( tx tagsql . Tx ) error {
2023-08-01 10:46:55 +01:00
err := db . UpdateSatelliteStatus ( ctx , satelliteID , exitStatus )
2019-10-01 15:34:03 +01:00
if err != nil {
return err
}
2023-08-01 10:46:55 +01:00
query := ` UPDATE satellite_exit_progress SET finished_at = ?, completion_receipt = ? WHERE satellite_id = ? `
2019-10-01 15:34:03 +01:00
_ , err = tx . ExecContext ( ctx , query , finishedAt . UTC ( ) , completionReceipt , satelliteID )
return err
} ) )
}
2020-07-16 15:18:02 +01:00
// ListGracefulExits lists all graceful exit records.
2019-10-01 15:34:03 +01:00
func ( db * satellitesDB ) ListGracefulExits ( ctx context . Context ) ( exitList [ ] satellites . ExitProgress , err error ) {
defer mon . Task ( ) ( & ctx ) ( & err )
2019-12-20 15:59:47 +00:00
2020-01-14 17:23:09 +00:00
query := ` SELECT satellite_id, initiated_at, finished_at, starting_disk_usage, bytes_deleted, completion_receipt, status FROM satellite_exit_progress INNER JOIN satellites ON satellite_exit_progress.satellite_id = satellites.node_id `
2019-12-20 15:59:47 +00:00
rows , err := db . QueryContext ( ctx , query )
if err != nil {
return nil , ErrSatellitesDB . Wrap ( err )
}
defer func ( ) {
err = ErrSatellitesDB . Wrap ( errs . Combine ( err , rows . Close ( ) ) )
} ( )
for rows . Next ( ) {
var exit satellites . ExitProgress
2020-01-14 17:23:09 +00:00
err := rows . Scan ( & exit . SatelliteID , & exit . InitiatedAt , & exit . FinishedAt , & exit . StartingDiskUsage , & exit . BytesDeleted , & exit . CompletionReceipt , & exit . Status )
2019-10-01 15:34:03 +01:00
if err != nil {
2019-12-20 15:59:47 +00:00
return nil , err
2019-10-01 15:34:03 +01:00
}
2019-12-20 15:59:47 +00:00
exitList = append ( exitList , exit )
}
2020-01-16 14:36:50 +00:00
return exitList , rows . Err ( )
2019-10-01 15:34:03 +01:00
}
2023-08-01 10:46:55 +01:00
// DeleteSatellite deletes the satellite from the database.
func ( db * satellitesDB ) DeleteSatellite ( ctx context . Context , satelliteID storj . NodeID ) ( err error ) {
defer mon . Task ( ) ( & ctx ) ( & err )
_ , err = db . ExecContext ( ctx , "DELETE FROM satellites WHERE node_id = ?" , satelliteID )
return ErrSatellitesDB . Wrap ( err )
}