FreeBSD/contrib/subversion/subversion/libsvn_fs_fs/transaction.c
/* Given a node-revision NODEREV in filesystem FS, return the
   representation in *REP to use as the base for a text representation
   delta if PROPS is FALSE.  If PROPS has been set, a suitable props
   base representation will be returned.  Perform temporary allocations
   in *POOL. */
Given a node-revision NODEREV in filesystem FS, return the
representation in *REP to use as the base for a text representation
delta if PROPS is FALSE.  If PROPS has been set, a suitable props
base representation will be returned.  Perform temporary allocations
in *POOL.
Given a node - revision NODEREV in filesystem FS return the representation in * REP to use as the base for a text representation delta if PROPS is FALSE . If PROPS has been set a suitable props base representation will be returned . Perform temporary allocations in * POOL .
static svn_error_t *
choose_delta_base(representation_t **rep,
                  svn_fs_t *fs,
                  node_revision_t *noderev,
                  svn_boolean_t props,
                  apr_pool_t *pool)
{
  int count;
  int walk;
  node_revision_t *base;
  fs_fs_data_t *ffd = fs->fsap_data;
  apr_pool_t *iterpool;
  if (! noderev->predecessor_count)
    {
      *rep = NULL;
      return SVN_NO_ERROR;
    }
  count = noderev->predecessor_count;
  count = count & (count - 1);
  walk = noderev->predecessor_count - count;
  if (walk > (int)ffd->max_deltification_walk)
    {
      *rep = NULL;
      return SVN_NO_ERROR;
    }
  if (walk < (int)ffd->max_linear_deltification)
    {
      int shards;
      SVN_ERR(shards_spanned(&shards, fs, noderev, walk, pool));
      if ((1 << (--shards)) <= walk)
        count = noderev->predecessor_count - 1;
    }
  base = noderev;
  iterpool = svn_pool_create(pool);
  while ((count++) < noderev->predecessor_count)
    {
      svn_pool_clear(iterpool);
      SVN_ERR(svn_fs_fs__get_node_revision(&base, fs,
                                           base->predecessor_id, pool,
                                           iterpool));
    }
  svn_pool_destroy(iterpool);
  *rep = props ? base->prop_rep : base->data_rep;
  if (*rep)
    {
      int chain_length = 0;
      int shard_count = 0;
      svn_filesize_t rep_size = (*rep)->expanded_size
                              ? (*rep)->expanded_size
                              : (*rep)->size;
      if (rep_size < 64)
        {
          *rep = NULL;
          return SVN_NO_ERROR;
        }
      SVN_ERR(svn_fs_fs__rep_chain_length(&chain_length, &shard_count,
                                          *rep, fs, pool));
      if (chain_length >= 2 * (int)ffd->max_linear_deltification + 2)
        *rep = NULL;
      else
        if (   shard_count > 1
            && ((svn_filesize_t)128 << shard_count) >= rep_size)
          *rep = NULL;
    }
  return SVN_NO_ERROR;
}
static svn_error_t * choose_delta_base ( representation_t * * rep , svn_fs_t * fs , node_revision_t * noderev , svn_boolean_t props , apr_pool_t * pool ) { int count ; int walk ; node_revision_t * base ; fs_fs_data_t * ffd = fs -> fsap_data ; apr_pool_t * iterpool ; if ( ! noderev -> predecessor_count ) { * rep = NULL ; return SVN_NO_ERROR ; } count = noderev -> predecessor_count ; count = count & ( count - 1 ) ; walk = noderev -> predecessor_count - count ; if ( walk > ( int ) ffd -> max_deltification_walk ) { * rep = NULL ; return SVN_NO_ERROR ; } if ( walk < ( int ) ffd -> max_linear_deltification ) { int shards ; SVN_ERR ( shards_spanned ( & shards , fs , noderev , walk , pool ) ) ; if ( ( 1 << ( -- shards ) ) <= walk ) count = noderev -> predecessor_count - 1 ; } base = noderev ; iterpool = svn_pool_create ( pool ) ; while ( ( count ++ ) < noderev -> predecessor_count ) { svn_pool_clear ( iterpool ) ; SVN_ERR ( svn_fs_fs__get_node_revision ( & base , fs , base -> predecessor_id , pool , iterpool ) ) ; } svn_pool_destroy ( iterpool ) ; * rep = props ? base -> prop_rep : base -> data_rep ; if ( * rep ) { int chain_length = 0 ; int shard_count = 0 ; svn_filesize_t rep_size = ( * rep ) -> expanded_size ? ( * rep ) -> expanded_size : ( * rep ) -> size ; if ( rep_size < 64 ) { * rep = NULL ; return SVN_NO_ERROR ; } SVN_ERR ( svn_fs_fs__rep_chain_length ( & chain_length , & shard_count , * rep , fs , pool ) ) ; if ( chain_length >= 2 * ( int ) ffd -> max_linear_deltification + 2 ) * rep = NULL ; else if ( shard_count > 1 && ( ( svn_filesize_t ) 128 << shard_count ) >= rep_size ) * rep = NULL ; } return SVN_NO_ERROR ; }
Given a node-revision NODEREV in filesystem FS, return the
representation in *REP to use as the base for a text representation
delta if PROPS is FALSE.
Given a node - revision NODEREV in filesystem FS return the representation in * REP to use as the base for a text representation delta if PROPS is FALSE .
/* The zero-based index (counting from the "oldest" end), along NODEREVs line
   * predecessors, of the node-rev we will use as delta base. */ /* The length of the linear part of a delta chain.  (Delta chains use
   * skip-delta bits for the high-order bits and are linear in the low-order
   * bits.) */ /* If we have no predecessors, or that one is empty, then use the empty
   * stream as a base. */ /* Flip the rightmost '1' bit of the predecessor count to determine
     which file rev (counting from 0) we want to use.  (To see why
     count & (count - 1) unsets the rightmost set bit, think about how
     you decrement a binary number.) */ /* Finding the delta base over a very long distance can become extremely
     expensive for very deep histories, possibly causing client timeouts etc.
     OTOH, this is a rare operation and its gains are minimal. Lets simply
     start deltification anew close every other 1000 changes or so.  */ /* We use skip delta for limiting the number of delta operations
     along very long node histories.  Close to HEAD however, we create
     a linear history to minimize delta size.  */ /* We also don't want the linear deltification to span more shards
         than if deltas we used in a simple skip-delta scheme. */ /* Walk back a number of predecessors equal to the difference
     between count and the original predecessor count.  (For example,
     if noderev has ten predecessors and we want the eighth file rev,
     walk back two predecessors.) */ /* return a suitable base representation */ /* if we encountered a shared rep, its parent chain may be different
   * from the node-rev parent chain. */ /* Very short rep bases are simply not worth it as we are unlikely
       * to re-coup the deltification space overhead of 20+ bytes. */ /* Check whether the length of the deltification chain is acceptable.
       * Otherwise, shared reps may form a non-skipping delta chain in
       * extreme cases. */ /* Some reasonable limit, depending on how acceptable longer linear
       * chains are in this repo.  Also, allow for some minimal chain. */ /* To make it worth opening additional shards / pack files, we
         * require that the reps have a certain minimal size.  To deltify
         * against a rep in different shard, the lower limit is 512 bytes
         * and doubles with every extra shard to visit along the delta
         * chain. */