[tor-commits] [tor/master] Add consensus_cache_entry spooling support to spooled_resource_t

nickm at torproject.org nickm at torproject.org
Thu May 4 12:58:39 UTC 2017


commit a32083bd03625c1d99a32971c1c1a574d7e6e014
Author: Nick Mathewson <nickm at torproject.org>
Date:   Sun Apr 16 17:47:28 2017 -0400

    Add consensus_cache_entry spooling support to spooled_resource_t
---
 src/or/dirserv.c | 64 ++++++++++++++++++++++++++++++++++++++++++++++++++------
 src/or/dirserv.h | 14 +++++++++++--
 2 files changed, 70 insertions(+), 8 deletions(-)

diff --git a/src/or/dirserv.c b/src/or/dirserv.c
index e76fd93..bdf40b6 100644
--- a/src/or/dirserv.c
+++ b/src/or/dirserv.c
@@ -13,6 +13,7 @@
 #include "command.h"
 #include "connection.h"
 #include "connection_or.h"
+#include "conscache.h"
 #include "control.h"
 #include "directory.h"
 #include "dirserv.h"
@@ -3392,6 +3393,9 @@ spooled_resource_new(dir_spool_source_t source,
     default:
       spooled->spool_eagerly = 1;
       break;
+    case DIR_SPOOL_CONSENSUS_CACHE_ENTRY:
+      tor_assert_unreached();
+      break;
   }
   tor_assert(digestlen <= sizeof(spooled->digest));
   if (digest)
@@ -3399,6 +3403,33 @@ spooled_resource_new(dir_spool_source_t source,
   return spooled;
 }
 
+/**
+ * Create a new spooled_resource_t to spool the contents of <b>entry</b> to
+ * the user.  Return the spooled object on success, or NULL on failure (which
+ * is probably caused by a failure to map the body of the item from disk).
+ *
+ * Adds a reference to entry's reference counter.
+ */
+spooled_resource_t *
+spooled_resource_new_from_cache_entry(consensus_cache_entry_t *entry)
+{
+  spooled_resource_t *spooled = tor_malloc_zero(sizeof(spooled_resource_t));
+  spooled->spool_source = DIR_SPOOL_CONSENSUS_CACHE_ENTRY;
+  spooled->spool_eagerly = 0;
+  consensus_cache_entry_incref(entry);
+  spooled->consensus_cache_entry = entry;
+
+  int r = consensus_cache_entry_get_body(entry,
+                                         &spooled->cce_body,
+                                         &spooled->cce_len);
+  if (r == 0) {
+    return spooled;
+  } else {
+    spooled_resource_free(spooled);
+    return NULL;
+  }
+}
+
 /** Release all storage held by <b>spooled</b>. */
 void
 spooled_resource_free(spooled_resource_t *spooled)
@@ -3410,6 +3441,10 @@ spooled_resource_free(spooled_resource_t *spooled)
     cached_dir_decref(spooled->cached_dir_ref);
   }
 
+  if (spooled->consensus_cache_entry) {
+    consensus_cache_entry_decref(spooled->consensus_cache_entry);
+  }
+
   tor_free(spooled);
 }
 
