diff options
author | Yorhel <git@yorhel.nl> | 2013-06-03 14:35:30 +0200 |
---|---|---|
committer | Yorhel <git@yorhel.nl> | 2013-06-03 14:40:48 +0200 |
commit | f5ffccfaa8303e814f65bac49aa59657d65f1971 (patch) | |
tree | 32abff7ecad980c37f8fce8dae0af8a2f8c712dd | |
parent | f44c4ea75635f723cd58a0e8723f7ace571aa2a0 (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.c | 86 |
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: */ |