aboutsummaryrefslogtreecommitdiffstats
path: root/src/note.c
diff options
context:
space:
mode:
authorLukas Fleischer <calcurse@cryptocrack.de>2011-09-01 15:29:19 +0200
committerLukas Fleischer <calcurse@cryptocrack.de>2011-10-05 12:25:47 +0200
commit8d71923d4f498c8d2fcb22a72346e3e77a7c4a5b (patch)
treefa1566974b5bb8afc8d9f5c3da5427b7856434f2 /src/note.c
parent6c7edfbb862b1598b74e4413121dfa42e3a79211 (diff)
downloadcalcurse-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>
Diffstat (limited to 'src/note.c')
-rw-r--r--src/note.c113
1 files changed, 113 insertions, 0 deletions
diff --git a/src/note.c b/src/note.c
index db5c45a..2fd022a 100644
--- a/src/note.c
+++ b/src/note.c
@@ -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);
+ }
+}