From 9fb1dd43a9b58ca99d91ac3c578a4251a2bf7282 Mon Sep 17 00:00:00 2001 From: Dirk McCormick Date: Mon, 22 Mar 2021 12:08:05 +0100 Subject: [PATCH 01/11] feat: update to markets v1.2.0 --- go.mod | 4 ++-- go.sum | 9 ++++----- node/modules/client.go | 27 +++++++++++++++++++++------ 3 files changed, 27 insertions(+), 13 deletions(-) diff --git a/go.mod b/go.mod index 621bea702..24e605b4c 100644 --- a/go.mod +++ b/go.mod @@ -32,9 +32,9 @@ require ( github.com/filecoin-project/go-cbor-util v0.0.0-20191219014500-08c40a1e63a2 github.com/filecoin-project/go-commp-utils v0.0.0-20201119054358-b88f7a96a434 github.com/filecoin-project/go-crypto v0.0.0-20191218222705-effae4ea9f03 - github.com/filecoin-project/go-data-transfer v1.2.7 + github.com/filecoin-project/go-data-transfer v1.2.9 github.com/filecoin-project/go-fil-commcid v0.0.0-20201016201715-d41df56b4f6a - github.com/filecoin-project/go-fil-markets v1.1.9 + github.com/filecoin-project/go-fil-markets v1.2.0 github.com/filecoin-project/go-jsonrpc v0.1.4-0.20210217175800-45ea43ac2bec github.com/filecoin-project/go-multistore v0.0.3 github.com/filecoin-project/go-padreader v0.0.0-20200903213702-ed5fae088b20 diff --git a/go.sum b/go.sum index e4b3d7d0e..e1d354fcd 100644 --- a/go.sum +++ b/go.sum @@ -265,16 +265,16 @@ github.com/filecoin-project/go-commp-utils v0.0.0-20201119054358-b88f7a96a434/go github.com/filecoin-project/go-crypto v0.0.0-20191218222705-effae4ea9f03 h1:2pMXdBnCiXjfCYx/hLqFxccPoqsSveQFxVLvNxy9bus= github.com/filecoin-project/go-crypto v0.0.0-20191218222705-effae4ea9f03/go.mod h1:+viYnvGtUTgJRdy6oaeF4MTFKAfatX071MPDPBL11EQ= github.com/filecoin-project/go-data-transfer v1.0.1/go.mod h1:UxvfUAY9v3ub0a21BSK9u3pB2aq30Y0KMsG+w9/ysyo= -github.com/filecoin-project/go-data-transfer v1.2.7 h1:WE5Cpp9eMt5BDoWOVR64QegSn6bwHQaDzyyjVU377Y0= -github.com/filecoin-project/go-data-transfer v1.2.7/go.mod h1:mvjZ+C3NkBX10JP4JMu27DCjUouHFjHwUGh+Xc4yvDA= +github.com/filecoin-project/go-data-transfer v1.2.9 h1:k6oXrI/6AfNdEfUVFAx6LbVMGNmdWWq97BiaDnhS3JE= +github.com/filecoin-project/go-data-transfer v1.2.9/go.mod h1:ps/AU2Ok4pf2oFevi5RmMr3JRAWcnSTA/Zag6VMygIc= github.com/filecoin-project/go-ds-versioning v0.1.0 h1:y/X6UksYTsK8TLCI7rttCKEvl8btmWxyFMEeeWGUxIQ= github.com/filecoin-project/go-ds-versioning v0.1.0/go.mod h1:mp16rb4i2QPmxBnmanUx8i/XANp+PFCCJWiAb+VW4/s= github.com/filecoin-project/go-fil-commcid v0.0.0-20200716160307-8f644712406f/go.mod h1:Eaox7Hvus1JgPrL5+M3+h7aSPHc0cVqpSxA+TxIEpZQ= github.com/filecoin-project/go-fil-commcid v0.0.0-20201016201715-d41df56b4f6a h1:hyJ+pUm/4U4RdEZBlg6k8Ma4rDiuvqyGpoICXAxwsTg= github.com/filecoin-project/go-fil-commcid v0.0.0-20201016201715-d41df56b4f6a/go.mod h1:Eaox7Hvus1JgPrL5+M3+h7aSPHc0cVqpSxA+TxIEpZQ= github.com/filecoin-project/go-fil-markets v1.0.5-0.20201113164554-c5eba40d5335/go.mod h1:AJySOJC00JRWEZzRG2KsfUnqEf5ITXxeX09BE9N4f9c= -github.com/filecoin-project/go-fil-markets v1.1.9 h1:sA0NIEOpy7brZaeXeNgdXg5pvHaBtD5OTRlraOUbI0w= -github.com/filecoin-project/go-fil-markets v1.1.9/go.mod h1:0yQu5gvrjFoAIyzPSSJ+xUdCG83vjInAFbTswIB5/hk= +github.com/filecoin-project/go-fil-markets v1.2.0 h1:zFQOeuEK7a9ajYfwLiTwvsKAqa9tcLbf3I5waHubI+I= +github.com/filecoin-project/go-fil-markets v1.2.0/go.mod h1:xWoSrWwnLg7N6OUFdlijGHfTj2alzgLZW2Z+a4p18vg= github.com/filecoin-project/go-hamt-ipld v0.1.5 h1:uoXrKbCQZ49OHpsTCkrThPNelC4W3LPEk0OrS/ytIBM= github.com/filecoin-project/go-hamt-ipld v0.1.5/go.mod h1:6Is+ONR5Cd5R6XZoCse1CWaXZc0Hdb/JeX+EQCQzX24= github.com/filecoin-project/go-hamt-ipld/v2 v2.0.0 h1:b3UDemBYN2HNfk3KOXNuxgTTxlWi3xVvbQP0IT38fvM= @@ -595,7 +595,6 @@ github.com/ipfs/go-fs-lock v0.0.6/go.mod h1:OTR+Rj9sHiRubJh3dRhD15Juhd/+w6VPOY28 github.com/ipfs/go-graphsync v0.1.0/go.mod h1:jMXfqIEDFukLPZHqDPp8tJMbHO9Rmeb9CEGevngQbmE= github.com/ipfs/go-graphsync v0.4.2/go.mod h1:/VmbZTUdUMTbNkgzAiCEucIIAU3BkLE2cZrDCVUhyi0= github.com/ipfs/go-graphsync v0.4.3/go.mod h1:mPOwDYv128gf8gxPFgXnz4fNrSYPsWyqisJ7ych+XDY= -github.com/ipfs/go-graphsync v0.5.2/go.mod h1:e2ZxnClqBBYAtd901g9vXMJzS47labjAtOzsWtOzKNk= github.com/ipfs/go-graphsync v0.6.0 h1:x6UvDUGA7wjaKNqx5Vbo7FGT8aJ5ryYA0dMQ5jN3dF0= github.com/ipfs/go-graphsync v0.6.0/go.mod h1:e2ZxnClqBBYAtd901g9vXMJzS47labjAtOzsWtOzKNk= github.com/ipfs/go-hamt-ipld v0.1.1/go.mod h1:1EZCr2v0jlCnhpa+aZ0JZYp8Tt2w16+JJOAVz17YcDk= diff --git a/node/modules/client.go b/node/modules/client.go index da6a4cd83..8e0a281ed 100644 --- a/node/modules/client.go +++ b/node/modules/client.go @@ -7,12 +7,10 @@ import ( "path/filepath" "time" - "github.com/filecoin-project/go-multistore" - "github.com/filecoin-project/go-state-types/abi" + "go.uber.org/fx" "golang.org/x/xerrors" - "go.uber.org/fx" - + "github.com/filecoin-project/go-data-transfer/channelmonitor" dtimpl "github.com/filecoin-project/go-data-transfer/impl" dtnet "github.com/filecoin-project/go-data-transfer/network" dtgstransport "github.com/filecoin-project/go-data-transfer/transport/graphsync" @@ -25,6 +23,8 @@ import ( storageimpl "github.com/filecoin-project/go-fil-markets/storagemarket/impl" "github.com/filecoin-project/go-fil-markets/storagemarket/impl/requestvalidation" smnet "github.com/filecoin-project/go-fil-markets/storagemarket/network" + "github.com/filecoin-project/go-multistore" + "github.com/filecoin-project/go-state-types/abi" "github.com/filecoin-project/go-storedcounter" "github.com/ipfs/go-datastore" "github.com/ipfs/go-datastore/namespace" @@ -135,8 +135,23 @@ func NewClientGraphsyncDataTransfer(lc fx.Lifecycle, h host.Host, gs dtypes.Grap return nil, err } - // data-transfer push channel restart configuration - dtRestartConfig := dtimpl.PushChannelRestartConfig(time.Minute, 10, 1024, 10*time.Minute, 3) + // data-transfer push / pull channel restart configuration: + dtRestartConfig := dtimpl.ChannelRestartConfig(channelmonitor.Config{ + // Wait up to 30s for the other side to respond to an Open channel message + AcceptTimeout: 30 * time.Second, + // Send a restart message if the data rate falls below 1024 bytes / minute + Interval: time.Minute, + MinBytesTransferred: 1024, + // Perform check 10 times / minute + ChecksPerInterval: 10, + // After sending a restart, wait for at least 1 minute before sending another + RestartBackoff: time.Minute, + // After trying to restart 3 times, give up and fail the transfer + MaxConsecutiveRestarts: 3, + // Wait up to 30s for the other side to send a Complete message once all + // data has been sent / received + CompleteTimeout: 30 * time.Second, + }) dt, err := dtimpl.NewDataTransfer(dtDs, filepath.Join(r.Path(), "data-transfer"), net, transport, sc, dtRestartConfig) if err != nil { return nil, err From aee9890ee7651eef65b87428bbd6fe4214c3029c Mon Sep 17 00:00:00 2001 From: Dirk McCormick Date: Tue, 23 Mar 2021 13:28:30 +0100 Subject: [PATCH 02/11] feat: update go-data-transfer and go-fil-markets --- go.mod | 4 ++-- go.sum | 8 ++++---- node/modules/client.go | 4 +--- node/modules/storageminer.go | 3 +-- 4 files changed, 8 insertions(+), 11 deletions(-) diff --git a/go.mod b/go.mod index 24e605b4c..e5f8900ae 100644 --- a/go.mod +++ b/go.mod @@ -32,9 +32,9 @@ require ( github.com/filecoin-project/go-cbor-util v0.0.0-20191219014500-08c40a1e63a2 github.com/filecoin-project/go-commp-utils v0.0.0-20201119054358-b88f7a96a434 github.com/filecoin-project/go-crypto v0.0.0-20191218222705-effae4ea9f03 - github.com/filecoin-project/go-data-transfer v1.2.9 + github.com/filecoin-project/go-data-transfer v1.3.0 github.com/filecoin-project/go-fil-commcid v0.0.0-20201016201715-d41df56b4f6a - github.com/filecoin-project/go-fil-markets v1.2.0 + github.com/filecoin-project/go-fil-markets v1.2.1 github.com/filecoin-project/go-jsonrpc v0.1.4-0.20210217175800-45ea43ac2bec github.com/filecoin-project/go-multistore v0.0.3 github.com/filecoin-project/go-padreader v0.0.0-20200903213702-ed5fae088b20 diff --git a/go.sum b/go.sum index e1d354fcd..ae66a5883 100644 --- a/go.sum +++ b/go.sum @@ -265,16 +265,16 @@ github.com/filecoin-project/go-commp-utils v0.0.0-20201119054358-b88f7a96a434/go github.com/filecoin-project/go-crypto v0.0.0-20191218222705-effae4ea9f03 h1:2pMXdBnCiXjfCYx/hLqFxccPoqsSveQFxVLvNxy9bus= github.com/filecoin-project/go-crypto v0.0.0-20191218222705-effae4ea9f03/go.mod h1:+viYnvGtUTgJRdy6oaeF4MTFKAfatX071MPDPBL11EQ= github.com/filecoin-project/go-data-transfer v1.0.1/go.mod h1:UxvfUAY9v3ub0a21BSK9u3pB2aq30Y0KMsG+w9/ysyo= -github.com/filecoin-project/go-data-transfer v1.2.9 h1:k6oXrI/6AfNdEfUVFAx6LbVMGNmdWWq97BiaDnhS3JE= -github.com/filecoin-project/go-data-transfer v1.2.9/go.mod h1:ps/AU2Ok4pf2oFevi5RmMr3JRAWcnSTA/Zag6VMygIc= +github.com/filecoin-project/go-data-transfer v1.3.0 h1:QZvpUVU0fVKH+wBH/QDPi5AB7fUI3NwwBLHK+d1Jed4= +github.com/filecoin-project/go-data-transfer v1.3.0/go.mod h1:n8kbDQXWrY1c4UgfMa9KERxNCWbOTDwdNhf2MpN9dpo= github.com/filecoin-project/go-ds-versioning v0.1.0 h1:y/X6UksYTsK8TLCI7rttCKEvl8btmWxyFMEeeWGUxIQ= github.com/filecoin-project/go-ds-versioning v0.1.0/go.mod h1:mp16rb4i2QPmxBnmanUx8i/XANp+PFCCJWiAb+VW4/s= github.com/filecoin-project/go-fil-commcid v0.0.0-20200716160307-8f644712406f/go.mod h1:Eaox7Hvus1JgPrL5+M3+h7aSPHc0cVqpSxA+TxIEpZQ= github.com/filecoin-project/go-fil-commcid v0.0.0-20201016201715-d41df56b4f6a h1:hyJ+pUm/4U4RdEZBlg6k8Ma4rDiuvqyGpoICXAxwsTg= github.com/filecoin-project/go-fil-commcid v0.0.0-20201016201715-d41df56b4f6a/go.mod h1:Eaox7Hvus1JgPrL5+M3+h7aSPHc0cVqpSxA+TxIEpZQ= github.com/filecoin-project/go-fil-markets v1.0.5-0.20201113164554-c5eba40d5335/go.mod h1:AJySOJC00JRWEZzRG2KsfUnqEf5ITXxeX09BE9N4f9c= -github.com/filecoin-project/go-fil-markets v1.2.0 h1:zFQOeuEK7a9ajYfwLiTwvsKAqa9tcLbf3I5waHubI+I= -github.com/filecoin-project/go-fil-markets v1.2.0/go.mod h1:xWoSrWwnLg7N6OUFdlijGHfTj2alzgLZW2Z+a4p18vg= +github.com/filecoin-project/go-fil-markets v1.2.1 h1:vsTf6x6ZvwbIuPxCXIAIKBLOnRewMPPiXhwkZwVxWEo= +github.com/filecoin-project/go-fil-markets v1.2.1/go.mod h1:G4d/D/RwxpwSmMS1VyJ72wq8IIDdIbIefM1vKKPesfw= github.com/filecoin-project/go-hamt-ipld v0.1.5 h1:uoXrKbCQZ49OHpsTCkrThPNelC4W3LPEk0OrS/ytIBM= github.com/filecoin-project/go-hamt-ipld v0.1.5/go.mod h1:6Is+ONR5Cd5R6XZoCse1CWaXZc0Hdb/JeX+EQCQzX24= github.com/filecoin-project/go-hamt-ipld/v2 v2.0.0 h1:b3UDemBYN2HNfk3KOXNuxgTTxlWi3xVvbQP0IT38fvM= diff --git a/node/modules/client.go b/node/modules/client.go index 8e0a281ed..d68e96406 100644 --- a/node/modules/client.go +++ b/node/modules/client.go @@ -121,8 +121,6 @@ func RegisterClientValidator(crv dtypes.ClientRequestValidator, dtm dtypes.Clien // NewClientGraphsyncDataTransfer returns a data transfer manager that just // uses the clients's Client DAG service for transfers func NewClientGraphsyncDataTransfer(lc fx.Lifecycle, h host.Host, gs dtypes.Graphsync, ds dtypes.MetadataDS, r repo.LockedRepo) (dtypes.ClientDataTransfer, error) { - sc := storedcounter.New(ds, datastore.NewKey("/datatransfer/client/counter")) - // go-data-transfer protocol retries: // 1s, 5s, 25s, 2m5s, 5m x 11 ~= 1 hour dtRetryParams := dtnet.RetryParameters(time.Second, 5*time.Minute, 15, 5) @@ -152,7 +150,7 @@ func NewClientGraphsyncDataTransfer(lc fx.Lifecycle, h host.Host, gs dtypes.Grap // data has been sent / received CompleteTimeout: 30 * time.Second, }) - dt, err := dtimpl.NewDataTransfer(dtDs, filepath.Join(r.Path(), "data-transfer"), net, transport, sc, dtRestartConfig) + dt, err := dtimpl.NewDataTransfer(dtDs, filepath.Join(r.Path(), "data-transfer"), net, transport, dtRestartConfig) if err != nil { return nil, err } diff --git a/node/modules/storageminer.go b/node/modules/storageminer.go index d89474eee..1781d0493 100644 --- a/node/modules/storageminer.go +++ b/node/modules/storageminer.go @@ -330,7 +330,6 @@ func HandleMigrateProviderFunds(lc fx.Lifecycle, ds dtypes.MetadataDS, node api. // NewProviderDAGServiceDataTransfer returns a data transfer manager that just // uses the provider's Staging DAG service for transfers func NewProviderDAGServiceDataTransfer(lc fx.Lifecycle, h host.Host, gs dtypes.StagingGraphsync, ds dtypes.MetadataDS, r repo.LockedRepo) (dtypes.ProviderDataTransfer, error) { - sc := storedcounter.New(ds, datastore.NewKey("/datatransfer/provider/counter")) net := dtnet.NewFromLibp2pHost(h) dtDs := namespace.Wrap(ds, datastore.NewKey("/datatransfer/provider/transfers")) @@ -340,7 +339,7 @@ func NewProviderDAGServiceDataTransfer(lc fx.Lifecycle, h host.Host, gs dtypes.S return nil, err } - dt, err := dtimpl.NewDataTransfer(dtDs, filepath.Join(r.Path(), "data-transfer"), net, transport, sc) + dt, err := dtimpl.NewDataTransfer(dtDs, filepath.Join(r.Path(), "data-transfer"), net, transport) if err != nil { return nil, err } From 1359fb6cc4e0072a7b07f6a9c1f4965d362ef610 Mon Sep 17 00:00:00 2001 From: Dirk McCormick Date: Wed, 24 Mar 2021 13:56:59 +0100 Subject: [PATCH 03/11] fix: disable pull channel monitoring for now --- go.mod | 4 ++-- go.sum | 8 ++++---- node/modules/client.go | 6 ++++++ 3 files changed, 12 insertions(+), 6 deletions(-) diff --git a/go.mod b/go.mod index e5f8900ae..7602b3845 100644 --- a/go.mod +++ b/go.mod @@ -32,9 +32,9 @@ require ( github.com/filecoin-project/go-cbor-util v0.0.0-20191219014500-08c40a1e63a2 github.com/filecoin-project/go-commp-utils v0.0.0-20201119054358-b88f7a96a434 github.com/filecoin-project/go-crypto v0.0.0-20191218222705-effae4ea9f03 - github.com/filecoin-project/go-data-transfer v1.3.0 + github.com/filecoin-project/go-data-transfer v1.4.0 github.com/filecoin-project/go-fil-commcid v0.0.0-20201016201715-d41df56b4f6a - github.com/filecoin-project/go-fil-markets v1.2.1 + github.com/filecoin-project/go-fil-markets v1.2.2 github.com/filecoin-project/go-jsonrpc v0.1.4-0.20210217175800-45ea43ac2bec github.com/filecoin-project/go-multistore v0.0.3 github.com/filecoin-project/go-padreader v0.0.0-20200903213702-ed5fae088b20 diff --git a/go.sum b/go.sum index ae66a5883..ca91c1763 100644 --- a/go.sum +++ b/go.sum @@ -265,16 +265,16 @@ github.com/filecoin-project/go-commp-utils v0.0.0-20201119054358-b88f7a96a434/go github.com/filecoin-project/go-crypto v0.0.0-20191218222705-effae4ea9f03 h1:2pMXdBnCiXjfCYx/hLqFxccPoqsSveQFxVLvNxy9bus= github.com/filecoin-project/go-crypto v0.0.0-20191218222705-effae4ea9f03/go.mod h1:+viYnvGtUTgJRdy6oaeF4MTFKAfatX071MPDPBL11EQ= github.com/filecoin-project/go-data-transfer v1.0.1/go.mod h1:UxvfUAY9v3ub0a21BSK9u3pB2aq30Y0KMsG+w9/ysyo= -github.com/filecoin-project/go-data-transfer v1.3.0 h1:QZvpUVU0fVKH+wBH/QDPi5AB7fUI3NwwBLHK+d1Jed4= -github.com/filecoin-project/go-data-transfer v1.3.0/go.mod h1:n8kbDQXWrY1c4UgfMa9KERxNCWbOTDwdNhf2MpN9dpo= +github.com/filecoin-project/go-data-transfer v1.4.0 h1:SRpFUp7WQdJe6iSmt7HfhMGDk7tniTVIlfmvQVBZhN8= +github.com/filecoin-project/go-data-transfer v1.4.0/go.mod h1:n8kbDQXWrY1c4UgfMa9KERxNCWbOTDwdNhf2MpN9dpo= github.com/filecoin-project/go-ds-versioning v0.1.0 h1:y/X6UksYTsK8TLCI7rttCKEvl8btmWxyFMEeeWGUxIQ= github.com/filecoin-project/go-ds-versioning v0.1.0/go.mod h1:mp16rb4i2QPmxBnmanUx8i/XANp+PFCCJWiAb+VW4/s= github.com/filecoin-project/go-fil-commcid v0.0.0-20200716160307-8f644712406f/go.mod h1:Eaox7Hvus1JgPrL5+M3+h7aSPHc0cVqpSxA+TxIEpZQ= github.com/filecoin-project/go-fil-commcid v0.0.0-20201016201715-d41df56b4f6a h1:hyJ+pUm/4U4RdEZBlg6k8Ma4rDiuvqyGpoICXAxwsTg= github.com/filecoin-project/go-fil-commcid v0.0.0-20201016201715-d41df56b4f6a/go.mod h1:Eaox7Hvus1JgPrL5+M3+h7aSPHc0cVqpSxA+TxIEpZQ= github.com/filecoin-project/go-fil-markets v1.0.5-0.20201113164554-c5eba40d5335/go.mod h1:AJySOJC00JRWEZzRG2KsfUnqEf5ITXxeX09BE9N4f9c= -github.com/filecoin-project/go-fil-markets v1.2.1 h1:vsTf6x6ZvwbIuPxCXIAIKBLOnRewMPPiXhwkZwVxWEo= -github.com/filecoin-project/go-fil-markets v1.2.1/go.mod h1:G4d/D/RwxpwSmMS1VyJ72wq8IIDdIbIefM1vKKPesfw= +github.com/filecoin-project/go-fil-markets v1.2.2 h1:BC9Ixdyy5J8VfirytWmX69Ntrk94rzm4WyExhwg/Kwc= +github.com/filecoin-project/go-fil-markets v1.2.2/go.mod h1:p5BIKl6sEoeOCKFa3/nfy66Q95rifEkJyGQgaNjPsno= github.com/filecoin-project/go-hamt-ipld v0.1.5 h1:uoXrKbCQZ49OHpsTCkrThPNelC4W3LPEk0OrS/ytIBM= github.com/filecoin-project/go-hamt-ipld v0.1.5/go.mod h1:6Is+ONR5Cd5R6XZoCse1CWaXZc0Hdb/JeX+EQCQzX24= github.com/filecoin-project/go-hamt-ipld/v2 v2.0.0 h1:b3UDemBYN2HNfk3KOXNuxgTTxlWi3xVvbQP0IT38fvM= diff --git a/node/modules/client.go b/node/modules/client.go index d68e96406..d54347835 100644 --- a/node/modules/client.go +++ b/node/modules/client.go @@ -135,6 +135,12 @@ func NewClientGraphsyncDataTransfer(lc fx.Lifecycle, h host.Host, gs dtypes.Grap // data-transfer push / pull channel restart configuration: dtRestartConfig := dtimpl.ChannelRestartConfig(channelmonitor.Config{ + // For now only monitor push channels (for storage deals) + MonitorPushChannels: true, + // TODO: Enable pull channel monitoring (for retrievals) when the + // following issue has been fixed: + // https://github.com/filecoin-project/go-data-transfer/issues/172 + MonitorPullChannels: false, // Wait up to 30s for the other side to respond to an Open channel message AcceptTimeout: 30 * time.Second, // Send a restart message if the data rate falls below 1024 bytes / minute From a202f9d19e1d841b88441b3b6e6252487a7692cd Mon Sep 17 00:00:00 2001 From: Anton Evangelatov Date: Wed, 24 Mar 2021 14:36:21 +0200 Subject: [PATCH 04/11] add cancel-retrieval-deal cmd --- api/api_full.go | 3 +++ api/apistruct/struct.go | 6 ++++++ api/mocks/mock_full.go | 15 +++++++++++++++ cli/client.go | 27 +++++++++++++++++++++++++++ documentation/en/api-methods.md | 16 ++++++++++++++++ node/impl/client/client.go | 23 +++++++++++++++++++++++ 6 files changed, 90 insertions(+) diff --git a/api/api_full.go b/api/api_full.go index b66b0e402..00dc86797 100644 --- a/api/api_full.go +++ b/api/api_full.go @@ -340,6 +340,9 @@ type FullNode interface { // which are stuck due to insufficient funds ClientRetrieveTryRestartInsufficientFunds(ctx context.Context, paymentChannel address.Address) error //perm:write + // ClientCancelRetrievalDeal cancels an ongoing retrieval deal based on DealID + ClientCancelRetrievalDeal(ctx context.Context, dealid retrievalmarket.DealID) error //perm:write + // ClientUnimport removes references to the specified file from filestore //ClientUnimport(path string) diff --git a/api/apistruct/struct.go b/api/apistruct/struct.go index 34cf52fce..afd177f86 100644 --- a/api/apistruct/struct.go +++ b/api/apistruct/struct.go @@ -154,6 +154,8 @@ type FullNodeStruct struct { ClientCancelDataTransfer func(p0 context.Context, p1 datatransfer.TransferID, p2 peer.ID, p3 bool) error `perm:"write"` + ClientCancelRetrievalDeal func(p0 context.Context, p1 retrievalmarket.DealID) error `perm:"write"` + ClientDataTransferUpdates func(p0 context.Context) (<-chan api.DataTransferChannel, error) `perm:"write"` ClientDealPieceCID func(p0 context.Context, p1 cid.Cid) (api.DataCIDSize, error) `perm:"read"` @@ -978,6 +980,10 @@ func (s *FullNodeStruct) ClientCancelDataTransfer(p0 context.Context, p1 datatra return s.Internal.ClientCancelDataTransfer(p0, p1, p2, p3) } +func (s *FullNodeStruct) ClientCancelRetrievalDeal(p0 context.Context, p1 retrievalmarket.DealID) error { + return s.Internal.ClientCancelRetrievalDeal(p0, p1) +} + func (s *FullNodeStruct) ClientDataTransferUpdates(p0 context.Context) (<-chan api.DataTransferChannel, error) { return s.Internal.ClientDataTransferUpdates(p0) } diff --git a/api/mocks/mock_full.go b/api/mocks/mock_full.go index 8fd646d9a..8de04cf4c 100644 --- a/api/mocks/mock_full.go +++ b/api/mocks/mock_full.go @@ -9,6 +9,7 @@ import ( address "github.com/filecoin-project/go-address" bitfield "github.com/filecoin-project/go-bitfield" datatransfer "github.com/filecoin-project/go-data-transfer" + retrievalmarket "github.com/filecoin-project/go-fil-markets/retrievalmarket" storagemarket "github.com/filecoin-project/go-fil-markets/storagemarket" auth "github.com/filecoin-project/go-jsonrpc/auth" multistore "github.com/filecoin-project/go-multistore" @@ -445,6 +446,20 @@ func (mr *MockFullNodeMockRecorder) ClientCancelDataTransfer(arg0, arg1, arg2, a return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ClientCancelDataTransfer", reflect.TypeOf((*MockFullNode)(nil).ClientCancelDataTransfer), arg0, arg1, arg2, arg3) } +// ClientCancelRetrievalDeal mocks base method +func (m *MockFullNode) ClientCancelRetrievalDeal(arg0 context.Context, arg1 retrievalmarket.DealID) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "ClientCancelRetrievalDeal", arg0, arg1) + ret0, _ := ret[0].(error) + return ret0 +} + +// ClientCancelRetrievalDeal indicates an expected call of ClientCancelRetrievalDeal +func (mr *MockFullNodeMockRecorder) ClientCancelRetrievalDeal(arg0, arg1 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ClientCancelRetrievalDeal", reflect.TypeOf((*MockFullNode)(nil).ClientCancelRetrievalDeal), arg0, arg1) +} + // ClientDataTransferUpdates mocks base method func (m *MockFullNode) ClientDataTransferUpdates(arg0 context.Context) (<-chan api.DataTransferChannel, error) { m.ctrl.T.Helper() diff --git a/cli/client.go b/cli/client.go index 98f4b0229..ecc31e1e5 100644 --- a/cli/client.go +++ b/cli/client.go @@ -95,6 +95,7 @@ var clientCmd = &cli.Command{ WithCategory("util", clientListTransfers), WithCategory("util", clientRestartTransfer), WithCategory("util", clientCancelTransfer), + WithCategory("util", clientCancelRetrievalDeal), }, } @@ -1975,6 +1976,32 @@ var clientCancelTransfer = &cli.Command{ }, } +var clientCancelRetrievalDeal = &cli.Command{ + Name: "cancel-retrieval-deal", + Usage: "Cancel a retrieval deal by DealID", + Flags: []cli.Flag{ + &cli.Int64Flag{ + Name: "dealid", + Usage: "specify retrieval deal by DealID", + Required: true, + }, + }, + Action: func(cctx *cli.Context) error { + api, closer, err := GetFullNodeAPI(cctx) + if err != nil { + return err + } + defer closer() + ctx := ReqContext(cctx) + + if cctx.Int64("dealid") == 0 { + return errors.New("deal id cannot be 0") + } + + return api.ClientCancelRetrievalDeal(ctx, retrievalmarket.DealID(cctx.Int64("dealid"))) + }, +} + var clientListTransfers = &cli.Command{ Name: "list-transfers", Usage: "List ongoing data transfers for deals", diff --git a/documentation/en/api-methods.md b/documentation/en/api-methods.md index b8764d5b1..82e7f3e05 100644 --- a/documentation/en/api-methods.md +++ b/documentation/en/api-methods.md @@ -35,6 +35,7 @@ * [Client](#Client) * [ClientCalcCommP](#ClientCalcCommP) * [ClientCancelDataTransfer](#ClientCancelDataTransfer) + * [ClientCancelRetrievalDeal](#ClientCancelRetrievalDeal) * [ClientDataTransferUpdates](#ClientDataTransferUpdates) * [ClientDealPieceCID](#ClientDealPieceCID) * [ClientDealSize](#ClientDealSize) @@ -921,6 +922,21 @@ Inputs: Response: `{}` +### ClientCancelRetrievalDeal +ClientCancelRetrievalDeal cancels an ongoing retrieval deal based on DealID + + +Perms: write + +Inputs: +```json +[ + 5 +] +``` + +Response: `{}` + ### ClientDataTransferUpdates diff --git a/node/impl/client/client.go b/node/impl/client/client.go index ac526ac60..1f5203754 100644 --- a/node/impl/client/client.go +++ b/node/impl/client/client.go @@ -475,6 +475,29 @@ func (a *API) ClientListImports(ctx context.Context) ([]api.Import, error) { return out, nil } +func (a *API) ClientCancelRetrievalDeal(ctx context.Context, dealid retrievalmarket.DealID) error { + cerr := make(chan error) + go func() { + err := a.Retrieval.CancelDeal(dealid) + + select { + case cerr <- err: + case <-ctx.Done(): + } + }() + + select { + case err := <-cerr: + if err != nil { + return xerrors.Errorf("canceling retrieval deal erred: %w", err) + } + + return nil + case <-ctx.Done(): + return xerrors.Errorf("canceling retrieval deal context timeout: %w", ctx.Err()) + } +} + func (a *API) ClientRetrieve(ctx context.Context, order api.RetrievalOrder, ref *api.FileRef) error { events := make(chan marketevents.RetrievalEvent) go a.clientRetrieve(ctx, order, ref, events) From 01340993151225ee4f1c8c5adefb773cf305875a Mon Sep 17 00:00:00 2001 From: Dirk McCormick Date: Thu, 25 Mar 2021 15:07:42 +0100 Subject: [PATCH 05/11] feat: markets v1.2.3 --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 7602b3845..f1bcab061 100644 --- a/go.mod +++ b/go.mod @@ -34,7 +34,7 @@ require ( github.com/filecoin-project/go-crypto v0.0.0-20191218222705-effae4ea9f03 github.com/filecoin-project/go-data-transfer v1.4.0 github.com/filecoin-project/go-fil-commcid v0.0.0-20201016201715-d41df56b4f6a - github.com/filecoin-project/go-fil-markets v1.2.2 + github.com/filecoin-project/go-fil-markets v1.2.3 github.com/filecoin-project/go-jsonrpc v0.1.4-0.20210217175800-45ea43ac2bec github.com/filecoin-project/go-multistore v0.0.3 github.com/filecoin-project/go-padreader v0.0.0-20200903213702-ed5fae088b20 diff --git a/go.sum b/go.sum index ca91c1763..93c6bb2d9 100644 --- a/go.sum +++ b/go.sum @@ -273,8 +273,8 @@ github.com/filecoin-project/go-fil-commcid v0.0.0-20200716160307-8f644712406f/go github.com/filecoin-project/go-fil-commcid v0.0.0-20201016201715-d41df56b4f6a h1:hyJ+pUm/4U4RdEZBlg6k8Ma4rDiuvqyGpoICXAxwsTg= github.com/filecoin-project/go-fil-commcid v0.0.0-20201016201715-d41df56b4f6a/go.mod h1:Eaox7Hvus1JgPrL5+M3+h7aSPHc0cVqpSxA+TxIEpZQ= github.com/filecoin-project/go-fil-markets v1.0.5-0.20201113164554-c5eba40d5335/go.mod h1:AJySOJC00JRWEZzRG2KsfUnqEf5ITXxeX09BE9N4f9c= -github.com/filecoin-project/go-fil-markets v1.2.2 h1:BC9Ixdyy5J8VfirytWmX69Ntrk94rzm4WyExhwg/Kwc= -github.com/filecoin-project/go-fil-markets v1.2.2/go.mod h1:p5BIKl6sEoeOCKFa3/nfy66Q95rifEkJyGQgaNjPsno= +github.com/filecoin-project/go-fil-markets v1.2.3 h1:JDbGKQf60tB00TFKG/nofSyHyIEbqowZqoLOfda7yTs= +github.com/filecoin-project/go-fil-markets v1.2.3/go.mod h1:p5BIKl6sEoeOCKFa3/nfy66Q95rifEkJyGQgaNjPsno= github.com/filecoin-project/go-hamt-ipld v0.1.5 h1:uoXrKbCQZ49OHpsTCkrThPNelC4W3LPEk0OrS/ytIBM= github.com/filecoin-project/go-hamt-ipld v0.1.5/go.mod h1:6Is+ONR5Cd5R6XZoCse1CWaXZc0Hdb/JeX+EQCQzX24= github.com/filecoin-project/go-hamt-ipld/v2 v2.0.0 h1:b3UDemBYN2HNfk3KOXNuxgTTxlWi3xVvbQP0IT38fvM= From 36c3086376ee760d1caefc9ebae119d75e7be7a0 Mon Sep 17 00:00:00 2001 From: aarshkshah1992 Date: Fri, 26 Mar 2021 09:48:50 +0530 Subject: [PATCH 06/11] changes as per review --- cli/client.go | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/cli/client.go b/cli/client.go index ecc31e1e5..787510821 100644 --- a/cli/client.go +++ b/cli/client.go @@ -95,7 +95,6 @@ var clientCmd = &cli.Command{ WithCategory("util", clientListTransfers), WithCategory("util", clientRestartTransfer), WithCategory("util", clientCancelTransfer), - WithCategory("util", clientCancelRetrievalDeal), }, } @@ -952,6 +951,9 @@ var clientRetrieveCmd = &cli.Command{ Name: "retrieve", Usage: "Retrieve data from network", ArgsUsage: "[dataCid outputPath]", + Subcommands: []*cli.Command{ + clientCancelRetrievalDeal, + }, Flags: []cli.Flag{ &cli.StringFlag{ Name: "from", @@ -1977,7 +1979,7 @@ var clientCancelTransfer = &cli.Command{ } var clientCancelRetrievalDeal = &cli.Command{ - Name: "cancel-retrieval-deal", + Name: "cancel", Usage: "Cancel a retrieval deal by DealID", Flags: []cli.Flag{ &cli.Int64Flag{ @@ -1994,8 +1996,8 @@ var clientCancelRetrievalDeal = &cli.Command{ defer closer() ctx := ReqContext(cctx) - if cctx.Int64("dealid") == 0 { - return errors.New("deal id cannot be 0") + if cctx.Int64("dealid") <= 0 { + return errors.New("deal id cannot be negative") } return api.ClientCancelRetrievalDeal(ctx, retrievalmarket.DealID(cctx.Int64("dealid"))) From b13f6a32090e51fcdd7098ba9cd2940a66531a93 Mon Sep 17 00:00:00 2001 From: Dirk McCormick Date: Fri, 26 Mar 2021 09:50:52 +0100 Subject: [PATCH 07/11] fix: cancel retrieval deal - disallow negative deal ID --- cli/client.go | 2 +- node/impl/client/client.go | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/cli/client.go b/cli/client.go index 787510821..24f1281c9 100644 --- a/cli/client.go +++ b/cli/client.go @@ -1996,7 +1996,7 @@ var clientCancelRetrievalDeal = &cli.Command{ defer closer() ctx := ReqContext(cctx) - if cctx.Int64("dealid") <= 0 { + if cctx.Int64("dealid") < 0 { return errors.New("deal id cannot be negative") } diff --git a/node/impl/client/client.go b/node/impl/client/client.go index 1f5203754..62198e0a2 100644 --- a/node/impl/client/client.go +++ b/node/impl/client/client.go @@ -489,12 +489,12 @@ func (a *API) ClientCancelRetrievalDeal(ctx context.Context, dealid retrievalmar select { case err := <-cerr: if err != nil { - return xerrors.Errorf("canceling retrieval deal erred: %w", err) + return xerrors.Errorf("failed to cancel retrieval deal: %w", err) } return nil case <-ctx.Done(): - return xerrors.Errorf("canceling retrieval deal context timeout: %w", ctx.Err()) + return xerrors.Errorf("context timeout while canceling retrieval deal: %w", ctx.Err()) } } From 85eab9e00eea6520a82a34b17390ac10df4e6f8e Mon Sep 17 00:00:00 2001 From: Dirk McCormick Date: Fri, 26 Mar 2021 09:53:01 +0100 Subject: [PATCH 08/11] fix: make docsgen --- build/openrpc/full.json.gz | Bin 22582 -> 22664 bytes build/openrpc/miner.json.gz | Bin 7643 -> 7639 bytes build/openrpc/worker.json.gz | Bin 2578 -> 2578 bytes 3 files changed, 0 insertions(+), 0 deletions(-) diff --git a/build/openrpc/full.json.gz b/build/openrpc/full.json.gz index 42d7e5b954d1b5f955c274b897f12b195c68386a..3901c839f738bc39b49283b34909cdc1edcaa556 100644 GIT binary patch delta 21687 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 aS)A5hzW)1wg@*R<@H?X-i_#qv?SBAdLo-VN delta 21583 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 MdO6Ksp!hid0rbL)S^xk5 diff --git a/build/openrpc/miner.json.gz b/build/openrpc/miner.json.gz index faab78eb76c65d98e3190189bcda59a2faa51f16..38f5f83500091bab5645a4b708932336e082dd92 100644 GIT binary patch literal 7639 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 F0RTDG0jvN3 literal 7643 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 JfEo*V0RT7s00{s9 diff --git a/build/openrpc/worker.json.gz b/build/openrpc/worker.json.gz index 7bf6216a75f64bf7adaa10fbee6e214287f259b6..be362b3e99aca73dba202e7f06afea8a94c60296 100644 GIT binary patch delta 1830 zcmV+>2if?N6p|FM(gFfrpOe%AHGdE}c$+T=e}b}S6{R4gspd7VjHM~p{cEQnbQ@O> zM?}q{;(ns|ogL2pNA5rk=W)qyInS|i5nrH-SR|gi^PjfhJY{{rtRj_?IxK;>ludDh zDXBzQvK@~uqsHa<^7uW}W~y=O8mI0+ow_%@0x+kHxb!DPucRWXr--X2g@2aimxN7g zf%JOsOSEoKdM`9-A5eNt%IYO>DopL?$wY!GH@9K7rRK!cOb0ap*8tq10^I9-fV*H5 zUJ=$bNq)X!eT_iZ+yqlmYdc9^X9PO*OMTiPV38;&E8d}v3xBtgxX{a!W`})-8SMA z^boR!q@lOa6c`BoHh-du?i@YLfJODLnQ!_-QW2r5?KsO*zj&OPIZQq&v6NB@26wX4 zX)~}Ll1iL(3Uc$8Kx*yMjOmI36v|s)1yvy8z+^pKNv^Ojw}}07uHb?>@FQGm&)qy$ zBbG@r`&*aW<4O2!d&V}p>`j2Rp8?iW%jOyF*x?4sey8_lH-CF5pU+m%CSYs=#={I4 zPdWul7?r6^B{+UT>If!Nx?z$BL?RklD;tLffu#kiu- z<{7+Cftx*;5q}jXB9SvOy$th~45WS#rZW8C6 zwBR~ahIe{4XPsW$S*Kp%?iN+=e%Tdak^42~+}*JME7iyod%)sq$RpxTA~l1hSQClB zJZmq-yM;b+h187bA5MhwW*(U%MeYC*G=T>s!RE}7NO7c1Dwz@m`hz0!4rzIH z0)KalJI;R3<+jb1u7uDREqfWa?49F;=ZLFHeww;C`Vf>&Hz`1-tzs?MS_Ba$I?CNP zn!J2yo40$uREg{tB)uTO_5x(^?Vs!)LKbr zyuek|)=!UpV&8!i_o6~qoG=Fw^nX#;nh`l`r3Gg@M+%y64rx}Vnw6=vOIVP+j8wX! zI~Y;rM>)i&t=LjL?UJq9*~uN22~M&|l6tlq7(6?D{kB^h2lrc`&I)pmUkO$J2`H$F zA{Eo+3e}SdoFr+!9K|)z*yZ+}L;+LOMQR2D5D|cwS*MXm1dN5NJHIG;FBdhVa`qZ8 U7B`Fk1pom5|90#~$^m--0M!nQ#{d8T delta 1830 zcmV+>2if?N6p|FM(gFg`-jmb(p2*rSH{wm>;AP<5W0=4 zha;k9QE@*}{LT(%|08#xhV!^&x18tLxQH*%MJy7}-T6;jaGtV0U{;YzNgb9zT*{_6 z!IV@YEZL4nmr>(#e0lsHYBSY1b&XSZpibTE*9Bls8FA@Ph+auWR8J9CO@9h4%P$F= z)&lAE-j`_Ip!8m7(mtT{nv~T`;8d8}&y$G+Rc>y>Y)j3FshJLH0ImVJ0|mG@C;0$( z!6v*StZ9<`e8u`2fv&j;rlQt%lDx>{=L!8yRVt&y|K?J~U1>)e-4i#^X7myy4}={_ zE_kEaTvD63c+l@!y5Q=8_uM$*IO8Z9LLL#h!w7v=LD=SrK(YntY$sgnzgoTM;7Ys+$00 z+1yT?(maL=0`p9z-A3m_!mc3lzl;bj7wi^R_)xQy|J3Mj#>@M_ZQ_Q!=RN%jbUG`Q z4cKCgzvo)W%$QqJ{-a=DgAb<4Rh$^~s^e_V!)w^cC=?_UogsQgVEKmL7ac1T)`J}{BN+}rJ z$xf%uz;;+FQIMOz1X634W=vNUpitiWDyRYx2PW&`N^*sLxkc=sa|IX7fgj;gd+z43 z8nH~0+26X{9#6t=+cUP&Wp4tk{S2_4S~kyU#|}48_B*{dyMNh3`Fys5HUVQ3Fdk;W zc+x3Y!ngz%h=eap0;#?MbB+3UuhM6`Z}OFUrA+&fuWXj-8;ol(?nPi+!Ghc+ggZB@ zLYpQkLNx8unm2rLeq>Op7^I?xG+{n2MR`ipMxWIT#MTZ5Cb=xBvIUA-P4{*y#ubG& z&)|Iu-0Z=OsDCgKiNrC4>mG=P6f7HD0da@i^Qg)S(bH;@pseQo8QCQ6Wtg{QAZ2`J zH&h*BD|!!^8vW?RZx~3LEi(S;S{Fm=$Qs^cdMNApBHd5pRqh3R?SogD72g9qz+0$@ z&w8xc4Aq)R*?EW%_B4!^{h~<;Ehbaw!U3k}geE07Gk3bdXlcV+(rU#C zhruImYlBH9^X~X3v4Qj+q%%94_ek$djeGJAJpViY@wXq$x#xc$dlQ&Xdi@FQ1@p5Y zfPVMBZyfGzwpYg>swDP!s(%(cc01wkHLP|0}mHi{fQ{+ivykn7TCb zCO-%2mw(*RZj;#DHyzps7c?tn&(AGu@TkF~L&c+loj2O9j|9|Dx2%Y_l5trJerh6B zim7DoqyenGP_lghtb@;)GKmwkc~IXi*j$qW#yZjGinv|?x{y`;@pcG}(Yvz$TQsfR0K@)gD5^T;Ki4;fLq>?F7pg$-g?~s;P zCx39axZ~{iTyEQJ=~@YWuV~rJxMlAgCp<@7Rr1r+#nFeLY`RGSGHn%W!PX*(Fws%& zw$bF}L)*OF^TkSJLE`%_BJa+P`Kl<53CcoA1mbF&Cc|#b-8WB4WxCDXOJs(>@^|63 z?>lWf46WMTMnbnBq5XnA%EPee8x>S;`yS)vmjnuzM85Ryu@_*F`GyH zZ`t>MV_14zY>MQPt>??=vIaW74mzD4Aai%gFGpw_7|+bo=K5ulH%pP%0<@I+!DF~# z&?iby$|#k)X#KG<+3_;c5dDJi%C!nAz zid0OOD^yP=aFV3?aunAdBH00ZEYFaQ7m From 47f7208f38a33776b5663487d813865760db0755 Mon Sep 17 00:00:00 2001 From: Dirk McCormick Date: Fri, 26 Mar 2021 10:19:19 +0100 Subject: [PATCH 09/11] fix: rename command to retrieve-cancel --- cli/client.go | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/cli/client.go b/cli/client.go index 24f1281c9..5d9257f01 100644 --- a/cli/client.go +++ b/cli/client.go @@ -89,6 +89,7 @@ var clientCmd = &cli.Command{ WithCategory("data", clientStat), WithCategory("retrieval", clientFindCmd), WithCategory("retrieval", clientRetrieveCmd), + WithCategory("retrieval", clientCancelRetrievalDeal), WithCategory("util", clientCommPCmd), WithCategory("util", clientCarGenCmd), WithCategory("util", clientBalancesCmd), @@ -951,9 +952,6 @@ var clientRetrieveCmd = &cli.Command{ Name: "retrieve", Usage: "Retrieve data from network", ArgsUsage: "[dataCid outputPath]", - Subcommands: []*cli.Command{ - clientCancelRetrievalDeal, - }, Flags: []cli.Flag{ &cli.StringFlag{ Name: "from", @@ -1979,7 +1977,7 @@ var clientCancelTransfer = &cli.Command{ } var clientCancelRetrievalDeal = &cli.Command{ - Name: "cancel", + Name: "retrieve-cancel", Usage: "Cancel a retrieval deal by DealID", Flags: []cli.Flag{ &cli.Int64Flag{ From fd91c095c48a9104eac0c770ae91c525d27539af Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ra=C3=BAl=20Kripalani?= Date: Fri, 26 Mar 2021 16:37:46 +0000 Subject: [PATCH 10/11] rename command to cancel-retrieval; rename args to follow Lotus style. --- cli/client.go | 17 +++++++++-------- node/impl/client/client.go | 4 ++-- 2 files changed, 11 insertions(+), 10 deletions(-) diff --git a/cli/client.go b/cli/client.go index 5d9257f01..67fc7faff 100644 --- a/cli/client.go +++ b/cli/client.go @@ -89,7 +89,7 @@ var clientCmd = &cli.Command{ WithCategory("data", clientStat), WithCategory("retrieval", clientFindCmd), WithCategory("retrieval", clientRetrieveCmd), - WithCategory("retrieval", clientCancelRetrievalDeal), + WithCategory("retrieval", clientCancelRetrievalDealCmd), WithCategory("util", clientCommPCmd), WithCategory("util", clientCarGenCmd), WithCategory("util", clientBalancesCmd), @@ -1976,13 +1976,13 @@ var clientCancelTransfer = &cli.Command{ }, } -var clientCancelRetrievalDeal = &cli.Command{ - Name: "retrieve-cancel", - Usage: "Cancel a retrieval deal by DealID", +var clientCancelRetrievalDealCmd = &cli.Command{ + Name: "cancel-retrieval", + Usage: "Cancel a retrieval deal by deal ID; this also cancels the associated transfer", Flags: []cli.Flag{ &cli.Int64Flag{ - Name: "dealid", - Usage: "specify retrieval deal by DealID", + Name: "deal-id", + Usage: "specify retrieval deal by deal ID", Required: true, }, }, @@ -1994,11 +1994,12 @@ var clientCancelRetrievalDeal = &cli.Command{ defer closer() ctx := ReqContext(cctx) - if cctx.Int64("dealid") < 0 { + id := cctx.Int64("deal-id") + if id < 0 { return errors.New("deal id cannot be negative") } - return api.ClientCancelRetrievalDeal(ctx, retrievalmarket.DealID(cctx.Int64("dealid"))) + return api.ClientCancelRetrievalDeal(ctx, retrievalmarket.DealID(id)) }, } diff --git a/node/impl/client/client.go b/node/impl/client/client.go index 62198e0a2..54fef4264 100644 --- a/node/impl/client/client.go +++ b/node/impl/client/client.go @@ -475,10 +475,10 @@ func (a *API) ClientListImports(ctx context.Context) ([]api.Import, error) { return out, nil } -func (a *API) ClientCancelRetrievalDeal(ctx context.Context, dealid retrievalmarket.DealID) error { +func (a *API) ClientCancelRetrievalDeal(ctx context.Context, dealID retrievalmarket.DealID) error { cerr := make(chan error) go func() { - err := a.Retrieval.CancelDeal(dealid) + err := a.Retrieval.CancelDeal(dealID) select { case cerr <- err: From 3895b2ccca396183b0d40380aeb0b6bdd5f9fefa Mon Sep 17 00:00:00 2001 From: yaohcn Date: Wed, 31 Mar 2021 14:30:24 +0800 Subject: [PATCH 11/11] fix reservations --- extern/sector-storage/stores/local.go | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/extern/sector-storage/stores/local.go b/extern/sector-storage/stores/local.go index a7df5ae21..5837b711c 100644 --- a/extern/sector-storage/stores/local.go +++ b/extern/sector-storage/stores/local.go @@ -392,8 +392,10 @@ func (st *Local) Reserve(ctx context.Context, sid storage.SectorRef, ft storifac } p.reserved += overhead + p.reservations[sid.ID] |= fileType prevDone := done + saveFileType := fileType done = func() { prevDone() @@ -401,6 +403,10 @@ func (st *Local) Reserve(ctx context.Context, sid storage.SectorRef, ft storifac defer st.localLk.Unlock() p.reserved -= overhead + p.reservations[sid.ID] ^= saveFileType + if p.reservations[sid.ID] == storiface.FTNone { + delete(p.reservations, sid.ID) + } } }