Skip to content

Commit 565251d

Browse files
committed
use sectorIndex declare
1 parent 31a5d37 commit 565251d

2 files changed

Lines changed: 83 additions & 88 deletions

File tree

cmd/curio/storacha-migration.go

Lines changed: 59 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package main
33
import (
44
"context"
55
"database/sql"
6+
"encoding/json"
67
"fmt"
78
"os"
89
"path/filepath"
@@ -17,9 +18,11 @@ import (
1718
"github.com/filecoin-project/go-padreader"
1819
"github.com/filecoin-project/go-state-types/abi"
1920

21+
"github.com/filecoin-project/curio/alertmanager/curioalerting"
2022
"github.com/filecoin-project/curio/deps"
2123
"github.com/filecoin-project/curio/harmony/harmonydb"
2224
"github.com/filecoin-project/curio/lib/parkpiece"
25+
"github.com/filecoin-project/curio/lib/paths"
2326
"github.com/filecoin-project/curio/lib/storiface"
2427
"github.com/filecoin-project/curio/market/mk20"
2528
)
@@ -61,7 +64,7 @@ var importPiecesCmd = &cli.Command{
6164
},
6265
&cli.StringFlag{
6366
Name: "target",
64-
Usage: "path to piece storage directory in Curio's attached permanent storage",
67+
Usage: "path to storage directory in Curio's attached permanent storage",
6568
},
6669
&cli.IntFlag{
6770
Name: "batch-size",
@@ -77,9 +80,9 @@ var importPiecesCmd = &cli.Command{
7780
7881
The source directory has Storacha CAR files named by piece CID v2. Curio's
7982
piece park stores the same bytes under a parked_pieces id, so the final
80-
filename becomes s-t00-<parked_piece_id>. That means the migration must
81-
first learn or create the parked_pieces row before it knows the final
82-
filename.
83+
file under the target storage root becomes piece/s-t00-<parked_piece_id>.
84+
That means the migration must first learn or create the parked_pieces
85+
row before it knows the final filename.
8386
8487
Every fresh source file is moved to target/storacha-staging first. That
8588
staging move is the first retry boundary: once the file leaves source, a
@@ -93,12 +96,13 @@ var importPiecesCmd = &cli.Command{
9396
file alone because that task owns the normal download/write path.
9497
4. Otherwise, ensure exactly one storacha-migration parked_piece_refs row
9598
and exactly one pdp_piecerefs row for that parked ref.
96-
5. After the transaction commits, move the staged file to s-t00-<id>,
97-
declare it in sector_location, then mark parked_pieces.complete=true.
99+
5. After the transaction commits, move the staged file to
100+
target/piece/s-t00-<id>, declare it in sector_location, then mark
101+
parked_pieces.complete=true.
98102
99103
recoverFinalStorachaPieces exists for the one point where staging can no
100-
longer help: if a previous run already renamed the file to s-t00-<id> and
101-
then crashed before declaring the file or marking the parked piece
104+
longer help: if a previous run already renamed the file into target/piece
105+
and then crashed before declaring the file or marking the parked piece
102106
complete. At that point there is no staged filename left to process, so
103107
recovery starts from the DB row/ref and checks whether the final file is
104108
already present.
@@ -122,12 +126,14 @@ var importPiecesCmd = &cli.Command{
122126
return xerrors.Errorf("resolving target path: %w", err)
123127
}
124128

125-
dep, err := deps.GetDepsCLI(ctx, cctx)
129+
db, err := deps.MakeDB(cctx)
126130
if err != nil {
127131
return err
128132
}
129133

130-
out, err := runImportPieces(ctx, dep, sourcePath, targetPath, cctx.Int("batch-size"))
134+
si := paths.NewDBIndex(curioalerting.NewAlertingSystem(), db)
135+
136+
out, err := runImportPieces(ctx, db, si, sourcePath, targetPath, cctx.Int("batch-size"))
131137
if err != nil {
132138
return err
133139
}
@@ -141,15 +147,10 @@ var importPiecesCmd = &cli.Command{
141147
},
142148
}
143149

144-
func runImportPieces(ctx context.Context, dep *deps.Deps, sourcePath, targetPath string, batchSize int) (importPiecesOutput, error) {
150+
func runImportPieces(ctx context.Context, db *harmonydb.DB, si paths.SectorIndex, sourcePath, targetPath string, batchSize int) (importPiecesOutput, error) {
145151
var out importPiecesOutput
146152

147-
targetPath, err := filepath.Abs(filepath.Clean(targetPath))
148-
if err != nil {
149-
return out, xerrors.Errorf("resolving target path: %w", err)
150-
}
151-
152-
storageID, err := pieceStorageID(ctx, dep, targetPath)
153+
storageID, err := pieceStorageID(targetPath)
153154
if err != nil {
154155
return out, err
155156
}
@@ -178,7 +179,7 @@ func runImportPieces(ctx context.Context, dep *deps.Deps, sourcePath, targetPath
178179
continue
179180
}
180181

181-
result, err := importStagedStorachaPiece(ctx, dep, storageID, targetPath, filepath.Join(staging, entry.Name()))
182+
result, err := importStagedStorachaPiece(ctx, db, si, storageID, targetPath, filepath.Join(staging, entry.Name()))
182183
if err != nil {
183184
return out, err
184185
}
@@ -191,7 +192,7 @@ func runImportPieces(ctx context.Context, dep *deps.Deps, sourcePath, targetPath
191192

192193
// This covers the crash point after staging was renamed to the final
193194
// piece path, but before sector_location/parked_pieces was finalized.
194-
err = recoverFinalStorachaPieces(ctx, dep, storageID, targetPath, &out, batchSize)
195+
err = recoverFinalStorachaPieces(ctx, db, si, storageID, targetPath, &out, batchSize)
195196
if err != nil {
196197
return out, err
197198
}
@@ -237,7 +238,7 @@ func runImportPieces(ctx context.Context, dep *deps.Deps, sourcePath, targetPath
237238
return out, xerrors.Errorf("renaming old path: %w", err)
238239
}
239240

240-
result, err := importStagedStorachaPiece(ctx, dep, storageID, targetPath, stagingPath)
241+
result, err := importStagedStorachaPiece(ctx, db, si, storageID, targetPath, stagingPath)
241242
if err != nil {
242243
return out, err
243244
}
@@ -251,27 +252,24 @@ func runImportPieces(ctx context.Context, dep *deps.Deps, sourcePath, targetPath
251252
}
252253

253254
// pieceStorageID maps the user-provided target directory back to Curio's
254-
// storage id. The target flag is expected to point at an attached storage
255-
// path's "piece" directory, because StorageDeclareSector needs the parent
256-
// storage id when it writes sector_location.
257-
func pieceStorageID(ctx context.Context, dep *deps.Deps, targetPath string) (storiface.ID, error) {
258-
localPaths, err := dep.LocalStore.Local(ctx)
255+
// storage id. The target flag is expected to point at the storage root that
256+
// contains sectorstore.json; final piece files are stored under target/piece.
257+
func pieceStorageID(targetPath string) (storiface.ID, error) {
258+
mb, err := os.ReadFile(filepath.Join(targetPath, paths.MetaFile))
259259
if err != nil {
260-
return "", xerrors.Errorf("listing local storage paths: %w", err)
260+
return "", xerrors.Errorf("reading storage metadata for %s: %w", targetPath, err)
261261
}
262262

263-
for _, localPath := range localPaths {
264-
piecePath := filepath.Join(localPath.LocalPath, storiface.FTPiece.String())
265-
piecePath, err = filepath.Abs(filepath.Clean(piecePath))
266-
if err != nil {
267-
return "", xerrors.Errorf("resolving piece path %s: %w", piecePath, err)
268-
}
269-
if piecePath == targetPath {
270-
return localPath.ID, nil
271-
}
263+
var meta storiface.LocalStorageMeta
264+
if err := json.Unmarshal(mb, &meta); err != nil {
265+
return "", xerrors.Errorf("unmarshalling storage metadata for %s: %w", targetPath, err)
266+
}
267+
268+
if meta.ID != ("") {
269+
return meta.ID, nil
272270
}
273271

274-
return "", xerrors.Errorf("target %s is not the piece directory of an attached local storage path", targetPath)
272+
return "", xerrors.Errorf("no storage ID found for %s", targetPath)
275273
}
276274

277275
// storachaPieceInfoFromFileName accepts only Storacha migration inputs named
@@ -300,10 +298,11 @@ func storachaPieceInfoFromFileName(name string) (*mk20.PieceInfo, bool, error) {
300298
// It first creates or reuses parked_pieces/refs in a committed DB transaction.
301299
// If an existing incomplete parked_piece still has a live task, it returns
302300
// Imported=false and leaves the staged file untouched for a later retry.
303-
// Otherwise it consumes the staged file: remove it if the final s-t00-<id>
304-
// already exists, or rename it to that final path. It then declares the piece
305-
// location and marks parked_pieces.complete unless the row was already complete.
306-
func importStagedStorachaPiece(ctx context.Context, dep *deps.Deps, storageID storiface.ID, targetPath, stagingPath string) (storachaImportResult, error) {
301+
// Otherwise it consumes the staged file: remove it if the final
302+
// target/piece/s-t00-<id> already exists, or rename it to that final path. It
303+
// then declares the piece location and marks parked_pieces.complete unless the
304+
// row was already complete.
305+
func importStagedStorachaPiece(ctx context.Context, db *harmonydb.DB, si paths.SectorIndex, storageID storiface.ID, targetPath, stagingPath string) (storachaImportResult, error) {
307306
info, err := os.Stat(stagingPath)
308307
if err != nil {
309308
return storachaImportResult{}, xerrors.Errorf("checking staging file: %w", err)
@@ -324,7 +323,7 @@ func importStagedStorachaPiece(ctx context.Context, dep *deps.Deps, storageID st
324323
// The transaction only decides ownership and DB references. It deliberately
325324
// does not move the file to s-t00-<id>; the id must be committed before the
326325
// filename depends on it.
327-
comm, err := dep.DB.BeginTransaction(ctx, func(tx *harmonydb.Tx) (commit bool, err error) {
326+
comm, err := db.BeginTransaction(ctx, func(tx *harmonydb.Tx) (commit bool, err error) {
328327
parkedPieceID, createdParkedPiece, err := parkpiece.UpsertSkipWithInserted(tx, pi.PieceCIDV1.String(), int64(pi.Size), int64(pi.RawSize), true, true)
329328
if err != nil {
330329
return false, xerrors.Errorf("upsert parked piece: %w", err)
@@ -386,14 +385,14 @@ func importStagedStorachaPiece(ctx context.Context, dep *deps.Deps, storageID st
386385
return storachaImportResult{}, xerrors.Errorf("checking final piece file: %w", err)
387386
}
388387

389-
if err := declareStorachaPiece(ctx, dep, storageID, state.ID); err != nil {
388+
if err := declareStorachaPiece(ctx, si, storageID, state.ID); err != nil {
390389
return storachaImportResult{}, err
391390
}
392391

393392
if !state.AlreadyComplete {
394393
// complete is last. If we crash before this, final-file recovery will see
395394
// s-t00-<id>, declare it again idempotently, and mark the row complete.
396-
if err := markParkedPieceComplete(ctx, dep.DB, state.ID); err != nil {
395+
if err := markParkedPieceComplete(ctx, db, state.ID); err != nil {
397396
return storachaImportResult{}, err
398397
}
399398
}
@@ -403,16 +402,17 @@ func importStagedStorachaPiece(ctx context.Context, dep *deps.Deps, storageID st
403402

404403
// recoverFinalStorachaPieces scans incomplete storacha-migration rows where the
405404
// DB/ref side already exists. For each row it checks whether the file has
406-
// already reached its final s-t00-<id> path. If yes, it finishes declaration and
407-
// complete=true. If no final file exists, it leaves the row alone; there is
408-
// nothing safe to do without either the staged file or the final file.
409-
func recoverFinalStorachaPieces(ctx context.Context, dep *deps.Deps, storageID storiface.ID, targetPath string, out *importPiecesOutput, batchSize int) error {
405+
// already reached its final target/piece/s-t00-<id> path. If yes, it finishes
406+
// declaration and complete=true. If no final file exists, it leaves the row
407+
// alone; there is nothing safe to do without either the staged file or the final
408+
// file.
409+
func recoverFinalStorachaPieces(ctx context.Context, db *harmonydb.DB, si paths.SectorIndex, storageID storiface.ID, targetPath string, out *importPiecesOutput, batchSize int) error {
410410
if out.Count >= batchSize {
411411
return nil
412412
}
413413

414414
var rows []storachaFinalRecoveryRow
415-
err := dep.DB.Select(ctx, &rows, `
415+
err := db.Select(ctx, &rows, `
416416
SELECT pp.id, pp.piece_cid, pp.piece_padded_size, pp.piece_raw_size
417417
FROM parked_pieces pp
418418
WHERE pp.complete = FALSE
@@ -436,7 +436,7 @@ func recoverFinalStorachaPieces(ctx context.Context, dep *deps.Deps, storageID s
436436
break
437437
}
438438

439-
imported, err := recoverFinalStorachaPiece(ctx, dep, storageID, targetPath, row)
439+
imported, err := recoverFinalStorachaPiece(ctx, db, si, storageID, targetPath, row)
440440
if err != nil {
441441
return err
442442
}
@@ -468,11 +468,11 @@ func storachaPieceCIDV2FromRow(row storachaFinalRecoveryRow) (string, error) {
468468
}
469469

470470
// recoverFinalStorachaPiece handles the post-rename crash window for one DB row.
471-
// It requires target/s-t00-<id> to exist, rebuilds the piece info from the DB
472-
// row, reuses the same claim/ref checks as staged import, then declares the
471+
// It requires target/piece/s-t00-<id> to exist, rebuilds the piece info from the
472+
// DB row, reuses the same claim/ref checks as staged import, then declares the
473473
// final file and marks the parked piece complete. It returns false when the
474474
// final file is missing or a live task still owns the parked_piece.
475-
func recoverFinalStorachaPiece(ctx context.Context, dep *deps.Deps, storageID storiface.ID, targetPath string, row storachaFinalRecoveryRow) (bool, error) {
475+
func recoverFinalStorachaPiece(ctx context.Context, db *harmonydb.DB, si paths.SectorIndex, storageID storiface.ID, targetPath string, row storachaFinalRecoveryRow) (bool, error) {
476476
finalPath := storachaFinalPiecePath(targetPath, row.ID)
477477
info, err := os.Stat(finalPath)
478478
if os.IsNotExist(err) {
@@ -496,7 +496,7 @@ func recoverFinalStorachaPiece(ctx context.Context, dep *deps.Deps, storageID st
496496
}
497497

498498
var state storachaParkedPieceState
499-
comm, err := dep.DB.BeginTransaction(ctx, func(tx *harmonydb.Tx) (commit bool, err error) {
499+
comm, err := db.BeginTransaction(ctx, func(tx *harmonydb.Tx) (commit bool, err error) {
500500
state, err = claimExistingStorachaPieceTx(tx, row.ID)
501501
if err != nil {
502502
return false, err
@@ -519,11 +519,11 @@ func recoverFinalStorachaPiece(ctx context.Context, dep *deps.Deps, storageID st
519519
return false, nil
520520
}
521521

522-
if err := declareStorachaPiece(ctx, dep, storageID, row.ID); err != nil {
522+
if err := declareStorachaPiece(ctx, si, storageID, row.ID); err != nil {
523523
return false, err
524524
}
525525
if !state.AlreadyComplete {
526-
if err := markParkedPieceComplete(ctx, dep.DB, row.ID); err != nil {
526+
if err := markParkedPieceComplete(ctx, db, row.ID); err != nil {
527527
return false, err
528528
}
529529
}
@@ -654,18 +654,18 @@ func ensureStorachaRefsTx(tx *harmonydb.Tx, parkedPieceID int64, pi *mk20.PieceI
654654
}
655655

656656
// storachaFinalPiecePath mirrors Curio's piece-park sector naming: parked piece
657-
// id N is stored as miner-zero piece sector s-t00-N under the target piece dir.
657+
// id N is stored as miner-zero piece sector s-t00-N under target/piece.
658658
func storachaFinalPiecePath(targetPath string, parkedPieceID int64) string {
659659
pieceNumber := storiface.PieceNumber(parkedPieceID)
660-
return filepath.Join(targetPath, storiface.SectorName(pieceNumber.Ref().ID))
660+
return filepath.Join(targetPath, "piece", storiface.SectorName(pieceNumber.Ref().ID))
661661
}
662662

663663
// declareStorachaPiece records the final piece file in sector_location. The
664664
// storage index upsert is idempotent, so recovery can call this again after a
665665
// crash between rename and complete=true.
666-
func declareStorachaPiece(ctx context.Context, dep *deps.Deps, storageID storiface.ID, parkedPieceID int64) error {
666+
func declareStorachaPiece(ctx context.Context, si paths.SectorIndex, storageID storiface.ID, parkedPieceID int64) error {
667667
pieceNumber := storiface.PieceNumber(parkedPieceID)
668-
err := dep.Si.StorageDeclareSector(ctx, storageID, pieceNumber.Ref().ID, storiface.FTPiece, true)
668+
err := si.StorageDeclareSector(ctx, storageID, pieceNumber.Ref().ID, storiface.FTPiece, true)
669669
if err != nil {
670670
return xerrors.Errorf("declaring storacha piece: %w", err)
671671
}

0 commit comments

Comments
 (0)