[svn.haxx.se] · SVN Dev · SVN Users · SVN Org · TSVN Dev · TSVN Users · Subclipse Dev · Subclipse Users · this month's index

progress report (for CMike)

From: Karl Fogel <kfogel_at_newton.ch.collab.net>
Date: 2003-01-08 05:50:11 CET

Hey Mike, thought I'd post a State Of The Bunion for you before I went
to bed.

My current patch is "supposed" to work. However, it fails fs-test 8,
by hanging forever. Backtrace is below, and you can reproduce it by:

   gdb fs-test

   1. break on main
   2. run 8
     <hit main>
   3. break write_and_read_file
   4. continue
     <hit write_and_read_file>
   5. break svn_fs__rep_contents_size
   6. continue
     <hit svn_fs__rep_contents_size>
     <At this point, you may want to go up 3 frames to see the context
      of the call -- you'll be in rep_write_get_baton(), which is
      essentially svn_fs__rep_contents_write_stream()'s way of
      guaranteeing that you have an empty rep before it gives you a
      write stream.>
   7. <step into svn_fs__bdb_read_rep>
   8. <step gingerly into fs->representations->get, knowing in advance
      that it is a black hole from which you will never return.>
     
(I don't know why it's freezing up like that.)

The reason I'm telling you all this is that I'm hoping to tandem debug
it with you tomorrow morning :-).

See you in the A.M... Here's the backtrace, followed by the current
patch:

#0 0x4009045e in __db_get () from /usr/local/BerkeleyDB.4.0/lib/libdb-4.0.so
#1 0x4003b969 in svn_fs__bdb_read_rep (rep_p=0xbffff350, fs=0x80779c8,
    key=0x808ba78 "1", trail=0x8066748)
    at subversion/libsvn_fs/bdb/reps-table.c:80
#2 0x40043eaa in svn_fs__rep_contents_size (size_p=0xbffff3d8, fs=0x80779c8,
    rep_key=0x808ba78 "1", trail=0x8066748)
    at subversion/libsvn_fs/reps-strings.c:657
#3 0x4004422f in txn_body_rep_size (baton=0xbffff3d0, trail=0x8066748)
    at subversion/libsvn_fs/reps-strings.c:837
#4 0x40046412 in svn_fs__retry_txn (fs=0x80779c8,
    txn_body=0x400441fc <txn_body_rep_size>, baton=0xbffff3d0, pool=0x8066448)
    at subversion/libsvn_fs/trail.c:131
#5 0x400442fa in rep_write_get_baton (baton_p=0xbffff430, fs=0x80779c8,
    rep_key=0x808ba78 "1", txn_id=0x808b158 "1", trail=0x0, pool=0x8066448)
    at subversion/libsvn_fs/reps-strings.c:871
#6 0x400447bf in svn_fs__rep_contents_write_stream (ws_p=0xbffff464,
    fs=0x80779c8, rep_key=0x808ba78 "1", txn_id=0x808b158 "1", trail=0x0,
    pool=0x8066448) at subversion/libsvn_fs/reps-strings.c:1073
#7 0x4003ff02 in svn_fs__dag_get_edit_stream (contents=0x8066700,
    file=0x808b8b8, pool=0x8066448, txn_id=0x808b158 "1", trail=0x8066710)
    at subversion/libsvn_fs/dag.c:1313
#8 0x4004a8e5 in txn_body_apply_textdelta (baton=0x80666e8, trail=0x8066710)
    at subversion/libsvn_fs/tree.c:3134
#9 0x40046412 in svn_fs__retry_txn (fs=0x80779c8,
    txn_body=0x4004a7e8 <txn_body_apply_textdelta>, baton=0x80666e8,
    pool=0x8066448) at subversion/libsvn_fs/trail.c:131
#10 0x4004aa4b in svn_fs_apply_textdelta (contents_p=0xbffff55c,
    contents_baton_p=0xbffff558, root=0x8089150, path=0x805acc8 "beer.txt",
    pool=0x8066448) at subversion/libsvn_fs/tree.c:3173
