diff --git a/api/api_full.go b/api/api_full.go index bcdfdad1009..59eecda51ae 100644 --- a/api/api_full.go +++ b/api/api_full.go @@ -353,6 +353,8 @@ type FullNode interface { ClientRetrieve(ctx context.Context, params RetrievalOrder) (*RestrievalRes, error) //perm:admin // ClientRetrieveWait waits for retrieval to be complete ClientRetrieveWait(ctx context.Context, deal retrievalmarket.DealID) error //perm:admin + // ClientRemoveRetrieval removes retrieved data from the local retrieval store + ClientRemoveRetrieval(ctx context.Context, exportRef ExportRef) error // ClientExport exports a file stored in the local filestore to a system file ClientExport(ctx context.Context, exportRef ExportRef, fileRef FileRef) error //perm:admin // ClientListRetrievals returns information about retrievals made by the local client diff --git a/api/mocks/mock_full.go b/api/mocks/mock_full.go index 5db190ba62f..e1e5918cc73 100644 --- a/api/mocks/mock_full.go +++ b/api/mocks/mock_full.go @@ -773,6 +773,20 @@ func (mr *MockFullNodeMockRecorder) ClientRemoveImport(arg0, arg1 interface{}) * return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ClientRemoveImport", reflect.TypeOf((*MockFullNode)(nil).ClientRemoveImport), arg0, arg1) } +// ClientRemoveRetrieval mocks base method. +func (m *MockFullNode) ClientRemoveRetrieval(arg0 context.Context, arg1 api.ExportRef) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "ClientRemoveRetrieval", arg0, arg1) + ret0, _ := ret[0].(error) + return ret0 +} + +// ClientRemoveRetrieval indicates an expected call of ClientRemoveRetrieval. +func (mr *MockFullNodeMockRecorder) ClientRemoveRetrieval(arg0, arg1 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ClientRemoveRetrieval", reflect.TypeOf((*MockFullNode)(nil).ClientRemoveRetrieval), arg0, arg1) +} + // ClientRestartDataTransfer mocks base method. func (m *MockFullNode) ClientRestartDataTransfer(arg0 context.Context, arg1 datatransfer.TransferID, arg2 peer.ID, arg3 bool) error { m.ctrl.T.Helper() diff --git a/api/proxy_gen.go b/api/proxy_gen.go index 300e6755528..d954cc727c2 100644 --- a/api/proxy_gen.go +++ b/api/proxy_gen.go @@ -194,6 +194,8 @@ type FullNodeStruct struct { ClientRemoveImport func(p0 context.Context, p1 imports.ID) error `perm:"admin"` + ClientRemoveRetrieval func(p0 context.Context, p1 ExportRef) error `` + ClientRestartDataTransfer func(p0 context.Context, p1 datatransfer.TransferID, p2 peer.ID, p3 bool) error `perm:"write"` ClientRetrieve func(p0 context.Context, p1 RetrievalOrder) (*RestrievalRes, error) `perm:"admin"` @@ -1601,6 +1603,17 @@ func (s *FullNodeStub) ClientRemoveImport(p0 context.Context, p1 imports.ID) err return ErrNotSupported } +func (s *FullNodeStruct) ClientRemoveRetrieval(p0 context.Context, p1 ExportRef) error { + if s.Internal.ClientRemoveRetrieval == nil { + return ErrNotSupported + } + return s.Internal.ClientRemoveRetrieval(p0, p1) +} + +func (s *FullNodeStub) ClientRemoveRetrieval(p0 context.Context, p1 ExportRef) error { + return ErrNotSupported +} + func (s *FullNodeStruct) ClientRestartDataTransfer(p0 context.Context, p1 datatransfer.TransferID, p2 peer.ID, p3 bool) error { if s.Internal.ClientRestartDataTransfer == nil { return ErrNotSupported diff --git a/build/openrpc/full.json.gz b/build/openrpc/full.json.gz index c27a0fc28a1..4598f37e595 100644 Binary files a/build/openrpc/full.json.gz and b/build/openrpc/full.json.gz differ diff --git a/build/openrpc/miner.json.gz b/build/openrpc/miner.json.gz index 952c771ca2d..43b182dfa58 100644 Binary files a/build/openrpc/miner.json.gz and b/build/openrpc/miner.json.gz differ diff --git a/build/openrpc/worker.json.gz b/build/openrpc/worker.json.gz index f1372a6602a..cbbeec7d1e4 100644 Binary files a/build/openrpc/worker.json.gz and b/build/openrpc/worker.json.gz differ diff --git a/documentation/en/api-v1-unstable-methods.md b/documentation/en/api-v1-unstable-methods.md index 5d4dab5339c..d57c85ee6e4 100644 --- a/documentation/en/api-v1-unstable-methods.md +++ b/documentation/en/api-v1-unstable-methods.md @@ -57,6 +57,7 @@ * [ClientMinerQueryOffer](#ClientMinerQueryOffer) * [ClientQueryAsk](#ClientQueryAsk) * [ClientRemoveImport](#ClientRemoveImport) + * [ClientRemoveRetrieval](#ClientRemoveRetrieval) * [ClientRestartDataTransfer](#ClientRestartDataTransfer) * [ClientRetrieve](#ClientRetrieve) * [ClientRetrieveTryRestartInsufficientFunds](#ClientRetrieveTryRestartInsufficientFunds) @@ -1929,6 +1930,33 @@ Inputs: Response: `{}` +### ClientRemoveRetrieval +ClientRemoveRetrieval removes retrieved data from the local retrieval store + + +Perms: + +Inputs: +```json +[ + { + "Root": { + "/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4" + }, + "DAGs": [ + { + "DataSelector": "Links/21/Hash/Links/42/Hash", + "ExportMerkleProof": true + } + ], + "FromLocalCAR": "string value", + "DealID": 5 + } +] +``` + +Response: `{}` + ### ClientRestartDataTransfer ClientRestartDataTransfer attempts to restart a data transfer with the given transfer ID and other peer diff --git a/node/impl/client/client.go b/node/impl/client/client.go index 5b4791cfa80..af41cebbf21 100644 --- a/node/impl/client/client.go +++ b/node/impl/client/client.go @@ -933,18 +933,21 @@ func (ed *ExportDest) doWrite(cb func(io.Writer) error) error { return f.Close() } -func (a *API) ClientExport(ctx context.Context, exportRef api.ExportRef, ref api.FileRef) error { - return a.ClientExportInto(ctx, exportRef, ref.IsCAR, ExportDest{Path: ref.Path}) -} +func (a *API) retrievalDagService(exportRef api.ExportRef) ( + dserv format.DAGService, + retrieveIntoIPFS bool, + retrievalBs bstore.Blockstore, + carPath string, + err error) { -func (a *API) ClientExportInto(ctx context.Context, exportRef api.ExportRef, car bool, dest ExportDest) error { proxyBss, retrieveIntoIPFS := a.RtvlBlockstoreAccessor.(*retrievaladapter.ProxyBlockstoreAccessor) carBss, retrieveIntoCAR := a.RtvlBlockstoreAccessor.(*retrievaladapter.CARBlockstoreAccessor) - carPath := exportRef.FromLocalCAR + carPath = exportRef.FromLocalCAR if carPath == "" { if !retrieveIntoIPFS && !retrieveIntoCAR { - return xerrors.Errorf("unsupported retrieval blockstore accessor") + err = xerrors.Errorf("unsupported retrieval blockstore accessor") + return } if retrieveIntoCAR { @@ -952,20 +955,44 @@ func (a *API) ClientExportInto(ctx context.Context, exportRef api.ExportRef, car } } - var retrievalBs bstore.Blockstore if retrieveIntoIPFS { retrievalBs = proxyBss.Blockstore } else { - cbs, err := stores.ReadOnlyFilestore(carPath) + var cbs stores.ClosableBlockstore + cbs, err = stores.ReadOnlyFilestore(carPath) if err != nil { - return err + return } defer cbs.Close() //nolint:errcheck retrievalBs = cbs } - dserv := merkledag.NewDAGService(blockservice.New(retrievalBs, offline.Exchange(retrievalBs))) + dserv = merkledag.NewDAGService(blockservice.New(retrievalBs, offline.Exchange(retrievalBs))) + return +} +func (a *API) ClientRemoveRetrieval(ctx context.Context, exportRef api.ExportRef) error { + dserv, _, _, carPath, err := a.retrievalDagService(exportRef) + if err != nil { + return err + } + if carPath != "" { + os.Remove(carPath) + } else { + dserv.Remove(ctx, exportRef.Root) + } + return nil +} + +func (a *API) ClientExport(ctx context.Context, exportRef api.ExportRef, ref api.FileRef) error { + return a.ClientExportInto(ctx, exportRef, ref.IsCAR, ExportDest{Path: ref.Path}) +} + +func (a *API) ClientExportInto(ctx context.Context, exportRef api.ExportRef, car bool, dest ExportDest) error { + dserv, retrieveIntoIPFS, retrievalBs, carPath, err := a.retrievalDagService(exportRef) + if err != nil { + return err + } // Are we outputting a CAR? if car { // not IPFS and we do full selection - just extract the CARv1 from the CARv2 we stored the retrieval in