[Author Prev][Author Next][Thread Prev][Thread Next][Author Index][Thread Index]

[or-cvs] r11301: Use (and debug) new file-writing functions in order to simpl (in tor/trunk: . doc src/common src/or src/tools)



Author: nickm
Date: 2007-08-29 15:02:43 -0400 (Wed, 29 Aug 2007)
New Revision: 11301

Modified:
   tor/trunk/
   tor/trunk/ChangeLog
   tor/trunk/doc/TODO
   tor/trunk/src/common/util.c
   tor/trunk/src/common/util.h
   tor/trunk/src/or/rephist.c
   tor/trunk/src/tools/tor-gencert.c
Log:
 r14832@catbus:  nickm | 2007-08-29 15:00:27 -0400
 Use (and debug) new file-writing functions in order to simplify code that formerly built big strings in RAM.



Property changes on: tor/trunk
___________________________________________________________________
 svk:merge ticket from /tor/trunk [r14832] on 8246c3cf-6607-4228-993b-4d95d33730f1

Modified: tor/trunk/ChangeLog
===================================================================
--- tor/trunk/ChangeLog	2007-08-29 19:02:37 UTC (rev 11300)
+++ tor/trunk/ChangeLog	2007-08-29 19:02:43 UTC (rev 11301)
@@ -18,6 +18,11 @@
       router, do not try to include the nickname if it is absent.  Fixes
       bug 467.
 
+  o Code simplifications and refactoring:
+    - Revamp file-writing logic so we don't need to have the entire contents
+      of a file in memory at once before we write to disk.  Tor, meet stdio.
+
+
 Changes in version 0.2.0.6-alpha - 2007-08-26
   o New directory authorities:
     - Set up Tonga as the default bridge directory authority.

Modified: tor/trunk/doc/TODO
===================================================================
--- tor/trunk/doc/TODO	2007-08-29 19:02:37 UTC (rev 11300)
+++ tor/trunk/doc/TODO	2007-08-29 19:02:43 UTC (rev 11301)
@@ -156,8 +156,8 @@
        (high expected time to failure) or good guard qualities (high
        fractional uptime).
      - AKA Track uptime as %-of-time-up, as well as time-since-last-down
-    - Should TrackHostExits expire TrackHostExitsExpire seconds after their
-       *last* use, not their *first* use?
+    - Make TrackHostExits expire TrackHostExitsExpire seconds after their
+       *last* use, not their *first* use.
     - Limit to 2 dir, 2 OR, N SOCKS connections per IP.
      - Or maybe close connections from same IP when we get a lot from one.
      - Or maybe block IPs that connect too many times at once.

Modified: tor/trunk/src/common/util.c
===================================================================
--- tor/trunk/src/common/util.c	2007-08-29 19:02:37 UTC (rev 11300)
+++ tor/trunk/src/common/util.c	2007-08-29 19:02:43 UTC (rev 11301)
@@ -72,13 +72,6 @@
 #include <malloc.h>
 #endif
 
-#ifndef O_BINARY
-#define O_BINARY 0
-#endif
-#ifndef O_TEXT
-#define O_TEXT 0
-#endif
-
 /* =====
  * Memory management
  * ===== */
@@ -1465,6 +1458,7 @@
   char *filename;
   int rename_on_close;
   int fd;
+  FILE *stdio_file;
 };
 
 /** DOCDOC */
@@ -1477,6 +1471,9 @@
   const char *open_name;
   tor_assert(fname);
   tor_assert(data_out);
+#if (O_BINARY != 0 && O_TEXT != 0)
+  tor_assert((open_flags & (O_BINARY|O_TEXT)) != 0);
+#endif
   new_file->fd = -1;
   tempname_len = strlen(fname)+16;
   tor_assert(tempname_len > strlen(fname)); /*check for overflow*/