#11 0x4001d9b1 in svn_test__set_file_contents (root=0x8089150,
    path=0x805acc8 "beer.txt",
    contents=0x8066480 "Wicki wild, wicki wicki wild.", pool=0x8066448)
    at subversion/tests/fs-helpers.c:176
#12 0x804aaea in write_and_read_file (msg=0xbffff5d0, msg_only=0,
    pool=0x8066448) at subversion/tests/libsvn_fs/fs-test.c:466
#13 0x40019f13 in do_test_num (progname=0xbffff82d "lt-fs-test", test_num=8,
    msg_only=0, pool=0x8066448) at subversion/tests/svn_tests_main.c:97
#14 0x4001a21c in main (argc=2, argv=0xbffff694)
    at subversion/tests/svn_tests_main.c:196
#15 0x4021bfd1 in __libc_start_main (main=0x8049a58 <main>, argc=2,
    ubp_av=0xbffff694, init=0x8049710 <_init>, fini=0x805a94c <_fini>,
    rtld_fini=0x4000e254 <_dl_fini>, stack_end=0xbffff68c)
    at ../sysdeps/generic/libc-start.c:118

-----------------------------------------------------------------------

   /*** PATCH IN PROGRESS; DO NOT USE IN A PRODUCTION BUILD ***/

More work on issue #649: Since it turns out we never need to append to
a non-empty rep, take away svn_fs_rep_contents_write_stream()'s
ability to do that. This means we will never have to resume
calculating a rep's checksum, which simplifies the task greatly.

Thanks to Brane and Bill Tutt for questioning the append behavior, and
Mike Pilato for sanity checks.

* subversion/include/svn_error_codes.h
  (SVN_ERR_FS_REP_NOT_EMPTY): New error code.

* subversion/libsvn_fs/reps-strings.h
  (svn_fs__rep_contents_write_stream): Return the stream by reference,
  via new parameter ws_p, so can return error directly. All callers
  changed.

* subversion/libsvn_fs/reps-strings.c
  (struct rep_size_args, txn_body_rep_size): New baton and function.
  (rep_write_get_baton): Return error if rep is not empty, and return
  baton by reference via new parameter baton_p.
  (svn_fs__rep_contents_write_stream): Don't clear the rep, just
  return error if rep_write_get_baton does, and return the stream by
  reference instead.
  (rep_contents_clear): Slate for removal.

Index: subversion/include/svn_error_codes.h
===================================================================
--- subversion/include/svn_error_codes.h (revision 4290)
+++ subversion/include/svn_error_codes.h (working copy)
@@ -453,6 +453,10 @@
               SVN_ERR_FS_CATEGORY_START + 30,
               "Berkeley DB deadlock error")
 
+ SVN_ERRDEF (SVN_ERR_FS_REP_NOT_EMPTY,
+ SVN_ERR_FS_CATEGORY_START + 31,
+ "Tried to obtain a write stream for a non-empty represntation")
+
   /* repos errors */
 
   SVN_ERRDEF (SVN_ERR_REPOS_LOCKED,
Index: subversion/libsvn_fs/reps-strings.c
===================================================================
--- subversion/libsvn_fs/reps-strings.c (revision 4290)
+++ subversion/libsvn_fs/reps-strings.c (working copy)
@@ -818,14 +818,62 @@
 };
 
 
