From f2c1beb5c3139238a3570d8f5052635519367d26 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Yaroslav=20de=20la=20Pe=C3=B1a=20Smirnov?= Date: Thu, 13 Oct 2022 01:13:12 +0300 Subject: Switch to vector + qsort instead of bst Doesn't improve perfomance that much (sorting is far from the hotspot), but I realized that I didn't really need a BST for this use-case and I felt dumb for using one :/ --- include/bstree.h | 68 ------------- include/components.h | 10 +- include/render.h | 3 +- include/site.h | 4 +- src/bstree.c | 183 ----------------------------------- src/components.c | 29 +++--- src/render.c | 52 +++++----- src/site.c | 262 +++++++++++++++++++++++++++------------------------ 8 files changed, 188 insertions(+), 423 deletions(-) delete mode 100644 include/bstree.h delete mode 100644 src/bstree.c diff --git a/include/bstree.h b/include/bstree.h deleted file mode 100644 index 9577b73..0000000 --- a/include/bstree.h +++ /dev/null @@ -1,68 +0,0 @@ -/* - * Copyright 2021 Yaroslav de la Peña Smirnov - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ -#ifndef BSTREE_H -#define BSTREE_H - -#include - -/* < 0 means a less than b; 0 means equal; > 0 means a more than b. */ -typedef int (*bst_cmp_fn)(const void *a, const void *b); -typedef void (*bst_free_fn)(void *data); - -struct bstree { - struct bstnode *root; - bst_cmp_fn cmp; - /* It can be NULL, in which case you will have to free the values manually */ - bst_free_fn free; -}; - -struct bstnode { - void *value; - struct bstnode *parent; - struct bstnode *left; - struct bstnode *right; -}; - -typedef bool (*bst_walk_cb)(struct bstnode *, void *data); - -struct bstree *bstree_new(bst_cmp_fn, bst_free_fn); - -struct bstnode *bstree_add(struct bstree *, void *val); - -/* Returns NULL if a node with the value wasn't found */ -struct bstnode *bstree_search(struct bstree *, void *val); - -struct bstnode *bstree_min(struct bstnode *); - -struct bstnode *bstree_max(struct bstnode *); - -struct bstnode *bstree_predecessor(struct bstnode *); - -struct bstnode *bstree_successor(struct bstnode *); - -bool bstree_inorder_walk(struct bstnode *, bst_walk_cb, void *data); - -void bstree_remove(struct bstree *, struct bstnode *); - -void bstree_destroy(struct bstree *); - -#endif diff --git a/include/components.h b/include/components.h index f08d79a..4317187 100644 --- a/include/components.h +++ b/include/components.h @@ -68,11 +68,11 @@ struct album { char year[8]; /* The date of the album is the date of the earliest image */ time_t tstamp; - /* - * Binary search tree with the images of this album sorted by date from + /* + * List/vector with the images of this album to be sorted by from * older to newer. */ - struct bstree *images; + struct vector *images; /* Files/dirs that belong to images and which shouldn't be deleted */ struct hmap *preserved; /* Reference counted hashmap with values to be passed to the template */ @@ -92,7 +92,7 @@ struct image *image_old(struct stat *istat); int image_cmp(const void *a, const void *b); -void image_destroy(void *data); +void image_destroy(struct image *); struct album *album_new(struct album_config *, struct site *, const char *src, const char *rsrc, const struct stat *); @@ -103,6 +103,6 @@ void album_add_image(struct album *, struct image *); void album_set_year(struct album *); -void album_destroy(void *data); +void album_destroy(struct album *); #endif diff --git a/include/render.h b/include/render.h index 9b5e9e2..24c931a 100644 --- a/include/render.h +++ b/include/render.h @@ -1,7 +1,6 @@ #ifndef REVELA_RENDER_H #define REVELA_RENDER_H -#include "bstree.h" #include "config.h" #include "components.h" @@ -86,7 +85,7 @@ bool render_make_image(struct render *r, const char *path, bool render_set_album_vars(struct render *, struct album *); bool render_init(struct render *, const char *path, struct site_config *, - struct bstree *albums); + struct vector *albums); void render_deinit(struct render *); diff --git a/include/site.h b/include/site.h index 43a20d2..0f45667 100644 --- a/include/site.h +++ b/include/site.h @@ -2,7 +2,6 @@ #define REVELA_SITE_H #include "config.h" -#include "bstree.h" #include "render.h" #include "components.h" @@ -29,7 +28,8 @@ struct site { * site_init() */ size_t rel_content_dir; - struct bstree *albums; + /* List/vector with the albums to be sorted from newer to older */ + struct vector *albums; /* Files/dirs that belong to albums and which shouldn't be deleted */ struct hmap *album_dirs; struct render render; diff --git a/src/bstree.c b/src/bstree.c deleted file mode 100644 index 7d4f14f..0000000 --- a/src/bstree.c +++ /dev/null @@ -1,183 +0,0 @@ -/* - * Copyright 2021 Yaroslav de la Peña Smirnov - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ -#include "bstree.h" - -#include - -struct bstree * -bstree_new(bst_cmp_fn bstcmp, bst_free_fn bstfree) -{ - struct bstree *tree = malloc(sizeof *tree); - tree->root = NULL; - tree->cmp = bstcmp; - tree->free = bstfree; - - return tree; -} - -struct bstnode * -bstree_add(struct bstree *tree, void *val) -{ - struct bstnode **cur; - struct bstnode *prev = NULL; - cur = &tree->root; - while (*cur != NULL) { - prev = *cur; - if (tree->cmp(val, prev->value) < 0) { - cur = &prev->left; - } else { - cur = &prev->right; - } - } - *cur = calloc(1, sizeof **cur); - (*cur)->value = val; - (*cur)->parent = prev; - - return *cur; -} - -struct bstnode * -bstree_search(struct bstree *tree, void *val) -{ - struct bstnode *node = tree->root; - while (node != NULL) { - int res; - if ((res = tree->cmp(val, node->value)) == 0) { - break; - } - if (res < 0) { - node = node->left; - } else { - node = node->right; - } - } - - return node; -} - -#define bstree_extreme(node, d) \ - while (node != NULL && node->d != NULL) { \ - node = node->d; \ - } - -struct bstnode * -bstree_max(struct bstnode *node) -{ - bstree_extreme(node, right) - return node; -} - -struct bstnode * -bstree_min(struct bstnode *node) -{ - bstree_extreme(node, left) - return node; -} - -#define bstree_xcessor(na, d, m) \ - if (na->d != NULL) { \ - return bstree_##m(na->d); \ - } \ - struct bstnode *nb = na->parent; \ - while (nb != NULL && nb->d == na) { \ - na = nb; \ - nb = nb->parent; \ - } \ - return nb - -struct bstnode * -bstree_successor(struct bstnode *na) -{ - bstree_xcessor(na, right, min); -} - -struct bstnode * -bstree_predecessor(struct bstnode *na) -{ - bstree_xcessor(na, left, max); -} - -bool -bstree_inorder_walk(struct bstnode *node, bst_walk_cb cb, void *data) -{ - if (node->left != NULL) { - if (!bstree_inorder_walk(node->left, cb, data)) return false; - } - if (!cb(node, data)) return false; - if (node->right != NULL) { - return bstree_inorder_walk(node->right, cb, data); - } - return true; -} - -static void -bstree_transplant(struct bstree *tree, struct bstnode *a, struct bstnode *b) -{ - if (a->parent == NULL) { - tree->root = b; - } else if (a == a->parent->left) { - a->parent->left = b; - } else { - a->parent->right = b; - } - if (b != NULL) { - b->parent = a->parent; - } -} - -void -bstree_remove(struct bstree *tree, struct bstnode *na) -{ - if (na->left == NULL) { - bstree_transplant(tree, na, na->right); - } else if (na->right == NULL) { - bstree_transplant(tree, na, na->left); - } else { - struct bstnode *nb = bstree_min(na->right); - if (nb->parent != na) { - bstree_transplant(tree, nb, nb->right); - nb->right = na->right; - nb->right->parent = nb; - } - bstree_transplant(tree, na, nb); - nb->left = na->left; - nb->left->parent = nb; - } - tree->free(na->value); - free(na); -} - -static void -bstree_subdestroy(struct bstree *tree, struct bstnode *node) -{ - if (node->right) bstree_subdestroy(tree, node->right); - if (node->left) bstree_subdestroy(tree, node->left); - tree->free(node->value); - free(node); -} - -void -bstree_destroy(struct bstree *tree) -{ - if (tree->root) bstree_subdestroy(tree, tree->root); - free(tree); -} diff --git a/src/components.c b/src/components.c index aeb14b1..f3d79d1 100644 --- a/src/components.c +++ b/src/components.c @@ -175,17 +175,16 @@ image_new(char *src, const struct stat *pstat, struct album *album) } int -image_cmp(const void *a, const void *b) +image_cmp(const void *va, const void *vb) { + struct image *a = *(struct image **)va, *b = *(struct image **)vb; /* Compare in ascending order */ - return (((struct image *)a)->tstamp > ((struct image *)b)->tstamp) - - (((struct image *)a)->tstamp < ((struct image *)b)->tstamp); + return (a->tstamp > b->tstamp) - (a->tstamp < b->tstamp); } void -image_destroy(void *data) +image_destroy(struct image *image) { - struct image *image = data; free(image->source); free(image->url); free(image->url_image); @@ -213,7 +212,7 @@ album_new(struct album_config *conf, struct site *site, const char *src, album->config = conf; album->source = strdup(src); album->slug = slugify(rsrc, site->config->base_url, &album->url); - album->images = bstree_new(image_cmp, image_destroy); + album->images = vector_new_with_cap(64); album->tstamp = MAXTIME; album->preserved = hmap_new(); album->map = roscha_object_new(hmap_new()); @@ -223,11 +222,11 @@ album_new(struct album_config *conf, struct site *site, const char *src, } int -album_cmp(const void *a, const void *b) +album_cmp(const void *va, const void *vb) { + struct album *a = *(struct album **)va, *b = *(struct album **)vb; /* Compare in descending order */ - return (((struct album *)a)->tstamp < ((struct album *)b)->tstamp) - - (((struct album *)a)->tstamp > ((struct album *)b)->tstamp); + return (a->tstamp < b->tstamp) - (a->tstamp > b->tstamp); } @@ -238,7 +237,7 @@ album_add_image(struct album *album, struct image *image) album->tstamp = image->tstamp; album->datestr = image->datestr; } - bstree_add(album->images, image); + vector_push(album->images, image); } void @@ -251,15 +250,19 @@ album_set_year(struct album *album) } void -album_destroy(void *data) +album_destroy(struct album *album) { - struct album *album = data; if (album->config != NULL) { album_config_destroy(album->config); } + size_t i; + struct image *img; + vector_foreach(album->images, i, img) { + image_destroy(img); + } + vector_free(album->images); free(album->source); free(album->url); - bstree_destroy(album->images); hmap_free(album->preserved); roscha_object_unref(album->map); roscha_object_unref(album->thumbs); diff --git a/src/render.c b/src/render.c index bc9b8df..9dbbe2a 100644 --- a/src/render.c +++ b/src/render.c @@ -7,33 +7,33 @@ #include "log.h" #include "site.h" -/* TODO: refactor to use roscha instead of unja */ - -static bool -images_walk(struct bstnode *node, void *data) +static void +images_walk(struct vector *images) { - struct image *image = node->value; - - roscha_hmap_set_new(image->map, "source", (slice_whole(image->url_image))); - roscha_hmap_set_new(image->map, "date", (slice_whole(image->datestr))); - struct bstnode *prev = bstree_predecessor(node), - *next = bstree_successor(node); - char *url; - if (prev) { - url = ((struct image *)prev->value)->url; - roscha_hmap_set_new(image->map, "prev", (slice_whole(url))); - } - if (next) { - url = ((struct image *)next->value)->url; - roscha_hmap_set_new(image->map, "next", (slice_whole(url))); - } - - roscha_hmap_set_new(image->thumb, "link", (slice_whole(image->url))); - roscha_hmap_set_new(image->thumb, "source", (slice_whole(image->url_thumb))); + size_t i; + struct image *image; + size_t last = images->len - 1; + + vector_foreach(images, i, image) { + roscha_hmap_set_new(image->map, "source", (slice_whole(image->url_image))); + roscha_hmap_set_new(image->map, "date", (slice_whole(image->datestr))); + char *url; + if (i > 0) { + struct image *prev = images->values[i - 1]; + url = prev->url; + roscha_hmap_set_new(image->map, "prev", (slice_whole(url))); + } + if (i < last) { + struct image *next = images->values[i + 1]; + url = next->url; + roscha_hmap_set_new(image->map, "next", (slice_whole(url))); + } - roscha_vector_push(image->album->thumbs, image->thumb); + roscha_hmap_set_new(image->thumb, "link", (slice_whole(image->url))); + roscha_hmap_set_new(image->thumb, "source", (slice_whole(image->url_thumb))); - return true; + roscha_vector_push(image->album->thumbs, image->thumb); + } } static inline void @@ -84,7 +84,7 @@ render_set_album_vars(struct render *r, struct album *album) roscha_hmap_set_new(album->map, "date", (slice_whole(album->datestr))); roscha_hmap_set_new(album->map, "year", (slice_whole(album->year))); - bstree_inorder_walk(album->images->root, images_walk, NULL); + images_walk(album->images); roscha_hmap_set(album->map, "thumbs", album->thumbs); @@ -182,7 +182,7 @@ done: bool render_init(struct render *r, const char *root, struct site_config *conf, - struct bstree *albums) + struct vector *albums) { char *tmplpath = joinpath(root, TEMPLATESDIR); struct stat tstat; diff --git a/src/site.c b/src/site.c index eedd30b..3937376 100644 --- a/src/site.c +++ b/src/site.c @@ -33,32 +33,33 @@ prerm_imagedir(const char *path, void *data) return false; } if (S_ISDIR(st.st_mode)) { - struct image *old = image_old(&st); - struct bstnode *imnode = bstree_add(album->images, old), - *prev = bstree_predecessor(imnode), - *next = bstree_successor(imnode); + struct image *prev, *next = NULL; + size_t i; + vector_foreach(album->images, i, prev) { + if (prev->tstamp > st.st_mtim.tv_sec) { + prev = next; + break; + } + next = prev; + } if (prev) { - struct image *imprev = (struct image *)prev->value; - if (!imprev->modified) { - joinpathb(htmlpath, imprev->dst, index_html); - if (!render_make_image(&album->site->render, htmlpath, imprev)) { + if (!prev->modified) { + joinpathb(htmlpath, prev->dst, index_html); + if (!render_make_image(&album->site->render, htmlpath, prev)) { goto fail; } } } - if (next) { - struct image *imnext = (struct image *)next->value; - if (!imnext->modified) { - joinpathb(htmlpath, imnext->dst, index_html); - if (!render_make_image(&album->site->render, htmlpath, imnext)) { + if (next != prev) { + if (!next->modified) { + joinpathb(htmlpath, next->dst, index_html); + if (!render_make_image(&album->site->render, htmlpath, next)) { goto fail; } } } - bstree_remove(album->images, imnode); return true; fail: - bstree_remove(album->images, imnode); return false; } return true; @@ -120,131 +121,134 @@ magick_fail: } static bool -images_walk(struct bstnode *node, void *data) +images_walk(struct site *site, struct vector *images) { - struct site *site = data; - struct image *image = node->value; - struct stat dstat; - struct timespec ddate = { .tv_sec = image->tstamp, .tv_nsec = 0 }; - int imgupdate, thumbupdate; - char htmlpath[PATH_MAX]; - const char *base = rbasename(image->dst); - - log_printl(LOG_DEBUG, "Image: %s, datetime %s", image->basename, - image->datestr); - - if (!nmkdir(image->dst, &dstat, site->dry_run)) return false; - - imgupdate = file_is_uptodate(image->dst_image, &image->modtime); - if (imgupdate == -1) goto magick_fail; - thumbupdate = file_is_uptodate(image->dst_image, &image->modtime); - if (thumbupdate == -1) goto magick_fail; - if (!site->dry_run && (!imgupdate || !thumbupdate)) { - TRYWAND(site->wand, MagickReadImage(site->wand, image->source)); - } - if (!imgupdate && !optimize_image(site->wand, image->dst_image, - &site->config->images, &image->modtime, site->dry_run)) { - goto magick_fail; - } - if (!thumbupdate && !optimize_image(site->wand, image->dst_thumb, - &site->config->thumbnails, &image->modtime, site->dry_run)) { - goto magick_fail; - } - if (!site->dry_run && (!imgupdate || !thumbupdate)) { - MagickRemoveImage(site->wand); - } + size_t i; + struct image *image; + + vector_foreach(images, i, image) { + struct stat dstat; + struct timespec ddate = { .tv_sec = image->tstamp, .tv_nsec = 0 }; + int imgupdate, thumbupdate; + char htmlpath[PATH_MAX]; + const char *base = rbasename(image->dst); + + log_printl(LOG_DEBUG, "Image: %s, datetime %s", image->basename, + image->datestr); + + if (!nmkdir(image->dst, &dstat, site->dry_run)) return false; + + imgupdate = file_is_uptodate(image->dst_image, &image->modtime); + if (imgupdate == -1) goto magick_fail; + thumbupdate = file_is_uptodate(image->dst_image, &image->modtime); + if (thumbupdate == -1) goto magick_fail; + if (!site->dry_run && (!imgupdate || !thumbupdate)) { + TRYWAND(site->wand, MagickReadImage(site->wand, image->source)); + } + if (!imgupdate && !optimize_image(site->wand, image->dst_image, + &site->config->images, &image->modtime, site->dry_run)) { + goto magick_fail; + } + if (!thumbupdate && !optimize_image(site->wand, image->dst_thumb, + &site->config->thumbnails, &image->modtime, site->dry_run)) { + goto magick_fail; + } + if (!site->dry_run && (!imgupdate || !thumbupdate)) { + MagickRemoveImage(site->wand); + } - joinpathb(htmlpath, image->dst, index_html); - hmap_set(image->album->preserved, base, (char *)base); + joinpathb(htmlpath, image->dst, index_html); + hmap_set(image->album->preserved, base, (char *)base); - int isupdate = file_is_uptodate(htmlpath, &site->render.modtime); - if (isupdate == -1) return false; - if (isupdate == 0) { - if (!render_make_image(&site->render, htmlpath, image)) { - return false; - } - image->modified = true; - image->album->images_updated++; - /* Check if previous image wasn't updated, if so, render it */ - struct bstnode *prev = bstree_predecessor(node); - if (prev) { - struct image *iprev = prev->value; - if (!iprev->modified) { - joinpathb(htmlpath, iprev->dst, index_html); - if (!render_make_image(&site->render, htmlpath, iprev)) { - return false; + int isupdate = file_is_uptodate(htmlpath, &site->render.modtime); + if (isupdate == -1) return false; + if (isupdate == 0) { + if (!render_make_image(&site->render, htmlpath, image)) { + return false; + } + image->modified = true; + image->album->images_updated++; + /* Check if previous image wasn't updated, if so, render it */ + if (i > 0) { + struct image *prev = images->values[i - 1]; + if (!prev->modified) { + joinpathb(htmlpath, prev->dst, index_html); + if (!render_make_image(&site->render, htmlpath, prev)) { + return false; + } + goto success; } - goto success; } - } - goto success; - } + goto success; + } - /* - * Render anyway if next image doesn't exist yet in directory or if previous - * image was updated. - */ - struct bstnode *next = bstree_successor(node), *prev = NULL; - if (next) { - struct image *inext = next->value; - if (access(inext->dst, F_OK) != 0) { - image->album->images_updated++; - return render_make_image(&site->render, htmlpath, image); + /* + * Render anyway if next image doesn't exist yet in directory or if + * previous image was updated. + */ + if (i < images->len - 1) { + struct image *next = images->values[i + 1]; + if (access(next->dst, F_OK) != 0) { + image->album->images_updated++; + return render_make_image(&site->render, htmlpath, image); + } } - } - if ((prev = bstree_predecessor(node)) != NULL) { - struct image *iprev = prev->value; - if (iprev->modified) { - image->album->images_updated++; - return render_make_image(&site->render, htmlpath, image); + if (i > 0) { + struct image *prev = images->values[i - 1]; + if (prev->modified) { + image->album->images_updated++; + return render_make_image(&site->render, htmlpath, image); + } } - } -success: - if (!site->dry_run) setdatetime(image->dst, &ddate); + success: + if (!site->dry_run) setdatetime(image->dst, &ddate); + continue; + magick_fail: + return false; + } return true; -magick_fail: - return false; } static bool -albums_walk(struct bstnode *node, void *data) +albums_walk(struct site *site) { - struct site *site = data; - struct album *album = node->value; - struct stat dstat; - if (!nmkdir(album->slug, &dstat, site->dry_run)) return false; - - hmap_set(site->album_dirs, album->slug, (char *)album->slug); - if (!site->dry_run) { - if (!render_set_album_vars(&site->render, album)) return false; + size_t i; + struct album *album; - } + vector_foreach(site->albums, i, album) { + struct stat dstat; + if (!nmkdir(album->slug, &dstat, site->dry_run)) return false; - log_printl(LOG_DEBUG, "Album: %s, datetime %s", album->slug, album->datestr); - if (!bstree_inorder_walk(album->images->root, images_walk, site)) { - return false; - } + hmap_set(site->album_dirs, album->slug, (char *)album->slug); + if (!site->dry_run) { + if (!render_set_album_vars(&site->render, album)) return false; - hmap_set(album->preserved, index_html, (char *)index_html); - ssize_t deleted = rmextra(album->slug, album->preserved, prerm_imagedir, - album, site->dry_run); - if (deleted < 0) { - log_printl_errno(LOG_ERROR, - "Something happened while deleting extraneous files"); - } else { - album->images_updated += deleted; - } - if (album->images_updated > 0) { - site->render.albums_updated++; - } + } - char htmlpath[PATH_MAX]; - joinpathb(htmlpath, album->slug, index_html); - if (!render_make_album(&site->render, htmlpath, album)) return false; + log_printl(LOG_DEBUG, "Album: %s, datetime %s", album->slug, album->datestr); + if (!images_walk(site, album->images)) { + return false; + } + hmap_set(album->preserved, index_html, (char *)index_html); + ssize_t deleted = rmextra(album->slug, album->preserved, prerm_imagedir, + album, site->dry_run); + if (deleted < 0) { + log_printl_errno(LOG_ERROR, + "Something happened while deleting extraneous files"); + } else { + album->images_updated += deleted; + } + if (album->images_updated > 0) { + site->render.albums_updated++; + } + char htmlpath[PATH_MAX]; + joinpathb(htmlpath, album->slug, index_html); + if (!render_make_album(&site->render, htmlpath, album)) return false; + } return true; } @@ -304,9 +308,11 @@ traverse(struct site *site, const char *path, struct stat *dstat) free(subpath); } - if (album->images->root != NULL) { + if (album->images->len != 0) { album_set_year(album); - bstree_add(site->albums, album); + qsort(album->images->values, + album->images->len, sizeof(void *), image_cmp); + vector_push(site->albums, album); closedir(dir); return true; } @@ -333,7 +339,7 @@ site_build(struct site *site) return false; } - if (!bstree_inorder_walk(site->albums->root, albums_walk, (void *)site)) { + if (!albums_walk(site)) { return false; } @@ -371,6 +377,7 @@ site_load(struct site *site) } if (!traverse(site, site->content_dir, &cstat)) return false; + qsort(site->albums->values, site->albums->len, sizeof(void *), album_cmp); return render_init(&site->render, site->root_dir, site->config, site->albums); } @@ -380,7 +387,7 @@ site_init(struct site *site) { site->config = site_config_init(); if (!site_config_read_ini(site->root_dir, site->config)) return false; - site->albums = bstree_new(album_cmp, album_destroy); + site->albums = vector_new(); if (site->root_dir == NULL) { site->root_dir = malloc(PATH_MAX); @@ -405,7 +412,14 @@ site_init(struct site *site) void site_deinit(struct site *site) { - if (site->albums) bstree_destroy(site->albums); + if (site->albums) { + size_t i; + struct album *a; + vector_foreach(site->albums, i, a) { + album_destroy(a); + } + vector_free(site->albums); + } site_config_destroy(site->config); free(site->content_dir); free(site->root_dir); -- cgit v1.2.3