about summary refs log tree commit diff
diff options
context:
space:
mode:
authorsternenseemann <0rpkxez4ksa01gb3typccl0i@systemli.org>2020-08-24 21:36:30 +0200
committersternenseemann <0rpkxez4ksa01gb3typccl0i@systemli.org>2020-08-24 21:36:30 +0200
commit82e095124dac524b28dff9d99bafa05a821ae732 (patch)
treea418d227c5c58ee8eda43c9cd0390dbe8eb08d3c
parentc44b9d201765ab71ae0a7a741a396b28f289dce0 (diff)
feat(rss,atom): mmap on demand like in blog_index
* entry
  * add entry_unget_text: implements unmmaping
  * free_entry: now expects pointer
* index: adjust for entry changes
* main
  * adjust for entry changes
  * use on demand mmaping in blog_atom and blog_rss
* shell.nix
  * add strace for mmap debugging
-rw-r--r--entry.c25
-rw-r--r--entry.h24
-rw-r--r--index.c4
-rw-r--r--main.c137
-rw-r--r--shell.nix2
5 files changed, 105 insertions, 87 deletions
diff --git a/entry.c b/entry.c
index 5714978..756a62e 100644
--- a/entry.c
+++ b/entry.c
@@ -190,21 +190,26 @@ int entry_get_text(struct entry *entry) {
     return 0;
 }
 
