FreeBSD/contrib/subversion/subversion/libsvn_fs_x/tree.c
/* For the given REVISION and PATH, return the respective entry in CACHE.
   If the entry is empty, its NODE member will be NULL and the caller
   may then set it to the corresponding DAG node allocated in CACHE->POOL.
 */
For the given REVISION and PATH, return the respective entry in CACHE.
If the entry is empty, its NODE member will be NULL and the caller
may then set it to the corresponding DAG node allocated in CACHE->POOL.
For the given REVISION and PATH return the respective entry in CACHE . If the entry is empty its NODE member will be NULL and the caller may then set it to the corresponding DAG node allocated in CACHE - > POOL .
static cache_entry_t *
cache_lookup( svn_fs_x__dag_cache_t *cache
            , svn_revnum_t revision
            , const char *path)
{
  apr_size_t i, bucket_index;
  apr_size_t path_len = strlen(path);
  apr_uint32_t hash_value = (apr_uint32_t)revision;
#if SVN_UNALIGNED_ACCESS_IS_OK
  const apr_uint32_t factor = 0xd1f3da69;
#endif
  cache_entry_t *result = &cache->buckets[cache->last_hit];
  if (   (result->revision == revision)
      && (result->path_len == path_len)
      && !memcmp(result->path, path, path_len))
    {
      if (result->node)
        cache->last_non_empty = cache->last_hit;
      return result;
    }
  i = 0;
#if SVN_UNALIGNED_ACCESS_IS_OK
  for (; i + 8 <= path_len; i += 8)
    hash_value = hash_value * factor * factor
               + (  *(const apr_uint32_t*)(path + i) * factor
                  + *(const apr_uint32_t*)(path + i + 4));
#endif
  for (; i < path_len; ++i)
    hash_value = hash_value * 32 + (hash_value + (unsigned char)path[i]);
  bucket_index = hash_value + (hash_value >> 16);
  bucket_index = (bucket_index + (bucket_index >> 8)) % BUCKET_COUNT;
  result = &cache->buckets[bucket_index];
  cache->last_hit = bucket_index;
  if (   (result->hash_value != hash_value)
      || (result->revision != revision)
      || (result->path_len != path_len)
      || memcmp(result->path, path, path_len))
    {
      result->hash_value = hash_value;
      result->revision = revision;
      if (result->path_len < path_len)
        result->path = apr_palloc(cache->pool, path_len + 1);
      result->path_len = path_len;
      memcpy(result->path, path, path_len + 1);
      result->node = NULL;
      cache->insertions++;
    }
  else if (result->node)
    {
      cache->last_non_empty = bucket_index;
    }
  return result;
}
static cache_entry_t * cache_lookup ( svn_fs_x__dag_cache_t * cache , svn_revnum_t revision , const char * path ) { apr_size_t i , bucket_index ; apr_size_t path_len = strlen ( path ) ; apr_uint32_t hash_value = ( apr_uint32_t ) revision ; #if SVN_UNALIGNED_ACCESS_IS_OK const apr_uint32_t factor = 0xd1f3da69 ; #endif cache_entry_t * result = & cache -> buckets [ cache -> last_hit ] ; if ( ( result -> revision == revision ) && ( result -> path_len == path_len ) && ! memcmp ( result -> path , path , path_len ) ) { if ( result -> node ) cache -> last_non_empty = cache -> last_hit ; return result ; } i = 0 ; #if SVN_UNALIGNED_ACCESS_IS_OK for ( ; i + 8 <= path_len ; i += 8 ) hash_value = hash_value * factor * factor + ( * ( const apr_uint32_t * ) ( path + i ) * factor + * ( const apr_uint32_t * ) ( path + i + 4 ) ) ; #endif for ( ; i < path_len ; ++ i ) hash_value = hash_value * 32 + ( hash_value + ( unsigned char ) path [ i ] ) ; bucket_index = hash_value + ( hash_value >> 16 ) ; bucket_index = ( bucket_index + ( bucket_index >> 8 ) ) % BUCKET_COUNT ; result = & cache -> buckets [ bucket_index ] ; cache -> last_hit = bucket_index ; if ( ( result -> hash_value != hash_value ) || ( result -> revision != revision ) || ( result -> path_len != path_len ) || memcmp ( result -> path , path , path_len ) ) { result -> hash_value = hash_value ; result -> revision = revision ; if ( result -> path_len < path_len ) result -> path = apr_palloc ( cache -> pool , path_len + 1 ) ; result -> path_len = path_len ; memcpy ( result -> path , path , path_len + 1 ) ; result -> node = NULL ; cache -> insertions ++ ; } else if ( result -> node ) { cache -> last_non_empty = bucket_index ; } return result ; }
For the given REVISION and PATH, return the respective entry in CACHE.
For the given REVISION and PATH return the respective entry in CACHE .
/* "randomizing" / distributing factor used in our hash function */ /* optimistic lookup: hit the same bucket again? */ /* Remember the position of the last node we found in this cache. */ /* need to do a full lookup.  Calculate the hash value
     (HASH_VALUE has been initialized to REVISION). */ /* We relax the dependency chain between iterations by processing
     two chunks from the input per hash_value self-multiplication.
     The HASH_VALUE update latency is now 1 MUL latency + 1 ADD latency
     per 2 chunks instead of 1 chunk.
   */ /* Help GCC to minimize the HASH_VALUE update latency by splitting the
       MUL 33 of the naive implementation: h = h * 33 + path[i].  This
       shortens the dependency chain from 1 shift + 2 ADDs to 1 shift + 1 ADD.
     */ /* access the corresponding bucket and remember its location */ /* if it is *NOT* a match,  clear the bucket, expect the caller to fill
     in the node and count it as an insertion */ /* This bucket is valid & has a suitable DAG node in it.
         Remember its location. */