subversion-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From gst...@apache.org
Subject svn commit: r1173751 - /subversion/trunk/subversion/libsvn_repos/reporter.c
Date Wed, 21 Sep 2011 16:44:37 GMT
Author: gstein
Date: Wed Sep 21 16:44:36 2011
New Revision: 1173751

URL: http://svn.apache.org/viewvc?rev=1173751&view=rev
Log:
Convert the reporter from (always) using a temporary file to a
spill-buffer which (may) use a file if the report is too large. For small
reports, it will be contained within memory and (thus) be much faster.

* subversion/libsvn_repos/reporter.c:
  (struct report_baton_t): switch TEMPFILE over to READER
  (read_number): switch TEMP param over to READER, and switch to using the
    spillbuf reader's getc function
  (read_string): switch TEMP param to READER, pass the READER to
    read_number, and use the svn_spillbuf_reader_read() function to get
    content out of the spillbuf reader. make sure not to call the reader
    with len==0 (an illegal call to the reader)
  (read_rev): switch TEMP param to READER, switch to the spillbuf getc
    function, and pass READER to read_number().
  (read_depth): switch TEMP param to READER and use the reader getc func
  (read_path_info): switch TEMP param to READER. use the appropriate getc
    function and pass the READER to other functions
  (fetch_path_info, skip_path_info): pass the baton's READER member rather
    than the old TEMPFILE
  (finish_report): write content into the spillbuf. no need to seek back
    to the beginning. pass READER to read_path_info()
  (write_path_info): write to the READER spillbuf
  (svn_repos_finish_report): just call finish_report(). no file to close.
  (svn_repos_abort_report): nothing to do (no file to close).
  (svn_repos_begin_report2): create a spillbuf reader rather than a
    temporary file.

Modified:
    subversion/trunk/subversion/libsvn_repos/reporter.c

Modified: subversion/trunk/subversion/libsvn_repos/reporter.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_repos/reporter.c?rev=1173751&r1=1173750&r2=1173751&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_repos/reporter.c (original)
+++ subversion/trunk/subversion/libsvn_repos/reporter.c Wed Sep 21 16:44:36 2011
@@ -32,17 +32,19 @@
 #include "svn_props.h"
 #include "repos.h"
 #include "svn_private_config.h"
+
 #include "private/svn_dep_compat.h"
 #include "private/svn_fspath.h"
+#include "private/svn_subr_private.h"
 
 #define NUM_CACHED_SOURCE_ROOTS 4
 
-/* Theory of operation: we write report operations out to a temporary
-   file as we receive them.  When the report is finished, we read the
+/* Theory of operation: we write report operations out to a spill-buffer
+   as we receive them.  When the report is finished, we read the
    operations back out again, using them to guide the progression of
    the delta between the source and target revs.
 
-   Temporary file format: we use a simple ad-hoc format to store the
+   Spill-buffer content format: we use a simple ad-hoc format to store the
    report operations.  Each report operation is the concatention of
    the following ("+/-" indicates the single character '+' or '-';
    <length> and <revnum> are written out as decimal strings):
@@ -122,8 +124,8 @@ typedef struct report_baton_t
   svn_repos_authz_func_t authz_read_func;
   void *authz_read_baton;
 
-  /* The temporary file in which we are stashing the report. */
-  apr_file_t *tempfile;
+  /* The spill-buffer holding the report. */
+  svn_spillbuf_reader_t *reader;
 
   /* For the actual editor drive, we'll need a lookahead path info
      entry, a cache of FS roots, and a pool to store them. */
