subversion-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From stef...@apache.org
Subject svn commit: r1717427 - in /subversion/trunk/subversion: include/svn_error_codes.h libsvn_fs_x/cached_data.c libsvn_fs_x/low_level.c libsvn_fs_x/low_level.h libsvn_fs_x/transaction.c
Date Tue, 01 Dec 2015 13:15:06 GMT
Author: stefan2
Date: Tue Dec  1 13:15:06 2015
New Revision: 1717427

URL: http://svn.apache.org/viewvc?rev=1717427&view=rev
Log:
In FSX, introduce a denser and easier to parse on-disk representation
for property lists.  In a first step, use it for node properties.

* subversion/include/svn_error_codes.h
  (SVN_ERR_FS_CORRUPT_PROPLIST): Define a new parser error code.

* subversion/libsvn_fs_x/low_level.h
  (svn_fs_x__parse_properties,
   svn_fs_x__write_properties): Declare new internal (de-)serialization APIs.

* subversion/libsvn_fs_x/low_level.c
  (svn_fs_x__parse_properties,
   svn_fs_x__write_properties): Implement them.

* subversion/libsvn_fs_x/cached_data.c
  (svn_fs_x__get_proplist): Call the new APIs to parse the prop lists.
                            Use the SVN_ERR_W macro instead of local code
                            for decorating error objects.

* subversion/libsvn_fs_x/transaction.c
  (svn_fs_x__set_proplist,
   write_hash_to_stream): Write node properties in the new format.

Modified:
    subversion/trunk/subversion/include/svn_error_codes.h
    subversion/trunk/subversion/libsvn_fs_x/cached_data.c
    subversion/trunk/subversion/libsvn_fs_x/low_level.c
    subversion/trunk/subversion/libsvn_fs_x/low_level.h
    subversion/trunk/subversion/libsvn_fs_x/transaction.c

Modified: subversion/trunk/subversion/include/svn_error_codes.h
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/include/svn_error_codes.h?rev=1717427&r1=1717426&r2=1717427&view=diff
==============================================================================
--- subversion/trunk/subversion/include/svn_error_codes.h (original)
+++ subversion/trunk/subversion/include/svn_error_codes.h Tue Dec  1 13:15:06 2015
@@ -873,6 +873,11 @@ SVN_ERROR_START
              SVN_ERR_FS_CATEGORY_START + 64,
              "Revprop manifest corrupt.")
 
