Author: stefan2
Date: Mon Jul 11 21:34:18 2011
New Revision: 1145366

URL: http://svn.apache.org/viewvc?rev=1145366&view=rev
Log:
On svn_mutex branch:
Switch  cache_membuffer to the safer __WITH_LOCK macro.
Simplify locking-related code when possible.

* subversion/libsvn_subr/cache-membuffer.c
  (find_entry): mark const parameter as such
  (membuffer_cache_set_internal): to-be-sync'ed part of membuffer_cache_set
  (membuffer_cache_set): remainder
  (membuffer_cache_get_internal): to-be-sync'ed part of membuffer_cache_get
  (membuffer_cache_get): remainder
  (membuffer_cache_get_partial_internal): to-be-sync'ed part of
   membuffer_cache_get_partial
  (membuffer_cache_get_partial): remainder
  (membuffer_cache_set_partial_internal): to-be-sync'ed part of
   membuffer_cache_set_partial
  (membuffer_cache_set_partial): remainder
  (svn_membuffer_get_segment_info): to-be-sync'ed part of
   svn_membuffer_cache_get_info
  (svn_membuffer_cache_get_info): remainder

Modified:
    subversion/branches/svn_mutex/subversion/libsvn_subr/cache-membuffer.c

Modified: subversion/branches/svn_mutex/subversion/libsvn_subr/cache-membuffer.c
URL: 
http://svn.apache.org/viewvc/subversion/branches/svn_mutex/subversion/libsvn_subr/cache-membuffer.c?rev=1145366&r1=1145365&r2=1145366&view=diff
==============================================================================
--- subversion/branches/svn_mutex/subversion/libsvn_subr/cache-membuffer.c 
(original)
+++ subversion/branches/svn_mutex/subversion/libsvn_subr/cache-membuffer.c Mon 
Jul 11 21:34:18 2011
@@ -675,7 +675,7 @@ initialize_group(svn_membuffer_t *cache,
 static entry_t *
 find_entry(svn_membuffer_t *cache,
            apr_uint32_t group_index,
-           unsigned char *to_find,
+           const unsigned char *to_find,
            svn_boolean_t find_empty)
 {
   entry_t *group;
@@ -1051,48 +1051,30 @@ svn_cache__membuffer_cache_create(svn_me
 }
 
 
-/* Try to insert the ITEM and use the KEY to unqiuely identify it.
+/* Try to insert the serialized item given in BUFFER with SIZE into
+ * the group GROUP_INDEX of CACHE and uniquely identify it by hash 
+ * value TO_FIND. 
+ * 
  * However, there is no guarantee that it will actually be put into
- * the cache. If there is already some data associated to the KEY,
+ * the cache. If there is already some data associated with TO_FIND,
  * it will be removed from the cache even if the new data cannot
  * be inserted.
- *
- * The SERIALIZER is called to transform the ITEM into a single,
- * flat data buffer. Temporary allocations may be done in POOL.
+ * 
+ * Note: This function requires the caller to serialization access.
+ * Don't call it directly, call membuffer_cache_get_partial instead.
  */
 static svn_error_t *
-membuffer_cache_set(svn_membuffer_t *cache,
-                    const void *key,
-                    apr_size_t key_len,
-                    void *item,
-                    svn_cache__serialize_func_t serializer,
-                    DEBUG_CACHE_MEMBUFFER_TAG_ARG
-                    apr_pool_t *scratch_pool)
+membuffer_cache_set_internal(svn_membuffer_t *cache,
+                             const unsigned char *to_find,
+                             apr_uint32_t group_index,
+                             char *buffer,
+                             apr_size_t size,
+                             DEBUG_CACHE_MEMBUFFER_TAG_ARG
+                             apr_pool_t *scratch_pool)
 {
-  apr_uint32_t group_index;
-  unsigned char to_find[KEY_SIZE];
-  entry_t *entry;
-  char *buffer;
-  apr_size_t size;
-
-  /* find the entry group that will hold the key.
-   */
-  group_index = get_group_index(&cache, key, key_len, to_find, scratch_pool);
-  if (group_index == NO_INDEX)
-    return SVN_NO_ERROR;
-
-  /* Serialize data data.
-   */
-  if (item)
-    SVN_ERR(serializer(&buffer, &size, item, scratch_pool));
-
-  /* The actual cache data access needs to sync'ed
-   */
-  SVN_ERR(svn_mutex__lock(cache->mutex));
-
   /* if necessary, enlarge the insertion window.
    */
-  if (   item != NULL
+  if (   buffer != NULL
       && cache->data_size / 4 > size
       && ensure_data_insertable(cache, size))
     {
@@ -1100,7 +1082,7 @@ membuffer_cache_set(svn_membuffer_t *cac
        * Get an unused entry for the key and and initialize it with
        * the serialized item's (future) posion within data buffer.
        */
-      entry = find_entry(cache, group_index, to_find, TRUE);
+      entry_t *entry = find_entry(cache, group_index, to_find, TRUE);
       entry->size = size;
       entry->offset = cache->current_data;
 
@@ -1129,44 +1111,76 @@ membuffer_cache_set(svn_membuffer_t *cac
        */
       find_entry(cache, group_index, to_find, TRUE);
     }
-
-  /* done here -> unlock the cache
-   */
-  return svn_mutex__unlock(cache->mutex, SVN_NO_ERROR);
 }
 
-/* Look for the *ITEM identified by KEY. If no item has been stored
- * for KEY, *ITEM will be NULL. Otherwise, the DESERIALIZER is called
- * re-construct the proper object from the serialized data.
- * Allocations will be done in POOL.
+/* Try to insert the ITEM and use the KEY to unqiuely identify it.
+ * However, there is no guarantee that it will actually be put into
+ * the cache. If there is already some data associated to the KEY,
+ * it will be removed from the cache even if the new data cannot
+ * be inserted.
+ *
+ * The SERIALIZER is called to transform the ITEM into a single,
+ * flat data buffer. Temporary allocations may be done in POOL.
  */
 static svn_error_t *
-membuffer_cache_get(svn_membuffer_t *cache,
+membuffer_cache_set(svn_membuffer_t *cache,
                     const void *key,
                     apr_size_t key_len,
-                    void **item,
-                    svn_cache__deserialize_func_t deserializer,
+                    void *item,
+                    svn_cache__serialize_func_t serializer,
                     DEBUG_CACHE_MEMBUFFER_TAG_ARG
-                    apr_pool_t *result_pool)
+                    apr_pool_t *scratch_pool)
 {
   apr_uint32_t group_index;
   unsigned char to_find[KEY_SIZE];
   entry_t *entry;
-  char *buffer;
+  char *buffer = NULL;
   apr_size_t size;
 
   /* find the entry group that will hold the key.
    */
-  group_index = get_group_index(&cache, key, key_len, to_find, result_pool);
+  group_index = get_group_index(&cache, key, key_len, to_find, scratch_pool);
   if (group_index == NO_INDEX)
-    {
-      /* Some error occured, return "item not found".
-       */
-      *item = NULL;
-      return SVN_NO_ERROR;
-    }
+    return SVN_NO_ERROR;
 
-  SVN_ERR(svn_mutex__lock(cache->mutex));
+  /* Serialize data data.
+   */
+  if (item)
+    SVN_ERR(serializer(&buffer, &size, item, scratch_pool));
+
+  /* The actual cache data access needs to sync'ed
+   */
+  SVN_MUTEX__WITH_LOCK(cache->mutex,
+                       membuffer_cache_set_internal(cache,
+                                                    to_find,
+                                                    group_index,
+                                                    buffer,
+                                                    size,
+                                                    DEBUG_CACHE_MEMBUFFER_TAG
+                                                    scratch_pool));
+  return SVN_NO_ERROR;
+}
+
+/* Look for the cache entry in group GROUP_INDEX of CACHE, identified
+ * by the hash value TO_FIND. If no item has been stored for KEY, 
+ * *BUFFER will be NULL. Otherwise, return a copy of the serialized
+ * data in *BUFFER and return its size in *ITEM_SIZE. Allocations will 
+ * be done in POOL.
+ * 
+ * Note: This function requires the caller to serialization access.
+ * Don't call it directly, call membuffer_cache_get_partial instead.
+ */
+static svn_error_t *
+membuffer_cache_get_internal(svn_membuffer_t *cache,
+                             apr_uint32_t group_index,
+                             const unsigned char *to_find,
+                             char **buffer,
+                             apr_size_t *item_size,
+                             DEBUG_CACHE_MEMBUFFER_TAG_ARG
+                             apr_pool_t *result_pool)
+{
+  entry_t *entry;
+  apr_size_t size;
 
   /* The actual cache data access needs to sync'ed
    */
@@ -1176,13 +1190,15 @@ membuffer_cache_get(svn_membuffer_t *cac
     {
       /* no such entry found.
        */
-      *item = NULL;
-      return svn_mutex__unlock(cache->mutex, SVN_NO_ERROR);
+      *buffer = NULL;
+      *item_size = 0;
+  
+      return SVN_NO_ERROR;
     }
-
+    
   size = ALIGN_VALUE(entry->size);
-  buffer = ALIGN_POINTER(apr_palloc(result_pool, size + ITEM_ALIGNMENT-1));
-  memcpy(buffer, (const char*)cache->data + entry->offset, size);
+  *buffer = ALIGN_POINTER(apr_palloc(result_pool, size + ITEM_ALIGNMENT-1));
+  memcpy(*buffer, (const char*)cache->data + entry->offset, size);
 
 #ifdef SVN_DEBUG_CACHE_MEMBUFFER
 
@@ -1205,45 +1221,91 @@ membuffer_cache_get(svn_membuffer_t *cac
   cache->hit_count++;
   cache->total_hits++;
 
-  SVN_ERR(svn_mutex__unlock(cache->mutex, SVN_NO_ERROR));
-
-  /* re-construct the original data object from its serialized form.
-   */
-  return deserializer(item, buffer, entry->size, result_pool);
+  *item_size = entry->size;
+  
+  return SVN_NO_ERROR;
 }
 
-/* Look for the cache entry identified by KEY and KEY_LEN. FOUND indicates
- * whether that entry exists. If not found, *ITEM will be NULL. Otherwise,
- * the DESERIALIZER is called with that entry and the BATON provided
- * and will extract the desired information. The result is set in *ITEM.
+/* Look for the *ITEM identified by KEY. If no item has been stored
+ * for KEY, *ITEM will be NULL. Otherwise, the DESERIALIZER is called
+ * re-construct the proper object from the serialized data.
  * Allocations will be done in POOL.
  */
 static svn_error_t *
-membuffer_cache_get_partial(svn_membuffer_t *cache,
-                            const void *key,
-                            apr_size_t key_len,
-                            void **item,
-                            svn_boolean_t *found,
-                            svn_cache__partial_getter_func_t deserializer,
-                            void *baton,
-                            DEBUG_CACHE_MEMBUFFER_TAG_ARG
-                            apr_pool_t *result_pool)
+membuffer_cache_get(svn_membuffer_t *cache,
+                    const void *key,
+                    apr_size_t key_len,
+                    void **item,
+                    svn_cache__deserialize_func_t deserializer,
+                    DEBUG_CACHE_MEMBUFFER_TAG_ARG
+                    apr_pool_t *result_pool)
 {
   apr_uint32_t group_index;
   unsigned char to_find[KEY_SIZE];
-  entry_t *entry;
-  svn_error_t *err = SVN_NO_ERROR;
+  char *buffer;
+  apr_size_t size;
 
+  /* find the entry group that will hold the key.
+   */
   group_index = get_group_index(&cache, key, key_len, to_find, result_pool);
+  if (group_index == NO_INDEX)
+    {
+      /* Some error occured, return "item not found".
+       */
+      *item = NULL;
+      return SVN_NO_ERROR;
+    }
 
-  SVN_ERR(svn_mutex__lock(cache->mutex));
+  SVN_MUTEX__WITH_LOCK(cache->mutex,
+                       membuffer_cache_get_internal(cache,
+                                                    group_index,
+                                                    to_find,
+                                                    &buffer,
+                                                    &size,
+                                                    DEBUG_CACHE_MEMBUFFER_TAG
+                                                    result_pool));
 
-  entry = find_entry(cache, group_index, to_find, FALSE);
+  /* re-construct the original data object from its serialized form.
+   */
+  if (buffer == NULL)
+    {
+      *item = NULL;
+      return SVN_NO_ERROR;
+    }
+    
+  return deserializer(item, buffer, size, result_pool);
+}
+
+/* Look for the cache entry in group GROUP_INDEX of CACHE, identified
+ * by the hash value TO_FIND. FOUND indicates whether that entry exists.
+ * If not found, *ITEM will be NULL.
+ * 
+ * Otherwise, the DESERIALIZER is called with that entry and the BATON 
+ * provided and will extract the desired information. The result is set
+ * in *ITEM. Allocations will be done in POOL.
+ * 
+ * Note: This function requires the caller to serialization access.
+ * Don't call it directly, call membuffer_cache_get_partial instead.
+ */
+static svn_error_t *
+membuffer_cache_get_partial_internal(svn_membuffer_t *cache,
+                                     apr_uint32_t group_index,
+                                     const unsigned char *to_find,
+                                     void **item,
+                                     svn_boolean_t *found,
+                                     svn_cache__partial_getter_func_t 
deserializer,
+                                     void *baton,
+                                     DEBUG_CACHE_MEMBUFFER_TAG_ARG
+                                     apr_pool_t *result_pool)
+{
+  entry_t *entry = find_entry(cache, group_index, to_find, FALSE);
   cache->total_reads++;
   if (entry == NULL)
     {
       *item = NULL;
       *found = FALSE;
+      
+      return SVN_NO_ERROR;
     }
   else
     {
@@ -1271,50 +1333,75 @@ membuffer_cache_get_partial(svn_membuffe
 
 #endif
 
-      err = deserializer(item,
-                         (const char*)cache->data + entry->offset,
-                         entry->size,
-                         baton,
-                         result_pool);
+      return deserializer(item,
+                          (const char*)cache->data + entry->offset,
+                          entry->size,
+                          baton,
+                          result_pool);
     }
-
-  /* done here -> unlock the cache
-   */
-  return svn_mutex__unlock(cache->mutex, err);
 }
 
-/* Look for the cache entry identified by KEY and KEY_LEN. If no entry
- * has been found, the function returns without modifying the cache.
- * Otherwise, FUNC is called with that entry and the BATON provided
- * and may modify the cache entry. Allocations will be done in POOL.
+/* Look for the cache entry identified by KEY and KEY_LEN. FOUND indicates
+ * whether that entry exists. If not found, *ITEM will be NULL. Otherwise,
+ * the DESERIALIZER is called with that entry and the BATON provided
+ * and will extract the desired information. The result is set in *ITEM.
+ * Allocations will be done in POOL.
  */
 static svn_error_t *
-membuffer_cache_set_partial(svn_membuffer_t *cache,
+membuffer_cache_get_partial(svn_membuffer_t *cache,
                             const void *key,
                             apr_size_t key_len,
-                            svn_cache__partial_setter_func_t func,
+                            void **item,
+                            svn_boolean_t *found,
+                            svn_cache__partial_getter_func_t deserializer,
                             void *baton,
                             DEBUG_CACHE_MEMBUFFER_TAG_ARG
-                            apr_pool_t *scratch_pool)
+                            apr_pool_t *result_pool)
 {
   apr_uint32_t group_index;
   unsigned char to_find[KEY_SIZE];
-  entry_t *entry;
-  svn_error_t *err = SVN_NO_ERROR;
 
-  /* cache item lookup
-   */
-  group_index = get_group_index(&cache, key, key_len, to_find, scratch_pool);
+  group_index = get_group_index(&cache, key, key_len, to_find, result_pool);
 
-  SVN_ERR(svn_mutex__lock(cache->mutex));
+  SVN_MUTEX__WITH_LOCK(cache->mutex,
+                       membuffer_cache_get_partial_internal
+                           (cache, group_index, to_find, item, found,
+                            deserializer, baton, DEBUG_CACHE_MEMBUFFER_TAG
+                            result_pool));
 
-  entry = find_entry(cache, group_index, to_find, FALSE);
+  return SVN_NO_ERROR;
+}
+
+/* Look for the cache entry in group GROUP_INDEX of CACHE, identified
+ * by the hash value TO_FIND. If no entry has been found, the function
+ * returns without modifying the cache.
+ * 
+ * Otherwise, FUNC is called with that entry and the BATON provided
+ * and may modify the cache entry. Allocations will be done in POOL.
+ * 
+ * Note: This function requires the caller to serialization access.
+ * Don't call it directly, call membuffer_cache_set_partial instead.
+ */
+static svn_error_t *
+membuffer_cache_set_partial_internal(svn_membuffer_t *cache,
+                                     apr_uint32_t group_index,
+                                     const unsigned char *to_find,
+                                     svn_cache__partial_setter_func_t func,
+                                     void *baton,
+                                     DEBUG_CACHE_MEMBUFFER_TAG_ARG
+                                     apr_pool_t *scratch_pool)
+{
+  /* cache item lookup
+   */
+  entry_t *entry = find_entry(cache, group_index, to_find, FALSE);
   cache->total_reads++;
 
   /* this function is a no-op if the item is not in cache
    */
   if (entry != NULL)
     {
+      svn_error_t *err;
+
       /* access the serialized cache item */
       char *data = (char*)cache->data + entry->offset;
       char *orig_data = data;
@@ -1388,9 +1475,41 @@ membuffer_cache_set_partial(svn_membuffe
         }
     }
 
+  return SVN_NO_ERROR;
+}
+
+/* Look for the cache entry identified by KEY and KEY_LEN. If no entry
+ * has been found, the function returns without modifying the cache.
+ * Otherwise, FUNC is called with that entry and the BATON provided
+ * and may modify the cache entry. Allocations will be done in POOL.
+ */
+static svn_error_t *
+membuffer_cache_set_partial(svn_membuffer_t *cache,
+                            const void *key,
+                            apr_size_t key_len,
+                            svn_cache__partial_setter_func_t func,
+                            void *baton,
+                            DEBUG_CACHE_MEMBUFFER_TAG_ARG
+                            apr_pool_t *scratch_pool)
+{
+  apr_uint32_t group_index;
+  unsigned char to_find[KEY_SIZE];
+  entry_t *entry;
+  svn_error_t *err = SVN_NO_ERROR;
+
+  /* cache item lookup
+   */
+  group_index = get_group_index(&cache, key, key_len, to_find, scratch_pool);
+
+  SVN_MUTEX__WITH_LOCK(cache->mutex,
+                       membuffer_cache_set_partial_internal
+                           (cache, group_index, to_find, func, baton,
+                            DEBUG_CACHE_MEMBUFFER_TAG_ARG
+                            scratch_pool));
+
   /* done here -> unlock the cache
    */
-  return svn_mutex__unlock(cache->mutex, err);
+  return SVN_NO_ERROR;
 }
 
 /* Implement the svn_cache__t interface on top of a shared membuffer cache.
@@ -1693,6 +1812,23 @@ svn_membuffer_cache_is_cachable(void *ca
       && (size < APR_UINT32_MAX - ITEM_ALIGNMENT);
 }
 
+/* Add statistics of SEGMENT to INFO.
+ */
+static svn_error_t *
+svn_membuffer_get_segment_info(svn_membuffer_t *segment,
+                               svn_cache__info_t *info)
+{
+  info->data_size += segment->data_size;
+  info->used_size += segment->data_used;
+  info->total_size += segment->data_size +
+      segment->group_count * GROUP_SIZE * sizeof(entry_t);
+
+  info->used_entries += segment->used_entries;
+  info->total_entries += segment->group_count * GROUP_SIZE;
+
+  return SVN_NO_ERROR;
+}
+
 /* Implement svn_cache__vtable_t.get_info
  */
 static svn_error_t *
@@ -1720,18 +1856,8 @@ svn_membuffer_cache_get_info(void *cache
   for (i = 0; i < cache->membuffer->segment_count; ++i)
     {
       svn_membuffer_t *segment = cache->membuffer + i;
-
-      SVN_ERR(svn_mutex__lock(segment->mutex));
-
-      info->data_size += segment->data_size;
-      info->used_size += segment->data_used;
-      info->total_size += segment->data_size +
-          segment->group_count * GROUP_SIZE * sizeof(entry_t);
-
-      info->used_entries += segment->used_entries;
-      info->total_entries += segment->group_count * GROUP_SIZE;
-
-      SVN_ERR(svn_mutex__unlock(segment->mutex, SVN_NO_ERROR));
+      SVN_MUTEX__WITH_LOCK(segment->mutex, 
+                           svn_membuffer_get_segment_info(segment, info));
     }
 
   return SVN_NO_ERROR;


Reply via email to