Initial implementation of path/resolver

This commit is contained in:
Jose Marcial Vieira Bisneto 2016-12-01 06:48:16 -03:00
parent 8553fcf6c1
commit a4b6a14ea5
2 changed files with 137 additions and 0 deletions

View file

@ -35,4 +35,13 @@
int ParseCidToPath (char *dst, char *txt);
int ParsePath (char *dst, char *txt);
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

128
path/resolver.c Normal file
View 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;
}