On Wed, May 27, 2009 at 4:48 PM, Hyrum K.
Wright<hyrum_wright_at_mail.utexas.edu> wrote:
>
> On May 27, 2009, at 3:17 PM, Paul T. Burba wrote:
>
>> Author: pburba
>> Date: Wed May 27 13:17:53 2009
>> New Revision: 37868
>>
>> Log:
>> Make svn_hash_read2 and svn_hash_read_incremental more memory efficient.
>>
>> * subversion/libsvn_subr/hash.c
>> Â (hash_read): Use an iterpool for temporary allocations.
>>
>> Modified:
>> Â trunk/subversion/libsvn_subr/hash.c
>>
>> Modified: trunk/subversion/libsvn_subr/hash.c
>> URL:
>> http://svn.collab.net/viewvc/svn/trunk/subversion/libsvn_subr/hash.c?pathrev=37868&r1=37867&r2=37868
>>
>> ==============================================================================
>> --- trunk/subversion/libsvn_subr/hash.c Wed May 27 12:30:14 2009
>> Â (r37867)
>> +++ trunk/subversion/libsvn_subr/hash.c Wed May 27 13:17:53 2009
>> Â (r37868)
>> @@ -85,27 +85,37 @@ hash_read(apr_hash_t *hash, svn_stream_t
>> Â svn_boolean_t eof;
>> Â apr_size_t len, keylen, vallen;
>> Â char c, *end, *keybuf, *valbuf;
>> + Â svn_error_t *err = SVN_NO_ERROR;
>> + Â apr_pool_t *iterpool = svn_pool_create(pool);
>>
>> Â while (1)
>> Â Â {
>> + Â Â Â svn_pool_clear(iterpool);
>> +
>> Â Â Â /* Read a key length line. Â Might be END, though. */
>> - Â Â Â SVN_ERR(svn_stream_readline(stream, &buf, "\n", &eof, pool));
>> + Â Â Â SVN_ERR(svn_stream_readline(stream, &buf, "\n", &eof, iterpool));
>>
>> Â Â Â /* Check for the end of the hash. */
>> Â Â Â if ((!terminator && eof && buf->len == 0)
>> Â Â Â Â Â || (terminator && (strcmp(buf->data, terminator) == 0)))
>> - Â Â Â Â return SVN_NO_ERROR;
>> + Â Â Â Â break;
>>
>> Â Â Â /* Check for unexpected end of stream */
>> Â Â Â if (eof)
>> - Â Â Â Â return svn_error_create(SVN_ERR_MALFORMED_FILE, NULL, NULL);
>> + Â Â Â Â {
>> + Â Â Â Â Â err = svn_error_create(SVN_ERR_MALFORMED_FILE, NULL, NULL);
>> + Â Â Â Â Â break;
>> + Â Â Â Â }
>>
>> Â Â Â if ((buf->len >= 3) && (buf->data[0] == 'K') && (buf->data[1] == '
>> '))
>> Â Â Â Â {
>> Â Â Â Â Â /* Get the length of the key */
>> Â Â Â Â Â keylen = (size_t) strtoul(buf->data + 2, &end, 10);
>> Â Â Â Â Â if (keylen == (size_t) ULONG_MAX || *end != '\0')
>> - Â Â Â Â Â Â return svn_error_create(SVN_ERR_MALFORMED_FILE, NULL, NULL);
>> + Â Â Â Â Â Â {
>> + Â Â Â Â Â Â Â err = svn_error_create(SVN_ERR_MALFORMED_FILE, NULL, NULL);
>> + Â Â Â Â Â Â Â break;
>> + Â Â Â Â Â Â }
>>
>> Â Â Â Â Â /* Now read that much into a buffer. */
>> Â Â Â Â Â keybuf = apr_palloc(pool, keylen + 1);
>> @@ -116,18 +126,24 @@ hash_read(apr_hash_t *hash, svn_stream_t
>> Â Â Â Â Â len = 1;
>> Â Â Â Â Â SVN_ERR(svn_stream_read(stream, &c, &len));
>> Â Â Â Â Â if (c != '\n')
>> - Â Â Â Â Â Â return svn_error_create(SVN_ERR_MALFORMED_FILE, NULL, NULL);
>> + Â Â Â Â Â Â {
>> + Â Â Â Â Â Â Â err = svn_error_create(SVN_ERR_MALFORMED_FILE, NULL, NULL);
>> + Â Â Â Â Â Â Â break;
>> + Â Â Â Â Â Â }
>>
>> Â Â Â Â Â /* Read a val length line */
>> - Â Â Â Â Â SVN_ERR(svn_stream_readline(stream, &buf, "\n", &eof, pool));
>> + Â Â Â Â Â SVN_ERR(svn_stream_readline(stream, &buf, "\n", &eof,
>> iterpool));
>>
>> Â Â Â Â Â if ((buf->data[0] == 'V') && (buf->data[1] == ' '))
>> Â Â Â Â Â Â {
>> Â Â Â Â Â Â Â vallen = (size_t) strtoul(buf->data + 2, &end, 10);
>> Â Â Â Â Â Â Â if (vallen == (size_t) ULONG_MAX || *end != '\0')
>> - Â Â Â Â Â Â Â Â return svn_error_create(SVN_ERR_MALFORMED_FILE, NULL,
>> NULL);
>> + Â Â Â Â Â Â Â Â {
>> + Â Â Â Â Â Â Â Â Â err = svn_error_create(SVN_ERR_MALFORMED_FILE, NULL,
>> NULL);
>> + Â Â Â Â Â Â Â Â Â break;
>> + Â Â Â Â Â Â Â Â }
>>
>> - Â Â Â Â Â Â Â valbuf = apr_palloc(pool, vallen + 1);
>> + Â Â Â Â Â Â Â valbuf = apr_palloc(iterpool, vallen + 1);
>> Â Â Â Â Â Â Â SVN_ERR(svn_stream_read(stream, valbuf, &vallen));
>> Â Â Â Â Â Â Â valbuf[vallen] = '\0';
>>
>> @@ -135,14 +151,20 @@ hash_read(apr_hash_t *hash, svn_stream_t
>> Â Â Â Â Â Â Â len = 1;
>> Â Â Â Â Â Â Â SVN_ERR(svn_stream_read(stream, &c, &len));
>> Â Â Â Â Â Â Â if (c != '\n')
>> - Â Â Â Â Â Â Â Â return svn_error_create(SVN_ERR_MALFORMED_FILE, NULL,
>> NULL);
>> + Â Â Â Â Â Â Â Â {
>> + Â Â Â Â Â Â Â Â Â err = svn_error_create(SVN_ERR_MALFORMED_FILE, NULL,
>> NULL);
>> + Â Â Â Â Â Â Â Â Â break;
>> + Â Â Â Â Â Â Â Â }
>>
>> Â Â Â Â Â Â Â /* Add a new hash entry. */
>> Â Â Â Â Â Â Â apr_hash_set(hash, keybuf, keylen,
>> Â Â Â Â Â Â Â Â Â Â Â Â Â svn_string_ncreate(valbuf, vallen, pool));
>> Â Â Â Â Â Â }
>> Â Â Â Â Â else
>> - Â Â Â Â Â Â return svn_error_create(SVN_ERR_MALFORMED_FILE, NULL, NULL);
>> + Â Â Â Â Â Â {
>> + Â Â Â Â Â Â Â err = svn_error_create(SVN_ERR_MALFORMED_FILE, NULL, NULL);
>> + Â Â Â Â Â Â Â break;
>> + Â Â Â Â Â Â }
>> Â Â Â Â }
>> Â Â Â else if (incremental && (buf->len >= 3)
>> Â Â Â Â Â Â Â && (buf->data[0] == 'D') && (buf->data[1] == ' '))
>> @@ -153,7 +175,7 @@ hash_read(apr_hash_t *hash, svn_stream_t
>> Â Â Â Â Â Â return svn_error_create(SVN_ERR_MALFORMED_FILE, NULL, NULL);
>>
>> Â Â Â Â Â /* Now read that much into a buffer. */
>> - Â Â Â Â Â keybuf = apr_palloc(pool, keylen + 1);
>> + Â Â Â Â Â keybuf = apr_palloc(iterpool, keylen + 1);
>> Â Â Â Â Â SVN_ERR(svn_stream_read(stream, keybuf, &keylen));
>> Â Â Â Â Â keybuf[keylen] = '\0';
>>
>> @@ -161,14 +183,23 @@ hash_read(apr_hash_t *hash, svn_stream_t
>> Â Â Â Â Â len = 1;
>> Â Â Â Â Â SVN_ERR(svn_stream_read(stream, &c, &len));
>> Â Â Â Â Â if (c != '\n')
>> - Â Â Â Â Â Â return svn_error_create(SVN_ERR_MALFORMED_FILE, NULL, NULL);
>> + Â Â Â Â Â Â {
>> + Â Â Â Â Â Â Â err = svn_error_create(SVN_ERR_MALFORMED_FILE, NULL, NULL);
>> + Â Â Â Â Â Â Â break;
>> + Â Â Â Â Â Â }
>>
>> Â Â Â Â Â /* Remove this hash entry. */
>> Â Â Â Â Â apr_hash_set(hash, keybuf, keylen, NULL);
>> Â Â Â Â }
>> Â Â Â else
>> - Â Â Â Â return svn_error_create(SVN_ERR_MALFORMED_FILE, NULL, NULL);
>> + Â Â Â Â {
>> + Â Â Â Â Â err = svn_error_create(SVN_ERR_MALFORMED_FILE, NULL, NULL);
>> + Â Â Â Â Â break;
>> + Â Â Â Â }
>> Â Â }
>> +
>> + Â svn_pool_destroy(iterpool);
>> + Â return err;
>
> Not a big deal, but the above should be:
> return svn_error_return(err)
>
> This ensures we get proper debug tracing even when directly returning
> errors.
>
>> ...
>
> I'm a little unsure why the whole break-on-error dance was needed. Â We have
> an pretty established habit of just returning errors from within loops and
> not destroying the loop pool. Â Usually, the loop pool isn't very big, and
> it'll get destroyed along with it's parent when the error gets handled.
Hi Hyrum,
Agreed, I was getting a bit out of hand with pool cleanup there.
r37979 returns to previous behavior of returning error from within the
loop.
Thanks,
Paul
------------------------------------------------------
http://subversion.tigris.org/ds/viewMessage.do?dsForumId=462&dsMessageId=2360947
Received on 2009-06-10 16:55:58 CEST