-static struct rep_write_baton *
-rep_write_get_baton (svn_fs_t *fs,
+/* Baton for txn_body_rep_size(). */
+struct rep_size_args
+{
+ svn_fs_t *fs;
+ const char *rep_key;
+ apr_size_t size;
+};
+
+
+/* BATON is of type `rep_size_args'.
+ Set BATON->size to the size (length) of BATON->rep_key. */
+static svn_error_t *
+txn_body_rep_size (void *baton, trail_t *trail)
+{
+ struct rep_size_args *args = baton;
+ SVN_ERR (svn_fs__rep_contents_size (&(args->size), args->fs, args->rep_key,
+ trail));
+ return SVN_NO_ERROR;
+}
+
+
+static svn_error_t *
+rep_write_get_baton (struct rep_write_baton **baton_p,
+ svn_fs_t *fs,
                      const char *rep_key,
                      const char *txn_id,
                      trail_t *trail,
                      apr_pool_t *pool)
 {
   struct rep_write_baton *b;
+ apr_size_t size;
+
+ if (trail)
+ {
+ SVN_ERR (svn_fs__rep_contents_size (&size, fs, rep_key, trail));
+ if (size != 0)
+ return svn_error_createf
+ (SVN_ERR_FS_REP_NOT_EMPTY, NULL, "rep \"%s\" not empty", rep_key);
+ }
+ else
+ {
+ struct rep_size_args args;
+
+ args.fs = fs;
+ args.rep_key = rep_key;
+
+ /* Trails don't clear their own subpools. We could make a
+ subpool for this call, then destroy it immediately
+ afterwards... But I suspect that rep_write_batons get created
+ about as often as new reps do; in other words, no big deal. */
+ SVN_ERR (svn_fs__retry_txn (fs, txn_body_rep_size, &args, pool));
+
+ if (args.size != 0)
+ return svn_error_createf
+ (SVN_ERR_FS_REP_NOT_EMPTY, NULL, "rep \"%s\" not empty", rep_key);
+ }
 
   b = apr_pcalloc (pool, sizeof (*b));
   b->fs = fs;
@@ -833,7 +881,10 @@
   b->pool = pool;
   b->rep_key = rep_key;
   b->txn_id = txn_id;
- return b;
+
+ *baton_p = b;
+
+ return SVN_NO_ERROR;
 }
 
 
@@ -971,6 +1022,12 @@
 }
 
 
+#if 0 /* ### See comment at the only call to this function. */
+
+/* Clear the contents of REP_KEY, so that it represents the empty
+ string, as part of TRAIL. TXN_ID is the id of the Subversion
+ transaction under which this occurs. If REP_KEY is not mutable,
+ return the error SVN_ERR_FS_REP_NOT_MUTABLE. */
 static svn_error_t *
 rep_contents_clear (svn_fs_t *fs,
                     const char *rep_key,
@@ -1000,29 +1057,32 @@
     }
   return SVN_NO_ERROR;
 }
+#endif /* 0 */
 
 
-
-svn_stream_t *
-svn_fs__rep_contents_write_stream (svn_fs_t *fs,
+svn_error_t *
+svn_fs__rep_contents_write_stream (svn_stream_t **ws_p,
+ svn_fs_t *fs,
                                    const char *rep_key,
                                    const char *txn_id,
                                    trail_t *trail,
                                    apr_pool_t *pool)
 {
- struct rep_write_baton *wb
- = rep_write_get_baton (fs, rep_key, txn_id, trail, pool);
-
- svn_stream_t *ws = svn_stream_create (wb, pool);
- svn_stream_set_write (ws, rep_write_contents);
+ struct rep_write_baton *wb;
 
- /* ### todo: This is yicky, but should be fixed in a forthcoming
- commit by kfogel, who is making this function return an
- svn_error_t *. */
- if (trail && rep_contents_clear (fs, rep_key, txn_id, trail))
- return NULL;
+#if 0
+ /* ### This shouldn't be necessary anymore; leaving it here while
+ testing the patch. Note that this is the only caller of
+ rep_contents_clear(). */
+ if (trail)
+ SVN_ERR (rep_contents_clear (fs, rep_key, txn_id, trail));
+#endif /* 0 */
+
+ SVN_ERR (rep_write_get_baton (&wb, fs, rep_key, txn_id, trail, pool));
+ *ws_p = svn_stream_create (wb, pool);
+ svn_stream_set_write (*ws_p, rep_write_contents);
 
- return ws;
+ return SVN_NO_ERROR;
 }
 
 
Index: subversion/libsvn_fs/reps-strings.h
===================================================================
--- subversion/libsvn_fs/reps-strings.h (revision 4290)
+++ subversion/libsvn_fs/reps-strings.h (working copy)
@@ -98,23 +98,25 @@
                                                 apr_pool_t *pool);
 
                                        