@@ -1485,7 +1482,7 @@
     open_name = fname;
     new_file->rename_on_close = 0;
   } else {
-    new_file->tempname = tor_malloc(tempname_len);
+    open_name = new_file->tempname = tor_malloc(tempname_len);
     if (tor_snprintf(new_file->tempname, tempname_len, "%s.tmp", fname)<0) {
       log(LOG_WARN, LD_GENERAL, "Failed to generate filename");
       goto err;
@@ -1493,10 +1490,10 @@
     new_file->rename_on_close = 1;
   }
 
-  if ((new_file->fd = open(new_file->tempname, open_flags, mode))
+  if ((new_file->fd = open(open_name, open_flags, mode))
       < 0) {
-    log(LOG_WARN, LD_FS, "Couldn't open \"%s\" for writing: %s",
-        new_file->tempname, strerror(errno));
+    log(LOG_WARN, LD_FS, "Couldn't open \"%s\" (%s) for writing: %s",
+        open_name, fname, strerror(errno));
     goto err;
   }
 
@@ -1512,16 +1509,49 @@
 }
 
 /** DOCDOC */
+FILE *
+fdopen_file(open_file_t *file_data)
+{
+  tor_assert(file_data);
+  if (file_data->stdio_file)
+    return file_data->stdio_file;
+  tor_assert(file_data->fd >= 0);
+  if (!(file_data->stdio_file = fdopen(file_data->fd, "a"))) {
+    log_warn(LD_FS, "Couldn't fdopen \"%s\": %s", file_data->filename,
+             strerror(errno));
+  }
+  return file_data->stdio_file;
+}
+
+/** DOCDOC */
+FILE *
+start_writing_to_stdio_file(const char *fname, int open_flags, int mode,
+                            open_file_t **data_out)
+{
+  FILE *res;
+  if (start_writing_to_file(fname, open_flags, mode, data_out)<0)
+    return NULL;
+  if (!(res = fdopen_file(*data_out)))
+    abort_writing_to_file(*data_out);
+  return res;
+}
+
+/** DOCDOC */
 static int
 finish_writing_to_file_impl(open_file_t *file_data, int abort_write)
 {
   int r = 0;
   tor_assert(file_data && file_data->filename);
-  if (file_data->fd >= 0 && close(file_data->fd) < 0) {
+  if (file_data->stdio_file) {
+    if (fclose(file_data->stdio_file)) {
+      log_warn(LD_FS, "Error closing \"%s\": %s", file_data->filename,
+               strerror(errno));
+      abort_write = r = -1;
+    }
+  } else if (file_data->fd >= 0 && close(file_data->fd) < 0) {
     log_warn(LD_FS, "Error flushing \"%s\": %s", file_data->filename,
              strerror(errno));
-    abort_write = 1;
-    r = -1;
+    abort_write = r = -1;
   }
 
   if (file_data->rename_on_close) {
@@ -1538,6 +1568,8 @@
     }
   }
 
+  memset(file_data, 0, sizeof(file_data));
+  file_data->fd = -1;
   tor_free(file_data->filename);
   tor_free(file_data->tempname);
   tor_free(file_data);
@@ -1593,7 +1625,7 @@
 int
 write_chunks_to_file(const char *fname, const smartlist_t *chunks, int bin)
 {
-  int flags = O_WRONLY|O_CREAT|O_TRUNC|(bin?O_BINARY:O_TEXT);
+  int flags = OPEN_FLAGS_REPLACE|(bin?O_BINARY:O_TEXT);
   return write_chunks_to_file_impl(fname, chunks, flags);
 }
 
@@ -1603,7 +1635,7 @@
 write_bytes_to_file(const char *fname, const char *str, size_t len,
                     int bin)
 {
-  int flags = O_WRONLY|O_CREAT|O_TRUNC|(bin?O_BINARY:O_TEXT);
+  int flags = OPEN_FLAGS_REPLACE|(bin?O_BINARY:O_TEXT);
   int r;
   sized_chunk_t c = { str, len };
   smartlist_t *chunks = smartlist_create();
@@ -1619,7 +1651,7 @@
 append_bytes_to_file(const char *fname, const char *str, size_t len,
                      int bin)
 {
-  int flags = O_WRONLY|O_CREAT|O_APPEND|(bin?O_BINARY:O_TEXT);
+  int flags = OPEN_FLAGS_APPEND|(bin?O_BINARY:O_TEXT);
   int r;
   sized_chunk_t c = { str, len };
   smartlist_t *chunks = smartlist_create();

Modified: tor/trunk/src/common/util.h
===================================================================
--- tor/trunk/src/common/util.h	2007-08-29 19:02:37 UTC (rev 11300)
+++ tor/trunk/src/common/util.h	2007-08-29 19:02:43 UTC (rev 11301)
@@ -18,6 +18,13 @@
 #include <stdio.h>
 #include <stdlib.h>
 
+#ifndef O_BINARY
+#define O_BINARY 0
+#endif
+#ifndef O_TEXT
+#define O_TEXT 0
+#endif
+
 /* Replace assert() with a variant that sends failures to the log before
  * calling assert() normally.
  */
@@ -213,9 +220,14 @@
  * directory; see that function's documentation for details. */
 typedef enum { CPD_NONE, CPD_CREATE, CPD_CHECK } cpd_check_t;
 int check_private_dir(const char *dirname, cpd_check_t check);
+#define OPEN_FLAGS_REPLACE (O_WRONLY|O_CREAT|O_TRUNC)
+#define OPEN_FLAGS_APPEND (O_WRONLY|O_CREAT|O_APPEND)
 typedef struct open_file_t open_file_t;
 int start_writing_to_file(const char *fname, int open_flags, int mode,
                           open_file_t **data_out);
+FILE *start_writing_to_stdio_file(const char *fname, int open_flags, int mode,
+                                  open_file_t **data_out);
+FILE *fdopen_file(open_file_t *file_data);
 int finish_writing_to_file(open_file_t *file_data);
 int abort_writing_to_file(open_file_t *file_data);
 int write_str_to_file(const char *fname, const char *str, int bin);

Modified: tor/trunk/src/or/rephist.c
===================================================================
--- tor/trunk/src/or/rephist.c	2007-08-29 19:02:37 UTC (rev 11300)
+++ tor/trunk/src/or/rephist.c	2007-08-29 19:02:43 UTC (rev 11301)
@@ -563,15 +563,24 @@
 int
 rep_hist_record_mtbf_data(void)
 {
-  char buf[128];
   char time_buf[ISO_TIME_LEN+1];
-  smartlist_t *lines;
 
   digestmap_iter_t *orhist_it;
   const char *digest;
   void *or_history_p;
   or_history_t *hist;
+  open_file_t *open_file = NULL;
+  FILE *f;
 
+  {
+    char *filename = get_mtbf_filename();
+    f = start_writing_to_stdio_file(filename, OPEN_FLAGS_REPLACE|O_TEXT, 0600,
+                                    &open_file);
+    tor_free(filename);
+    if (!f)
+      return -1;
+  }
+
   /* File format is:
    *   FormatLine *KeywordLine Data
    *
@@ -581,27 +590,24 @@
    *   RouterMTBFLine = Fingerprint SP WeightedRunLen SP
    *           TotalRunWeights [SP S=StartRunTime] NL
    */
+#define PUT(s) STMT_BEGIN if (fputs((s),f)<0) goto err; STMT_END
+#define PRINTF(args) STMT_BEGIN if (fprintf args <0) goto err; STMT_END
 
-  lines = smartlist_create();
+  PUT("format 1\n");
 
-  smartlist_add(lines, tor_strdup("format 1\n"));
-
   format_iso_time(time_buf, time(NULL));
-  tor_snprintf(buf, sizeof(buf), "stored-at %s\n", time_buf);
-  smartlist_add(lines, tor_strdup(buf));
+  PRINTF((f, "stored-at %s\n", time_buf));
 
   if (started_tracking_stability) {
     format_iso_time(time_buf, started_tracking_stability);
-    tor_snprintf(buf, sizeof(buf), "tracked-since %s\n", time_buf);
-    smartlist_add(lines, tor_strdup(buf));
+    PRINTF((f, "tracked-since %s\n", time_buf));
   }
   if (stability_last_downrated) {
     format_iso_time(time_buf, stability_last_downrated);
-    tor_snprintf(buf, sizeof(buf), "last-downrated %s\n", time_buf);
-    smartlist_add(lines, tor_strdup(buf));
+    PRINTF((f, "last-downrated %s\n", time_buf));
   }
 
-  smartlist_add(lines, tor_strdup("data\n"));
+  PUT("data\n");
 
   for (orhist_it = digestmap_iter_init(history_map);
        !digestmap_iter_done(orhist_it);
@@ -616,28 +622,20 @@
       format_iso_time(time_buf, hist->start_of_run);
       t = time_buf;
     }
-    tor_snprintf(buf, sizeof(buf), "%s %lu %.5lf%s%s\n",
-                 dbuf, hist->weighted_run_length, hist->total_run_weights,
-                 t ? " S=" : "", t ? t : "");
-    smartlist_add(lines, tor_strdup(buf));
+    PRINTF((f, "%s %lu %.5lf%s%s\n",
+            dbuf, hist->weighted_run_length, hist->total_run_weights,
+            t ? " S=" : "", t ? t : ""));
   }
 
-  smartlist_add(lines, tor_strdup(".\n"));
+  PUT(".\n");
 
-  {
-    size_t sz;
-    /* XXXX This isn't terribly efficient; line-at-a-time would be
-     * way faster. */
-    char *filename = get_mtbf_filename();
-    char *data = smartlist_join_strings(lines, "", 0, &sz);
-    int r = write_bytes_to_file(filename, data, sz, 0);
+#undef PUT
+#undef PRINTF
 
-    tor_free(data);
-    tor_free(filename);
-    SMARTLIST_FOREACH(lines, char *, cp, tor_free(cp));
-    smartlist_free(lines);
-    return r;
-  }
+  return finish_writing_to_file(open_file);
+ err:
+  abort_writing_to_file(open_file);
+  return -1;
 }
 
 /** Load MTBF data from disk.  Returns 0 on success or recoverable error, -1

Modified: tor/trunk/src/tools/tor-gencert.c
===================================================================
--- tor/trunk/src/tools/tor-gencert.c	2007-08-29 19:02:37 UTC (rev 11300)
+++ tor/trunk/src/tools/tor-gencert.c	2007-08-29 19:02:43 UTC (rev 11301)
@@ -151,7 +151,7 @@
   FILE *f;
 
   if (make_new_id) {
-    int fd;
+    open_file_t *open_file = NULL;
     RSA *key;
     if (status != FN_NOENT) {
       log_err(LD_GENERAL, "--create-identity-key was specified, but %s "
@@ -171,19 +171,11 @@
       return 1;
     }
 
-    if ((fd = open(identity_key_file, O_CREAT|O_EXCL|O_WRONLY, 0400))<0) {
-      log_err(LD_GENERAL, "Couldn't fdopen %s for writing: %s",
-              identity_key_file, strerror(errno));
+    if (!(f = start_writing_to_stdio_file(identity_key_file,
+                                          OPEN_FLAGS_REPLACE, 0400,
+                                          &open_file)))
       return 1;
-    }
 
-    if (!(f = fdopen(fd, "w"))) {
-      close(fd);
-      log_err(LD_GENERAL, "Couldn't fdopen %s for writing: %s",
-              identity_key_file, strerror(errno));
-      return 1;
-    }
-
     if (!PEM_write_PKCS8PrivateKey_nid(f, identity_key,
                                        NID_pbe_WithSHA1And3_Key_TripleDES_CBC,
                                        NULL, 0, /* no password here. */
@@ -191,9 +183,10 @@
       log_err(LD_GENERAL, "Couldn't write identity key to %s",
               identity_key_file);
       crypto_log_errors(LOG_ERR, "Writing identity key");
+      abort_writing_to_file(open_file);
       return 1;
     }
-    fclose(f);
+    finish_writing_to_file(open_file);
   } else {
     if (status != FN_FILE) {
       log_err(LD_GENERAL,
@@ -224,7 +217,7 @@
 static int
 generate_signing_key(void)
 {
-  int fd;
+  open_file_t *open_file;
   FILE *f;
   RSA *key;
   log_notice(LD_GENERAL, "Generating %d-bit RSA signing key.",
@@ -240,26 +233,19 @@
     return 1;
   }
 
-  if ((fd = open(signing_key_file, O_CREAT|O_EXCL|O_WRONLY, 0600))<0) {
-    log_err(LD_GENERAL, "Couldn't open %s for writing: %s",
-            signing_key_file, strerror(errno));
+  if (!(f = start_writing_to_stdio_file(signing_key_file,
+                                        OPEN_FLAGS_REPLACE, 0600,
+                                        &open_file)))
     return 1;
-  }
 
-  if (!(f = fdopen(fd, "w"))) {
-    close(fd);
-    log_err(LD_GENERAL, "Couldn't open %s for writing: %s",
-            signing_key_file, strerror(errno));
-    return 1;
-  }
-
   /* Write signing key with no encryption. */
   if (!PEM_write_RSAPrivateKey(f, key, NULL, NULL, 0, NULL, NULL)) {
     crypto_log_errors(LOG_WARN, "writing signing key");
+    abort_writing_to_file(open_file);
     return 1;
   }
 
-  fclose(f);
+  finish_writing_to_file(open_file);
 
   return 0;
 }