smb_cache.c revision 9fb67ea305c66b6a297583b9b0db6796b0dfe497
/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (the "License").
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright 2010 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#include <assert.h>
/*
* Cache lock modes
*/
#define SMB_CACHE_RDLOCK 0
#define SMB_CACHE_WRLOCK 1
#define SMB_CACHE_STATE_NOCACHE 0
#define SMB_CACHE_STATE_READY 1
#define SMB_CACHE_STATE_REFRESHING 2
#define SMB_CACHE_STATE_DESTROYING 3
static int smb_cache_lock(smb_cache_t *, int);
static int smb_cache_rdlock(smb_cache_t *);
static int smb_cache_wrlock(smb_cache_t *);
static void smb_cache_unlock(smb_cache_t *);
static void smb_cache_destroy_nodes(smb_cache_t *);
/*
* Creates an AVL tree and initializes the given cache handle.
* Transfers the cache to READY state.
*
* This function does not populate the cache.
*
* chandle pointer to a smb_cache_t structure
* waittime see smb_cache_refreshing() comments
* cmpfn compare function used by AVL tree
* freefn if set, it will be used to free any allocated
* memory for the node data stored in the cache when
* that node is removed.
* copyfn this function has to be set and it is used
* to provide a copy of the node data stored in the
* cache to the caller of smb_cache_iterate or any other
* function that is used to access nodes data.
* This can typically be 'bcopy' if data is fixed size.
* datasz Size of data stored in the cache if it's fixed size.
* This size will be passed to the copy function.
*/
void
int (*cmpfn) (const void *, const void *),
void (*freefn)(void *),
{
return;
}
}
/*
* Destroys the cache.
*
* Transfers the cache to DESTROYING state while it's waiting for
* in-flight operation to finish, this will prevent any new operation
* to start. When all entries are removed the cache is transferred to
* NOCACHE state.
*/
void
{
case SMB_CACHE_STATE_NOCACHE:
return;
default:
break;
}
}
/*
* Removes and frees all the cache entries without destroy
* the cache itself.
*/
void
{
if (smb_cache_wrlock(chandle) == 0) {
chandle->ch_sequence++;
}
}
/*
* Based on the specified flag either add or replace given
* data. If ADD flag is specified and the item is already in
* the cache EEXIST error code is returned.
*/
int
{
int rc = 0;
return (rc);
return (ENOMEM);
}
if (flags & SMB_CACHE_REPLACE) {
} else {
return (EEXIST);
}
}
chandle->ch_sequence++;
return (rc);
}
/*
* Uses the given 'data' as key to find a cache entry
* and remove it. The memory allocated for the found node
* and its data is freed.
*/
void
{
if (smb_cache_wrlock(chandle) != 0)
return;
if (node) {
chandle->ch_sequence++;
}
}
/*
* Initializes the given cursor for iterating the cache
*/
void
{
}
/*
* Iterate the cache using the given cursor.
*
* Data is copied to the given buffer ('data') using the copy function
* specified at cache creation time.
*
* If the cache is modified while an iteration is in progress it causes
* the iteration to finish prematurely. This is to avoid the need to lock
* the whole cache while it is being iterated.
*/
{
if (smb_cache_rdlock(chandle) != 0)
return (B_FALSE);
return (B_FALSE);
}
else
}
/*
* Returns the number of cache entries
*/
{
if (smb_cache_rdlock(chandle) == 0) {
}
return (num);
}
/*
* Transfers the cache into REFRESHING state. This function needs
* to be called when the whole cache is being populated or refereshed
* and not for individual changes.
*
* Calling this function will ensure any read access to the cache will
* be stalled until the update is finished, which is to avoid providing
* incomplete, inconsistent or stale information. Read accesses will be
* stalled for 'ch_wait' seconds (see smb_cache_lock), which is set at
* the cache creation time.
*
* If it is okay for the cache to be accessed while it's being populated
* or refreshed, then there is no need to call this function.
*
* If another thread is already updating the cache, other callers will wait
* until cache is no longer in REFRESHING state. The return code is decided
* based on the new state of the cache.
*
* This function does NOT perform the actual refresh.
*/
int
{
int rc = 0;
case SMB_CACHE_STATE_READY:
rc = 0;
break;
rc = 0;
} else {
}
break;
case SMB_CACHE_STATE_NOCACHE:
break;
default:
assert(0);
}
return (rc);
}
/*
* Transfers the cache from REFRESHING to READY state.
*
* Nothing will happen if the cache is no longer available
* or it is being destroyed.
*
* This function should only be called if smb_cache_refreshing()
* has already been invoked.
*/
void
{
break;
case SMB_CACHE_STATE_NOCACHE:
break;
case SMB_CACHE_STATE_READY:
default:
assert(0);
}
}
/*
* Lock the cache with the specified mode.
* If the cache is in updating state and a read lock is
* requested, the lock won't be granted until either the
* update is finished or SMB_CACHE_UPDATE_WAIT has passed.
*
* Whenever a lock is granted, the number of inflight cache
* operations is incremented.
*/
static int
{
case SMB_CACHE_STATE_NOCACHE:
return (ENODATA);
/*
* Read operations should wait until the update
* is completed.
*/
if (mode == SMB_CACHE_RDLOCK) {
if (!smb_cache_wait(chandle)) {
return (ETIME);
}
}
/* FALLTHROUGH */
case SMB_CACHE_STATE_READY:
break;
default:
assert(0);
}
/*
* Lock has to be taken outside the mutex otherwise
* there could be a deadlock
*/
if (mode == SMB_CACHE_RDLOCK)
else
return (0);
}
/*
* Lock the cache for reading
*/
static int
{
}
/*
* Lock the cache for modification
*/
static int
{
}
/*
* Unlock the cache
*/
static void
{
}
/*
* Waits for ch_wait seconds if cache is in UPDATING state.
* Upon wake up returns true if cache is ready to be used,
* otherwise it returns false.
*/
static boolean_t
{
int err;
return (B_TRUE);
break;
}
}
/*
* Removes and frees all the cache entries
*/
static void
{
}
}