fix: Support Delete NFT (#1695)

Fixes #1677
This commit is contained in:
Peter Chen
2024-10-25 11:27:02 -04:00
committed by Alex Kremer
parent ffc9deb0f8
commit 081adf1cae
3 changed files with 198 additions and 104 deletions

View File

@@ -51,15 +51,19 @@ var (
userName = app.Flag("username", "Username to use when connecting to the cluster").String() userName = app.Flag("username", "Username to use when connecting to the cluster").String()
password = app.Flag("password", "Password to use when connecting to the cluster").String() password = app.Flag("password", "Password to use when connecting to the cluster").String()
skipSuccessorTable = app.Flag("skip-successor", "Whether to skip deletion from successor table").Default("false").Bool() skipSuccessorTable = app.Flag("skip-successor", "Whether to skip deletion from successor table").Default("false").Bool()
skipObjectsTable = app.Flag("skip-objects", "Whether to skip deletion from objects table").Default("false").Bool() skipObjectsTable = app.Flag("skip-objects", "Whether to skip deletion from objects table").Default("false").Bool()
skipLedgerHashesTable = app.Flag("skip-ledger-hashes", "Whether to skip deletion from ledger_hashes table").Default("false").Bool() skipLedgerHashesTable = app.Flag("skip-ledger-hashes", "Whether to skip deletion from ledger_hashes table").Default("false").Bool()
skipTransactionsTable = app.Flag("skip-transactions", "Whether to skip deletion from transactions table").Default("false").Bool() skipTransactionsTable = app.Flag("skip-transactions", "Whether to skip deletion from transactions table").Default("false").Bool()
skipDiffTable = app.Flag("skip-diff", "Whether to skip deletion from diff table").Default("false").Bool() skipDiffTable = app.Flag("skip-diff", "Whether to skip deletion from diff table").Default("false").Bool()
skipLedgerTransactionsTable = app.Flag("skip-ledger-transactions", "Whether to skip deletion from ledger_transactions table").Default("false").Bool() skipLedgerTransactionsTable = app.Flag("skip-ledger-transactions", "Whether to skip deletion from ledger_transactions table").Default("false").Bool()
skipLedgersTable = app.Flag("skip-ledgers", "Whether to skip deletion from ledgers table").Default("false").Bool() skipLedgersTable = app.Flag("skip-ledgers", "Whether to skip deletion from ledgers table").Default("false").Bool()
skipWriteLatestLedger = app.Flag("skip-write-latest-ledger", "Whether to skip writing the latest ledger index").Default("false").Bool() skipWriteLatestLedger = app.Flag("skip-write-latest-ledger", "Whether to skip writing the latest ledger index").Default("false").Bool()
skipAccTransactionsTable = app.Flag("skip-account-transactions", "Whether to skip deletion from account_transactions table").Default("false").Bool() skipAccTransactionsTable = app.Flag("skip-account-transactions", "Whether to skip deletion from account_transactions table").Default("false").Bool()
skipNFTokenTable = app.Flag("skip-nf-tokens", "Whether to skip deletion from nf_tokens table").Default("false").Bool()
skipIssuerNFTokenTable = app.Flag("skip-issuer-nf-tokens-v2", "Whether to skip deletion from issuer_nf_tokens_v2 table").Default("false").Bool()
skipNFTokenURITable = app.Flag("skip-nf-tokens-uri", "Whether to skip deletion from nf_token_uris table").Default("false").Bool()
skipNFTokenTransactionsTable = app.Flag("skip-nf-token-transactions", "Whether to skip deletion from nf_token_transactions table").Default("false").Bool()
workerCount = 1 // the calculated number of parallel goroutines the client should run workerCount = 1 // the calculated number of parallel goroutines the client should run
ranges []*util.TokenRange // the calculated ranges to be executed in parallel ranges []*util.TokenRange // the calculated ranges to be executed in parallel
@@ -81,19 +85,24 @@ func main() {
} }
clioCass := cass.NewClioCass(&cass.Settings{ clioCass := cass.NewClioCass(&cass.Settings{
SkipSuccessorTable: *skipSuccessorTable, SkipSuccessorTable: *skipSuccessorTable,
SkipObjectsTable: *skipObjectsTable, SkipObjectsTable: *skipObjectsTable,
SkipLedgerHashesTable: *skipLedgerHashesTable, SkipLedgerHashesTable: *skipLedgerHashesTable,
SkipTransactionsTable: *skipTransactionsTable, SkipTransactionsTable: *skipTransactionsTable,
SkipDiffTable: *skipDiffTable, SkipDiffTable: *skipDiffTable,
SkipLedgerTransactionsTable: *skipLedgerHashesTable, SkipLedgerTransactionsTable: *skipLedgerHashesTable,
SkipLedgersTable: *skipLedgersTable, SkipLedgersTable: *skipLedgersTable,
SkipWriteLatestLedger: *skipWriteLatestLedger, SkipWriteLatestLedger: *skipWriteLatestLedger,
SkipAccTransactionsTable: *skipAccTransactionsTable, SkipAccTransactionsTable: *skipAccTransactionsTable,
WorkerCount: workerCount, SkipNFTokenTable: *skipNFTokenTable,
Ranges: ranges, SkipIssuerNFTokenTable: *skipIssuerNFTokenTable,
RangesRead: ledgerOrTokenRange, SkipNFTokenURITable: *skipNFTokenURITable,
Command: cmd}, cluster) SkipNFTokenTransactionsTable: *skipNFTokenTransactionsTable,
WorkerCount: workerCount,
Ranges: ranges,
RangesRead: ledgerOrTokenRange,
Command: cmd}, cluster)
switch command { switch command {
case deleteAfter.FullCommand(): case deleteAfter.FullCommand():
@@ -171,6 +180,10 @@ Skip deletion of:
- ledger_transactions table : %t - ledger_transactions table : %t
- ledgers table : %t - ledgers table : %t
- account_tx table : %t - account_tx table : %t
- nf_tokens table : %t
- issuer_nf_tokens_v2 table : %t
- nf_token_uris table : %t
- nf_token_transactions table : %t
Will update ledger_range : %t Will update ledger_range : %t
@@ -194,6 +207,10 @@ Will update ledger_range : %t
*skipLedgerTransactionsTable, *skipLedgerTransactionsTable,
*skipLedgersTable, *skipLedgersTable,
*skipAccTransactionsTable, *skipAccTransactionsTable,
*skipNFTokenTable,
*skipIssuerNFTokenTable,
*skipNFTokenURITable,
*skipNFTokenTransactionsTable,
!*skipWriteLatestLedger, !*skipWriteLatestLedger,
) )
@@ -264,6 +281,15 @@ func prepareResume(cmd *string) {
// should be already deleted so we skip for deletion // should be already deleted so we skip for deletion
tableFound := false tableFound := false
switch scanner.Text() { switch scanner.Text() {
case "nf_token_transactions":
*skipNFTokenURITable = true
fallthrough
case "nf_token_uris":
*skipNFTokenTable = true
fallthrough
case "nf_tokens":
*skipAccTransactionsTable = true
fallthrough
case "account_tx": case "account_tx":
*skipLedgersTable = true *skipLedgersTable = true
fallthrough fallthrough

View File

@@ -38,15 +38,19 @@ type deleteMethod struct {
} }
type Settings struct { type Settings struct {
SkipSuccessorTable bool SkipSuccessorTable bool
SkipObjectsTable bool SkipObjectsTable bool
SkipLedgerHashesTable bool SkipLedgerHashesTable bool
SkipTransactionsTable bool SkipTransactionsTable bool
SkipDiffTable bool SkipDiffTable bool
SkipLedgerTransactionsTable bool SkipLedgerTransactionsTable bool
SkipLedgersTable bool SkipLedgersTable bool
SkipWriteLatestLedger bool SkipWriteLatestLedger bool
SkipAccTransactionsTable bool SkipAccTransactionsTable bool
SkipNFTokenTable bool
SkipIssuerNFTokenTable bool
SkipNFTokenURITable bool
SkipNFTokenTransactionsTable bool
WorkerCount int WorkerCount int
Ranges []*util.TokenRange Ranges []*util.TokenRange
@@ -54,44 +58,6 @@ type Settings struct {
Command string Command string
} }
type Marker struct {
cmd string
file *os.File
}
func NewMarker(cmd string) *Marker {
return &Marker{cmd: cmd}
}
func CloseMarker(m *Marker) {
if m.file != nil {
m.file.Close()
}
os.Remove("continue.txt")
}
func (m *Marker) EnterTable(table string) error {
// Create the file
file, err := os.OpenFile("continue.txt", os.O_WRONLY|os.O_TRUNC|os.O_CREATE, 0644)
m.file = file
if err != nil {
return fmt.Errorf("failed to create file: %w", err)
}
fmt.Fprintf(m.file, "%s\n", m.cmd)
m.file.WriteString(fmt.Sprintf("%s\n", table))
return nil
}
func (m *Marker) MarkProgress(x int64, y int64) {
fmt.Fprintf(m.file, "%d, %d \n", x, y)
}
func (m *Marker) ExitTable() {
m.file.Close()
m.file = nil
os.Remove("continue.txt")
}
type Cass interface { type Cass interface {
GetLedgerRange() (uint64, uint64, error) GetLedgerRange() (uint64, uint64, error)
DeleteBefore(ledgerIdx uint64) DeleteBefore(ledgerIdx uint64)
@@ -227,7 +193,7 @@ func (c *ClioCass) pruneData(
// successor queries // successor queries
if !c.settings.SkipSuccessorTable { if !c.settings.SkipSuccessorTable {
marker := NewMarker(c.settings.Command) marker := util.NewMarker(c.settings.Command)
if err := marker.EnterTable("successor"); err != nil { if err := marker.EnterTable("successor"); err != nil {
return err return err
} }
@@ -235,7 +201,7 @@ func (c *ClioCass) pruneData(
log.Println("Generating delete queries for successor table") log.Println("Generating delete queries for successor table")
rowsCount, deleteCount, errCount = c.prepareAndExecuteDeleteQueries(marker, fromLedgerIdx, toLedgerIdx, rowsCount, deleteCount, errCount = c.prepareAndExecuteDeleteQueries(marker, fromLedgerIdx, toLedgerIdx,
"SELECT key, seq FROM successor WHERE token(key) >= ? AND token(key) <= ?", "SELECT key, seq FROM successor WHERE token(key) >= ? AND token(key) <= ?",
"DELETE FROM successor WHERE key = ? AND seq = ?", deleteMethod{deleteGeneral: maybe.Set(true)}, columnSettings{UseBlob: true, UseSeq: false}) "DELETE FROM successor WHERE key = ? AND seq = ?", deleteMethod{deleteGeneral: maybe.Set(true)}, columnSettings{})
log.Printf("Total delete queries: %d\n", deleteCount) log.Printf("Total delete queries: %d\n", deleteCount)
log.Printf("Total traversed rows: %d\n\n", rowsCount) log.Printf("Total traversed rows: %d\n\n", rowsCount)
totalRows += rowsCount totalRows += rowsCount
@@ -247,7 +213,7 @@ func (c *ClioCass) pruneData(
// objects queries // objects queries
if !c.settings.SkipObjectsTable { if !c.settings.SkipObjectsTable {
marker := NewMarker(c.settings.Command) marker := util.NewMarker(c.settings.Command)
if err := marker.EnterTable("objects"); err != nil { if err := marker.EnterTable("objects"); err != nil {
return err return err
} }
@@ -255,7 +221,7 @@ func (c *ClioCass) pruneData(
log.Println("Generating delete queries for objects table") log.Println("Generating delete queries for objects table")
rowsCount, deleteCount, errCount = c.prepareAndExecuteDeleteQueries(marker, fromLedgerIdx, toLedgerIdx, rowsCount, deleteCount, errCount = c.prepareAndExecuteDeleteQueries(marker, fromLedgerIdx, toLedgerIdx,
"SELECT key, sequence FROM objects WHERE token(key) >= ? AND token(key) <= ?", "SELECT key, sequence FROM objects WHERE token(key) >= ? AND token(key) <= ?",
"DELETE FROM objects WHERE key = ? AND sequence = ?", deleteMethod{deleteObject: maybe.Set(true)}, columnSettings{UseBlob: true, UseSeq: true}) "DELETE FROM objects WHERE key = ? AND sequence = ?", deleteMethod{deleteObject: maybe.Set(true)}, columnSettings{})
log.Printf("Total delete queries: %d\n", deleteCount) log.Printf("Total delete queries: %d\n", deleteCount)
log.Printf("Total traversed rows: %d\n\n", rowsCount) log.Printf("Total traversed rows: %d\n\n", rowsCount)
totalErrors += errCount totalErrors += errCount
@@ -267,7 +233,7 @@ func (c *ClioCass) pruneData(
// ledger_hashes queries // ledger_hashes queries
if !c.settings.SkipLedgerHashesTable { if !c.settings.SkipLedgerHashesTable {
marker := NewMarker(c.settings.Command) marker := util.NewMarker(c.settings.Command)
if err := marker.EnterTable("ledger_hashes"); err != nil { if err := marker.EnterTable("ledger_hashes"); err != nil {
return err return err
} }
@@ -287,7 +253,7 @@ func (c *ClioCass) pruneData(
// transactions queries // transactions queries
if !c.settings.SkipTransactionsTable { if !c.settings.SkipTransactionsTable {
marker := NewMarker(c.settings.Command) marker := util.NewMarker(c.settings.Command)
if err := marker.EnterTable("transactions"); err != nil { if err := marker.EnterTable("transactions"); err != nil {
return err return err
} }
@@ -306,8 +272,9 @@ func (c *ClioCass) pruneData(
} }
// diff queries // diff queries
if !c.settings.SkipDiffTable { if !c.settings.SkipDiffTable {
marker := NewMarker(c.settings.Command) marker := util.NewMarker(c.settings.Command)
if err := marker.EnterTable("diff"); err != nil { if err := marker.EnterTable("diff"); err != nil {
return err return err
} }
@@ -324,7 +291,7 @@ func (c *ClioCass) pruneData(
// ledger_transactions queries // ledger_transactions queries
if !c.settings.SkipLedgerTransactionsTable { if !c.settings.SkipLedgerTransactionsTable {
marker := NewMarker(c.settings.Command) marker := util.NewMarker(c.settings.Command)
if err := marker.EnterTable("ledger_transactions"); err != nil { if err := marker.EnterTable("ledger_transactions"); err != nil {
return err return err
} }
@@ -341,7 +308,7 @@ func (c *ClioCass) pruneData(
// ledgers queries // ledgers queries
if !c.settings.SkipLedgersTable { if !c.settings.SkipLedgersTable {
marker := NewMarker(c.settings.Command) marker := util.NewMarker(c.settings.Command)
if err := marker.EnterTable("ledgers"); err != nil { if err := marker.EnterTable("ledgers"); err != nil {
return err return err
} }
@@ -358,7 +325,7 @@ func (c *ClioCass) pruneData(
// account_tx queries // account_tx queries
if !c.settings.SkipAccTransactionsTable { if !c.settings.SkipAccTransactionsTable {
marker := NewMarker(c.settings.Command) marker := util.NewMarker(c.settings.Command)
if err := marker.EnterTable("account_tx"); err != nil { if err := marker.EnterTable("account_tx"); err != nil {
return err return err
} }
@@ -366,7 +333,7 @@ func (c *ClioCass) pruneData(
log.Println("Generating delete queries for account transactions table") log.Println("Generating delete queries for account transactions table")
rowsCount, deleteCount, errCount = c.prepareAndExecuteDeleteQueries(marker, fromLedgerIdx, toLedgerIdx, rowsCount, deleteCount, errCount = c.prepareAndExecuteDeleteQueries(marker, fromLedgerIdx, toLedgerIdx,
"SELECT account, seq_idx FROM account_tx WHERE token(account) >= ? AND token(account) <= ?", "SELECT account, seq_idx FROM account_tx WHERE token(account) >= ? AND token(account) <= ?",
"DELETE FROM account_tx WHERE account = ? AND seq_idx = (?, ?)", deleteMethod{deleteTransaction: maybe.Set(true)}, columnSettings{UseBlob: true, UseSeq: false}) "DELETE FROM account_tx WHERE account = ? AND seq_idx = (?, ?)", deleteMethod{deleteTransaction: maybe.Set(true)}, columnSettings{})
log.Printf("Total delete queries: %d\n", deleteCount) log.Printf("Total delete queries: %d\n", deleteCount)
log.Printf("Total traversed rows: %d\n\n", rowsCount) log.Printf("Total traversed rows: %d\n\n", rowsCount)
totalRows += rowsCount totalRows += rowsCount
@@ -376,7 +343,67 @@ func (c *ClioCass) pruneData(
marker.ExitTable() marker.ExitTable()
} }
// TODO: take care of nft tables and other stuff like that // nf_token queries
if !c.settings.SkipNFTokenTable {
marker := util.NewMarker(c.settings.Command)
if err := marker.EnterTable("nf_tokens"); err != nil {
return err
}
log.Println("Generating delete queries for nft tokens table")
rowsCount, deleteCount, errCount = c.prepareAndExecuteDeleteQueries(marker, fromLedgerIdx, toLedgerIdx,
"SELECT token_id, sequence FROM nf_tokens WHERE token(token_id) >= ? AND token(token_id) <= ?",
"DELETE FROM nf_tokens WHERE token_id = ? AND sequence = ?", deleteMethod{deleteObject: maybe.Set(true)}, columnSettings{})
log.Printf("Total delete queries: %d\n", deleteCount)
log.Printf("Total traversed rows: %d\n\n", rowsCount)
totalRows += rowsCount
totalErrors += errCount
totalDeletes += deleteCount
marker.ExitTable()
}
// issuer_nf_tokens_v2: skipped because table is small and not trivial to delete
// nf_token_URI queries
if !c.settings.SkipNFTokenURITable {
marker := util.NewMarker(c.settings.Command)
if err := marker.EnterTable("nf_token_uris"); err != nil {
return err
}
log.Println("Generating delete queries for nft token URI table")
rowsCount, deleteCount, errCount = c.prepareAndExecuteDeleteQueries(marker, fromLedgerIdx, toLedgerIdx,
"SELECT token_id, sequence FROM nf_token_uris WHERE token(token_id) >= ? AND token(token_id) <= ?",
"DELETE FROM nf_token_uris WHERE token_id = ? AND sequence = ?", deleteMethod{deleteObject: maybe.Set(true)}, columnSettings{})
log.Printf("Total delete queries: %d\n", deleteCount)
log.Printf("Total traversed rows: %d\n\n", rowsCount)
totalRows += rowsCount
totalErrors += errCount
totalDeletes += deleteCount
marker.ExitTable()
}
// nf_token_transactions
if !c.settings.SkipNFTokenTransactionsTable {
marker := util.NewMarker(c.settings.Command)
if err := marker.EnterTable("nf_token_transactions"); err != nil {
return err
}
log.Println("Generating delete queries for nft token transactions table")
rowsCount, deleteCount, errCount = c.prepareAndExecuteDeleteQueries(marker, fromLedgerIdx, toLedgerIdx,
"SELECT token_id, seq_idx FROM nf_token_transactions WHERE token(token_id) >= ? AND token(token_id) <= ?",
"DELETE FROM nf_token_transactions WHERE token_id = ? AND seq_idx = (?, ?)", deleteMethod{deleteTransaction: maybe.Set(true)}, columnSettings{})
log.Printf("Total delete queries: %d\n", deleteCount)
log.Printf("Total traversed rows: %d\n\n", rowsCount)
totalRows += rowsCount
totalErrors += errCount
totalDeletes += deleteCount
marker.ExitTable()
}
if !c.settings.SkipWriteLatestLedger { if !c.settings.SkipWriteLatestLedger {
var ( var (
@@ -424,7 +451,7 @@ func (c *ClioCass) prepareAndExecuteSimpleDeleteQueries(
info.Data = append(info.Data, deleteParams{Seq: i}) info.Data = append(info.Data, deleteParams{Seq: i})
// for every 1000 queries in data, delete // for every 1000 queries in data, delete
if len(info.Data) == 1000 { if len(info.Data) == 1000 {
_, err := c.performDeleteQueries(&info, session, colSettings) err := c.performDeleteQueries(&info, session, colSettings)
atomic.AddUint64(&totalDeletes, uint64(len(info.Data))) atomic.AddUint64(&totalDeletes, uint64(len(info.Data)))
atomic.AddUint64(&totalErrors, err) atomic.AddUint64(&totalErrors, err)
info = deleteInfo{Query: deleteQueryTemplate} info = deleteInfo{Query: deleteQueryTemplate}
@@ -432,7 +459,7 @@ func (c *ClioCass) prepareAndExecuteSimpleDeleteQueries(
} }
// delete the rest of queries if exists // delete the rest of queries if exists
if len(info.Data) > 0 { if len(info.Data) > 0 {
_, err := c.performDeleteQueries(&info, session, colSettings) err := c.performDeleteQueries(&info, session, colSettings)
atomic.AddUint64(&totalDeletes, uint64(len(info.Data))) atomic.AddUint64(&totalDeletes, uint64(len(info.Data)))
atomic.AddUint64(&totalErrors, err) atomic.AddUint64(&totalErrors, err)
} }
@@ -543,7 +570,7 @@ func (c *ClioCass) prepareAccTxnDelete(
} }
func (c *ClioCass) prepareAndExecuteDeleteQueries( func (c *ClioCass) prepareAndExecuteDeleteQueries(
marker *Marker, marker *util.Marker,
fromLedgerIdx maybe.Maybe[uint64], fromLedgerIdx maybe.Maybe[uint64],
toLedgerIdx maybe.Maybe[uint64], toLedgerIdx maybe.Maybe[uint64],
queryTemplate string, queryTemplate string,
@@ -612,6 +639,8 @@ func (c *ClioCass) prepareAndExecuteDeleteQueries(
prepareDeleteResult = c.prepareAccTxnDelete(scanner, &info, fromLedgerIdx, toLedgerIdx, &rowsRetrieved) prepareDeleteResult = c.prepareAccTxnDelete(scanner, &info, fromLedgerIdx, toLedgerIdx, &rowsRetrieved)
} else if method.deleteGeneral.HasValue() && method.deleteGeneral.Value() { } else if method.deleteGeneral.HasValue() && method.deleteGeneral.Value() {
prepareDeleteResult = c.prepareDefaultDelete(scanner, &info, fromLedgerIdx, toLedgerIdx, &rowsRetrieved) prepareDeleteResult = c.prepareDefaultDelete(scanner, &info, fromLedgerIdx, toLedgerIdx, &rowsRetrieved)
} else {
log.Fatal("Deletion method not supported")
} }
if !prepareDeleteResult { if !prepareDeleteResult {
@@ -620,19 +649,20 @@ func (c *ClioCass) prepareAndExecuteDeleteQueries(
atomic.AddUint64(&totalErrors, 1) atomic.AddUint64(&totalErrors, 1)
} }
if len(nextPageState) == 0 { // Checks for delete queries when there are queries available to delete
// Checks for delete queries after iterating all pages if len(info.Data) > 0 {
if len(info.Data) > 0 { numErr := c.performDeleteQueries(&info, session, colSettings)
_, numErr := c.performDeleteQueries(&info, session, colSettings) atomic.AddUint64(&totalErrors, numErr)
atomic.AddUint64(&totalErrors, numErr) atomic.AddUint64(&totalDeletes, uint64(len(info.Data)))
atomic.AddUint64(&totalDeletes, uint64(len(info.Data))) if totalDeletes >= counter {
if totalDeletes >= counter { log.Printf("... deleted %d queries ...", counter)
log.Printf("... deleted %d queries ...", counter) counter += 1000
counter += 1000
}
// reset back to the deleted query template after finishing executing delete
info = deleteInfo{Query: deleteQueryTemplate}
} }
// reset back to the deleted query template after finishing executing delete
info = deleteInfo{Query: deleteQueryTemplate}
}
if len(nextPageState) == 0 {
break break
} }
pageState = nextPageState pageState = nextPageState
@@ -681,10 +711,9 @@ func (c *ClioCass) splitDeleteWork(info *deleteInfo) [][]deleteParams {
return chunks return chunks
} }
func (c *ClioCass) performDeleteQueries(info *deleteInfo, session *gocql.Session, colSettings columnSettings) (uint64, uint64) { func (c *ClioCass) performDeleteQueries(info *deleteInfo, session *gocql.Session, colSettings columnSettings) uint64 {
var wg sync.WaitGroup var wg sync.WaitGroup
var sessionCreationWaitGroup sync.WaitGroup var sessionCreationWaitGroup sync.WaitGroup
var totalDeletes uint64
var totalErrors uint64 var totalErrors uint64
chunks := c.splitDeleteWork(info) chunks := c.splitDeleteWork(info)
@@ -727,11 +756,6 @@ func (c *ClioCass) performDeleteQueries(info *deleteInfo, session *gocql.Session
log.Printf("DELETE ERROR: %s\n", err) log.Printf("DELETE ERROR: %s\n", err)
fmt.Fprintf(os.Stderr, "FAILED QUERY: %s\n", fmt.Sprintf("%s [blob=0x%x][seq=%d]", info.Query, r.Blob, r.Seq)) fmt.Fprintf(os.Stderr, "FAILED QUERY: %s\n", fmt.Sprintf("%s [blob=0x%x][seq=%d]", info.Query, r.Blob, r.Seq))
atomic.AddUint64(&totalErrors, 1) atomic.AddUint64(&totalErrors, 1)
} else {
atomic.AddUint64(&totalDeletes, 1)
if atomic.LoadUint64(&totalDeletes)%10000 == 0 {
log.Printf("... %d deletes ...\n", totalDeletes)
}
} }
} }
} }
@@ -739,7 +763,7 @@ func (c *ClioCass) performDeleteQueries(info *deleteInfo, session *gocql.Session
} }
wg.Wait() wg.Wait()
return totalDeletes, totalErrors return totalErrors
} }
func (c *ClioCass) updateLedgerRange(newStartLedger maybe.Maybe[uint64], newEndLedger maybe.Maybe[uint64]) error { func (c *ClioCass) updateLedgerRange(newStartLedger maybe.Maybe[uint64], newEndLedger maybe.Maybe[uint64]) error {

View File

@@ -0,0 +1,44 @@
package util
import (
"fmt"
"os"
)
type Marker struct {
Cmd string
File *os.File
}
func NewMarker(cmd string) *Marker {
return &Marker{Cmd: cmd}
}
func CloseMarker(m *Marker) {
if m.File != nil {
m.File.Close()
}
os.Remove("continue.txt")
}
func (m *Marker) EnterTable(table string) error {
// Create the file
file, err := os.OpenFile("continue.txt", os.O_WRONLY|os.O_TRUNC|os.O_CREATE, 0644)
m.File = file
if err != nil {
return fmt.Errorf("failed to create file: %w", err)
}
fmt.Fprintf(m.File, "%s\n", m.Cmd)
m.File.WriteString(fmt.Sprintf("%s\n", table))
return nil
}
func (m *Marker) MarkProgress(x int64, y int64) {
fmt.Fprintf(m.File, "%d, %d \n", x, y)
}
func (m *Marker) ExitTable() {
m.File.Close()
m.File = nil
os.Remove("continue.txt")
}