/*
* 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 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <pthread.h>
#include <libelf.h>
#include <libelf.h>
#include "isns_server.h"
#include "isns_cache.h"
#include "isns_htab.h"
#include "isns_log.h"
/*
* external variables.
*/
extern int cache_flag;
/*
* ****************************************************************************
* avl_search:
* search a node from an AVL tree.
*
* tab - the hash table.
* uid - the object UID.
* return - the node which matches the object UID.
*
* ****************************************************************************
*/
static htab_itemx_t *
)
{
while (x != NULL) {
x = x->l;
x = x->r;
} else {
break;
}
}
return (x);
}
/*
* ****************************************************************************
* avl_search_next:
* search a node from an AVL tree, the object UID of the node
* is next to the previous object UID.
*
* tab - the hash table.
* uid - the previous object UID.
* return - the next node.
*
* ****************************************************************************
*/
static htab_itemx_t *
)
{
htab_itemx_t *p = NULL;
while (x != NULL) {
p = x;
x = x->l;
x = x->r;
}
}
return (p);
}
/*
* ****************************************************************************
* avl_ll:
* perform LL balance rotation on an AVL tree (or the subtree).
*
* a - the left child.
* b - the right child.
* return - the new root.
*
* ****************************************************************************
*/
static htab_itemx_t *
htab_itemx_t *a,
htab_itemx_t *b
)
{
/* rotate right */
a->l = b->r;
a->bf = 0;
b->r = a;
b->bf = 0;
return (b);
}
/*
* ****************************************************************************
* avl_rr:
* perform RR balance rotation on an AVL tree (or the subtree).
*
* a - the left child.
* b - the right child.
* return - the new root.
*
* ****************************************************************************
*/
static htab_itemx_t *
htab_itemx_t *a,
htab_itemx_t *b
)
{
/* rotate left */
a->r = b->l;
a->bf = 0;
b->l = a;
b->bf = 0;
return (b);
}
/*
* ****************************************************************************
* avl_lr:
* perform LR balance rotation on an AVL tree (or the subtree).
*
* a - the left child.
* b - the right child.
* return - the new root.
*
* ****************************************************************************
*/
static htab_itemx_t *
htab_itemx_t *a,
htab_itemx_t *b
)
{
htab_itemx_t *c;
c = b->r;
/* rotate left and then right */
a->l = c->r;
c->r = a;
b->r = c->l;
c->l = b;
/* update balance factor */
switch (c->bf) {
case -1:
/* on c's right */
a->bf = 0;
b->bf = 1;
break;
case 0:
/* on c itself */
a->bf = 0;
b->bf = 0;
break;
case 1:
/* on c's left */
a->bf = -1;
b->bf = 0;
break;
}
c->bf = 0;
return (c);
}
/*
* ****************************************************************************
* avl_rl:
* perform RL balance rotation on an AVL tree (or the subtree).
*
* a - the left child.
* b - the right child.
* return - the new root.
*
* ****************************************************************************
*/
static htab_itemx_t *
htab_itemx_t *a,
htab_itemx_t *b
)
{
htab_itemx_t *c;
c = b->l;
/* rotate right and then left */
a->r = c->l;
c->l = a;
b->l = c->r;
c->r = b;
/* update balance factor */
switch (c->bf) {
case -1:
/* on c's right */
a->bf = 1;
b->bf = 0;
break;
case 0:
/* on c itself */
a->bf = 0;
b->bf = 0;
break;
case 1:
/* on c's left */
a->bf = 0;
b->bf = -1;
break;
}
c->bf = 0;
return (c);
}
/*
* ****************************************************************************
* avl_insert:
* insert a node into an AVL tree.
*
* tab - the hash table.
* x - the node being added.
*
* ****************************************************************************
*/
static void
htab_itemx_t *x
)
{
htab_itemx_t *f, *a, *p, *q, *b, *c;
int d;
/* initialize the new one */
x->bf = 0;
x->l = NULL;
x->r = NULL;
} else {
/* locate the position */
f = NULL;
q = NULL;
while (p != NULL) {
if (p->bf != 0) {
a = p;
f = q;
}
q = p;
p = p->l;
} else {
p = p->r;
}
}
/* insert it */
q->l = x;
} else {
q->r = x;
}
/* update the balance factor between a to x */
p = a->l;
d = 1;
} else {
p = a->r;
d = -1;
}
b = p;
while (p != x) {
p->bf = 1;
p = p->l;
} else {
p->bf = -1;
p = p->r;
}
}
/* brance is not broken */
if (a->bf == 0) {
a->bf = d;
goto bal_done;
} else if (a->bf + d == 0) {
a->bf = 0;
goto bal_done;
}
/* rotate the tree */
if (d == 1) {
if (b->bf == 1) {
/* LL rotate */
c = avl_ll(a, b);
} else if (b->bf == -1) {
/* LR rotate */
c = avl_lr(a, b);
}
} else {
if (b->bf == -1) {
/* RR rotate */
c = avl_rr(a, b);
} else if (b->bf == 1) {
/* RL rotate */
c = avl_rl(a, b);
}
}
/* update the parent */
if (f == NULL) {
} else if (f->l == a) {
f->l = c;
} else if (f->r == a) {
f->r = c;
}
}
}
}
/*
* ****************************************************************************
* new_uid:
* allocate new node(s) of the avl tree.
*
* tab - the hash table.
* uid - the UID of the node.
* return - the newly allocated UID node.
*
* ****************************************************************************
*/
static htab_itemx_t *
)
{
htab_itemx_t *x = NULL;
/* overflow happened */
if (uid == 0) {
/* search for an unused one */
uid ++;
while (uid != 0 &&
uid ++;
}
if (uid == 0) {
/* all are used up, sigh! */
return (NULL);
}
}
/* check if there is a gap and the gap needs to be filled up */
} else {
}
/* make new UID(s) */
do {
if (x != NULL) {
x->hval = BAD_HVAL_MASK;
x->t = 0;
/* put it to the start of the fifo list */
}
}
if (x != NULL) {
x->n = NULL;
/* insert it to the tree */
avl_insert(tab, x);
}
start ++;
return (x);
}
/*
* ****************************************************************************
* uid_insert:
* insert a new UID node to the avl tree.
*
* tab - the hash table.
* uid_p- the pointer of the UID.
* hval - the hash value of the new node.
* return - 0: no UID value assigned;
* 1: assigned an UID.
* -1: no memory.
* -2: invalid UID.
*
* ****************************************************************************
*/
static int
)
{
int assignx = 0;
htab_itemx_t *x, *n;
if (uid != 0) {
/* search the existing one from the tree */
if (x == NULL) {
/* the item with this uid will override an */
/* existing item, we treat this as an error */
return (-2);
}
} else {
/* assign a value */
/* strip off the used ones */
while (x != NULL &&
n = x->n;
x->n = NULL;
x = n;
}
if (x == NULL ||
/* none is available, make a new one */
} else {
n = x->n;
x->n = NULL;
}
/* update the available list */
}
assignx = 1;
if (x != NULL) {
}
}
if (x == NULL) {
return (-1); /* no memory */
}
x->t = 0; /* registration initial time */
return (assignx);
}
/*
* ****************************************************************************
* enlarge_htab:
* enlarge the hash table when it gets too full.
*
* tab - the hash table.
*
* ****************************************************************************
*/
static void
)
{
uint16_t i;
uint32_t j;
/* enlarge the logsize by one */
/* re-hash all items to the new table */
i = 0;
j = 0;
while (j < oldsz) {
uid) {
}
}
j ++;
}
i ++;
}
} else {
}
}
/*
* ****************************************************************************
* htab_init:
* some generic initialization for the hash table.
*
* ****************************************************************************
*/
void
)
{
/* do nothing */
}
/*
* ****************************************************************************
* htab_create:
* create a new hash table.
*
* flags - UID_FLAGS_SEQ: the UID in the table needs to be sequential.
* logsize - the hash table logsize.
* chunks - the number of seperated chunks of the table.
* return - the newly created hash table.
*
* ****************************************************************************
*/
htab_t *
int flags,
)
{
/* do not enlarge it if the logsize reaches the maximum */
if (logsize <= MAX_LOGSIZE &&
chunks > 0) {
} else {
}
}
}
return (tab);
}
/*
* ****************************************************************************
* htab_compute_hval:
* compute a hash value for the specified key.
*
* key - the key of the hash.
* return - the hash value.
*
* ****************************************************************************
*/
)
{
/* use classic Dan Bernstein hash alorigthm */
int c;
while ((c = *key++) != 0) {
}
return (hash);
}
/*
* ****************************************************************************
* htab_add:
* add an object to the hash table.
*
* tab - the hash table.
* p - the object.
* flag - 0: not an association object; otherwise association object.
* uid_p- pointer of UID for returning.
* update_p - pointer of update flag for returning.
* return - error code.
*
* ****************************************************************************
*/
int
void *p,
int flag,
int *update_p
)
{
int ec = 0;
int i;
/* compute the hash value */
/* check for duplicate */
if (flag == 0) {
}
*update_p = 1;
}
goto add_done;
}
}
/* add new object */
*update_p = 0;
}
/* make new items for the object */
/* no memory or table is full */
goto add_done;
}
/* check if the table needs is too full */
}
/* put the UID of the object to the avl tree */
case -2:
goto add_done;
case -1:
goto add_done;
case 0:
break;
case 1:
break;
default:
break;
}
/* update data store before putting to hash table */
if (flag == 0) {
/* not association object */
}
/* put the object to the table */
for (i = 0; ec == 0; ) {
items[i].p = p;
}
i ++;
} else {
break;
}
}
/* cache has been successfully updated */
/* successfully added */
if (ec == 0) {
/* perform the Default DD behavior */
/* set the return uid */
}
}
}
return (ec);
}
/*
* ****************************************************************************
* htab_remove:
* remove an object from the hash table.
*
* tab - the hash table.
* p - the lookup control for the object.
* uid - the UID of the object.
* clone_flag - indicate if the removing is for an association object.
* return - the removed object.
*
* ****************************************************************************
*/
void *p,
int clone_flag
)
{
htab_itemx_t *x = NULL;
int i;
/* get the object hash value */
if (uid != 0) {
} else {
goto remove_done;
}
} else {
flags = 0 | FLAGS_CTRL_MASK;
}
/* search the object from the table */
flags = 0;
for (i = 0; ; ) {
/* found it */
/* make an association object if the object */
/* has membership in user-defined DD(s). */
if (i == 0) {
clone_flag)) == NULL) {
}
}
/* remove it */
/* itself is an association object */
goto remove_done;
} else {
/* replace it with association */
}
if (i == 0) {
/* obj has been removed or updated */
}
break;
}
}
i ++;
} else {
break;
}
}
/* update the node in the avl tree */
if (x == NULL) {
}
/* mark the uid item as invalid */
x->hval |= BAD_HVAL_MASK;
/* update the timestamp */
/* put it to the end of fifo list */
} else {
}
}
}
return (zhizi);
}
/*
* ****************************************************************************
* htab_lookup:
* lookup an object from the hash table.
*
* tab - the hash table.
* p - the lookup control for the item.
* uid - the UID of the object.
* uid_p- the pointer of UID for returning.
* callback - callback function if the object is found.
* rekey - flag that indicates if the callback function will update
* the key of the object.
* return - error code.
*
* ****************************************************************************
*/
int
void *p,
int (*callback)(void *, void *),
int rekey
)
{
htab_itemx_t *x = NULL;
int i;
/* compute the hash value */
if (uid != 0) {
if (x != NULL) {
} else {
}
} else {
}
/* find the object */
i = flags & FLAGS_CHUNK_MASK;
break;
}
}
}
/* found it */
/* set the return uid */
}
/* invoke callback */
}
/* Rekey works for one-chunk hash table only. */
/* remove from previous slot */
/* add it to the new slot */
flags = 0;
}
}
/* set the return uid to 0 */
*uid_p = 0;
}
return (ret);
}
/*
* ****************************************************************************
* htab_get_next:
* get the next object UID from the hash table.
*
* tab - the hash table.
* uid - the previous objet UID.
* return - the next object UID.
*
* ****************************************************************************
*/
)
{
htab_itemx_t *x;
do {
/* search the next node from the avl tree */
if (x != NULL) {
/* validate the node */
return (uid);
}
}
} while (x != NULL);
/* no more node is available */
return (0);
}
/*
* ****************************************************************************
* htab_dump:
* dump all objects stored in the hash table for debug purpose.
*
* tab - the hash table.
*
* ****************************************************************************
*/
#ifdef DEBUG
void
)
{
uint32_t i;
for (i = 0; i < chunksz; i++) {
}
}
}
#endif