mirror of
https://github.com/wavetermdev/backup.git
synced 2026-08-05 13:57:07 -07:00
checkpoint, compiling again
This commit is contained in:
+170
-408
File diff suppressed because it is too large
Load Diff
+229
-293
File diff suppressed because it is too large
Load Diff
@@ -3,7 +3,7 @@ package blockstore
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"sync/atomic"
|
||||
"os"
|
||||
|
||||
"github.com/wavetermdev/waveterm/wavesrv/pkg/dbutil"
|
||||
)
|
||||
@@ -54,14 +54,15 @@ func dbGetAllBlockIds(ctx context.Context) ([]string, error) {
|
||||
}
|
||||
|
||||
func dbGetFileParts(ctx context.Context, blockId string, name string, parts []int) (map[int]*DataCacheEntry, error) {
|
||||
if len(parts) == 0 {
|
||||
return nil, nil
|
||||
}
|
||||
return WithTxRtn(ctx, func(tx *TxWrap) (map[int]*DataCacheEntry, error) {
|
||||
var data []*DataCacheEntry
|
||||
query := "SELECT partidx, data FROM db_block_data WHERE blockid = ? AND name = ? AND partidx IN (SELECT value FROM json_each(?))"
|
||||
tx.Select(&data, query, blockId, name, dbutil.QuickJsonArr(parts))
|
||||
rtn := make(map[int]*DataCacheEntry)
|
||||
for _, d := range data {
|
||||
d.Dirty = &atomic.Bool{}
|
||||
d.Flushing = &atomic.Bool{}
|
||||
if cap(d.Data) != int(partDataSize) {
|
||||
newData := make([]byte, len(d.Data), partDataSize)
|
||||
copy(newData, d.Data)
|
||||
@@ -81,26 +82,22 @@ func dbGetBlockFiles(ctx context.Context, blockId string) ([]*BlockFile, error)
|
||||
})
|
||||
}
|
||||
|
||||
func dbWriteCacheEntry(ctx context.Context, fileEntry *FileCacheEntry, dataEntries []*DataCacheEntry) error {
|
||||
if fileEntry == nil {
|
||||
return fmt.Errorf("fileEntry or fileEntry.File is nil")
|
||||
}
|
||||
func dbWriteCacheEntry(ctx context.Context, file *BlockFile, dataEntries map[int]*DataCacheEntry) error {
|
||||
return WithTx(ctx, func(tx *TxWrap) error {
|
||||
query := `SELECT blockid FROM db_block_file WHERE blockid = ? AND name = ?`
|
||||
if !tx.Exists(query, fileEntry.File.BlockId, fileEntry.File.Name) {
|
||||
if !tx.Exists(query, file.BlockId, file.Name) {
|
||||
// since deletion is synchronous this stops us from writing to a deleted file
|
||||
return fmt.Errorf("file not found in db")
|
||||
}
|
||||
if fileEntry.Dirty.Load() {
|
||||
query := `UPDATE db_block_file SET size = ?, createdts = ?, modts = ?, opts = ?, meta = ? WHERE blockid = ? AND name = ?`
|
||||
tx.Exec(query, fileEntry.File.Size, fileEntry.File.CreatedTs, fileEntry.File.ModTs, dbutil.QuickJson(fileEntry.File.Opts), dbutil.QuickJson(fileEntry.File.Meta), fileEntry.File.BlockId, fileEntry.File.Name)
|
||||
return os.ErrNotExist
|
||||
}
|
||||
// we don't update CreatedTs or Opts
|
||||
query = `UPDATE db_block_file SET size = ?, modts = ?, meta = ? WHERE blockid = ? AND name = ?`
|
||||
tx.Exec(query, file.Size, file.ModTs, dbutil.QuickJson(file.Meta), file.BlockId, file.Name)
|
||||
dataPartQuery := `REPLACE INTO db_block_data (blockid, name, partidx, data) VALUES (?, ?, ?, ?)`
|
||||
for _, dataEntry := range dataEntries {
|
||||
if dataEntry == nil || !dataEntry.Dirty.Load() {
|
||||
continue
|
||||
for partIdx, dataEntry := range dataEntries {
|
||||
if partIdx != dataEntry.PartIdx {
|
||||
panic(fmt.Sprintf("partIdx:%d and dataEntry.PartIdx:%d do not match", partIdx, dataEntry.PartIdx))
|
||||
}
|
||||
tx.Exec(dataPartQuery, fileEntry.File.BlockId, fileEntry.File.Name, dataEntry.PartIdx, dataEntry.Data)
|
||||
tx.Exec(dataPartQuery, file.BlockId, file.Name, dataEntry.PartIdx, dataEntry.Data)
|
||||
}
|
||||
return nil
|
||||
})
|
||||
|
||||
@@ -45,6 +45,43 @@ func cleanupDb(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func (s *BlockStore) getCacheSize() int {
|
||||
s.Lock.Lock()
|
||||
defer s.Lock.Unlock()
|
||||
return len(s.Cache)
|
||||
}
|
||||
|
||||
func (s *BlockStore) clearCache() {
|
||||
s.Lock.Lock()
|
||||
defer s.Lock.Unlock()
|
||||
s.Cache = make(map[cacheKey]*CacheEntry)
|
||||
}
|
||||
|
||||
//lint:ignore U1000 used for testing
|
||||
func (e *CacheEntry) dump() string {
|
||||
var buf bytes.Buffer
|
||||
fmt.Fprintf(&buf, "CacheEntry [BlockId: %q, Name: %q] PinCount: %d\n", e.BlockId, e.Name, e.PinCount)
|
||||
fmt.Fprintf(&buf, " FileEntry: %v\n", e.File)
|
||||
for idx, dce := range e.DataEntries {
|
||||
fmt.Fprintf(&buf, " DataEntry[%d]: %q\n", idx, string(dce.Data))
|
||||
}
|
||||
return buf.String()
|
||||
}
|
||||
|
||||
//lint:ignore U1000 used for testing
|
||||
func (s *BlockStore) dump() string {
|
||||
s.Lock.Lock()
|
||||
defer s.Lock.Unlock()
|
||||
var buf bytes.Buffer
|
||||
buf.WriteString(fmt.Sprintf("BlockStore %d entries\n", len(s.Cache)))
|
||||
for _, v := range s.Cache {
|
||||
entryStr := v.dump()
|
||||
buf.WriteString(entryStr)
|
||||
buf.WriteString("\n")
|
||||
}
|
||||
return buf.String()
|
||||
}
|
||||
|
||||
func TestCreate(t *testing.T) {
|
||||
initDb(t)
|
||||
defer cleanupDb(t)
|
||||
@@ -426,14 +463,14 @@ func TestCircularWrites(t *testing.T) {
|
||||
}
|
||||
checkFileSize(t, ctx, blockId, "c1", 128)
|
||||
checkFileData(t, ctx, blockId, "c1", " 123456789 123456789 123456789 bar456789 123456789")
|
||||
GBS.withLock(blockId, "c1", false, func(entry *CacheEntry) {
|
||||
err = withLock(GBS, blockId, "c1", func(entry *CacheEntry) error {
|
||||
if entry == nil {
|
||||
err = fmt.Errorf("entry not found")
|
||||
return
|
||||
return fmt.Errorf("entry not found")
|
||||
}
|
||||
if len(entry.DataEntries) != 1 {
|
||||
err = fmt.Errorf("data entries mismatch: expected 1, got %d", len(entry.DataEntries))
|
||||
return fmt.Errorf("data entries mismatch: expected 1, got %d", len(entry.DataEntries))
|
||||
}
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatalf("error checking data entries: %v", err)
|
||||
|
||||
Reference in New Issue
Block a user