Merge pull request #1516 from ipfs-cluster/crdtdot
Allow exporting CRDT dag to dot files with: "ipfs-cluster-service state crdt dot"
This commit is contained in:
commit
b80f89dd01
|
@ -24,10 +24,10 @@ import (
|
||||||
"go.opencensus.io/tag"
|
"go.opencensus.io/tag"
|
||||||
|
|
||||||
ds "github.com/ipfs/go-datastore"
|
ds "github.com/ipfs/go-datastore"
|
||||||
host "github.com/libp2p/go-libp2p/core/host"
|
|
||||||
peer "github.com/libp2p/go-libp2p/core/peer"
|
|
||||||
dual "github.com/libp2p/go-libp2p-kad-dht/dual"
|
dual "github.com/libp2p/go-libp2p-kad-dht/dual"
|
||||||
pubsub "github.com/libp2p/go-libp2p-pubsub"
|
pubsub "github.com/libp2p/go-libp2p-pubsub"
|
||||||
|
host "github.com/libp2p/go-libp2p/core/host"
|
||||||
|
peer "github.com/libp2p/go-libp2p/core/peer"
|
||||||
|
|
||||||
ma "github.com/multiformats/go-multiaddr"
|
ma "github.com/multiformats/go-multiaddr"
|
||||||
|
|
||||||
|
|
|
@ -12,15 +12,20 @@ import (
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
ipfslite "github.com/hsanjuan/ipfs-lite"
|
||||||
ipfscluster "github.com/ipfs-cluster/ipfs-cluster"
|
ipfscluster "github.com/ipfs-cluster/ipfs-cluster"
|
||||||
"github.com/ipfs-cluster/ipfs-cluster/api"
|
"github.com/ipfs-cluster/ipfs-cluster/api"
|
||||||
"github.com/ipfs-cluster/ipfs-cluster/cmdutils"
|
"github.com/ipfs-cluster/ipfs-cluster/cmdutils"
|
||||||
|
"github.com/ipfs-cluster/ipfs-cluster/consensus/crdt"
|
||||||
"github.com/ipfs-cluster/ipfs-cluster/pstoremgr"
|
"github.com/ipfs-cluster/ipfs-cluster/pstoremgr"
|
||||||
"github.com/ipfs-cluster/ipfs-cluster/version"
|
"github.com/ipfs-cluster/ipfs-cluster/version"
|
||||||
peer "github.com/libp2p/go-libp2p/core/peer"
|
peer "github.com/libp2p/go-libp2p/core/peer"
|
||||||
ma "github.com/multiformats/go-multiaddr"
|
ma "github.com/multiformats/go-multiaddr"
|
||||||
|
|
||||||
semver "github.com/blang/semver"
|
semver "github.com/blang/semver"
|
||||||
|
"github.com/ipfs/go-datastore"
|
||||||
|
"github.com/ipfs/go-datastore/namespace"
|
||||||
|
dscrdt "github.com/ipfs/go-ds-crdt"
|
||||||
logging "github.com/ipfs/go-log/v2"
|
logging "github.com/ipfs/go-log/v2"
|
||||||
cli "github.com/urfave/cli"
|
cli "github.com/urfave/cli"
|
||||||
)
|
)
|
||||||
|
@ -452,8 +457,114 @@ the peer IDs in the given multiaddresses.
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Name: "state",
|
Name: "state",
|
||||||
Usage: "Manages the peer's consensus state (pinset)",
|
Usage: "Manages the peer's persistent state (pinset)",
|
||||||
Subcommands: []cli.Command{
|
Subcommands: []cli.Command{
|
||||||
|
{
|
||||||
|
Name: "crdt",
|
||||||
|
Usage: "CRDT-state commands",
|
||||||
|
Before: func(c *cli.Context) error {
|
||||||
|
// Load all the configurations and identity
|
||||||
|
cfgHelper, err := cmdutils.NewLoadedConfigHelper(configPath, identityPath)
|
||||||
|
cfgs := cfgHelper.Configs()
|
||||||
|
checkErr("loading configurations", err)
|
||||||
|
defer cfgHelper.Manager().Shutdown()
|
||||||
|
|
||||||
|
if cfgHelper.GetConsensus() != cfgs.Crdt.ConfigKey() {
|
||||||
|
checkErr("", errors.New("crdt subcommands can only be run on peers initialized with crdt consensus"))
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
},
|
||||||
|
|
||||||
|
Subcommands: []cli.Command{
|
||||||
|
{
|
||||||
|
Name: "dot",
|
||||||
|
Usage: "Write the CRDT-DAG as DOT file",
|
||||||
|
Description: `
|
||||||
|
This command generates a DOT file representing the CRDT-DAG of this node.
|
||||||
|
The DOT file can then be visualized, converted to SVG etc.
|
||||||
|
|
||||||
|
This is a debugging command to visualize how the DAG looks like, whether there
|
||||||
|
is a lot of branching etc. large DAGs will generate large DOT files.
|
||||||
|
Use with caution!
|
||||||
|
`,
|
||||||
|
Flags: []cli.Flag{
|
||||||
|
cli.StringFlag{
|
||||||
|
Name: "file, f",
|
||||||
|
Value: "",
|
||||||
|
Usage: "writes to file instead of stdout",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Action: func(c *cli.Context) error {
|
||||||
|
locker.lock()
|
||||||
|
defer locker.tryUnlock()
|
||||||
|
|
||||||
|
// Load all the configurations and identity
|
||||||
|
cfgHelper, err := cmdutils.NewLoadedConfigHelper(configPath, identityPath)
|
||||||
|
checkErr("loading configurations", err)
|
||||||
|
defer cfgHelper.Manager().Shutdown()
|
||||||
|
|
||||||
|
// Get a state manager and the datastore
|
||||||
|
mgr, err := cmdutils.NewStateManagerWithHelper(cfgHelper)
|
||||||
|
checkErr("creating state manager", err)
|
||||||
|
store, err := mgr.GetStore()
|
||||||
|
checkErr("opening datastore", err)
|
||||||
|
batching, ok := store.(datastore.Batching)
|
||||||
|
if !ok {
|
||||||
|
checkErr("", errors.New("no batching store"))
|
||||||
|
}
|
||||||
|
|
||||||
|
crdtNs := cfgHelper.Configs().Crdt.DatastoreNamespace
|
||||||
|
|
||||||
|
var blocksDatastore datastore.Batching = namespace.Wrap(
|
||||||
|
batching,
|
||||||
|
datastore.NewKey(crdtNs).ChildString(crdt.BlocksNs),
|
||||||
|
)
|
||||||
|
|
||||||
|
ipfs, err := ipfslite.New(
|
||||||
|
context.Background(),
|
||||||
|
blocksDatastore,
|
||||||
|
nil,
|
||||||
|
nil,
|
||||||
|
&ipfslite.Config{
|
||||||
|
Offline: true,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
checkErr("creating ipfs-lite offline node", err)
|
||||||
|
|
||||||
|
opts := dscrdt.DefaultOptions()
|
||||||
|
crdt, err := dscrdt.New(
|
||||||
|
batching,
|
||||||
|
datastore.NewKey(crdtNs),
|
||||||
|
ipfs,
|
||||||
|
nil,
|
||||||
|
opts,
|
||||||
|
)
|
||||||
|
checkErr("creating crdt node", err)
|
||||||
|
|
||||||
|
var w io.WriteCloser
|
||||||
|
outputPath := c.String("file")
|
||||||
|
if outputPath == "" {
|
||||||
|
// Output to stdout
|
||||||
|
w = os.Stdout
|
||||||
|
} else {
|
||||||
|
// Create the export file
|
||||||
|
w, err = os.Create(outputPath)
|
||||||
|
checkErr("creating output file", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 256KiB of buffer size.
|
||||||
|
buf := bufio.NewWriterSize(w, 1<<18)
|
||||||
|
defer buf.Flush()
|
||||||
|
|
||||||
|
logger.Info("initiating CDRT-DAG DOT file export. Export might take a long time on large graphs")
|
||||||
|
checkErr("generating graph", crdt.DotDAG(buf))
|
||||||
|
logger.Info("dot file ")
|
||||||
|
return nil
|
||||||
|
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
{
|
{
|
||||||
Name: "export",
|
Name: "export",
|
||||||
Usage: "save the state to a JSON file",
|
Usage: "save the state to a JSON file",
|
||||||
|
@ -572,7 +683,7 @@ to import. If no argument is provided, stdin will be used.
|
||||||
Usage: "remove persistent data",
|
Usage: "remove persistent data",
|
||||||
Description: `
|
Description: `
|
||||||
This command removes any persisted consensus data in this peer, including the
|
This command removes any persisted consensus data in this peer, including the
|
||||||
current pinset (state). The next start of the peer will be like the first start
|
current pinset (state). The next start of the peer will be like a first start
|
||||||
to all effects. Peers may need to bootstrap and sync from scratch after this.
|
to all effects. Peers may need to bootstrap and sync from scratch after this.
|
||||||
`,
|
`,
|
||||||
Flags: []cli.Flag{
|
Flags: []cli.Flag{
|
||||||
|
|
|
@ -21,12 +21,12 @@ import (
|
||||||
crdt "github.com/ipfs/go-ds-crdt"
|
crdt "github.com/ipfs/go-ds-crdt"
|
||||||
dshelp "github.com/ipfs/go-ipfs-ds-help"
|
dshelp "github.com/ipfs/go-ipfs-ds-help"
|
||||||
logging "github.com/ipfs/go-log/v2"
|
logging "github.com/ipfs/go-log/v2"
|
||||||
|
rpc "github.com/libp2p/go-libp2p-gorpc"
|
||||||
|
pubsub "github.com/libp2p/go-libp2p-pubsub"
|
||||||
host "github.com/libp2p/go-libp2p/core/host"
|
host "github.com/libp2p/go-libp2p/core/host"
|
||||||
peer "github.com/libp2p/go-libp2p/core/peer"
|
peer "github.com/libp2p/go-libp2p/core/peer"
|
||||||
peerstore "github.com/libp2p/go-libp2p/core/peerstore"
|
peerstore "github.com/libp2p/go-libp2p/core/peerstore"
|
||||||
"github.com/libp2p/go-libp2p/core/routing"
|
"github.com/libp2p/go-libp2p/core/routing"
|
||||||
rpc "github.com/libp2p/go-libp2p-gorpc"
|
|
||||||
pubsub "github.com/libp2p/go-libp2p-pubsub"
|
|
||||||
multihash "github.com/multiformats/go-multihash"
|
multihash "github.com/multiformats/go-multihash"
|
||||||
|
|
||||||
ipfslite "github.com/hsanjuan/ipfs-lite"
|
ipfslite "github.com/hsanjuan/ipfs-lite"
|
||||||
|
@ -36,7 +36,8 @@ import (
|
||||||
var logger = logging.Logger("crdt")
|
var logger = logging.Logger("crdt")
|
||||||
|
|
||||||
var (
|
var (
|
||||||
blocksNs = "b" // blockstore namespace
|
// BlocksNs is the namespace to use as blockstore with ipfs-lite.
|
||||||
|
BlocksNs = "b"
|
||||||
connMgrTag = "crdt"
|
connMgrTag = "crdt"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -115,7 +116,7 @@ func New(
|
||||||
|
|
||||||
var blocksDatastore ds.Batching
|
var blocksDatastore ds.Batching
|
||||||
ns := ds.NewKey(cfg.DatastoreNamespace)
|
ns := ds.NewKey(cfg.DatastoreNamespace)
|
||||||
blocksDatastore = namespace.Wrap(store, ns.ChildString(blocksNs))
|
blocksDatastore = namespace.Wrap(store, ns.ChildString(BlocksNs))
|
||||||
|
|
||||||
ipfs, err := ipfslite.New(
|
ipfs, err := ipfslite.New(
|
||||||
ctx,
|
ctx,
|
||||||
|
@ -706,7 +707,7 @@ func OfflineState(cfg *Config, store ds.Datastore) (state.BatchingState, error)
|
||||||
|
|
||||||
var blocksDatastore ds.Batching = namespace.Wrap(
|
var blocksDatastore ds.Batching = namespace.Wrap(
|
||||||
batching,
|
batching,
|
||||||
ds.NewKey(cfg.DatastoreNamespace).ChildString(blocksNs),
|
ds.NewKey(cfg.DatastoreNamespace).ChildString(BlocksNs),
|
||||||
)
|
)
|
||||||
|
|
||||||
ipfs, err := ipfslite.New(
|
ipfs, err := ipfslite.New(
|
||||||
|
|
Loading…
Reference in New Issue
Block a user