summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTavian Barnes <tavianator@tavianator.com>2019-03-06 22:25:56 -0800
committerTavian Barnes <tavianator@tavianator.com>2019-03-06 22:25:56 -0800
commitb1d0e0e97ce747534a945a6fe0c3a15ccd8dbf00 (patch)
tree57b2f054611114783e7499996e730611691f94ff
parentd4a4ef26ef5245813ed74847147ce7f58c5a5232 (diff)
downloadbfs-b1d0e0e97ce747534a945a6fe0c3a15ccd8dbf00.tar.xz
parse: Use a trie to hold currently open files
-rw-r--r--cmdline.h8
-rw-r--r--eval.c6
-rw-r--r--parse.c39
-rw-r--r--stat.c5
-rw-r--r--stat.h10
5 files changed, 37 insertions, 31 deletions
diff --git a/cmdline.h b/cmdline.h
index 3a8c064..06b8725 100644
--- a/cmdline.h
+++ b/cmdline.h
@@ -22,6 +22,7 @@
#define BFS_CMDLINE_H
#include "color.h"
+#include "trie.h"
/**
* Various debugging flags.
@@ -56,11 +57,6 @@ struct root {
};
/**
- * An open file for the command line.
- */
-struct open_file;
-
-/**
* The parsed command line.
*/
struct cmdline {
@@ -103,7 +99,7 @@ struct cmdline {
struct expr *expr;
/** All the open files owned by the command line. */
- struct open_file *open_files;
+ struct trie open_files;
/** The number of open files owned by the command line. */
int nopen_files;
};
diff --git a/eval.c b/eval.c
index d4097ef..53eacf8 100644
--- a/eval.c
+++ b/eval.c
@@ -1142,10 +1142,8 @@ static bool eval_file_unique(struct eval_state *state, struct trie *seen) {
return false;
}
- // Glue the device and inode numbers together as a unique ID
- unsigned char id[sizeof(statbuf->dev) + sizeof(statbuf->ino)];
- memcpy(id, &statbuf->dev, sizeof(statbuf->dev));
- memcpy(id + sizeof(statbuf->dev), &statbuf->ino, sizeof(statbuf->ino));
+ bfs_file_id id;
+ bfs_stat_id(statbuf, &id);
struct trie_leaf *leaf = trie_insert_mem(seen, id, sizeof(id));
if (!leaf) {
diff --git a/parse.c b/parse.c
index 780f678..f58b716 100644
--- a/parse.c
+++ b/parse.c
@@ -246,12 +246,6 @@ struct open_file {
CFILE *cfile;
/** The path to the file (for diagnostics). */
const char *path;
- /** Device number (for deduplication). */
- dev_t dev;
- /** Inode number (for deduplication). */
- ino_t ino;
- /** The next open file in the chain. */
- struct open_file *next;
};
/**
@@ -268,9 +262,9 @@ int free_cmdline(struct cmdline *cmdline) {
free_bfs_mtab(cmdline->mtab);
- struct open_file *ofile = cmdline->open_files;
- while (ofile) {
- struct open_file *next = ofile->next;
+ struct trie_leaf *leaf;
+ while ((leaf = trie_first_leaf(&cmdline->open_files))) {
+ struct open_file *ofile = (struct open_file *)leaf->value;
if (cfclose(ofile->cfile) != 0) {
if (cerr) {
@@ -280,8 +274,9 @@ int free_cmdline(struct cmdline *cmdline) {
}
free(ofile);
- ofile = next;
+ trie_remove_mem(&cmdline->open_files, leaf->key, leaf->length);
}
+ trie_destroy(&cmdline->open_files);
if (cout && fflush(cout->file) != 0) {
if (cerr) {
@@ -429,26 +424,27 @@ static int expr_open(struct parser_state *state, struct expr *expr, const char *
goto out_close;
}
- for (struct open_file *ofile = cmdline->open_files; ofile; ofile = ofile->next) {
- if (ofile->dev == sb.dev && ofile->ino == sb.ino) {
- expr->cfile = ofile->cfile;
- ret = 0;
- goto out_close;
- }
+ bfs_file_id id;
+ bfs_stat_id(&sb, &id);
+
+ struct trie_leaf *leaf = trie_insert_mem(&cmdline->open_files, id, sizeof(id));
+ if (leaf->value) {
+ struct open_file *ofile = (struct open_file *)leaf->value;
+ expr->cfile = ofile->cfile;
+ ret = 0;
+ goto out_close;
}
struct open_file *ofile = malloc(sizeof(*ofile));
if (!ofile) {
perror("malloc()");
+ trie_remove_mem(&cmdline->open_files, leaf->key, leaf->length);
goto out_close;
}
ofile->cfile = cfile;
ofile->path = path;
- ofile->dev = sb.dev;
- ofile->ino = sb.ino;
- ofile->next = cmdline->open_files;
- cmdline->open_files = ofile;
+ leaf->value = ofile;
++cmdline->nopen_files;
expr->cfile = cfile;
@@ -3139,9 +3135,10 @@ struct cmdline *parse_cmdline(int argc, char *argv[]) {
cmdline->ignore_races = false;
cmdline->unique = false;
cmdline->expr = &expr_true;
- cmdline->open_files = NULL;
cmdline->nopen_files = 0;
+ trie_init(&cmdline->open_files);
+
static char* default_argv[] = {"bfs", NULL};
if (argc < 1) {
argc = 1;
diff --git a/stat.c b/stat.c
index d223ff8..d94ddb0 100644
--- a/stat.c
+++ b/stat.c
@@ -334,3 +334,8 @@ const struct timespec *bfs_stat_time(const struct bfs_stat *buf, enum bfs_stat_f
return NULL;
}
}
+
+void bfs_stat_id(const struct bfs_stat *buf, bfs_file_id *id) {
+ memcpy(*id, &buf->dev, sizeof(buf->dev));
+ memcpy(*id + sizeof(buf->dev), &buf->ino, sizeof(buf->ino));
+}
diff --git a/stat.h b/stat.h
index 3887db4..59a9712 100644
--- a/stat.h
+++ b/stat.h
@@ -126,4 +126,14 @@ int bfs_fstat(int fd, struct bfs_stat *buf);
*/
const struct timespec *bfs_stat_time(const struct bfs_stat *buf, enum bfs_stat_field field);
+/**
+ * A unique ID for a file.
+ */
+typedef unsigned char bfs_file_id[sizeof(dev_t) + sizeof(ino_t)];
+
+/**
+ * Compute a unique ID for a file.
+ */
+void bfs_stat_id(const struct bfs_stat *buf, bfs_file_id *id);
+
#endif // BFS_STAT_H