+  /** @since New in 1.10. */
+  SVN_ERRDEF(SVN_ERR_FS_CORRUPT_PROPLIST,
+             SVN_ERR_FS_CATEGORY_START + 65,
+             "Property list is corrupt.")
+
   /* repos errors */
 
   SVN_ERRDEF(SVN_ERR_REPOS_LOCKED,

Modified: subversion/trunk/subversion/libsvn_fs_x/cached_data.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_fs_x/cached_data.c?rev=1717427&r1=1717426&r2=1717427&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_fs_x/cached_data.c (original)
+++ subversion/trunk/subversion/libsvn_fs_x/cached_data.c Tue Dec  1 13:15:06 2015
@@ -30,6 +30,7 @@
 
 #include "private/svn_io_private.h"
 #include "private/svn_sorts_private.h"
+#include "private/svn_string_private.h"
 #include "private/svn_subr_private.h"
 #include "private/svn_temp_serializer.h"
 
@@ -2727,89 +2728,71 @@ svn_fs_x__rep_contents_dir_entry(svn_fs_
 }
 
 svn_error_t *
-svn_fs_x__get_proplist(apr_hash_t **proplist_p,
+svn_fs_x__get_proplist(apr_hash_t **proplist,
                        svn_fs_t *fs,
                        svn_fs_x__noderev_t *noderev,
                        apr_pool_t *result_pool,
                        apr_pool_t *scratch_pool)
 {
-  apr_hash_t *proplist;
   svn_stream_t *stream;
   const svn_fs_x__id_t *noderev_id = &noderev->noderev_id;
-  svn_error_t *err;
 
   if (noderev->prop_rep
       && !svn_fs_x__is_revision(noderev->prop_rep->id.change_set))
     {
+      svn_stringbuf_t *content;
+      svn_string_t *as_string;
       const char *filename = svn_fs_x__path_txn_node_props(fs, noderev_id,
                                                            scratch_pool,
                                                            scratch_pool);
-      proplist = apr_hash_make(result_pool);
-
-      SVN_ERR(svn_stream_open_readonly(&stream, filename, scratch_pool,
-                                       scratch_pool));
-      err = svn_hash_read2(proplist, stream, SVN_HASH_TERMINATOR,
-                          result_pool);
-      if (err)
-        {
-          svn_string_t *id_str = svn_fs_x__id_unparse(&noderev->noderev_id,
-                                                      scratch_pool);
-
-          err = svn_error_compose_create(err, svn_stream_close(stream));
-          return svn_error_quick_wrapf(err,
-                   _("malformed property list for node-revision '%s' in '%s'"),
-                   id_str->data, filename);
-        }
+      SVN_ERR(svn_stringbuf_from_file2(&content, filename, result_pool));
 
-      SVN_ERR(svn_stream_close(stream));
+      as_string = svn_stringbuf__morph_into_string(content);
+      SVN_ERR_W(svn_fs_x__parse_properties(proplist, as_string, result_pool),
+                apr_psprintf(scratch_pool,
+                    "malformed property list for node-revision '%s' in '%s'",
+                    svn_fs_x__id_unparse(&noderev->noderev_id,
+                                         scratch_pool)->data,
+                    filename));
     }
   else if (noderev->prop_rep)
     {
       svn_fs_x__data_t *ffd = fs->fsap_data;
       svn_fs_x__representation_t *rep = noderev->prop_rep;
       svn_fs_x__pair_cache_key_t key = { 0 };
+      svn_string_t *content;
 
       key.revision = svn_fs_x__get_revnum(rep->id.change_set);
       key.second = rep->id.number;
       if (SVN_IS_VALID_REVNUM(key.revision))
         {
           svn_boolean_t is_cached;
-          SVN_ERR(svn_cache__get((void **) proplist_p, &is_cached,
+          SVN_ERR(svn_cache__get((void **) proplist, &is_cached,
                                  ffd->properties_cache, &key, result_pool));
           if (is_cached)
             return SVN_NO_ERROR;
         }
 
-      proplist = apr_hash_make(result_pool);
-      SVN_ERR(svn_fs_x__get_contents(&stream, fs, noderev->prop_rep, FALSE,
-                                     scratch_pool));
-      err = svn_hash_read2(proplist, stream, SVN_HASH_TERMINATOR,
-                           result_pool);
-      if (err)
-        {
-          svn_string_t *id_str = svn_fs_x__id_unparse(&noderev->noderev_id,
-                                                      scratch_pool);
-
-          err = svn_error_compose_create(err, svn_stream_close(stream));
-          return svn_error_quick_wrapf(err,
-                   _("malformed property list for node-revision '%s'"),
-                   id_str->data);
-        }
-
-      SVN_ERR(svn_stream_close(stream));
+      SVN_ERR(svn_fs_x__get_contents(&stream, fs, rep, FALSE, scratch_pool));
+      SVN_ERR(svn_string_from_stream2(&content, stream, rep->expanded_size,
+                                      result_pool));
+
+      SVN_ERR_W(svn_fs_x__parse_properties(proplist, content, result_pool),
+                apr_psprintf(scratch_pool,
+                    "malformed property list for node-revision '%s'",
+                    svn_fs_x__id_unparse(&noderev->noderev_id,
+                                         scratch_pool)->data));
 
       if (SVN_IS_VALID_REVNUM(rep->id.change_set))
-        SVN_ERR(svn_cache__set(ffd->properties_cache, &key, proplist,
+        SVN_ERR(svn_cache__set(ffd->properties_cache, &key, *proplist,
                                scratch_pool));
     }
   else
     {
       /* return an empty prop list if the node doesn't have any props */
-      proplist = apr_hash_make(result_pool);
+      *proplist = apr_hash_make(result_pool);
     }
 
-  *proplist_p = proplist;
-
   return SVN_NO_ERROR;
 }
 

Modified: subversion/trunk/subversion/libsvn_fs_x/low_level.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_fs_x/low_level.c?rev=1717427&r1=1717426&r2=1717427&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_fs_x/low_level.c (original)
+++ subversion/trunk/subversion/libsvn_fs_x/low_level.c Tue Dec  1 13:15:06 2015
@@ -1146,3 +1146,107 @@ svn_fs_x__write_changes(svn_stream_t *st
   return SVN_NO_ERROR;
 }
 
+svn_error_t *
+svn_fs_x__parse_properties(apr_hash_t **properties,
+                           svn_string_t *content,
+                           apr_pool_t *result_pool)
+{
+  const apr_byte_t *p = (const apr_byte_t *)content->data;
+  const apr_byte_t *end = p + content->len;
+  apr_uint64_t count;
+
+  *properties = apr_hash_make(result_pool);
+
+  /* Extract the number of properties we are expected to read. */
+  p = svn__decode_uint(&count, p, end);
+
+  /* Read all the properties we find.
+     Because prop-name and prop-value are nicely NUL-terminated
+     sub-strings of CONTENT, we can simply reference them there.
+     I.e. there is no need to copy them around.
+   */
+  while (p < end)
+    {
+      apr_uint64_t value_len;
+      svn_string_t *value;
+
+      const char *key = (const char *)p;
+
+      /* Note that this may never overflow / segfault because
+         CONTENT itself is NUL-terminated. */
+      apr_size_t key_len = strlen(key);
+      p += key_len + 1;
+      if (key[key_len])
+        return svn_error_createf(SVN_ERR_FS_CORRUPT_PROPLIST, NULL,
+                                 "Property name not NUL terminated");
+
+      if (p >= end)
+        return svn_error_createf(SVN_ERR_FS_CORRUPT_PROPLIST, NULL,
+                                 "Property value missing");
+      p = svn__decode_uint(&value_len, p, end);
+      if (value_len >= (end - p))
+        return svn_error_createf(SVN_ERR_FS_CORRUPT_PROPLIST, NULL,
+                                 "Property value too long");
+
+      value = apr_pcalloc(result_pool, sizeof(*value));
+      value->data = (const char *)p;
+      value->len = (apr_size_t)value_len;
+      if (p[value->len])
+        return svn_error_createf(SVN_ERR_FS_CORRUPT_PROPLIST, NULL,
+                                 "Property value not NUL terminated");
+
+      p += value->len + 1;
+
+      apr_hash_set(*properties, key, key_len, value);
+    }
+
+  /* Check that we read the expected number of properties. */
+  if ((apr_uint64_t)apr_hash_count(*properties) != count)
+    return svn_error_createf(SVN_ERR_FS_CORRUPT_PROPLIST, NULL,
+                             "Property count mismatch");
+
+  return SVN_NO_ERROR;
+}
+
+svn_error_t *
+svn_fs_x__write_properties(svn_stream_t *stream,
+                           apr_hash_t *proplist,
+                           apr_pool_t *scratch_pool)
+{
+  apr_byte_t buffer[SVN__MAX_ENCODED_UINT_LEN];
+  apr_size_t len;
+  apr_hash_index_t *hi;
+
+  /* Write the number of properties in this list. */
+  len = svn__encode_uint(buffer, apr_hash_count(proplist)) - buffer;
+  SVN_ERR(svn_stream_write(stream, (const char *)buffer, &len));
+
+  /* Serialize each property as follows:
+     <Prop-name> <NUL>
+     <Value-len> <Prop-value> <NUL>
+   */
+  for (hi = apr_hash_first(scratch_pool, proplist);
+       hi;
+       hi = apr_hash_next(hi))
+    {
+      const char *key;
+      apr_size_t key_len;
+      svn_string_t *value;
+      apr_hash_this(hi, (const void **)&key, (apr_ssize_t *)&key_len,
+                    (void **)&value);
+
+      /* Include the terminating NUL. */
+      ++key_len;
+      SVN_ERR(svn_stream_write(stream, key, &key_len));
+
+      len = svn__encode_uint(buffer, value->len) - buffer;
+      SVN_ERR(svn_stream_write(stream, (const char *)buffer, &len));
+      SVN_ERR(svn_stream_write(stream, value->data, &value->len));
+
+      /* Terminate with NUL. */
+      len = 1;
+      SVN_ERR(svn_stream_write(stream, "", &len));
+    }
+
+  return SVN_NO_ERROR;
+}

Modified: subversion/trunk/subversion/libsvn_fs_x/low_level.h
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_fs_x/low_level.h?rev=1717427&r1=1717426&r2=1717427&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_fs_x/low_level.h (original)
+++ subversion/trunk/subversion/libsvn_fs_x/low_level.h Tue Dec  1 13:15:06 2015
@@ -210,6 +210,23 @@ svn_fs_x__write_changes(svn_stream_t *st
                         svn_boolean_t terminate_list,
                         apr_pool_t *scratch_pool);
 
+/* Parse the property list serialized in CONTENT and return it in
+   *PROPERTIES, allocated from RESULT_POOL.  CONTENT must remain
+   valid at least until the next cleanup of RESULT_POOL.
+ */
+svn_error_t *
+svn_fs_x__parse_properties(apr_hash_t **properties,
+                           svn_string_t *content,
+                           apr_pool_t *result_pool);
+
+/* Write the property list PROPLIST to STREAM in serialized format.
+   Use SCRATCH_POOL for temporary allocations.
+ */
+svn_error_t *
+svn_fs_x__write_properties(svn_stream_t *stream,
+                           apr_hash_t *proplist,
+                           apr_pool_t *scratch_pool);
+
 #ifdef __cplusplus
 }
 #endif /* __cplusplus */

Modified: subversion/trunk/subversion/libsvn_fs_x/transaction.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_fs_x/transaction.c?rev=1717427&r1=1717426&r2=1717427&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_fs_x/transaction.c (original)
+++ subversion/trunk/subversion/libsvn_fs_x/transaction.c Tue Dec  1 13:15:06 2015
@@ -2680,7 +2680,7 @@ svn_fs_x__set_proplist(svn_fs_t *fs,
                            APR_WRITE | APR_CREATE | APR_TRUNCATE
                            | APR_BUFFERED, APR_OS_DEFAULT, scratch_pool));
   out = svn_stream_from_aprfile2(file, TRUE, scratch_pool);
-  SVN_ERR(svn_hash_write2(proplist, out, SVN_HASH_TERMINATOR, scratch_pool));
+  SVN_ERR(svn_fs_x__write_properties(out, proplist, scratch_pool));
   SVN_ERR(svn_io_file_close(file, scratch_pool));
 
   /* Mark the node-rev's prop rep as mutable, if not already done. */
@@ -2747,7 +2747,7 @@ write_hash_to_stream(svn_stream_t *strea
                      apr_pool_t *scratch_pool)
 {
   apr_hash_t *hash = baton;
-  SVN_ERR(svn_hash_write2(hash, stream, SVN_HASH_TERMINATOR, scratch_pool));
+  SVN_ERR(svn_fs_x__write_properties(stream, hash, scratch_pool));
 
   return SVN_NO_ERROR;
 }



Mime
View raw message