From owner-p4-projects@FreeBSD.ORG Tue Nov 21 16:20:30 2006 Return-Path: X-Original-To: p4-projects@freebsd.org Delivered-To: p4-projects@freebsd.org Received: by hub.freebsd.org (Postfix, from userid 32767) id 37A3F16AED6; Tue, 21 Nov 2006 16:20:30 +0000 (UTC) X-Original-To: perforce@freebsd.org Delivered-To: perforce@freebsd.org Received: from mx1.FreeBSD.org (mx1.freebsd.org [69.147.83.52]) by hub.freebsd.org (Postfix) with ESMTP id DECCE16ADD7 for ; Tue, 21 Nov 2006 16:20:28 +0000 (UTC) (envelope-from bushman@freebsd.org) Received: from repoman.freebsd.org (repoman.freebsd.org [69.147.83.41]) by mx1.FreeBSD.org (Postfix) with ESMTP id 6B4C443E0B for ; Tue, 21 Nov 2006 16:19:01 +0000 (GMT) (envelope-from bushman@freebsd.org) Received: from repoman.freebsd.org (localhost [127.0.0.1]) by repoman.freebsd.org (8.13.6/8.13.6) with ESMTP id kALGJ5WM045912 for ; Tue, 21 Nov 2006 16:19:05 GMT (envelope-from bushman@freebsd.org) Received: (from perforce@localhost) by repoman.freebsd.org (8.13.6/8.13.4/Submit) id kALGJ5Qw045908 for perforce@freebsd.org; Tue, 21 Nov 2006 16:19:05 GMT (envelope-from bushman@freebsd.org) Date: Tue, 21 Nov 2006 16:19:05 GMT Message-Id: <200611211619.kALGJ5Qw045908@repoman.freebsd.org> X-Authentication-Warning: repoman.freebsd.org: perforce set sender to bushman@freebsd.org using -f From: Michael Bushkov To: Perforce Change Reviews Cc: Subject: PERFORCE change 110296 for review X-BeenThere: p4-projects@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: p4 projects tree changes List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 21 Nov 2006 16:20:30 -0000 http://perforce.freebsd.org/chv.cgi?CH=110296 Change 110296 by bushman@bushman_nss_ldap_cached on 2006/11/20 13:44:08 - pending_write_session removed + reference counting for cache multipart write sessions added to simplify the "clear cached" command implementation Affected files ... .. //depot/projects/soc2006/nss_ldap_cached/src/usr.sbin/cached/cachelib.c#7 edit .. //depot/projects/soc2006/nss_ldap_cached/src/usr.sbin/cached/cachelib.h#5 edit .. //depot/projects/soc2006/nss_ldap_cached/src/usr.sbin/cached/query.c#11 edit Differences ... ==== //depot/projects/soc2006/nss_ldap_cached/src/usr.sbin/cached/cachelib.c#7 (text) ==== @@ -51,9 +51,11 @@ static int cache_lifetime_common_continue_func(struct cache_common_entry_ *, struct cache_policy_item_ *); static void clear_cache_entry(struct cache_entry_ *); +static void delete_cache_mp_write_session(struct cache_mp_write_session_ *); static void destroy_cache_entry(struct cache_entry_ *); static void destroy_cache_mp_read_session(struct cache_mp_read_session_ *); static void destroy_cache_mp_write_session(struct cache_mp_write_session_ *); +static void destroy_queued_cache_mp_write_sessions(struct cache_mp_entry_ *); static int entries_bsearch_cmp_func(const void *, const void *); static int entries_qsort_cmp_func(const void *, const void *); static struct cache_entry_ ** find_cache_entry_p(struct cache_ *, @@ -182,6 +184,21 @@ } static void +delete_cache_mp_write_session(struct cache_mp_write_session_ *ws) +{ + + TRACE_IN(delete_cache_mp_write_session); + assert(ws != NULL); + assert(ws->parent_entry != NULL); + + if (ws->parent_entry->rs_size == 0) + destroy_cache_mp_write_session(ws); + else + TAILQ_INSERT_HEAD(&ws->parent_entry->del_ws_head, ws, entries); + TRACE_OUT(delete_cache_mp_write_session); +} + +static void destroy_cache_mp_write_session(struct cache_mp_write_session_ *ws) { @@ -200,6 +217,26 @@ TRACE_OUT(destroy_cache_mp_write_session); } +static void +destroy_queued_cache_mp_write_sessions(struct cache_mp_entry_ *entry) +{ + + struct cache_mp_write_session_ *ws, *nws; + + TRACE_IN(destroy_queued_cache_mp_write_sessions); + assert(entry != NULL); + + nws = NULL; + TAILQ_FOREACH_SAFE(ws, &entry->del_ws_head, entries, nws) { + if (ws->ref_counter == 0) { + TAILQ_REMOVE(&entry->del_ws_head, ws, entries); + destroy_cache_mp_write_session(ws); + } + } + + TRACE_OUT(destroy_queued_cache_mp_write_sessions); +} + static void destroy_cache_mp_read_session(struct cache_mp_read_session_ *rs) { @@ -258,6 +295,12 @@ TAILQ_REMOVE(&mp_entry->ws_head, ws, entries); destroy_cache_mp_write_session(ws); } + + while (!TAILQ_EMPTY(&mp_entry->del_ws_head)) { + ws = TAILQ_FIRST(&mp_entry->del_ws_head); + TAILQ_REMOVE(&mp_entry->del_ws_head, ws, entries); + destroy_cache_mp_write_session(ws); + } while (!TAILQ_EMPTY(&mp_entry->rs_head)) { rs = TAILQ_FIRST(&mp_entry->rs_head); @@ -268,10 +311,6 @@ if (mp_entry->completed_write_session != NULL) destroy_cache_mp_write_session( mp_entry->completed_write_session); - - if (mp_entry->pending_write_session != NULL) - destroy_cache_mp_write_session( - mp_entry->pending_write_session); } free(entry->name); @@ -322,24 +361,17 @@ } else { mp_entry = (struct cache_mp_entry_ *)entry; - /* - * NOTE: currently multipart entries are cleared only if - * there are no opened read sessions. It leads to possible - * failues of cache clearing requests. Possibly, some simple - * reference counting should be used to avoid this - */ - if (mp_entry->rs_size == 0) { - if (mp_entry->completed_write_session != NULL) { - destroy_cache_mp_write_session( - mp_entry->completed_write_session); - mp_entry->completed_write_session = NULL; - } + if (mp_entry->completed_write_session != NULL) { + delete_cache_mp_write_session( + mp_entry->completed_write_session); + mp_entry->completed_write_session = NULL; + } + destroy_queued_cache_mp_write_sessions(mp_entry); - memset(&mp_entry->creation_time, 0, - sizeof(struct timeval)); - memset(&mp_entry->last_request_time, 0, - sizeof(struct timeval)); - } + memset(&mp_entry->creation_time, 0, + sizeof(struct timeval)); + memset(&mp_entry->last_request_time, 0, + sizeof(struct timeval)); } } @@ -693,6 +725,7 @@ new_mp_entry->name = new_mp_entry->mp_params.entry_name; TAILQ_INIT(&new_mp_entry->ws_head); + TAILQ_INIT(&new_mp_entry->del_ws_head); TAILQ_INIT(&new_mp_entry->rs_head); new_mp_entry->get_time_func = the_cache->params.get_time_func; @@ -1097,25 +1130,12 @@ TAILQ_REMOVE(&ws->parent_entry->ws_head, ws, entries); --ws->parent_entry->ws_size; - if (ws->parent_entry->completed_write_session == NULL) { - /* - * If there is no completed session yet, this will be the one - */ - ws->parent_entry->get_time_func( - &ws->parent_entry->creation_time); - ws->parent_entry->completed_write_session = ws; - } else { - /* - * If there is a completed session, then we'll save our session - * as a pending session. If there is already a pending session, - * it would be destroyed. - */ - if (ws->parent_entry->pending_write_session != NULL) - destroy_cache_mp_write_session( - ws->parent_entry->pending_write_session); + if (ws->parent_entry->completed_write_session != NULL) + delete_cache_mp_write_session( + ws->parent_entry->completed_write_session); - ws->parent_entry->pending_write_session = ws; - } + ws->parent_entry->get_time_func(&ws->parent_entry->creation_time); + ws->parent_entry->completed_write_session = ws; TRACE_OUT(close_cache_mp_write_session); } @@ -1126,7 +1146,7 @@ struct cache_mp_read_session_ * open_cache_mp_read_session(struct cache_entry_ *entry) { - struct cache_mp_entry_ *mp_entry; + struct cache_mp_entry_ *mp_entry; struct cache_mp_read_session_ *retval; TRACE_IN(open_cache_mp_read_session); @@ -1157,6 +1177,8 @@ } memset(retval, 0, sizeof(struct cache_mp_read_session_)); + ++mp_entry->completed_write_session->ref_counter; + retval->linked_ws = mp_entry->completed_write_session; retval->parent_entry = mp_entry; retval->current_item = TAILQ_FIRST( &mp_entry->completed_write_session->items); @@ -1233,16 +1255,9 @@ assert(rs->parent_entry != NULL); TAILQ_REMOVE(&rs->parent_entry->rs_head, rs, entries); - --rs->parent_entry->rs_size; - - if ((rs->parent_entry->rs_size == 0) && - (rs->parent_entry->pending_write_session != NULL)) { - destroy_cache_mp_write_session( - rs->parent_entry->completed_write_session); - rs->parent_entry->completed_write_session = - rs->parent_entry->pending_write_session; - rs->parent_entry->pending_write_session = NULL; - } + --rs->parent_entry->rs_size; + --rs->linked_ws->ref_counter; + destroy_queued_cache_mp_write_sessions(rs->parent_entry); destroy_cache_mp_read_session(rs); TRACE_OUT(close_cache_mp_read_session); ==== //depot/projects/soc2006/nss_ldap_cached/src/usr.sbin/cached/cachelib.h#5 (text) ==== @@ -183,12 +183,14 @@ size_t items_size; TAILQ_ENTRY(cache_mp_write_session_) entries; + int ref_counter; }; struct cache_mp_read_session_ { struct cache_mp_entry_ *parent_entry; struct cache_mp_data_item_ *current_item; + struct cache_mp_write_session_ *linked_ws; /* Data are read from it*/ TAILQ_ENTRY(cache_mp_read_session_) entries; }; @@ -204,9 +206,13 @@ TAILQ_HEAD(write_sessions_head, cache_mp_write_session_) ws_head; size_t ws_size; + /* Write sessions, queued for deletion */ + TAILQ_HEAD(del_write_sessions_head, cache_mp_write_session_) + del_ws_head; + /* All opened read sessions */ TAILQ_HEAD(read_sessions_head, cache_mp_read_session_) rs_head; - size_t rs_size; + size_t rs_size; /* * completed_write_session is the committed write sessions. All read @@ -218,7 +224,6 @@ * the read sessions. */ struct cache_mp_write_session_ *completed_write_session; - struct cache_mp_write_session_ *pending_write_session; struct timeval creation_time; struct timeval last_request_time; ==== //depot/projects/soc2006/nss_ldap_cached/src/usr.sbin/cached/query.c#11 (text) ==== @@ -1097,6 +1097,7 @@ break; default: transform_response->error_code = -1; + break; } fin: