From 4922c95589d78433f554e2fc236cc44326360e5d Mon Sep 17 00:00:00 2001 From: Hector Sanjuan Date: Fri, 1 Dec 2017 12:56:26 +0100 Subject: [PATCH] Support --local parameter for Status[Local] and Sync[Local] operations This allows to call the Rest API's status and sync endpoints with a "?local=true" parameter. This will trigger operations but only on the local peer. Cluster *Local and RPC-*Local methods have been accordingly, although they are aliases for the PinTracker methods (but otherwise they would not be exposed in external APIs). ipfs-cluster-ctl has been updated to support the new flag. The rationaly behind this feature is that sometimes, a single cluster peer (or the ipfs daemon in it) is misbehaving. The user then wants to Sync, Recover, or see Status for that single peer. This is specially relevant when working with big pinsets in larger clusters, as a Status() call will be considerably more expensive when broadcasted everywhere. Note that the Rest API keeps returning GlobalPinInfo objects even on local=true calls. This ensures that the user always gets the same datatype from an endpoint. License: MIT Signed-off-by: Hector Sanjuan --- api/rest/restapi.go | 139 ++++++++++++++++++++++++++++----------- api/rest/restapi_test.go | 51 +++++++++++++- cluster.go | 60 ++++++++++------- ipfs-cluster-ctl/main.go | 48 ++++++++++---- rpc_api.go | 63 +++++++++++------- test/rpc_api_mock.go | 115 +++++++++++++++++++++++++------- 6 files changed, 356 insertions(+), 120 deletions(-) diff --git a/api/rest/restapi.go b/api/rest/restapi.go index 4ac5b123..c76f89bc 100644 --- a/api/rest/restapi.go +++ b/api/rest/restapi.go @@ -426,46 +426,98 @@ func (api *API) allocationHandler(w http.ResponseWriter, r *http.Request) { } func (api *API) statusAllHandler(w http.ResponseWriter, r *http.Request) { - var pinInfos []types.GlobalPinInfoSerial - err := api.rpcClient.Call("", - "Cluster", - "StatusAll", - struct{}{}, - &pinInfos) - sendResponse(w, err, pinInfos) + queryValues := r.URL.Query() + local := queryValues.Get("local") + + if local == "true" { + var pinInfos []types.PinInfoSerial + err := api.rpcClient.Call("", + "Cluster", + "StatusAllLocal", + struct{}{}, + &pinInfos) + sendResponse(w, err, pinInfosToGlobal(pinInfos)) + } else { + var pinInfos []types.GlobalPinInfoSerial + err := api.rpcClient.Call("", + "Cluster", + "StatusAll", + struct{}{}, + &pinInfos) + sendResponse(w, err, pinInfos) + } } func (api *API) statusHandler(w http.ResponseWriter, r *http.Request) { + queryValues := r.URL.Query() + local := queryValues.Get("local") + if c := parseCidOrError(w, r); c.Cid != "" { - var pinInfo types.GlobalPinInfoSerial - err := api.rpcClient.Call("", - "Cluster", - "Status", - c, - &pinInfo) - sendResponse(w, err, pinInfo) + if local == "true" { + var pinInfo types.PinInfoSerial + err := api.rpcClient.Call("", + "Cluster", + "StatusLocal", + c, + &pinInfo) + sendResponse(w, err, pinInfoToGlobal(pinInfo)) + } else { + var pinInfo types.GlobalPinInfoSerial + err := api.rpcClient.Call("", + "Cluster", + "Status", + c, + &pinInfo) + sendResponse(w, err, pinInfo) + } } } func (api *API) syncAllHandler(w http.ResponseWriter, r *http.Request) { - var pinInfos []types.GlobalPinInfoSerial - err := api.rpcClient.Call("", - "Cluster", - "SyncAll", - struct{}{}, - &pinInfos) - sendResponse(w, err, pinInfos) + queryValues := r.URL.Query() + local := queryValues.Get("local") + + if local == "true" { + var pinInfos []types.PinInfoSerial + err := api.rpcClient.Call("", + "Cluster", + "SyncAllLocal", + struct{}{}, + &pinInfos) + sendResponse(w, err, pinInfosToGlobal(pinInfos)) + } else { + var pinInfos []types.GlobalPinInfoSerial + err := api.rpcClient.Call("", + "Cluster", + "SyncAll", + struct{}{}, + &pinInfos) + sendResponse(w, err, pinInfos) + } } func (api *API) syncHandler(w http.ResponseWriter, r *http.Request) { + queryValues := r.URL.Query() + local := queryValues.Get("local") + if c := parseCidOrError(w, r); c.Cid != "" { - var pinInfo types.GlobalPinInfoSerial - err := api.rpcClient.Call("", - "Cluster", - "Sync", - c, - &pinInfo) - sendResponse(w, err, pinInfo) + if local == "true" { + var pinInfo types.PinInfoSerial + err := api.rpcClient.Call("", + "Cluster", + "SyncLocal", + c, + &pinInfo) + sendResponse(w, err, pinInfoToGlobal(pinInfo)) + } else { + var pinInfo types.GlobalPinInfoSerial + err := api.rpcClient.Call("", + "Cluster", + "Sync", + c, + &pinInfo) + sendResponse(w, err, pinInfo) + } } } @@ -479,21 +531,17 @@ func (api *API) recoverAllHandler(w http.ResponseWriter, r *http.Request) { "RecoverAllLocal", struct{}{}, &pinInfos) - sendResponse(w, err, pinInfos) + sendResponse(w, err, pinInfosToGlobal(pinInfos)) } else { sendErrorResponse(w, 400, "only requests with parameter local=true are supported") } } func (api *API) recoverHandler(w http.ResponseWriter, r *http.Request) { + queryValues := r.URL.Query() + local := queryValues.Get("local") + if c := parseCidOrError(w, r); c.Cid != "" { - queryValues := r.URL.Query() - local := queryValues.Get("local") - - // Is it RESTful to return two different types - // depending on a flag? Should PinInfo - // be converted to a GlobalPinInfo ? - if local == "true" { var pinInfo types.PinInfoSerial err := api.rpcClient.Call("", @@ -501,7 +549,7 @@ func (api *API) recoverHandler(w http.ResponseWriter, r *http.Request) { "RecoverLocal", c, &pinInfo) - sendResponse(w, err, pinInfo) + sendResponse(w, err, pinInfoToGlobal(pinInfo)) } else { var pinInfo types.GlobalPinInfoSerial err := api.rpcClient.Call("", @@ -548,6 +596,23 @@ func parsePidOrError(w http.ResponseWriter, r *http.Request) peer.ID { return pid } +func pinInfoToGlobal(pInfo types.PinInfoSerial) types.GlobalPinInfoSerial { + return types.GlobalPinInfoSerial{ + Cid: pInfo.Cid, + PeerMap: map[string]types.PinInfoSerial{ + pInfo.Peer: pInfo, + }, + } +} + +func pinInfosToGlobal(pInfos []types.PinInfoSerial) []types.GlobalPinInfoSerial { + gPInfos := make([]types.GlobalPinInfoSerial, len(pInfos), len(pInfos)) + for i, p := range pInfos { + gPInfos[i] = pinInfoToGlobal(p) + } + return gPInfos +} + func sendResponse(w http.ResponseWriter, rpcErr error, resp interface{}) { if checkRPCErr(w, rpcErr) { sendJSONResponse(w, 200, resp) diff --git a/api/rest/restapi_test.go b/api/rest/restapi_test.go index 9871e74c..51b23733 100644 --- a/api/rest/restapi_test.go +++ b/api/rest/restapi_test.go @@ -232,7 +232,14 @@ func TestAPIStatusAllEndpoint(t *testing.T) { if len(resp) != 3 || resp[0].Cid != test.TestCid1 || resp[1].PeerMap[test.TestPeerID1.Pretty()].Status != "pinning" { - t.Errorf("unexpected statusResp:\n %+v", resp) + t.Errorf("unexpected statusAll resp:\n %+v", resp) + } + + // Test local=true + var resp2 []api.GlobalPinInfoSerial + makeGet(t, "/pins?local=true", &resp2) + if len(resp2) != 2 { + t.Errorf("unexpected statusAll+local resp:\n %+v", resp) } } @@ -253,6 +260,21 @@ func TestAPIStatusEndpoint(t *testing.T) { if info.Status != "pinned" { t.Error("expected different status") } + + // Test local=true + var resp2 api.GlobalPinInfoSerial + makeGet(t, "/pins/"+test.TestCid1+"?local=true", &resp2) + + if resp2.Cid != test.TestCid1 { + t.Error("expected the same cid") + } + info, ok = resp2.PeerMap[test.TestPeerID2.Pretty()] + if !ok { + t.Fatal("expected info for test.TestPeerID2") + } + if info.Status != "pinned" { + t.Error("expected different status") + } } func TestAPISyncAllEndpoint(t *testing.T) { @@ -265,7 +287,15 @@ func TestAPISyncAllEndpoint(t *testing.T) { if len(resp) != 3 || resp[0].Cid != test.TestCid1 || resp[1].PeerMap[test.TestPeerID1.Pretty()].Status != "pinning" { - t.Errorf("unexpected statusResp:\n %+v", resp) + t.Errorf("unexpected syncAll resp:\n %+v", resp) + } + + // Test local=true + var resp2 []api.GlobalPinInfoSerial + makePost(t, "/pins/sync?local=true", []byte{}, &resp2) + + if len(resp2) != 2 { + t.Errorf("unexpected syncAll+local resp:\n %+v", resp2) } } @@ -286,6 +316,21 @@ func TestAPISyncEndpoint(t *testing.T) { if info.Status != "pinned" { t.Error("expected different status") } + + // Test local=true + var resp2 api.GlobalPinInfoSerial + makePost(t, "/pins/"+test.TestCid1+"/sync?local=true", []byte{}, &resp2) + + if resp2.Cid != test.TestCid1 { + t.Error("expected the same cid") + } + info, ok = resp2.PeerMap[test.TestPeerID2.Pretty()] + if !ok { + t.Fatal("expected info for test.TestPeerID2") + } + if info.Status != "pinned" { + t.Error("expected different status") + } } func TestAPIRecoverEndpoint(t *testing.T) { @@ -311,7 +356,7 @@ func TestAPIRecoverAllEndpoint(t *testing.T) { rest := testAPI(t) defer rest.Shutdown() - var resp []api.PinInfoSerial + var resp []api.GlobalPinInfoSerial makePost(t, "/pins/recover?local=true", []byte{}, &resp) if len(resp) != 0 { diff --git a/cluster.go b/cluster.go index 1913c70c..4be78b46 100644 --- a/cluster.go +++ b/cluster.go @@ -835,20 +835,40 @@ func (c *Cluster) StateSync() ([]api.PinInfo, error) { return infos, nil } -// StatusAll returns the GlobalPinInfo for all tracked Cids. If an error -// happens, the slice will contain as much information as could be fetched. +// StatusAll returns the GlobalPinInfo for all tracked Cids in all peers. +// If an error happens, the slice will contain as much information as +// could be fetched from other peers. func (c *Cluster) StatusAll() ([]api.GlobalPinInfo, error) { return c.globalPinInfoSlice("TrackerStatusAll") } -// Status returns the GlobalPinInfo for a given Cid. If an error happens, -// the GlobalPinInfo should contain as much information as could be fetched. +// StatusAllLocal returns the PinInfo for all the tracked Cids in this peer. +func (c *Cluster) StatusAllLocal() []api.PinInfo { + return c.tracker.StatusAll() +} + +// Status returns the GlobalPinInfo for a given Cid as fetched from all +// current peers. If an error happens, the GlobalPinInfo should contain +// as much information as could be fetched from the other peers. func (c *Cluster) Status(h *cid.Cid) (api.GlobalPinInfo, error) { return c.globalPinInfoCid("TrackerStatus", h) } +// StatusLocal returns this peer's PinInfo for a given Cid. +func (c *Cluster) StatusLocal(h *cid.Cid) api.PinInfo { + return c.tracker.Status(h) +} + +// SyncAll triggers SyncAllLocal() operations in all cluster peers, making sure +// that the state of tracked items matches the state reported by the IPFS daemon +// and returning the results as GlobalPinInfo. If an error happens, the slice +// will contain as much information as could be fetched from the peers. +func (c *Cluster) SyncAll() ([]api.GlobalPinInfo, error) { + return c.globalPinInfoSlice("SyncAllLocal") +} + // SyncAllLocal makes sure that the current state for all tracked items -// matches the state reported by the IPFS daemon. +// in this peer matches the state reported by the IPFS daemon. // // SyncAllLocal returns the list of PinInfo that where updated because of // the operation, along with those in error states. @@ -863,6 +883,12 @@ func (c *Cluster) SyncAllLocal() ([]api.PinInfo, error) { return syncedItems, err } +// Sync triggers a LocalSyncCid() operation for a given Cid +// in all cluster peers. +func (c *Cluster) Sync(h *cid.Cid) (api.GlobalPinInfo, error) { + return c.globalPinInfoCid("SyncLocal", h) +} + // SyncLocal performs a local sync operation for the given Cid. This will // tell the tracker to verify the status of the Cid against the IPFS daemon. // It returns the updated PinInfo for the Cid. @@ -878,23 +904,7 @@ func (c *Cluster) SyncLocal(h *cid.Cid) (api.PinInfo, error) { return pInfo, err } -// SyncAll triggers LocalSync() operations in all cluster peers. -func (c *Cluster) SyncAll() ([]api.GlobalPinInfo, error) { - return c.globalPinInfoSlice("SyncAllLocal") -} - -// Sync triggers a LocalSyncCid() operation for a given Cid -// in all cluster peers. -func (c *Cluster) Sync(h *cid.Cid) (api.GlobalPinInfo, error) { - return c.globalPinInfoCid("SyncLocal", h) -} - -// RecoverLocal triggers a recover operation for a given Cid. -func (c *Cluster) RecoverLocal(h *cid.Cid) (api.PinInfo, error) { - return c.tracker.Recover(h) -} - -// RecoverAllLocal triggers a recover operation for all Cids tracked +// RecoverAllLocal triggers a RecoverLocal operation for all Cids tracked // by this peer. func (c *Cluster) RecoverAllLocal() ([]api.PinInfo, error) { return c.tracker.RecoverAll() @@ -906,6 +916,12 @@ func (c *Cluster) Recover(h *cid.Cid) (api.GlobalPinInfo, error) { return c.globalPinInfoCid("TrackerRecover", h) } +// RecoverLocal triggers a recover operation for a given Cid in this peer only. +// It returns the updated PinInfo, after recovery. +func (c *Cluster) RecoverLocal(h *cid.Cid) (api.PinInfo, error) { + return c.tracker.Recover(h) +} + // Pins returns the list of Cids managed by Cluster and which are part // of the current global state. This is the source of truth as to which // pins are managed and their allocation, but does not indicate if diff --git a/ipfs-cluster-ctl/main.go b/ipfs-cluster-ctl/main.go index d291827f..9340afe8 100644 --- a/ipfs-cluster-ctl/main.go +++ b/ipfs-cluster-ctl/main.go @@ -327,16 +327,27 @@ item. The status of a CID may not be accurate. A manual sync can be triggered with "sync". + +When the --local flag is passed, it will only fetch the status from the +contacted cluster peer. By default, status will be fetched from all peers. `, ArgsUsage: "[CID]", - Flags: []cli.Flag{parseFlag(formatGPInfo)}, + Flags: []cli.Flag{ + parseFlag(formatGPInfo), + localFlag(), + }, Action: func(c *cli.Context) error { + local := "false" + if c.Bool("local") { + local = "true" + } + cidStr := c.Args().First() if cidStr != "" { _, err := cid.Decode(cidStr) checkErr("parsing cid", err) } - resp := request("GET", "/pins/"+cidStr, nil) + resp := request("GET", "/pins/"+cidStr+"?local="+local, nil) formatResponse(c, resp) return nil }, @@ -355,18 +366,28 @@ have changed status because of the sync or are in error state in some node, therefore, the output should be empty if no operations were performed. CIDs in error state may be manually recovered with "recover". + +When the --local flag is passed, it will only trigger sync +operations on the contacted peer. By default, all peers will sync. `, ArgsUsage: "[CID]", - Flags: []cli.Flag{parseFlag(formatGPInfo)}, + Flags: []cli.Flag{ + parseFlag(formatGPInfo), + localFlag(), + }, Action: func(c *cli.Context) error { + local := "false" + if c.Bool("local") { + local = "true" + } cidStr := c.Args().First() var resp *http.Response if cidStr != "" { _, err := cid.Decode(cidStr) checkErr("parsing cid", err) - resp = request("POST", "/pins/"+cidStr+"/sync", nil) + resp = request("POST", "/pins/"+cidStr+"/sync?local="+local, nil) } else { - resp = request("POST", "/pins/sync", nil) + resp = request("POST", "/pins/sync?local="+local, nil) } formatResponse(c, resp) return nil @@ -383,22 +404,18 @@ The command will wait for any operations to succeed and will return the status of the item upon completion. Note that, when running on the full sets of tracked CIDs (without argument), it may take considerable long time. -A --local flag must be passed. This will only trigger recover -operations on the contacted peer (and not on every peer). +When the --local flag is passed, it will only trigger recover +operations on the contacted peer (as opposed to on every peer). `, ArgsUsage: "[CID]", Flags: []cli.Flag{ parseFlag(formatGPInfo), - cli.BoolFlag{ - Name: "local", - Usage: "recover only on the contacted peer", - }, + localFlag(), }, Action: func(c *cli.Context) error { local := "false" if c.Bool("local") { local = "true" - c.Set("parseAs", fmt.Sprintf("%d", formatPInfo)) } cidStr := c.Args().First() var resp *http.Response @@ -453,6 +470,13 @@ func parseFlag(t int) cli.IntFlag { } } +func localFlag() cli.BoolFlag { + return cli.BoolFlag{ + Name: "local", + Usage: "run operation only on the contacted peer", + } +} + func walkCommands(cmds []cli.Command, parentHelpName string) { for _, c := range cmds { h := c.HelpName diff --git a/rpc_api.go b/rpc_api.go index 12186a54..74bea280 100644 --- a/rpc_api.go +++ b/rpc_api.go @@ -108,6 +108,13 @@ func (rpcapi *RPCAPI) StatusAll(in struct{}, out *[]api.GlobalPinInfoSerial) err return err } +// StatusAllLocal runs Cluster.StatusAllLocal(). +func (rpcapi *RPCAPI) StatusAllLocal(in struct{}, out *[]api.PinInfoSerial) error { + pinfos := rpcapi.c.StatusAllLocal() + *out = pinInfoSliceToSerial(pinfos) + return nil +} + // Status runs Cluster.Status(). func (rpcapi *RPCAPI) Status(in api.PinSerial, out *api.GlobalPinInfoSerial) error { c := in.ToPin().Cid @@ -116,19 +123,12 @@ func (rpcapi *RPCAPI) Status(in api.PinSerial, out *api.GlobalPinInfoSerial) err return err } -// SyncAllLocal runs Cluster.SyncAllLocal(). -func (rpcapi *RPCAPI) SyncAllLocal(in struct{}, out *[]api.PinInfoSerial) error { - pinfos, err := rpcapi.c.SyncAllLocal() - *out = pinInfoSliceToSerial(pinfos) - return err -} - -// SyncLocal runs Cluster.SyncLocal(). -func (rpcapi *RPCAPI) SyncLocal(in api.PinSerial, out *api.PinInfoSerial) error { +// StatusLocal runs Cluster.StatusLocal(). +func (rpcapi *RPCAPI) StatusLocal(in api.PinSerial, out *api.PinInfoSerial) error { c := in.ToPin().Cid - pinfo, err := rpcapi.c.SyncLocal(c) + pinfo := rpcapi.c.StatusLocal(c) *out = pinfo.ToSerial() - return err + return nil } // SyncAll runs Cluster.SyncAll(). @@ -138,6 +138,13 @@ func (rpcapi *RPCAPI) SyncAll(in struct{}, out *[]api.GlobalPinInfoSerial) error return err } +// SyncAllLocal runs Cluster.SyncAllLocal(). +func (rpcapi *RPCAPI) SyncAllLocal(in struct{}, out *[]api.PinInfoSerial) error { + pinfos, err := rpcapi.c.SyncAllLocal() + *out = pinInfoSliceToSerial(pinfos) + return err +} + // Sync runs Cluster.Sync(). func (rpcapi *RPCAPI) Sync(in api.PinSerial, out *api.GlobalPinInfoSerial) error { c := in.ToPin().Cid @@ -146,9 +153,17 @@ func (rpcapi *RPCAPI) Sync(in api.PinSerial, out *api.GlobalPinInfoSerial) error return err } -// StateSync runs Cluster.StateSync(). -func (rpcapi *RPCAPI) StateSync(in struct{}, out *[]api.PinInfoSerial) error { - pinfos, err := rpcapi.c.StateSync() +// SyncLocal runs Cluster.SyncLocal(). +func (rpcapi *RPCAPI) SyncLocal(in api.PinSerial, out *api.PinInfoSerial) error { + c := in.ToPin().Cid + pinfo, err := rpcapi.c.SyncLocal(c) + *out = pinfo.ToSerial() + return err +} + +// RecoverAllLocal runs Cluster.RecoverAllLocal(). +func (rpcapi *RPCAPI) RecoverAllLocal(in struct{}, out *[]api.PinInfoSerial) error { + pinfos, err := rpcapi.c.RecoverAllLocal() *out = pinInfoSliceToSerial(pinfos) return err } @@ -169,9 +184,9 @@ func (rpcapi *RPCAPI) RecoverLocal(in api.PinSerial, out *api.PinInfoSerial) err return err } -// RecoverAllLocal runs Cluster.RecoverAllLocal(). -func (rpcapi *RPCAPI) RecoverAllLocal(in struct{}, out *[]api.PinInfoSerial) error { - pinfos, err := rpcapi.c.RecoverAllLocal() +// StateSync runs Cluster.StateSync(). +func (rpcapi *RPCAPI) StateSync(in struct{}, out *[]api.PinInfoSerial) error { + pinfos, err := rpcapi.c.StateSync() *out = pinInfoSliceToSerial(pinfos) return err } @@ -205,6 +220,13 @@ func (rpcapi *RPCAPI) TrackerStatus(in api.PinSerial, out *api.PinInfoSerial) er return nil } +// TrackerRecoverAll runs PinTracker.RecoverAll(). +func (rpcapi *RPCAPI) TrackerRecoverAll(in struct{}, out *[]api.PinInfoSerial) error { + pinfos, err := rpcapi.c.tracker.RecoverAll() + *out = pinInfoSliceToSerial(pinfos) + return err +} + // TrackerRecover runs PinTracker.Recover(). func (rpcapi *RPCAPI) TrackerRecover(in api.PinSerial, out *api.PinInfoSerial) error { c := in.ToPin().Cid @@ -213,13 +235,6 @@ func (rpcapi *RPCAPI) TrackerRecover(in api.PinSerial, out *api.PinInfoSerial) e return err } -// TrackerRecoverAll runs PinTracker.RecoverAll(). -func (rpcapi *RPCAPI) TrackerRecoverAll(in struct{}, out *[]api.PinInfoSerial) error { - pinfos, err := rpcapi.c.tracker.RecoverAll() - *out = pinInfoSliceToSerial(pinfos) - return err -} - /* IPFS Connector component methods */ diff --git a/test/rpc_api_mock.go b/test/rpc_api_mock.go index 8e256af6..a0c4160a 100644 --- a/test/rpc_api_mock.go +++ b/test/rpc_api_mock.go @@ -118,15 +118,6 @@ func (mock *mockService) PeerRemove(in peer.ID, out *struct{}) error { return nil } -// FIXME: dup from util.go -func globalPinInfoSliceToSerial(gpi []api.GlobalPinInfo) []api.GlobalPinInfoSerial { - gpis := make([]api.GlobalPinInfoSerial, len(gpi), len(gpi)) - for i, v := range gpi { - gpis[i] = v.ToSerial() - } - return gpis -} - func (mock *mockService) StatusAll(in struct{}, out *[]api.GlobalPinInfoSerial) error { c1, _ := cid.Decode(TestCid1) c2, _ := cid.Decode(TestCid2) @@ -169,6 +160,10 @@ func (mock *mockService) StatusAll(in struct{}, out *[]api.GlobalPinInfoSerial) return nil } +func (mock *mockService) StatusAllLocal(in struct{}, out *[]api.PinInfoSerial) error { + return mock.TrackerStatusAll(in, out) +} + func (mock *mockService) Status(in api.PinSerial, out *api.GlobalPinInfoSerial) error { if in.Cid == ErrorCid { return ErrBadCid @@ -188,24 +183,95 @@ func (mock *mockService) Status(in api.PinSerial, out *api.GlobalPinInfoSerial) return nil } +func (mock *mockService) StatusLocal(in api.PinSerial, out *api.PinInfoSerial) error { + return mock.TrackerStatus(in, out) +} + func (mock *mockService) SyncAll(in struct{}, out *[]api.GlobalPinInfoSerial) error { return mock.StatusAll(in, out) } +func (mock *mockService) SyncAllLocal(in struct{}, out *[]api.PinInfoSerial) error { + return mock.StatusAllLocal(in, out) +} + func (mock *mockService) Sync(in api.PinSerial, out *api.GlobalPinInfoSerial) error { return mock.Status(in, out) } +func (mock *mockService) SyncLocal(in api.PinSerial, out *api.PinInfoSerial) error { + return mock.StatusLocal(in, out) +} + func (mock *mockService) StateSync(in struct{}, out *[]api.PinInfoSerial) error { *out = make([]api.PinInfoSerial, 0, 0) return nil } +func (mock *mockService) RecoverAllLocal(in struct{}, out *[]api.PinInfoSerial) error { + return mock.TrackerRecoverAll(in, out) +} + func (mock *mockService) Recover(in api.PinSerial, out *api.GlobalPinInfoSerial) error { return mock.Status(in, out) } func (mock *mockService) RecoverLocal(in api.PinSerial, out *api.PinInfoSerial) error { + return mock.TrackerRecover(in, out) +} + +/* Tracker methods */ + +func (mock *mockService) Track(in api.PinSerial, out *struct{}) error { + return nil +} + +func (mock *mockService) Untrack(in api.PinSerial, out *struct{}) error { + return nil +} + +func (mock *mockService) TrackerStatusAll(in struct{}, out *[]api.PinInfoSerial) error { + c1, _ := cid.Decode(TestCid1) + c3, _ := cid.Decode(TestCid3) + + *out = pinInfoSliceToSerial([]api.PinInfo{ + { + Cid: c1, + Peer: TestPeerID1, + Status: api.TrackerStatusPinned, + TS: time.Now(), + }, + { + Cid: c3, + Peer: TestPeerID1, + Status: api.TrackerStatusPinError, + TS: time.Now(), + }, + }) + return nil +} + +func (mock *mockService) TrackerStatus(in api.PinSerial, out *api.PinInfoSerial) error { + if in.Cid == ErrorCid { + return ErrBadCid + } + c1, _ := cid.Decode(TestCid1) + + *out = api.PinInfo{ + Cid: c1, + Peer: TestPeerID2, + Status: api.TrackerStatusPinned, + TS: time.Now(), + }.ToSerial() + return nil +} + +func (mock *mockService) TrackerRecoverAll(in struct{}, out *[]api.PinInfoSerial) error { + *out = make([]api.PinInfoSerial, 0, 0) + return nil +} + +func (mock *mockService) TrackerRecover(in api.PinSerial, out *api.PinInfoSerial) error { in2 := in.ToPin() *out = api.PinInfo{ Cid: in2.Cid, @@ -216,19 +282,6 @@ func (mock *mockService) RecoverLocal(in api.PinSerial, out *api.PinInfoSerial) return nil } -func (mock *mockService) RecoverAllLocal(in struct{}, out *[]api.PinInfoSerial) error { - *out = make([]api.PinInfoSerial, 0, 0) - return nil -} - -func (mock *mockService) Track(in api.PinSerial, out *struct{}) error { - return nil -} - -func (mock *mockService) Untrack(in api.PinSerial, out *struct{}) error { - return nil -} - /* PeerManager methods */ func (mock *mockService) PeerManagerAddPeer(in api.MultiaddrSerial, out *struct{}) error { @@ -301,3 +354,21 @@ func (mock *mockService) ConsensusPeers(in struct{}, out *[]peer.ID) error { *out = []peer.ID{TestPeerID1, TestPeerID2, TestPeerID3} return nil } + +// FIXME: dup from util.go +func globalPinInfoSliceToSerial(gpi []api.GlobalPinInfo) []api.GlobalPinInfoSerial { + gpis := make([]api.GlobalPinInfoSerial, len(gpi), len(gpi)) + for i, v := range gpi { + gpis[i] = v.ToSerial() + } + return gpis +} + +// FIXME: dup from util.go +func pinInfoSliceToSerial(pi []api.PinInfo) []api.PinInfoSerial { + pis := make([]api.PinInfoSerial, len(pi), len(pi)) + for i, v := range pi { + pis[i] = v.ToSerial() + } + return pis +}