1
0
Fork 0
You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

160 lines
4.2 KiB
Go

package db
import (
"fmt"
"io"
"os"
"sync"
command "github.com/rqlite/rqlite/v8/command/proto"
)
8 months ago
// SwappableDB is a wrapper around DB that allows the underlying database to be swapped out
// in a thread-safe manner.
type SwappableDB struct {
db *DB
dbMu sync.RWMutex
}
8 months ago
// OpenSwappable returns a new SwappableDB instance, which opens the database at the given path.
func OpenSwappable(dbPath string, fkEnabled, wal bool) (*SwappableDB, error) {
db, err := Open(dbPath, fkEnabled, wal)
if err != nil {
return nil, err
}
return &SwappableDB{db: db}, nil
}
// Swap swaps the underlying database with that at the given path. The Swap operation
// may fail on some platforms if the file at path is open by another process. It is
// the caller's responsibility to ensure the file at path is not in use.
func (s *SwappableDB) Swap(path string, fkConstraints, walEnabled bool) error {
if !IsValidSQLiteFile(path) {
return fmt.Errorf("invalid SQLite data")
}
s.dbMu.Lock()
defer s.dbMu.Unlock()
if err := s.db.Close(); err != nil {
return fmt.Errorf("failed to close: %s", err)
}
if err := RemoveFiles(s.db.Path()); err != nil {
return fmt.Errorf("failed to remove files: %s", err)
}
if err := os.Rename(path, s.db.Path()); err != nil {
return fmt.Errorf("failed to rename database: %s", err)
}
db, err := Open(s.db.Path(), fkConstraints, walEnabled)
if err != nil {
return fmt.Errorf("open SQLite file failed: %s", err)
}
s.db = db
return nil
}
8 months ago
// Close closes the underlying database.
func (s *SwappableDB) Close() error {
s.dbMu.RLock()
defer s.dbMu.RUnlock()
return s.db.Close()
}
8 months ago
// Stats returns the underlying database's stats.
func (s *SwappableDB) Stats() (map[string]interface{}, error) {
s.dbMu.RLock()
defer s.dbMu.RUnlock()
return s.db.Stats()
}
8 months ago
// Request calls Request on the underlying database.
func (s *SwappableDB) Request(req *command.Request, xTime bool) ([]*command.ExecuteQueryResponse, error) {
s.dbMu.RLock()
defer s.dbMu.RUnlock()
return s.db.Request(req, xTime)
}
8 months ago
// Execute calls Execute on the underlying database.
func (s *SwappableDB) Execute(ex *command.Request, xTime bool) ([]*command.ExecuteResult, error) {
s.dbMu.RLock()
defer s.dbMu.RUnlock()
return s.db.Execute(ex, xTime)
}
8 months ago
// Query calls Query on the underlying database.
func (s *SwappableDB) Query(q *command.Request, xTime bool) ([]*command.QueryRows, error) {
s.dbMu.RLock()
defer s.dbMu.RUnlock()
return s.db.Query(q, xTime)
}
// QueryStringStmt calls QueryStringStmt on the underlying database.
func (s *SwappableDB) QueryStringStmt(query string) ([]*command.QueryRows, error) {
s.dbMu.RLock()
defer s.dbMu.RUnlock()
return s.db.QueryStringStmt(query)
}
8 months ago
// VacuumInto calls VacuumInto on the underlying database.
func (s *SwappableDB) VacuumInto(path string) error {
s.dbMu.RLock()
defer s.dbMu.RUnlock()
return s.db.VacuumInto(path)
}
8 months ago
// Backup calls Backup on the underlying database.
func (s *SwappableDB) Backup(path string, vacuum bool) error {
s.dbMu.RLock()
defer s.dbMu.RUnlock()
return s.db.Backup(path, vacuum)
}
8 months ago
// Serialize calls Serialize on the underlying database.
func (s *SwappableDB) Serialize() ([]byte, error) {
s.dbMu.RLock()
defer s.dbMu.RUnlock()
return s.db.Serialize()
}
8 months ago
// StmtReadOnly calls StmtReadOnly on the underlying database.
func (s *SwappableDB) StmtReadOnly(sql string) (bool, error) {
s.dbMu.RLock()
defer s.dbMu.RUnlock()
return s.db.StmtReadOnly(sql)
}
8 months ago
// Checkpoint calls Checkpoint on the underlying database.
func (s *SwappableDB) Checkpoint(mode CheckpointMode) error {
s.dbMu.RLock()
defer s.dbMu.RUnlock()
return s.db.Checkpoint(mode)
}
8 months ago
// Path calls Path on the underlying database.
func (s *SwappableDB) Path() string {
s.dbMu.RLock()
defer s.dbMu.RUnlock()
return s.db.Path()
}
8 months ago
// Dump calls Dump on the underlying database.
func (s *SwappableDB) Dump(w io.Writer) error {
s.dbMu.RLock()
defer s.dbMu.RUnlock()
return s.db.Dump(w)
}
8 months ago
// FKEnabled calls FKEnabled on the underlying database.
func (s *SwappableDB) FKEnabled() bool {
s.dbMu.RLock()
defer s.dbMu.RUnlock()
8 months ago
return s.db.FKEnabled()
}
8 months ago
// WALEnabled calls WALEnabled on the underlying database.
func (s *SwappableDB) WALEnabled() bool {
s.dbMu.RLock()
defer s.dbMu.RUnlock()
8 months ago
return s.db.WALEnabled()
}