Skip to content

odb--daemon: implement get-parent and get-ancestor commands #2

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 5 commits into
base: hackweek/more-odb-over-ipc
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
112 changes: 112 additions & 0 deletions builtin/odb--daemon.c
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#include "builtin.h"
#include "config.h"
#include "object-file.h"
#include "object-name.h"
#include "object-store.h"
#include "oidmap.h"
#include "parse-options.h"
Expand Down Expand Up @@ -211,6 +212,93 @@ static int odb_ipc_cb__hash_object(struct my_odb_ipc_state *state,
return 0;
}

static int odb_ipc_cb__get_parent(struct my_odb_ipc_state *state,
const char *command, size_t command_len,
ipc_server_reply_cb *reply_cb,
struct ipc_server_reply_data *reply_data)
{
struct odb_over_ipc__get_parent__request *req;
struct odb_over_ipc__get_parent__response *resp;
const char *name;
size_t name_len;
int ret;

if (command_len < sizeof(*req))
BUG("incorrect size for binary data");

req = (struct odb_over_ipc__get_parent__request *)command;

name = command + sizeof(*req);
name_len = command_len - sizeof(*req);

if (req->name_len != name_len)
BUG("incorrect data length");

resp = xmalloc(sizeof(*resp));
memcpy(&resp->key.key, "get-parent", 11);

ret = get_parent(the_repository, name, name_len, &resp->oid, req->idx);

if (ret != FOUND)
goto fail;

reply_cb(reply_data, (const char *)resp, sizeof(*resp));

return 0;

fail:
/*
* Send the client an error response to force it to do
* the work itself.
*/
reply_cb(reply_data, "error", 6);
return 0;
}

static int odb_ipc_cb__get_ancestor(struct my_odb_ipc_state *state,
const char *command, size_t command_len,
ipc_server_reply_cb *reply_cb,
struct ipc_server_reply_data *reply_data)
{
struct odb_over_ipc__get_ancestor__request *req;
struct odb_over_ipc__get_ancestor__response *resp;
const char *name;
size_t name_len;
int ret;

if (command_len < sizeof(*req))
BUG("incorrect size for binary data");

req = (struct odb_over_ipc__get_ancestor__request *)command;

name = command + sizeof(*req);
name_len = command_len - sizeof(*req);

if (req->name_len != name_len)
BUG("incorrect data length");

resp = xmalloc(sizeof(*resp));
memcpy(&resp->key.key, "get-ancestor", 11);

ret = get_nth_ancestor(the_repository, name, name_len, &resp->oid,
req->generation);

if (ret != FOUND)
goto fail;

reply_cb(reply_data, (const char *)resp, sizeof(*resp));

return 0;

fail:
/*
* Send the client an error response to force it to do
* the work itself.
*/
reply_cb(reply_data, "error", 6);
return 0;
}

/*
* This callback handles IPC requests from clients. We run on an
* arbitrary thread.
Expand Down Expand Up @@ -277,6 +365,30 @@ static int odb_ipc_cb(void *data,
return 0;
}

if (!strcmp(command, "get-parent")) {
/*
* A client has requested that we find the parent of a given
* object.
*/
trace2_region_enter("odb-daemon", "get-parent", NULL);
ret = odb_ipc_cb__get_parent(state, command, command_len,
reply_cb, reply_data);
trace2_region_leave("odb-daemon", "get-parent", NULL);
return 0;
}

if (!strcmp(command, "get-ancestor")) {
/*
* A client has requested that we find the nth ancestpr of a
* given object.
*/
trace2_region_enter("odb-daemon", "get-nth-ancestor", NULL);
ret = odb_ipc_cb__get_ancestor(state, command, command_len,
reply_cb, reply_data);
trace2_region_leave("odb-daemon", "get-nth-ancestor", NULL);
return 0;
}

// TODO respond to other requests from client.
//
// TODO decide how to return an error for unknown commands.
Expand Down
26 changes: 17 additions & 9 deletions object-name.c
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
#include "commit-reach.h"
#include "date.h"
#include "object-file-convert.h"
#include "odb-over-ipc.h"

static int get_oid_oneline(struct repository *r, const char *, struct object_id *, struct commit_list *);

Expand Down Expand Up @@ -1081,18 +1082,22 @@ static int get_oid_basic(struct repository *r, const char *str, int len,
return 0;
}

