--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/cache_test.c Sat Aug 09 01:00:35 2008 +0300
@@ -0,0 +1,391 @@
+#include <unistd.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include "cache.h"
+#include "cache_engines.h"
+#include "common.h"
+
+#define LINE_LENGTH 1024
+#define REQ_COUNT 8
+
+static struct cache *cache = NULL;
+static struct cache_engine *fs_engine = NULL;
+static struct cache_req_ctx {
+ struct cache_req *req;
+ int index;
+
+ int pipe_read;
+ int pipe_write;
+
+} req_list[REQ_COUNT];
+static int quit = 0;
+
+void usage (char *argv_0) {
+ err_exit("Usage: %s [-h] <cache_dir>", argv_0);
+}
+
+const char *cache_state_str (enum cache_req_state state) {
+ switch (state) {
+ case CACHE_STATE_INVALID: return "INVALID";
+ case CACHE_STATE_LOOKUP: return "LOOKUP";
+ case CACHE_STATE_READ_BEGIN: return "READ_BEGIN";
+ case CACHE_STATE_WRITE_BEGIN: return "WRITE_BEGIN";
+ case CACHE_STATE_WRITE: return "WRITE";
+ case CACHE_STATE_WRITE_PAUSE: return "WRITE_PAUSE";
+ case CACHE_STATE_READ: return "READ";
+ case CACHE_STATE_DONE: return "DONE";
+ case CACHE_STATE_ERROR: return "ERROR";
+ default: return "???";
+ }
+}
+/*
+const char *cache_event_str (enum cache_req_event event) {
+ switch (event) {
+ case CACHE_EVENT_HIT: return "HIT";
+ case CACHE_EVENT_MISS: return "MISS";
+ case CACHE_EVENT_BEGIN_WRITE: return "BEGIN_WRITE";
+ case CACHE_EVENT_BEGIN_READ: return "BEGIN_READ";
+ case CACHE_EVENT_PAUSE_WRITE: return "PAUSE_WRITE";
+ case CACHE_EVENT_RESUME_WRITE: return "RESUME_WRITE";
+ case CACHE_EVENT_DATA_AVAILABLE:return "DATA_AVAILABLE";
+ case CACHE_EVENT_DONE: return "DONE";
+ case CACHE_EVENT_ERROR: return "ERROR";
+ default: return "???";
+ }
+}
+*/
+
+//int cache_cb (struct cache_req *req, enum cache_req_event event, void *arg) {
+int cache_cb (struct cache_req *req, void *arg) {
+ struct cache_req_ctx *ctx = arg;
+
+ const struct cache_key *key = cache_req_key(ctx->req);
+
+ INFO("Request %d (%*s) event: state = %s",
+ ctx->index,
+ (int) key->length, key->buf,
+ cache_state_str(cache_req_state(req))
+ );
+
+ return 0;
+}
+
+void cmd_help (int index, char *cmd_name);
+void cmd_quit (int index, char *cmd_name);
+void cmd_req (int index, char *key_buf);
+void cmd_status (int index, char *key);
+void cmd_available (int index, char *unused);
+void cmd_write (int index, char *unused);
+void cmd_push (int index, char *data);
+void cmd_done (int index, char *unused);
+void cmd_release (int index, char *unused);
+
+struct cmd {
+ char *name;
+ void (*func)(int index, char *str);
+ char *usage;
+
+} _commands[] = {
+ { "quit", &cmd_quit, "quit" },
+ { "help", &cmd_help, "help [<ignored> <cmd>]" },
+ { "req", &cmd_req, "req <req_id> <key>" },
+ { "status", &cmd_status, "status <req_id>" },
+ { "available",&cmd_available, "available <req_id>" },
+ { "write", &cmd_write, "write <req_id> [<size_hint>]" },
+ { "push", &cmd_push, "push <req_id> <data>" },
+ { "done", &cmd_done, "done <req_id>" },
+ { "release", &cmd_release, "release <req_id>" },
+ { NULL, NULL, NULL }
+};
+
+
+void cmd_help (int index, char *cmd_name) {
+ struct cmd *cmd;
+
+ if (cmd_name == NULL) {
+ printf("Available commands: ");
+
+ for (cmd = _commands; cmd->func != NULL; cmd++) {
+ printf("%s ", cmd->name);
+ }
+
+ printf("\n");
+
+ } else {
+ for (cmd = _commands; cmd->func != NULL; cmd++) {
+ if (strcmp(cmd->name, cmd_name) == 0)
+ break;
+ }
+
+ if (cmd->func) {
+ INFO("%s", cmd->usage);
+
+ } else {
+ ERROR("Unknown command: '%s'", cmd_name);
+ }
+ }
+
+error:
+ return;
+}
+
+void cmd_quit (int index, char *cmd_name) {
+ quit = 1;
+}
+
+void cmd_req (int index, char *key_buf) {
+ struct cache_key key;
+
+ if (index < 0 || index >= REQ_COUNT)
+ ERROR("index is out of range");
+
+ if (!key_buf)
+ ERROR("No key given");
+
+ key.buf = key_buf;
+ key.length = 0;
+
+ if ((req_list[index].req = cache_req(cache, &key, &cache_cb, &req_list[index])) == NULL)
+ ERROR("req_list failed");
+
+ INFO("Request opened: %s", cache_state_str(cache_req_state(req_list[index].req)));
+
+error:
+ return;
+}
+
+void cmd_status (int index, char *unused) {
+ const struct cache_key *key;
+
+ if (index < 0 || index >= REQ_COUNT)
+ ERROR("index is out of range");
+
+ if (unused)
+ ERROR("Too many arguments");
+
+ key = cache_req_key(req_list[index].req);
+
+ INFO("Request %d (%*s) status: %s", index, (int) key->length, key->buf, cache_state_str(cache_req_state(req_list[index].req)));
+
+error:
+ return;
+
+}
+
+void cmd_available (int index, char *unused) {
+ const struct cache_key *key;
+ size_t size, offset, available;
+
+ if (index < 0 || index >= REQ_COUNT)
+ ERROR("index is out of range");
+
+ if (unused)
+ ERROR("Too many arguments");
+
+ key = cache_req_key(req_list[index].req);
+
+ if (cache_req_available(req_list[index].req, &size, &offset, &available))
+ ERROR("cache_req_available failed");
+
+ INFO("Request %d (%*s) available: %zu/%zu, %zu to read",
+ index,
+ (int) key->length, key->buf,
+ offset, size, available
+ );
+
+error:
+ return;
+
+}
+
+
+void cmd_write (int index, char *hint_str) {
+ size_t hint;
+
+ const struct cache_key *key;
+
+ if (index < 0 || index >= REQ_COUNT)
+ ERROR("index is out of range");
+
+ if (hint_str)
+ hint = atoi(hint_str);
+ else
+ hint = 0;
+
+ key = cache_req_key(req_list[index].req);
+
+ INFO("Request %d (%*s): beginning write",
+ index, (int) key->length, key->buf
+ );
+
+ if (cache_req_begin_write(req_list[index].req, hint))
+ ERROR("cache_req_begin_write failed");
+
+error:
+ return;
+}
+
+void cmd_push (int index, char *data) {
+ size_t data_length, length;
+ const struct cache_key *key;
+
+ data_length = data ? strlen(data) : 0;
+
+ if (data) {
+ // write to the pipe
+ if ((length = write(req_list[index].pipe_write, data, data_length)) == -1)
+ PERROR("write");
+
+ if (length != data_length)
+ PWARNING("Only %zu/%zu bytes written to pipe!", length, data_length);
+ }
+
+ // unknown size
+ length = 0;
+
+ key = cache_req_key(req_list[index].req);
+
+ if (cache_req_push(req_list[index].req, req_list[index].pipe_read, &length))
+ ERROR("cache_req_push failed");
+
+ INFO("Request %d (%*s): pushed %zu/%zu bytes",
+ index, (int) key->length, key->buf,
+ length, data_length
+ );
+
+error:
+ return;
+}
+
+void cmd_done (int index, char *unused) {
+ const struct cache_key *key;
+
+ key = cache_req_key(req_list[index].req);
+
+ if (cache_req_done(req_list[index].req))
+ ERROR("cache_req_done failed");
+
+ INFO("Request %d (%*s): done",
+ index, (int) key->length, key->buf
+ );
+
+error:
+ return;
+}
+
+void cmd_release (int index, char *unused) {
+ const struct cache_key *key;
+
+ key = cache_req_key(req_list[index].req);
+
+ cache_req_release(req_list[index].req);
+
+ INFO("Request %d (%*s): released",
+ index, (int) key->length, key->buf
+ );
+
+ req_list[index].req = NULL;
+}
+
+int main (int argc, char **argv) {
+ int pipefds[2];
+ char line[LINE_LENGTH];
+
+ // init req_list
+ for (int index = 0; index < REQ_COUNT; index++) {
+ req_list[index].index = index;
+
+ if (pipe(pipefds))
+ PFATAL("pipe");
+
+ req_list[index].pipe_read = pipefds[0];
+ req_list[index].pipe_write = pipefds[1];
+ }
+
+ // parse arguments
+ int opt;
+ char *cache_dir;
+
+ while ((opt = getopt(argc, argv, "h")) != -1) {
+ switch (opt) {
+
+ case 'h':
+ default:
+ usage(argv[0]);
+ }
+ }
+
+ // the cache_dir argument
+ if (optind >= argc)
+ usage(argv[0]);
+
+ cache_dir = argv[optind];
+
+ // create the fs_engine
+ if ((fs_engine = cache_engine_fs(cache_dir)) == NULL)
+ FATAL("failed to initialize fs cache engine");
+
+ // create the cache
+ if ((cache = cache_open(fs_engine)) == NULL)
+ FATAL("failed to open the cache");
+
+ INFO("Filesystem cache opened at '%s'", cache_dir);
+
+ // enter the interactive loop
+ do {
+ printf(" > ");
+
+
+ if (fgets(line, LINE_LENGTH, stdin) == NULL)
+ quit = 1;
+ else {
+ char *line_ptr = line;
+ char *cmd_name = NULL, *str = NULL, *nl = NULL;
+ int index = 0;
+
+ // strip the newline
+ if ((nl = strchr(line, '\n')) != NULL)
+ *nl = '\0';
+
+ // parse the command/args
+ if (line_ptr)
+ cmd_name = strsep(&line_ptr, " ");
+
+ if (strlen(cmd_name) == 0)
+ cmd_name = NULL;
+
+ if (line_ptr)
+ index = atoi(strsep(&line_ptr, " "));
+
+ if (line_ptr)
+ str = strsep(&line_ptr, " ");
+
+ if (!cmd_name) {
+ continue;
+ }
+
+ struct cmd *cmd;
+
+ for (cmd = _commands; cmd->func != NULL; cmd++) {
+ if (strcmp(cmd->name, cmd_name) == 0)
+ break;
+ }
+
+ if (!cmd->func) {
+ INFO("Unknown command");
+
+ continue;
+ }
+
+ cmd->func(index, str);
+ }
+
+ printf("\n");
+
+ } while (!quit);
+
+ return 0;
+}
+