@@ -158,14 +160,14 @@ static svn_error_t *delta_dirs(report_ba
 /* --- READING PREVIOUSLY STORED REPORT INFORMATION --- */
 
 static svn_error_t *
-read_number(apr_uint64_t *num, apr_file_t *temp, apr_pool_t *pool)
+read_number(apr_uint64_t *num, svn_spillbuf_reader_t *reader, apr_pool_t *pool)
 {
   char c;
 
   *num = 0;
   while (1)
     {
-      SVN_ERR(svn_io_file_getc(&c, temp, pool));
+      SVN_ERR(svn_spillbuf_reader_getc(&c, reader, pool));
       if (c == ':')
         break;
       *num = *num * 10 + (c - '0');
@@ -174,13 +176,14 @@ read_number(apr_uint64_t *num, apr_file_
 }
 
 static svn_error_t *
-read_string(const char **str, apr_file_t *temp, apr_pool_t *pool)
+read_string(const char **str, svn_spillbuf_reader_t *reader, apr_pool_t *pool)
 {
   apr_uint64_t len;
   apr_size_t size;
+  apr_size_t amt;
   char *buf;
 
-  SVN_ERR(read_number(&len, temp, pool));
+  SVN_ERR(read_number(&len, reader, pool));
 
   /* Len can never be less than zero.  But could len be so large that
      len + 1 wraps around and we end up passing 0 to apr_palloc(),
@@ -201,22 +204,26 @@ read_string(const char **str, apr_file_t
 
   size = (apr_size_t)len;
   buf = apr_palloc(pool, size+1);
-  SVN_ERR(svn_io_file_read_full2(temp, buf, size, NULL, NULL, pool));
+  if (size > 0)
+    {
+      SVN_ERR(svn_spillbuf_reader_read(&amt, reader, buf, size, pool));
+      SVN_ERR_ASSERT(amt == size);
+    }
   buf[len] = 0;
   *str = buf;
   return SVN_NO_ERROR;
 }
 
 static svn_error_t *
-read_rev(svn_revnum_t *rev, apr_file_t *temp, apr_pool_t *pool)
+read_rev(svn_revnum_t *rev, svn_spillbuf_reader_t *reader, apr_pool_t *pool)
 {
   char c;
   apr_uint64_t num;
 
-  SVN_ERR(svn_io_file_getc(&c, temp, pool));
+  SVN_ERR(svn_spillbuf_reader_getc(&c, reader, pool));
   if (c == '+')
     {
-      SVN_ERR(read_number(&num, temp, pool));
+      SVN_ERR(read_number(&num, reader, pool));
       *rev = (svn_revnum_t) num;
     }
   else
@@ -225,15 +232,15 @@ read_rev(svn_revnum_t *rev, apr_file_t *
 }
 
 /* Read a single character to set *DEPTH (having already read '+')
-   from TEMP.  PATH is the path to which the depth applies, and is
+   from READER.  PATH is the path to which the depth applies, and is
    used for error reporting only. */
 static svn_error_t *
-read_depth(svn_depth_t *depth, apr_file_t *temp, const char *path,
+read_depth(svn_depth_t *depth, svn_spillbuf_reader_t *reader, const char *path,
            apr_pool_t *pool)
 {
   char c;
 
-  SVN_ERR(svn_io_file_getc(&c, temp, pool));
+  SVN_ERR(svn_spillbuf_reader_getc(&c, reader, pool));
   switch (c)
     {
     case 'X':
@@ -260,14 +267,16 @@ read_depth(svn_depth_t *depth, apr_file_
   return SVN_NO_ERROR;
 }
 
-/* Read a report operation *PI out of TEMP.  Set *PI to NULL if we
+/* Read a report operation *PI out of READER.  Set *PI to NULL if we
    have reached the end of the report. */
 static svn_error_t *
-read_path_info(path_info_t **pi, apr_file_t *temp, apr_pool_t *pool)
+read_path_info(path_info_t **pi,
+               svn_spillbuf_reader_t *reader,
+               apr_pool_t *pool)
 {
   char c;
 
-  SVN_ERR(svn_io_file_getc(&c, temp, pool));
+  SVN_ERR(svn_spillbuf_reader_getc(&c, reader, pool));
   if (c == '-')
     {
       *pi = NULL;
@@ -275,23 +284,23 @@ read_path_info(path_info_t **pi, apr_fil
     }
 
   *pi = apr_palloc(pool, sizeof(**pi));
-  SVN_ERR(read_string(&(*pi)->path, temp, pool));
-  SVN_ERR(svn_io_file_getc(&c, temp, pool));
+  SVN_ERR(read_string(&(*pi)->path, reader, pool));
+  SVN_ERR(svn_spillbuf_reader_getc(&c, reader, pool));
   if (c == '+')
-    SVN_ERR(read_string(&(*pi)->link_path, temp, pool));
+    SVN_ERR(read_string(&(*pi)->link_path, reader, pool));
   else
     (*pi)->link_path = NULL;
-  SVN_ERR(read_rev(&(*pi)->rev, temp, pool));
-  SVN_ERR(svn_io_file_getc(&c, temp, pool));
+  SVN_ERR(read_rev(&(*pi)->rev, reader, pool));
+  SVN_ERR(svn_spillbuf_reader_getc(&c, reader, pool));
   if (c == '+')
-    SVN_ERR(read_depth(&((*pi)->depth), temp, (*pi)->path, pool));
+    SVN_ERR(read_depth(&((*pi)->depth), reader, (*pi)->path, pool));
   else
     (*pi)->depth = svn_depth_infinity;
-  SVN_ERR(svn_io_file_getc(&c, temp, pool));
+  SVN_ERR(svn_spillbuf_reader_getc(&c, reader, pool));
   (*pi)->start_empty = (c == '+');
-  SVN_ERR(svn_io_file_getc(&c, temp, pool));
+  SVN_ERR(svn_spillbuf_reader_getc(&c, reader, pool));
   if (c == '+')
-    SVN_ERR(read_string(&(*pi)->lock_token, temp, pool));
+    SVN_ERR(read_string(&(*pi)->lock_token, reader, pool));
   else
     (*pi)->lock_token = NULL;
   (*pi)->pool = pool;
@@ -306,7 +315,7 @@ relevant(path_info_t *pi, const char *pr
           (!*prefix || pi->path[plen] == '/'));
 }
 
-/* Fetch the next pathinfo from B->tempfile for a descendant of
+/* Fetch the next pathinfo from B->reader for a descendant of
    PREFIX.  If the next pathinfo is for an immediate child of PREFIX,
    set *ENTRY to the path component of the report information and
    *INFO to the path information for that entry.  If the next pathinfo
@@ -353,7 +362,7 @@ fetch_path_info(report_baton_t *b, const
           *entry = relpath;
           *info = b->lookahead;
           subpool = svn_pool_create(b->pool);
-          SVN_ERR(read_path_info(&b->lookahead, b->tempfile, subpool));
+          SVN_ERR(read_path_info(&b->lookahead, b->reader, subpool));
         }
     }
   return SVN_NO_ERROR;
@@ -371,7 +380,7 @@ skip_path_info(report_baton_t *b, const 
     {
       svn_pool_destroy(b->lookahead->pool);
       subpool = svn_pool_create(b->pool);
-      SVN_ERR(read_path_info(&b->lookahead, b->tempfile, subpool));
+      SVN_ERR(read_path_info(&b->lookahead, b->reader, subpool));
     }
   return SVN_NO_ERROR;
 }
@@ -1279,7 +1288,6 @@ drive(report_baton_t *b, svn_revnum_t s_
 static svn_error_t *
 finish_report(report_baton_t *b, apr_pool_t *pool)
 {
-  apr_off_t offset;
   path_info_t *info;
   apr_pool_t *subpool;
   svn_revnum_t s_rev;
@@ -1288,14 +1296,12 @@ finish_report(report_baton_t *b, apr_poo
   /* Save our pool to manage the lookahead and fs_root cache with. */
   b->pool = pool;
 
-  /* Add an end marker and rewind the temporary file. */
-  SVN_ERR(svn_io_file_write_full(b->tempfile, "-", 1, NULL, pool));
-  offset = 0;
-  SVN_ERR(svn_io_file_seek(b->tempfile, APR_SET, &offset, pool));
+  /* Add the end marker. */
+  SVN_ERR(svn_spillbuf_reader_write(b->reader, "-", 1, pool));
 
   /* Read the first pathinfo from the report and verify that it is a top-level
      set_path entry. */
-  SVN_ERR(read_path_info(&info, b->tempfile, pool));
+  SVN_ERR(read_path_info(&info, b->reader, pool));
   if (!info || strcmp(info->path, b->s_operand) != 0
       || info->link_path || !SVN_IS_VALID_REVNUM(info->rev))
     return svn_error_create(SVN_ERR_REPOS_BAD_REVISION_REPORT, NULL,
@@ -1304,7 +1310,7 @@ finish_report(report_baton_t *b, apr_poo
 
   /* Initialize the lookahead pathinfo. */
   subpool = svn_pool_create(pool);
-  SVN_ERR(read_path_info(&b->lookahead, b->tempfile, subpool));
+  SVN_ERR(read_path_info(&b->lookahead, b->reader, subpool));
 
   if (b->lookahead && strcmp(b->lookahead->path, b->s_operand) == 0)
     {
@@ -1322,7 +1328,7 @@ finish_report(report_baton_t *b, apr_poo
           b->lookahead->depth = info->depth;
         }
       info = b->lookahead;
-      SVN_ERR(read_path_info(&b->lookahead, b->tempfile, subpool));
+      SVN_ERR(read_path_info(&b->lookahead, b->reader, subpool));
     }
 
   /* Open the target root and initialize the source root cache. */
@@ -1344,7 +1350,7 @@ finish_report(report_baton_t *b, apr_poo
 
 /* --- COLLECTING THE REPORT INFORMATION --- */
 
-/* Record a report operation into the temporary file.  Return an error
+/* Record a report operation into the spill buffer.  Return an error
    if DEPTH is svn_depth_unknown. */
 static svn_error_t *
 write_path_info(report_baton_t *b, const char *path, const char *lpath,
@@ -1383,7 +1389,7 @@ write_path_info(report_baton_t *b, const
   rep = apr_psprintf(pool, "+%" APR_SIZE_T_FMT ":%s%s%s%s%c%s",
                      strlen(path), path, lrep, rrep, drep,
                      start_empty ? '+' : '-', ltrep);
-  return svn_io_file_write_full(b->tempfile, rep, strlen(rep), NULL, pool);
+  return svn_spillbuf_reader_write(b->reader, rep, strlen(rep), pool);
 }
 
 svn_error_t *
@@ -1422,20 +1428,14 @@ svn_error_t *
 svn_repos_finish_report(void *baton, apr_pool_t *pool)
 {
   report_baton_t *b = baton;
-  svn_error_t *finish_err, *close_err;
-
-  finish_err = finish_report(b, pool);
-  close_err = svn_io_file_close(b->tempfile, pool);
 
-  return svn_error_trace(svn_error_compose_create(finish_err, close_err));
+  return svn_error_trace(finish_report(b, pool));
 }
 
 svn_error_t *
 svn_repos_abort_report(void *baton, apr_pool_t *pool)
 {
-  report_baton_t *b = baton;
-
-  return svn_error_trace(svn_io_file_close(b->tempfile, pool));
+  return SVN_NO_ERROR;
 }
 
 /* --- BEGINNING THE REPORT --- */
@@ -1484,10 +1484,9 @@ svn_repos_begin_report2(void **report_ba
   b->authz_read_baton = authz_read_baton;
   b->revision_infos = apr_hash_make(pool);
   b->pool = pool;
-
-  SVN_ERR(svn_io_open_unique_file3(&b->tempfile, NULL, NULL,
-                                   svn_io_file_del_on_pool_cleanup,
-                                   pool, pool));
+  b->reader = svn_spillbuf_reader_create(1000 /* blocksize */,
+                                         1000000 /* maxsize */,
+                                         pool);
 
   /* Hand reporter back to client. */
   *report_baton = b;



Mime
View raw message