Initial implementation of path/resolver
This commit is contained in:
parent
8553fcf6c1
commit
a4b6a14ea5
2 changed files with 137 additions and 0 deletions
|
@ -35,4 +35,13 @@
|
||||||
int ParseCidToPath (char *dst, char *txt);
|
int ParseCidToPath (char *dst, char *txt);
|
||||||
int ParsePath (char *dst, char *txt);
|
int ParsePath (char *dst, char *txt);
|
||||||
int PathIsValid (char *p);
|
int PathIsValid (char *p);
|
||||||
|
|
||||||
|
// Resolver provides path resolution to IPFS
|
||||||
|
// It has a pointer to a DAGService, which is uses to resolve nodes.
|
||||||
|
// TODO: now that this is more modular, try to unify this code with the
|
||||||
|
// the resolvers in namesys
|
||||||
|
typedef struct s_resolver {
|
||||||
|
DAGService DAG;
|
||||||
|
int (*ResolveOnce)(NodeLink **lnk, Context ctx, DAGService *ds, Node **nd, char *name);
|
||||||
|
} Resolver;
|
||||||
#endif // IPFS_PATH_H
|
#endif // IPFS_PATH_H
|
||||||
|
|
128
path/resolver.c
Normal file
128
path/resolver.c
Normal file
|
@ -0,0 +1,128 @@
|
||||||
|
#include "ipfs/cid/cid.h"
|
||||||
|
#include "ipfs/path/path.h"
|
||||||
|
|
||||||
|
Resolver* NewBasicResolver (DAGService *ds)
|
||||||
|
{
|
||||||
|
Resolver *ret = malloc(sizeof(Resolver));
|
||||||
|
if (!ret) return NULL;
|
||||||
|
ret->DAG = ds;
|
||||||
|
ret->ResolveOnce = ResolveSingle;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
// SplitAbsPath clean up and split fpath. It extracts the first component (which
|
||||||
|
// must be a Multihash) and return it separately.
|
||||||
|
int SplitAbsPath (struct Cid* cid, char ***parts, char *fpath)
|
||||||
|
{
|
||||||
|
*parts = Segments(fpath);
|
||||||
|
|
||||||
|
if (strcmp (**parts, "ipfs") == 0) *parts++;
|
||||||
|
|
||||||
|
// if nothing, bail.
|
||||||
|
if (!**parts) return ErrNoComponents;
|
||||||
|
|
||||||
|
// first element in the path is a cid
|
||||||
|
cid_decode_from_string(**parts, strlen(**parts), cid);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ResolvePath fetches the node for given path. It returns the last item
|
||||||
|
// returned by ResolvePathComponents.
|
||||||
|
int ResolvePath(Node **nd, Context ctx, Resolver *s, char *fpath)
|
||||||
|
{
|
||||||
|
int err = IsValid(fpath);
|
||||||
|
Node **ndd;
|
||||||
|
|
||||||
|
if (err) {
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
err = ResolvePathComponents(&ndd, ctx, s, fpath);
|
||||||
|
if (err) {
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
if (ndd == NULL) {
|
||||||
|
return ErrBadPath;
|
||||||
|
}
|
||||||
|
while(*ndd) {
|
||||||
|
*nd = *ndd;
|
||||||
|
ndd++;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int ResolveSingle(NodeLink **lnk, Context ctx, DAGService *ds, Node **nd, char *name)
|
||||||
|
{
|
||||||
|
return ResolveLink(lnk, name);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ResolvePathComponents fetches the nodes for each segment of the given path.
|
||||||
|
// It uses the first path component as a hash (key) of the first node, then
|
||||||
|
// resolves all other components walking the links, with ResolveLinks.
|
||||||
|
int ResolvePathComponents(Node ***nd, Context ctx, Resolver *s, char *fpath)
|
||||||
|
{
|
||||||
|
int err;
|
||||||
|
struct Cid h;
|
||||||
|
char **parts;
|
||||||
|
|
||||||
|
err = SplitAbsPath(&h, &parts, fpath);
|
||||||
|
if (err) {
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
//log.Debug("resolve dag get");
|
||||||
|
//*nd = s->DAG.Get(ctx, h);
|
||||||
|
//if (nd == DAG_ERR_VAL) {
|
||||||
|
// return DAG_ERR_VAL;
|
||||||
|
//}
|
||||||
|
|
||||||
|
return ResolveLinks(ctx, *nd, parts);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ResolveLinks iteratively resolves names by walking the link hierarchy.
|
||||||
|
// Every node is fetched from the DAGService, resolving the next name.
|
||||||
|
// Returns the list of nodes forming the path, starting with ndd. This list is
|
||||||
|
// guaranteed never to be empty.
|
||||||
|
//
|
||||||
|
// ResolveLinks(nd, []string{"foo", "bar", "baz"})
|
||||||
|
// would retrieve "baz" in ("bar" in ("foo" in nd.Links).Links).Links
|
||||||
|
int ResolveLinks(Node ***result, Context ctx, Node *ndd, char **names)
|
||||||
|
{
|
||||||
|
int err, idx = 0;
|
||||||
|
NodeLink *lnk;
|
||||||
|
Node *nd;
|
||||||
|
|
||||||
|
*result = calloc (sizeof(Node*), SegmentsLength(names) + 1);
|
||||||
|
if (!*result) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
memset (*result, NULL, sizeof(Node*) * (SegmentsLength(names)+1));
|
||||||
|
|
||||||
|
*result[idx++] = ndd;
|
||||||
|
nd = ndd; // dup arg workaround
|
||||||
|
|
||||||
|
while (*names) {
|
||||||
|
//TODO
|
||||||
|
//var cancel context.CancelFunc
|
||||||
|
//ctx, cancel = context.WithTimeout(ctx, time.Minute)
|
||||||
|
//defer cancel()
|
||||||
|
|
||||||
|
// for each of the path components
|
||||||
|
err = ResolveLink(&lnk, *names);
|
||||||
|
if (err) {
|
||||||
|
char msg[51];
|
||||||
|
*result[idx] = NULL;
|
||||||
|
snprintf(msg, sizeof(msg), ErrPath[ErrNoLinkFmt], *names, nd->Cid);
|
||||||
|
if (ErrPath[ErrNoLink]) {
|
||||||
|
free(ErrPath[ErrNoLink]);
|
||||||
|
}
|
||||||
|
ErrPath[ErrNoLink] = malloc(strlen(msg) + 1);
|
||||||
|
if (ErrPath[ErrNoLink]) {
|
||||||
|
strcpy(ErrPath[ErrNoLink], msg);
|
||||||
|
}
|
||||||
|
free (*result);
|
||||||
|
return ErrNoLink;
|
||||||
|
}
|
||||||
|
names++;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
Loading…
Reference in a new issue