@@ -3456,6 +3491,9 @@ spooled_resource_estimate_size(const spooled_resource_t *spooled,
     return bodylen;
   } else {
     cached_dir_t *cached;
+    if (spooled->consensus_cache_entry) {
+      return spooled->cce_len;
+    }
     if (spooled->cached_dir_ref) {
       cached = spooled->cached_dir_ref;
     } else {
@@ -3505,7 +3543,8 @@ spooled_resource_flush_some(spooled_resource_t *spooled,
     return SRFS_DONE;
   } else {
     cached_dir_t *cached = spooled->cached_dir_ref;
-    if (cached == NULL) {
+    consensus_cache_entry_t *cce = spooled->consensus_cache_entry;
+    if (cached == NULL && cce == NULL) {
       /* The cached_dir_t hasn't been materialized yet. So let's look it up. */
       cached = spooled->cached_dir_ref =
         spooled_resource_lookup_cached_dir(spooled, NULL);
@@ -3517,22 +3556,34 @@ spooled_resource_flush_some(spooled_resource_t *spooled,
       tor_assert_nonfatal(spooled->cached_dir_offset == 0);
     }
 
+    if (BUG(!cached && !cce))
+      return SRFS_DONE;
+
+    int64_t total_len;
+    const char *ptr;
+    if (cached) {
+      total_len = cached->dir_z_len;
+      ptr = cached->dir_z;
+    } else {
+      total_len = spooled->cce_len;
+      ptr = (const char *)spooled->cce_body;
+    }
     /* How many bytes left to flush? */
-    int64_t remaining = 0;
-    remaining = cached->dir_z_len - spooled->cached_dir_offset;
+    int64_t remaining;
+    remaining = total_len - spooled->cached_dir_offset;
     if (BUG(remaining < 0))
       return SRFS_ERR;
     ssize_t bytes = (ssize_t) MIN(DIRSERV_CACHED_DIR_CHUNK_SIZE, remaining);
     if (conn->compress_state) {
       connection_write_to_buf_compress(
-              cached->dir_z + spooled->cached_dir_offset,
+              ptr + spooled->cached_dir_offset,
               bytes, conn, 0);
     } else {
-      connection_write_to_buf(cached->dir_z + spooled->cached_dir_offset,
+      connection_write_to_buf(ptr + spooled->cached_dir_offset,
                               bytes, TO_CONN(conn));
     }
     spooled->cached_dir_offset += bytes;
-    if (spooled->cached_dir_offset >= (off_t)cached->dir_z_len) {
+    if (spooled->cached_dir_offset >= (off_t)total_len) {
       return SRFS_DONE;
     } else {
       return SRFS_MORE;
@@ -3608,6 +3659,7 @@ spooled_resource_lookup_body(const spooled_resource_t *spooled,
       return 0;
     }
     case DIR_SPOOL_NETWORKSTATUS:
+    case DIR_SPOOL_CONSENSUS_CACHE_ENTRY:
     default:
       /* LCOV_EXCL_START */
       tor_assert_nonfatal_unreached();
diff --git a/src/or/dirserv.h b/src/or/dirserv.h
index f707237..4b09f87 100644
--- a/src/or/dirserv.h
+++ b/src/or/dirserv.h
@@ -38,6 +38,7 @@ typedef enum dir_spool_source_t {
     DIR_SPOOL_EXTRA_BY_DIGEST, DIR_SPOOL_EXTRA_BY_FP,
     DIR_SPOOL_MICRODESC,
     DIR_SPOOL_NETWORKSTATUS,
+    DIR_SPOOL_CONSENSUS_CACHE_ENTRY,
 } dir_spool_source_t;
 #define dir_spool_source_bitfield_t ENUM_BF(dir_spool_source_t)
 
@@ -74,8 +75,15 @@ typedef struct spooled_resource_t {
    */
   struct cached_dir_t *cached_dir_ref;
   /**
-   * The current offset into cached_dir. Only used when spool_eagerly is
-   * false */
+   * A different kind of large object that we might be spooling. Also
+   * reference-counted.  Also only used when spool_eagerly is false.
+   */
+  struct consensus_cache_entry_t *consensus_cache_entry;
+  const uint8_t *cce_body;
+  size_t cce_len;
+  /**
+   * The current offset into cached_dir or cce_body. Only used when
+   * spool_eagerly is false */
   off_t cached_dir_offset;
 } spooled_resource_t;
 
@@ -184,6 +192,8 @@ int dirserv_read_guardfraction_file(const char *fname,
 spooled_resource_t *spooled_resource_new(dir_spool_source_t source,
                                          const uint8_t *digest,
                                          size_t digestlen);
+spooled_resource_t *spooled_resource_new_from_cache_entry(
+                                      struct consensus_cache_entry_t *entry);
 void spooled_resource_free(spooled_resource_t *spooled);
 void dirserv_spool_remove_missing_and_guess_size(dir_connection_t *conn,
                                                  time_t cutoff,





More information about the tor-commits mailing list