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 <code@hector.link>
This commit is contained in:
Hector Sanjuan 2017-12-01 12:56:26 +01:00
parent e824aea55e
commit 4922c95589
6 changed files with 356 additions and 120 deletions

View File

@ -426,46 +426,98 @@ func (api *API) allocationHandler(w http.ResponseWriter, r *http.Request) {
} }
func (api *API) statusAllHandler(w http.ResponseWriter, r *http.Request) { func (api *API) statusAllHandler(w http.ResponseWriter, r *http.Request) {
var pinInfos []types.GlobalPinInfoSerial queryValues := r.URL.Query()
err := api.rpcClient.Call("", local := queryValues.Get("local")
"Cluster",
"StatusAll", if local == "true" {
struct{}{}, var pinInfos []types.PinInfoSerial
&pinInfos) err := api.rpcClient.Call("",
sendResponse(w, err, pinInfos) "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) { 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 != "" { if c := parseCidOrError(w, r); c.Cid != "" {
var pinInfo types.GlobalPinInfoSerial if local == "true" {
err := api.rpcClient.Call("", var pinInfo types.PinInfoSerial
"Cluster", err := api.rpcClient.Call("",
"Status", "Cluster",
c, "StatusLocal",
&pinInfo) c,
sendResponse(w, err, pinInfo) &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) { func (api *API) syncAllHandler(w http.ResponseWriter, r *http.Request) {
var pinInfos []types.GlobalPinInfoSerial queryValues := r.URL.Query()
err := api.rpcClient.Call("", local := queryValues.Get("local")
"Cluster",
"SyncAll", if local == "true" {
struct{}{}, var pinInfos []types.PinInfoSerial
&pinInfos) err := api.rpcClient.Call("",
sendResponse(w, err, pinInfos) "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) { 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 != "" { if c := parseCidOrError(w, r); c.Cid != "" {
var pinInfo types.GlobalPinInfoSerial if local == "true" {
err := api.rpcClient.Call("", var pinInfo types.PinInfoSerial
"Cluster", err := api.rpcClient.Call("",
"Sync", "Cluster",
c, "SyncLocal",
&pinInfo) c,
sendResponse(w, err, pinInfo) &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", "RecoverAllLocal",
struct{}{}, struct{}{},
&pinInfos) &pinInfos)
sendResponse(w, err, pinInfos) sendResponse(w, err, pinInfosToGlobal(pinInfos))
} else { } else {
sendErrorResponse(w, 400, "only requests with parameter local=true are supported") sendErrorResponse(w, 400, "only requests with parameter local=true are supported")
} }
} }
func (api *API) recoverHandler(w http.ResponseWriter, r *http.Request) { 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 != "" { 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" { if local == "true" {
var pinInfo types.PinInfoSerial var pinInfo types.PinInfoSerial
err := api.rpcClient.Call("", err := api.rpcClient.Call("",
@ -501,7 +549,7 @@ func (api *API) recoverHandler(w http.ResponseWriter, r *http.Request) {
"RecoverLocal", "RecoverLocal",
c, c,
&pinInfo) &pinInfo)
sendResponse(w, err, pinInfo) sendResponse(w, err, pinInfoToGlobal(pinInfo))
} else { } else {
var pinInfo types.GlobalPinInfoSerial var pinInfo types.GlobalPinInfoSerial
err := api.rpcClient.Call("", err := api.rpcClient.Call("",
@ -548,6 +596,23 @@ func parsePidOrError(w http.ResponseWriter, r *http.Request) peer.ID {
return pid 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{}) { func sendResponse(w http.ResponseWriter, rpcErr error, resp interface{}) {
if checkRPCErr(w, rpcErr) { if checkRPCErr(w, rpcErr) {
sendJSONResponse(w, 200, resp) sendJSONResponse(w, 200, resp)

View File

@ -232,7 +232,14 @@ func TestAPIStatusAllEndpoint(t *testing.T) {
if len(resp) != 3 || if len(resp) != 3 ||
resp[0].Cid != test.TestCid1 || resp[0].Cid != test.TestCid1 ||
resp[1].PeerMap[test.TestPeerID1.Pretty()].Status != "pinning" { 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" { if info.Status != "pinned" {
t.Error("expected different status") 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) { func TestAPISyncAllEndpoint(t *testing.T) {
@ -265,7 +287,15 @@ func TestAPISyncAllEndpoint(t *testing.T) {
if len(resp) != 3 || if len(resp) != 3 ||
resp[0].Cid != test.TestCid1 || resp[0].Cid != test.TestCid1 ||
resp[1].PeerMap[test.TestPeerID1.Pretty()].Status != "pinning" { 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" { if info.Status != "pinned" {
t.Error("expected different status") 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) { func TestAPIRecoverEndpoint(t *testing.T) {
@ -311,7 +356,7 @@ func TestAPIRecoverAllEndpoint(t *testing.T) {
rest := testAPI(t) rest := testAPI(t)
defer rest.Shutdown() defer rest.Shutdown()
var resp []api.PinInfoSerial var resp []api.GlobalPinInfoSerial
makePost(t, "/pins/recover?local=true", []byte{}, &resp) makePost(t, "/pins/recover?local=true", []byte{}, &resp)
if len(resp) != 0 { if len(resp) != 0 {

View File

@ -835,20 +835,40 @@ func (c *Cluster) StateSync() ([]api.PinInfo, error) {
return infos, nil return infos, nil
} }
// StatusAll returns the GlobalPinInfo for all tracked Cids. If an error // StatusAll returns the GlobalPinInfo for all tracked Cids in all peers.
// happens, the slice will contain as much information as could be fetched. // 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) { func (c *Cluster) StatusAll() ([]api.GlobalPinInfo, error) {
return c.globalPinInfoSlice("TrackerStatusAll") return c.globalPinInfoSlice("TrackerStatusAll")
} }
// Status returns the GlobalPinInfo for a given Cid. If an error happens, // StatusAllLocal returns the PinInfo for all the tracked Cids in this peer.
// the GlobalPinInfo should contain as much information as could be fetched. 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) { func (c *Cluster) Status(h *cid.Cid) (api.GlobalPinInfo, error) {
return c.globalPinInfoCid("TrackerStatus", h) 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 // 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 // SyncAllLocal returns the list of PinInfo that where updated because of
// the operation, along with those in error states. // the operation, along with those in error states.
@ -863,6 +883,12 @@ func (c *Cluster) SyncAllLocal() ([]api.PinInfo, error) {
return syncedItems, err 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 // 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. // tell the tracker to verify the status of the Cid against the IPFS daemon.
// It returns the updated PinInfo for the Cid. // 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 return pInfo, err
} }
// SyncAll triggers LocalSync() operations in all cluster peers. // RecoverAllLocal triggers a RecoverLocal operation for all Cids tracked
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
// by this peer. // by this peer.
func (c *Cluster) RecoverAllLocal() ([]api.PinInfo, error) { func (c *Cluster) RecoverAllLocal() ([]api.PinInfo, error) {
return c.tracker.RecoverAll() return c.tracker.RecoverAll()
@ -906,6 +916,12 @@ func (c *Cluster) Recover(h *cid.Cid) (api.GlobalPinInfo, error) {
return c.globalPinInfoCid("TrackerRecover", h) 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 // 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 // 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 // pins are managed and their allocation, but does not indicate if

View File

@ -327,16 +327,27 @@ item.
The status of a CID may not be accurate. A manual sync can be triggered The status of a CID may not be accurate. A manual sync can be triggered
with "sync". 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]", ArgsUsage: "[CID]",
Flags: []cli.Flag{parseFlag(formatGPInfo)}, Flags: []cli.Flag{
parseFlag(formatGPInfo),
localFlag(),
},
Action: func(c *cli.Context) error { Action: func(c *cli.Context) error {
local := "false"
if c.Bool("local") {
local = "true"
}
cidStr := c.Args().First() cidStr := c.Args().First()
if cidStr != "" { if cidStr != "" {
_, err := cid.Decode(cidStr) _, err := cid.Decode(cidStr)
checkErr("parsing cid", err) checkErr("parsing cid", err)
} }
resp := request("GET", "/pins/"+cidStr, nil) resp := request("GET", "/pins/"+cidStr+"?local="+local, nil)
formatResponse(c, resp) formatResponse(c, resp)
return nil 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. therefore, the output should be empty if no operations were performed.
CIDs in error state may be manually recovered with "recover". 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]", ArgsUsage: "[CID]",
Flags: []cli.Flag{parseFlag(formatGPInfo)}, Flags: []cli.Flag{
parseFlag(formatGPInfo),
localFlag(),
},
Action: func(c *cli.Context) error { Action: func(c *cli.Context) error {
local := "false"
if c.Bool("local") {
local = "true"
}
cidStr := c.Args().First() cidStr := c.Args().First()
var resp *http.Response var resp *http.Response
if cidStr != "" { if cidStr != "" {
_, err := cid.Decode(cidStr) _, err := cid.Decode(cidStr)
checkErr("parsing cid", err) checkErr("parsing cid", err)
resp = request("POST", "/pins/"+cidStr+"/sync", nil) resp = request("POST", "/pins/"+cidStr+"/sync?local="+local, nil)
} else { } else {
resp = request("POST", "/pins/sync", nil) resp = request("POST", "/pins/sync?local="+local, nil)
} }
formatResponse(c, resp) formatResponse(c, resp)
return nil 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 of the item upon completion. Note that, when running on the full sets of tracked
CIDs (without argument), it may take considerable long time. CIDs (without argument), it may take considerable long time.
A --local flag must be passed. This will only trigger recover When the --local flag is passed, it will only trigger recover
operations on the contacted peer (and not on every peer). operations on the contacted peer (as opposed to on every peer).
`, `,
ArgsUsage: "[CID]", ArgsUsage: "[CID]",
Flags: []cli.Flag{ Flags: []cli.Flag{
parseFlag(formatGPInfo), parseFlag(formatGPInfo),
cli.BoolFlag{ localFlag(),
Name: "local",
Usage: "recover only on the contacted peer",
},
}, },
Action: func(c *cli.Context) error { Action: func(c *cli.Context) error {
local := "false" local := "false"
if c.Bool("local") { if c.Bool("local") {
local = "true" local = "true"
c.Set("parseAs", fmt.Sprintf("%d", formatPInfo))
} }
cidStr := c.Args().First() cidStr := c.Args().First()
var resp *http.Response 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) { func walkCommands(cmds []cli.Command, parentHelpName string) {
for _, c := range cmds { for _, c := range cmds {
h := c.HelpName h := c.HelpName

View File

@ -108,6 +108,13 @@ func (rpcapi *RPCAPI) StatusAll(in struct{}, out *[]api.GlobalPinInfoSerial) err
return 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(). // Status runs Cluster.Status().
func (rpcapi *RPCAPI) Status(in api.PinSerial, out *api.GlobalPinInfoSerial) error { func (rpcapi *RPCAPI) Status(in api.PinSerial, out *api.GlobalPinInfoSerial) error {
c := in.ToPin().Cid c := in.ToPin().Cid
@ -116,19 +123,12 @@ func (rpcapi *RPCAPI) Status(in api.PinSerial, out *api.GlobalPinInfoSerial) err
return err return err
} }
// SyncAllLocal runs Cluster.SyncAllLocal(). // StatusLocal runs Cluster.StatusLocal().
func (rpcapi *RPCAPI) SyncAllLocal(in struct{}, out *[]api.PinInfoSerial) error { func (rpcapi *RPCAPI) StatusLocal(in api.PinSerial, 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 {
c := in.ToPin().Cid c := in.ToPin().Cid
pinfo, err := rpcapi.c.SyncLocal(c) pinfo := rpcapi.c.StatusLocal(c)
*out = pinfo.ToSerial() *out = pinfo.ToSerial()
return err return nil
} }
// SyncAll runs Cluster.SyncAll(). // SyncAll runs Cluster.SyncAll().
@ -138,6 +138,13 @@ func (rpcapi *RPCAPI) SyncAll(in struct{}, out *[]api.GlobalPinInfoSerial) error
return 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
}
// Sync runs Cluster.Sync(). // Sync runs Cluster.Sync().
func (rpcapi *RPCAPI) Sync(in api.PinSerial, out *api.GlobalPinInfoSerial) error { func (rpcapi *RPCAPI) Sync(in api.PinSerial, out *api.GlobalPinInfoSerial) error {
c := in.ToPin().Cid c := in.ToPin().Cid
@ -146,9 +153,17 @@ func (rpcapi *RPCAPI) Sync(in api.PinSerial, out *api.GlobalPinInfoSerial) error
return err return err
} }
// StateSync runs Cluster.StateSync(). // SyncLocal runs Cluster.SyncLocal().
func (rpcapi *RPCAPI) StateSync(in struct{}, out *[]api.PinInfoSerial) error { func (rpcapi *RPCAPI) SyncLocal(in api.PinSerial, out *api.PinInfoSerial) error {
pinfos, err := rpcapi.c.StateSync() 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) *out = pinInfoSliceToSerial(pinfos)
return err return err
} }
@ -169,9 +184,9 @@ func (rpcapi *RPCAPI) RecoverLocal(in api.PinSerial, out *api.PinInfoSerial) err
return err return err
} }
// RecoverAllLocal runs Cluster.RecoverAllLocal(). // StateSync runs Cluster.StateSync().
func (rpcapi *RPCAPI) RecoverAllLocal(in struct{}, out *[]api.PinInfoSerial) error { func (rpcapi *RPCAPI) StateSync(in struct{}, out *[]api.PinInfoSerial) error {
pinfos, err := rpcapi.c.RecoverAllLocal() pinfos, err := rpcapi.c.StateSync()
*out = pinInfoSliceToSerial(pinfos) *out = pinInfoSliceToSerial(pinfos)
return err return err
} }
@ -205,6 +220,13 @@ func (rpcapi *RPCAPI) TrackerStatus(in api.PinSerial, out *api.PinInfoSerial) er
return nil 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(). // TrackerRecover runs PinTracker.Recover().
func (rpcapi *RPCAPI) TrackerRecover(in api.PinSerial, out *api.PinInfoSerial) error { func (rpcapi *RPCAPI) TrackerRecover(in api.PinSerial, out *api.PinInfoSerial) error {
c := in.ToPin().Cid c := in.ToPin().Cid
@ -213,13 +235,6 @@ func (rpcapi *RPCAPI) TrackerRecover(in api.PinSerial, out *api.PinInfoSerial) e
return err 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 IPFS Connector component methods
*/ */

View File

@ -118,15 +118,6 @@ func (mock *mockService) PeerRemove(in peer.ID, out *struct{}) error {
return nil 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 { func (mock *mockService) StatusAll(in struct{}, out *[]api.GlobalPinInfoSerial) error {
c1, _ := cid.Decode(TestCid1) c1, _ := cid.Decode(TestCid1)
c2, _ := cid.Decode(TestCid2) c2, _ := cid.Decode(TestCid2)
@ -169,6 +160,10 @@ func (mock *mockService) StatusAll(in struct{}, out *[]api.GlobalPinInfoSerial)
return nil 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 { func (mock *mockService) Status(in api.PinSerial, out *api.GlobalPinInfoSerial) error {
if in.Cid == ErrorCid { if in.Cid == ErrorCid {
return ErrBadCid return ErrBadCid
@ -188,24 +183,95 @@ func (mock *mockService) Status(in api.PinSerial, out *api.GlobalPinInfoSerial)
return nil 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 { func (mock *mockService) SyncAll(in struct{}, out *[]api.GlobalPinInfoSerial) error {
return mock.StatusAll(in, out) 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 { func (mock *mockService) Sync(in api.PinSerial, out *api.GlobalPinInfoSerial) error {
return mock.Status(in, out) 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 { func (mock *mockService) StateSync(in struct{}, out *[]api.PinInfoSerial) error {
*out = make([]api.PinInfoSerial, 0, 0) *out = make([]api.PinInfoSerial, 0, 0)
return nil 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 { func (mock *mockService) Recover(in api.PinSerial, out *api.GlobalPinInfoSerial) error {
return mock.Status(in, out) return mock.Status(in, out)
} }
func (mock *mockService) RecoverLocal(in api.PinSerial, out *api.PinInfoSerial) error { 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() in2 := in.ToPin()
*out = api.PinInfo{ *out = api.PinInfo{
Cid: in2.Cid, Cid: in2.Cid,
@ -216,19 +282,6 @@ func (mock *mockService) RecoverLocal(in api.PinSerial, out *api.PinInfoSerial)
return nil 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 */ /* PeerManager methods */
func (mock *mockService) PeerManagerAddPeer(in api.MultiaddrSerial, out *struct{}) error { 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} *out = []peer.ID{TestPeerID1, TestPeerID2, TestPeerID3}
return nil 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
}