-/* Return a stream to write new contents of REP_KEY. Allocate the
- stream in POOL. TXN_ID is the id of the Subversion transaction
+/* Set *WS_P to a stream to write the contents of REP_KEY. Allocate
+ the stream in POOL. TXN_ID is the id of the Subversion transaction
    under which this occurs.
 
- If the rep already has contents, they will be cleared.
-
    If TRAIL is non-null, the stream's writes are part of TRAIL;
    otherwise, each write happens in an internal, one-off trail.
    POOL may be TRAIL->pool.
 
- If REP_KEY is not mutable, writes will return the error
- SVN_ERR_FS_REP_NOT_MUTABLE. */
-svn_stream_t *svn_fs__rep_contents_write_stream (svn_fs_t *fs,
- const char *rep_key,
- const char *txn_id,
- trail_t *trail,
- apr_pool_t *pool);
+ If REP_KEY is not empty, return SVN_ERR_FS_REP_NOT_EMPTY.
+
+ If REP_KEY is not mutable, writes to *WS_P will return the
+ error SVN_ERR_FS_REP_NOT_MUTABLE. */
+svn_error_t *svn_fs__rep_contents_write_stream (svn_stream_t **ws_p,
+ svn_fs_t *fs,
+ const char *rep_key,
+ const char *txn_id,
+ trail_t *trail,
+ apr_pool_t *pool);
+
 
 
 /*** Deltified storage. ***/
Index: subversion/libsvn_fs/dag.c
===================================================================
--- subversion/libsvn_fs/dag.c (revision 4290)
+++ subversion/libsvn_fs/dag.c (working copy)
@@ -563,8 +563,8 @@
   /* Finally, replace the old entries list with the new one. */
   SVN_ERR (svn_fs__unparse_entries_skel (&entries_skel, entries, trail->pool));
   raw_entries_buf = svn_fs__unparse_skel (entries_skel, trail->pool);
- wstream = svn_fs__rep_contents_write_stream (fs, mutable_rep_key, txn_id,
- trail, trail->pool);
+ SVN_ERR (svn_fs__rep_contents_write_stream (&wstream, fs, mutable_rep_key,
+ txn_id, trail, trail->pool));
   len = raw_entries_buf->len;
   svn_stream_write (wstream, raw_entries_buf->data, &len);
   return SVN_NO_ERROR;
@@ -748,8 +748,8 @@
     SVN_ERR (svn_fs__unparse_proplist_skel (&proplist_skel, proplist,
                                             trail->pool));
     raw_proplist_buf = svn_fs__unparse_skel (proplist_skel, trail->pool);
- wstream = svn_fs__rep_contents_write_stream (fs, mutable_rep_key, txn_id,
- trail, trail->pool);
+ SVN_ERR (svn_fs__rep_contents_write_stream (&wstream, fs, mutable_rep_key,
+ txn_id, trail, trail->pool));
     len = raw_proplist_buf->len;
     SVN_ERR (svn_stream_write (wstream, raw_proplist_buf->data, &len));
   }
@@ -1032,8 +1032,8 @@
     SVN_ERR (svn_fs__unparse_entries_skel (&entries_skel, entries,
                                            trail->pool));
     unparsed_entries = svn_fs__unparse_skel (entries_skel, trail->pool);
- ws = svn_fs__rep_contents_write_stream (fs, mutable_rep_key, txn_id,
- trail, trail->pool);
+ SVN_ERR (svn_fs__rep_contents_write_stream (&ws, fs, mutable_rep_key,
+ txn_id, trail, trail->pool));
     len = unparsed_entries->len;
     SVN_ERR (svn_stream_write (ws, unparsed_entries->data, &len));
   }
@@ -1309,8 +1309,8 @@
   SVN_ERR (svn_fs__bdb_put_node_revision (fs, file->id, noderev, trail));
 
   /* Return a writable stream with which to set new contents. */
- ws = svn_fs__rep_contents_write_stream (fs, mutable_rep_key, txn_id,
- NULL, pool);
+ SVN_ERR (svn_fs__rep_contents_write_stream (&ws, fs, mutable_rep_key,
+ txn_id, NULL, pool));
   *contents = ws;
 
   return SVN_NO_ERROR;

---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@subversion.tigris.org
For additional commands, e-mail: dev-help@subversion.tigris.org
Received on Wed Jan 8 06:34:50 2003

This is an archived mail posted to the Subversion Dev mailing list.