summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorYorhel <git@yorhel.nl>2013-06-03 14:35:30 +0200
committerYorhel <git@yorhel.nl>2013-06-03 14:40:48 +0200
commitf5ffccfaa8303e814f65bac49aa59657d65f1971 (patch)
tree32abff7ecad980c37f8fce8dae0af8a2f8c712dd
parentf44c4ea75635f723cd58a0e8723f7ace571aa2a0 (diff)
share/scan: Add function to scan multiple filesystem paths
Still untested, and the code is still never called.
-rw-r--r--src/share/scan.c86
1 files changed, 84 insertions, 2 deletions
diff --git a/src/share/scan.c b/src/share/scan.c
index affb685..4d29f4b 100644
--- a/src/share/scan.c
+++ b/src/share/scan.c
@@ -91,6 +91,7 @@
*/
#define SHARE_MAXFILESIZE (((uint64_t)1)<<44)
+typedef struct share_scan_t share_scan_t;
typedef struct {
evtp_work_t w;
@@ -100,6 +101,12 @@ typedef struct {
} share_scan_work_t;
+struct share_scan_t {
+ share_fl_t *dir;
+ share_scan_work_t **work, **next;
+};
+
+
static share_fl_t *share_scan_thread_item(share_scan_work_t *w, const char *fname, kstring_t *buf) {
struct stat st;
share_fl_t *fl;
@@ -111,6 +118,7 @@ static share_fl_t *share_scan_thread_item(share_scan_work_t *w, const char *fnam
buf->l = 0;
ksprintf(buf, "%s/%s", w->fspath, fname);
+ ylog(YLOG_TRACE, "Stat()ing '%s'", buf->s);
/* TODO: Use stat() when FollowSymlinks is enabled. */
if(lstat(buf->s, &st) == -1) {
@@ -221,9 +229,9 @@ static void share_scan_thread_merge(share_scan_work_t *w, share_flv_t *lst) {
}
-/* TODO: should be static */
-void share_scan_thread(evtp_work_t *_w) {
+static void share_scan_work(evtp_work_t *_w) {
share_scan_work_t *w = (share_scan_work_t *)_w;
+ ylog(YLOG_TRACE, "Scanning '%s'", w->fspath);
share_flv_t lst = share_scan_thread_readdir(w);
if(lst.n)
qsort(lst.a, lst.n, sizeof(*lst.a), share_fl_sort_cmp);
@@ -231,4 +239,78 @@ void share_scan_thread(evtp_work_t *_w) {
share_scan_thread_merge(w, &lst);
}
+
+static void share_scan_work_done(evtp_work_t *_w) {
+ share_scan_work_t *w = (share_scan_work_t *)_w;
+ share_scan_t *sc = _w->data;
+ share_flv_t dest = w->dest;
+ free(w);
+
+ /* Scan aborted, throw away results */
+ if(!sc) {
+ free(dest.a);
+ return;
+ }
+
+ *(sc->next++) = NULL;
+ if(*sc->next) { /* More directories to scan, queue the next one */
+ (*sc->next)->dest = dest;
+ evtp_submit(&(*sc->next)->w, threadpool, share_scan_work, share_scan_work_done);
+ return;
+ }
+
+ /* All directories scanned */
+ free(sc->work);
+ /* TODO: merge results into share structure */
+}
+
+
+/* TODO: vpath can be obtained from dir and vice-versa, so one argument could
+ * be removed. */
+void share_scan_dir(share_t *s, share_scan_t *sc, const char *vpath, share_fl_t *dir) {
+ sc->dir = dir;
+
+ /* Figure out which filesystem directories to scan and create appropriate work objects */
+ vec_t(share_scan_work_t *) work = {};
+ kstring_t buf = {};
+ size_t i;
+ for(i=0; i<s->paths.n; i++) {
+ share_path_t *p = s->paths.a[i];
+ char *ps = p->props.VirtualPath;
+ size_t pl = strlen(ps);
+ if(!(strncmp(ps, vpath, pl) == 0 && (!vpath[pl] || vpath[pl] == '/')))
+ continue;
+
+ buf.l = 0;
+ kputs(p->props.FilesystemPath, &buf);
+ if(vpath[pl])
+ kputs(vpath+pl, &buf);
+
+ share_scan_work_t *w = malloc(offsetof(share_scan_work_t, fspath) + 1 + buf.l);
+ w->w.data = sc;
+ w->pathid = p->id;
+ strcpy(w->fspath, buf.s);
+ vec_insert_order(work, work.n, w);
+ }
+ free(buf.s);
+ vec_insert_order(work, work.n, NULL);
+ /* TODO: It's possible that there are no matching directories here. (e.g.
+ * vpath="/", but all configured paths start at "/abc" or so). That case
+ * should be handled. */
+
+ sc->work = sc->next = work.a;
+ memset(&(*sc->next)->dest, 0, sizeof(share_flv_t));
+ evtp_submit(&(*sc->next)->w, threadpool, share_scan_work, share_scan_work_done);
+}
+
+
+void share_scan_cancel(share_scan_t *sc) {
+ if(*sc->next)
+ (*sc->next)->w.data = NULL;
+ while(*(++sc->next))
+ free(*sc->next);
+ free(sc->work);
+}
+
+
/* vim: set noet sw=4 ts=4: */