-void free_entry(struct entry entry) {
-    if(entry.path != NULL) {
-        free(entry.path);
+void entry_unget_text(struct entry *entry) {
+    if(entry->text_size > 0 && entry->text != NULL &&
+       munmap(entry->text, entry->text_size) != -1) {
+        entry->text_size = -1;
+        entry->text = NULL;
     }
+}
 
-    if(entry.link != NULL) {
-        free(entry.link);
+void free_entry(struct entry *entry) {
+    if(entry->path != NULL) {
+        free(entry->path);
     }
 
-    if(entry.title != NULL) {
-        free(entry.title);
+    if(entry->link != NULL) {
+        free(entry->link);
     }
 
-    if(entry.text != NULL) {
-        // TODO return value
-        munmap(entry.text, entry.text_size);
+    if(entry->title != NULL) {
+        free(entry->title);
     }
+
+    entry_get_text(entry);
 }
diff --git a/entry.h b/entry.h
index 669e7a9..de8d868 100644
--- a/entry.h
+++ b/entry.h
@@ -73,12 +73,25 @@ int make_entry(const char *blog_dir, char *script_name, char *path_info, struct
  *
  * @return 0 on success, -1 on error, currently errno is not set correctly
  *
+ * @see entry_unget_text
  * @see make_entry
  * @see free_entry
  */
 int entry_get_text(struct entry *entry);
 
 /*!
+ * @brief Unmap the file referenced in a `struct entry`
+ *
+ * Tries to `munmap()` the file pointed to by `entry->text`
+ * if present, and updates `entry->text_size` accordingly.
+ *
+ * The rest of the struct is left untouched.
+ *
+ * @see free_entry
+ */
+void entry_unget_text(struct entry *entry);
+
+/*!
  * @brief Free dynamically allocated parts on an `entry`
  *
  * Frees any non `NULL` pointers in the given `entry` structure.
@@ -86,8 +99,11 @@ int entry_get_text(struct entry *entry);
  * after being called, so you can always call `free_entry()` after
  * `make_entry()`.
  *
- * It also unmaps the mapped file in `text` if it is not `NULL`.
- * For this `text_size` is needed which is set correctly
- * by `entry_get_text()`.
+ * It also unmaps the mapped file in `text` if it is not `NULL`
+ * using `entry_unget_text()`.
+ *
+ * Warning: It won't call `free()` on the entire entry structure.
+ *
+ * @see entry_unget_text
  */
-void free_entry(struct entry entry);
+void free_entry(struct entry *entry);
diff --git a/index.c b/index.c
index 0a0ee67..bb94bb9 100644
--- a/index.c
+++ b/index.c
@@ -107,7 +107,7 @@ int make_index(const char *blog_dir, char *script_name, bool get_text, struct en
 
                 index_count++;
             } else {
-                free_entry(tmp_entry);
+                free_entry(&tmp_entry);
             }
         }
     }
@@ -125,7 +125,7 @@ int make_index(const char *blog_dir, char *script_name, bool get_text, struct en
 void free_index(struct entry *entries[], int count) {
     if(count > 0) {
         for(int i = 0; i < count; i++) {
-            free_entry(*(*entries + i));
+            free_entry(*entries + i);
         }
     }
 
diff --git a/main.c b/main.c
index 55d8000..21ab753 100644
--- a/main.c
+++ b/main.c
@@ -95,11 +95,6 @@
 #include "template.h"
 #include "xml.h"
 
-// TODO sandbox
-//      caching
-//      reduce memory usage by only using get_text in the inner loop
-//      and unmapping the file directly afterwards
-
 void send_standard_headers(int status, char content_type[]);
 
 /*!
@@ -166,7 +161,6 @@ int main(void) {
         template_error(500);
         template_footer();
 
-        // TODO exit failure on error?
         return EXIT_SUCCESS;
     }
 
@@ -217,12 +211,7 @@ void blog_index(char script_name[]) {
         for(int i = 0; i < count; i++) {
             if(entry_get_text(&entries[i]) != -1) {
                 template_index_entry(entries[i]);
-
-                // unmap file
-                if(munmap(entries[i].text, entries[i].text_size) != -1) {
-                    entries[i].text_size = -1;
-                    entries[i].text = NULL;
-                }
+                entry_unget_text(&entries[i]);
             }
         }
 
@@ -252,14 +241,14 @@ void blog_entry(char script_name[], char path_info[]) {
         template_footer();
     }
 
-    free_entry(entry);
+    free_entry(&entry);
 }
 
 void blog_rss(char script_name[]) {
     // index
     struct entry *entries = NULL;
 
-    int count = make_index(BLOG_DIR, script_name, 1, &entries);
+    int count = make_index(BLOG_DIR, script_name, 0, &entries);
 
     if(count < 0) {
         send_standard_headers(500, "text/plain");
@@ -315,38 +304,42 @@ void blog_rss(char script_name[]) {
     }
 
     for(int i = 0; i < count; i++) {
-        xml_open_tag(&ctx, "item");
-        xml_open_tag(&ctx, "title");
-        xml_escaped(&ctx, entries[i].title);
-        xml_close_tag(&ctx, "title");
-
-        xml_open_tag(&ctx, "link");
-        xml_escaped(&ctx, BLOG_SERVER_URL);
-        xml_escaped(&ctx, entries[i].link);
-        xml_close_tag(&ctx, "link");
-
-        xml_open_tag(&ctx, "guid");
-        xml_escaped(&ctx, BLOG_SERVER_URL);
-        xml_escaped(&ctx, entries[i].link);
-        xml_close_tag(&ctx, "guid");
-
-        if(entries[i].text_size > 0) {
-            xml_open_tag(&ctx, "description");
-            xml_open_cdata(&ctx);
-            xml_raw(&ctx, entries[i].text);
-            xml_close_cdata(&ctx);
-            xml_close_tag(&ctx, "description");
-        }
+        if(entry_get_text(&entries[i]) != -1) {
+            xml_open_tag(&ctx, "item");
+            xml_open_tag(&ctx, "title");
+            xml_escaped(&ctx, entries[i].title);
+            xml_close_tag(&ctx, "title");
+
+            xml_open_tag(&ctx, "link");
+            xml_escaped(&ctx, BLOG_SERVER_URL);
+            xml_escaped(&ctx, entries[i].link);
+            xml_close_tag(&ctx, "link");
+
+            xml_open_tag(&ctx, "guid");
+            xml_escaped(&ctx, BLOG_SERVER_URL);
+            xml_escaped(&ctx, entries[i].link);
+            xml_close_tag(&ctx, "guid");
+
+            if(entries[i].text_size > 0) {
+                xml_open_tag(&ctx, "description");
+                xml_open_cdata(&ctx);
+                xml_raw(&ctx, entries[i].text);
+                xml_close_cdata(&ctx);
+                xml_close_tag(&ctx, "description");
+            }
 
-        char strtime_entry[MAX_TIMESTR_SIZE];
+            char strtime_entry[MAX_TIMESTR_SIZE];
 
-        if(flocaltime(strtime_entry, RSS_TIME_FORMAT, MAX_TIMESTR_SIZE, &entries[i].time) > 0) {
-            xml_open_tag(&ctx, "pubDate");
-            xml_escaped(&ctx, strtime_entry);
-            xml_close_tag(&ctx, "pubDate");
-        }
+            if(flocaltime(strtime_entry, RSS_TIME_FORMAT, MAX_TIMESTR_SIZE, &entries[i].time) > 0) {
+                xml_open_tag(&ctx, "pubDate");
+                xml_escaped(&ctx, strtime_entry);
+                xml_close_tag(&ctx, "pubDate");
+            }
 
-        xml_close_tag(&ctx, "item");
+            xml_close_tag(&ctx, "item");
+
+            entry_unget_text(&entries[i]);
+        }
     }
 
     xml_close_all(&ctx);
@@ -359,7 +352,7 @@ void blog_rss(char script_name[]) {
 void blog_atom(char script_name[]) {
     struct entry *entries = NULL;
 
-    int count = make_index(BLOG_DIR, script_name, 1, &entries);
+    int count = make_index(BLOG_DIR, script_name, 0, &entries);
 
     if(count < 0) {
         send_standard_headers(500, "text/plain");
@@ -431,37 +424,41 @@ void blog_atom(char script_name[]) {
     }
 
     for(int i = 0; i < count; i++) {
-        xml_open_tag(&ctx, "entry");
+        if(entry_get_text(&entries[i]) != -1) {
+            xml_open_tag(&ctx, "entry");
+
+            xml_open_tag(&ctx, "id");
+            xml_escaped(&ctx, BLOG_SERVER_URL);
+            xml_escaped(&ctx, entries[i].link);
+            xml_close_tag(&ctx, "id");
+
+            xml_open_tag(&ctx, "title");
+            xml_escaped(&ctx, entries[i].title);
+            xml_close_tag(&ctx, "title");
+
+            char strtime_entry[MAX_TIMESTR_SIZE];
+            if(flocaltime(strtime_entry, ATOM_TIME_FORMAT, MAX_TIMESTR_SIZE, &entries[i].time) > 0) {
+                xml_open_tag(&ctx, "updated");
+                xml_escaped(&ctx, strtime_entry);
+                xml_close_tag(&ctx, "updated");
+            }
 
-        xml_open_tag(&ctx, "id");
-        xml_escaped(&ctx, BLOG_SERVER_URL);
-        xml_escaped(&ctx, entries[i].link);
-        xml_close_tag(&ctx, "id");
+            char *entry_url = catn_alloc(2, BLOG_SERVER_URL, entries[i].link);
+            if(entry_url != NULL) {
+                xml_empty_tag(&ctx, "link", 3, "rel", "alternate", "type", "text/html", "href", entry_url);
+                free(entry_url);
+            }
 
-        xml_open_tag(&ctx, "title");
-        xml_escaped(&ctx, entries[i].title);
-        xml_close_tag(&ctx, "title");
+            xml_open_tag_attrs(&ctx, "content", 1, "type", "html");
+            xml_open_cdata(&ctx);
+            xml_raw(&ctx, entries[i].text);
+            xml_close_cdata(&ctx);
+            xml_close_tag(&ctx, "content");
 
-        char strtime_entry[MAX_TIMESTR_SIZE];
-        if(flocaltime(strtime_entry, ATOM_TIME_FORMAT, MAX_TIMESTR_SIZE, &entries[i].time) > 0) {
-            xml_open_tag(&ctx, "updated");
-            xml_escaped(&ctx, strtime_entry);
-            xml_close_tag(&ctx, "updated");
-        }
+            xml_close_tag(&ctx, "entry");
 
-        char *entry_url = catn_alloc(2, BLOG_SERVER_URL, entries[i].link);
-        if(entry_url != NULL) {
-            xml_empty_tag(&ctx, "link", 3, "rel", "alternate", "type", "text/html", "href", entry_url);
-            free(entry_url);
+            entry_unget_text(&entries[i]);
         }
-
-        xml_open_tag_attrs(&ctx, "content", 1, "type", "html");
-        xml_open_cdata(&ctx);
-        xml_raw(&ctx, entries[i].text);
-        xml_close_cdata(&ctx);
-        xml_close_tag(&ctx, "content");
-
-        xml_close_tag(&ctx, "entry");
     }
 
     xml_close_tag(&ctx, "feed");
diff --git a/shell.nix b/shell.nix
index ca97a56..4b23757 100644
--- a/shell.nix
+++ b/shell.nix
@@ -3,5 +3,5 @@
 pkgs.mkShell {
   name = "sternenblog-env";
 
-  buildInputs = with pkgs; [ gnumake valgrind gdb doxygen ];
+  buildInputs = with pkgs; [ gnumake valgrind gdb doxygen strace ];
 }