diff options
author | Lukas Fleischer <calcurse@cryptocrack.de> | 2011-09-01 15:29:19 +0200 |
---|---|---|
committer | Lukas Fleischer <calcurse@cryptocrack.de> | 2011-10-05 12:25:47 +0200 |
commit | 8d71923d4f498c8d2fcb22a72346e3e77a7c4a5b (patch) | |
tree | fa1566974b5bb8afc8d9f5c3da5427b7856434f2 | |
parent | 6c7edfbb862b1598b74e4413121dfa42e3a79211 (diff) | |
download | calcurse-8d71923d4f498c8d2fcb22a72346e3e77a7c4a5b.tar.gz calcurse-8d71923d4f498c8d2fcb22a72346e3e77a7c4a5b.zip |
Add a garbage collector for note files
Now that we use hashes to identify notes, a garbage collector comes in
handy. We search for note files that aren't referenced anywhere. Such
files might come up if a note, that isn't connected with any other item,
is edited.
Huge parts of this code are very hackish due to our data structure
layout and the way our hash table implementation works.
Signed-off-by: Lukas Fleischer <calcurse@cryptocrack.de>
-rw-r--r-- | src/calcurse.h | 4 | ||||
-rw-r--r-- | src/note.c | 113 |
2 files changed, 117 insertions, 0 deletions
diff --git a/src/calcurse.h b/src/calcurse.h index adf9d2d..956010d 100644 --- a/src/calcurse.h +++ b/src/calcurse.h @@ -145,6 +145,9 @@ #define KEYS_LABELEN 8 /* length of command description */ #define KEYS_CMDS_PER_LINE 6 /* max number of commands per line */ +/* Size of the hash table the note garbage collector uses. */ +#define NOTE_GC_HSIZE 1024 + #define ERROR_MSG(...) do { \ char msg[BUFSIZ]; \ int len; \ @@ -754,6 +757,7 @@ void edit_note (char **, char *); void view_note (char *, char *); void erase_note (char **); void note_read (char *, FILE *); +void note_gc (void); /* notify.c */ int notify_time_left (void); @@ -35,10 +35,17 @@ */ #include <unistd.h> +#include <dirent.h> #include "calcurse.h" #include "sha1.h" +struct note_gc_hash { + char *hash; + char buf[MAX_NOTESIZ + 1]; + HTABLE_ENTRY (note_gc_hash); +}; + /* Edit a note with an external editor. */ void edit_note (char **note, char *editor) @@ -120,3 +127,109 @@ note_read (char *buffer, FILE *fp) while (getc (fp) != ' '); buffer[MAX_NOTESIZ] = '\0'; } + +static void +note_gc_extract_key (struct note_gc_hash *data, char **key, int *len) +{ + *key = data->hash; + *len = strlen (data->hash); +} + +static int +note_gc_cmp (struct note_gc_hash *a, struct note_gc_hash *b) +{ + return strcmp (a->hash, b->hash); +} + +/* Spot and unlink unused note files. */ +void +note_gc (void) +{ + HTABLE_HEAD (htp, NOTE_GC_HSIZE, note_gc_hash) gc_htable = + HTABLE_INITIALIZER (&gc_htable); + struct note_gc_hash *hp; + DIR *dirp; + struct dirent *dp; + llist_item_t *i; + struct note_gc_hash tmph; + char notepath[BUFSIZ]; + + if (!(dirp = opendir (path_notes))) + return; + + /* Insert all note file names into a hash table. */ + HTABLE_GENERATE (htp, note_gc_hash, note_gc_extract_key, note_gc_cmp); + do + { + if ((dp = readdir (dirp)) && *(dp->d_name) != '.') + { + hp = mem_malloc (sizeof (struct note_gc_hash)); + + strncpy (hp->buf, dp->d_name, MAX_NOTESIZ + 1); + hp->hash = hp->buf; + + HTABLE_INSERT (htp, &gc_htable, hp); + } + } + while (dp); + + closedir (dirp); + + /* Remove hashes that are actually in use. */ + LLIST_TS_FOREACH (&alist_p, i) + { + struct apoint *apt = LLIST_GET_DATA (i); + if (apt->note) + { + tmph.hash = apt->note; + free (HTABLE_REMOVE (htp, &gc_htable, &tmph)); + } + } + + LLIST_FOREACH (&eventlist, i) + { + struct event *ev = LLIST_GET_DATA (i); + if (ev->note) + { + tmph.hash = ev->note; + free (HTABLE_REMOVE (htp, &gc_htable, &tmph)); + } + } + + LLIST_TS_FOREACH (&recur_alist_p, i) + { + struct recur_apoint *rapt = LLIST_GET_DATA (i); + if (rapt->note) + { + tmph.hash = rapt->note; + free (HTABLE_REMOVE (htp, &gc_htable, &tmph)); + } + } + + LLIST_FOREACH (&recur_elist, i) + { + struct recur_event *rev = LLIST_GET_DATA (i); + if (rev->note) + { + tmph.hash = rev->note; + free (HTABLE_REMOVE (htp, &gc_htable, &tmph)); + } + } + + LLIST_FOREACH (&todolist, i) + { + struct todo *todo = LLIST_GET_DATA (i); + if (todo->note) + { + tmph.hash = todo->note; + free (HTABLE_REMOVE (htp, &gc_htable, &tmph)); + } + } + + /* Unlink unused note files. */ + HTABLE_FOREACH (hp, htp, &gc_htable) + { + snprintf (notepath, BUFSIZ, "%s%s", path_notes, hp->hash); + unlink (notepath); + } +} |