static enum get_oid_result get_parent(struct repository *r,
const char *name, int len,
struct object_id *result, int idx)
enum get_oid_result get_parent(struct repository *r,
const char *name, int len,
struct object_id *result, int idx)
{
struct object_id oid;
enum get_oid_result ret = get_oid_1(r, name, len, &oid,
GET_OID_COMMITTISH);
enum get_oid_result ret;
struct commit *commit;
struct commit_list *p;

if (odb_over_ipc__get_parent(r, name, len, idx, result) == 0)
return FOUND;

ret = get_oid_1(r, name, len, &oid, GET_OID_COMMITTISH);
if (ret)
return ret;

commit = lookup_commit_reference(r, &oid);
if (repo_parse_commit(r, commit))
return MISSING_OBJECT;
Expand All @@ -1111,15 +1116,18 @@ static enum get_oid_result get_parent(struct repository *r,
return MISSING_OBJECT;
}

static enum get_oid_result get_nth_ancestor(struct repository *r,
const char *name, int len,
struct object_id *result,
int generation)
enum get_oid_result get_nth_ancestor(struct repository *r,
const char *name, int len,
struct object_id *result,
int generation)
{
struct object_id oid;
struct commit *commit;
int ret;

if (odb_over_ipc__get_ancestor(r, name, len, generation, result) == 0)
return FOUND;

ret = get_oid_1(r, name, len, &oid, GET_OID_COMMITTISH);
if (ret)
return ret;
Expand Down
9 changes: 9 additions & 0 deletions object-name.h
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,15 @@ struct object *repo_peel_to_type(struct repository *r,
const char *name, int namelen,
struct object *o, enum object_type);

enum get_oid_result get_parent(struct repository *r,
const char *name, int len,
struct object_id *result, int idx);

enum get_oid_result get_nth_ancestor(struct repository *r,
const char *name, int len,
struct object_id *result,
int generation);

/* Convert to/from hex/sha1 representation */
#define MINIMUM_ABBREV minimum_abbrev
#define DEFAULT_ABBREV default_abbrev
Expand Down
95 changes: 95 additions & 0 deletions odb-over-ipc.c
Original file line number Diff line number Diff line change
Expand Up @@ -264,4 +264,99 @@ int odb_over_ipc__hash_object(struct repository *r, struct object_id *oid,
return ret;
}

int odb_over_ipc__get_parent(struct repository *r, const char *name, int len,
int idx, struct object_id *result)
{
struct odb_over_ipc__get_parent__request req;
struct odb_over_ipc__get_parent__response *resp;
struct strbuf msg = STRBUF_INIT;
struct strbuf answer = STRBUF_INIT;
int ret;

if (is_daemon)
return -1;

if (!core_use_odb_over_ipc)
return -1;

if (r != the_repository) // TODO not dealing with this
return -1;

memset(&req, 0, sizeof(req));
memcpy(req.key.key, "get-parent", 10);
req.idx = idx;
req.name_len = len;

/* Append the name at the end of the request */
strbuf_init(&msg, sizeof(req) + len);
strbuf_add(&msg, &req, sizeof(req));
strbuf_add(&msg, name, len);

ret = odb_over_ipc__command((const char *)msg.buf, msg.len, &answer);
if (ret)
return ret;

if (!strncmp(answer.buf, "error", 5)) {
trace2_printf("odb-over-ipc: failed");
return -1;
}

if (answer.len != sizeof(*resp))
BUG("incorrect size for binary data");
resp = (struct odb_over_ipc__get_parent__response *)answer.buf;

oidcpy(result, &resp->oid);

strbuf_release(&answer);
return ret;
}

int odb_over_ipc__get_ancestor(struct repository *r, const char *name,
int len, int generation,
struct object_id *result)
{
struct odb_over_ipc__get_ancestor__request req;
struct odb_over_ipc__get_ancestor__response *resp;
struct strbuf msg = STRBUF_INIT;
struct strbuf answer = STRBUF_INIT;
int ret;

if (is_daemon)
return -1;

if (!core_use_odb_over_ipc)
return -1;

if (r != the_repository) // TODO not dealing with this
return -1;

memset(&req, 0, sizeof(req));
memcpy(req.key.key, "get-ancestor", 12);
req.generation = generation;
req.name_len = len;

/* Append the name at the end of the request */
strbuf_init(&msg, sizeof(req) + len);
strbuf_add(&msg, &req, sizeof(req));
strbuf_add(&msg, name, len);

ret = odb_over_ipc__command((const char *)msg.buf, msg.len, &answer);
if (ret)
return ret;

if (!strncmp(answer.buf, "error", 5)) {
trace2_printf("odb-over-ipc: failed");
return -1;
}

if (answer.len != sizeof(*resp))
BUG("incorrect size for binary data");
resp = (struct odb_over_ipc__get_ancestor__response *)answer.buf;

oidcpy(result, &resp->oid);

strbuf_release(&answer);
return ret;
}

#endif /* SUPPORTS_SIMPLE_IPC */
33 changes: 33 additions & 0 deletions odb-over-ipc.h
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,32 @@ struct odb_over_ipc__hash_object__response
struct object_id oid;
};

struct odb_over_ipc__get_parent__request
{
struct odb_over_ipc__key key;
int idx;
int name_len;
};

struct odb_over_ipc__get_parent__response
{
struct odb_over_ipc__key key;
struct object_id oid;
};

struct odb_over_ipc__get_ancestor__request
{
struct odb_over_ipc__key key;
int generation;
int name_len;
};

struct odb_over_ipc__get_ancestor__response
{
struct odb_over_ipc__key key;
struct object_id oid;
};

/*
* Connect to an existing `git odb--daemon` process and ask it for
* an object. This is intended to be inserted into the client
Expand All @@ -100,6 +126,13 @@ int odb_over_ipc__get_oid(struct repository *r, const struct object_id *oid,
int odb_over_ipc__hash_object(struct repository *r, struct object_id *oid,
int fd, enum object_type type, unsigned flags);

int odb_over_ipc__get_parent(struct repository *r, const char *name, int len,
int idx, struct object_id *result);

int odb_over_ipc__get_ancestor(struct repository *r, const char *name,
int len, int generation,
struct object_id *result);

/*
* Explicitly shutdown IPC connection to the `git odb--daemon` process.
* The connection is implicitly created upon the first request and we
Expand Down
Loading