Initial import of the CDE 2.1.30 sources from the Open Group.
This commit is contained in:
39
cde/programs/dtinfo/DtMmdb/dynhash/Imakefile
Normal file
39
cde/programs/dtinfo/DtMmdb/dynhash/Imakefile
Normal file
@@ -0,0 +1,39 @@
|
||||
XCOMM $XConsortium: Imakefile /main/8 1996/08/21 15:51:56 drk $
|
||||
|
||||
XCOMM ** WARNING **
|
||||
XCOMM
|
||||
XCOMM The files named here may appear in many different Imakefiles.
|
||||
XCOMM If you add or remove a file, be sure to update all locations.
|
||||
XCOMM It's unfortunate, but all this redundancy serves a purpose.
|
||||
XCOMM
|
||||
XCOMM Other possible locations are:
|
||||
XCOMM .../lib/DtMmdb/Imakefile
|
||||
XCOMM .../lib/DtMmdb/<subdir>/Imakefile
|
||||
XCOMM .../programs/dtinfo/mmdb/Imakefile
|
||||
XCOMM .../programs/dtinfo/mmdb/<subdir>/Imakefile
|
||||
|
||||
#define DoNormalLib NormalLibDtMmdb
|
||||
#define DoSharedLib SharedLibDtMmdb
|
||||
#define DoDebugLib DebugLibDtMmdb
|
||||
#define DoProfileLib ProfileLibDtMmdb
|
||||
#define LibName DtMmdb
|
||||
#define SoRev SODTMMDBREV
|
||||
#define LibHeaders NO
|
||||
#define LibCreate NO
|
||||
#define LargePICTable YES
|
||||
|
||||
#define CplusplusSource YES
|
||||
DEPEND_DEFINES = $(CXXDEPENDINCLUDES)
|
||||
|
||||
XCOMM In DtMmdb we compile as C_API sources.
|
||||
DEFINES = -DC_API
|
||||
INCLUDES = -I.. $(EXCEPTIONS_INCLUDES)
|
||||
|
||||
SRCS = data_t.C imp_bucket.C imp_die.C
|
||||
OBJS = $(SRCS:.C=.o)
|
||||
|
||||
#include <Library.tmpl>
|
||||
|
||||
SubdirLibraryRule($(OBJS))
|
||||
|
||||
DependTarget()
|
||||
101
cde/programs/dtinfo/DtMmdb/dynhash/bsearch.C
Normal file
101
cde/programs/dtinfo/DtMmdb/dynhash/bsearch.C
Normal file
@@ -0,0 +1,101 @@
|
||||
/*
|
||||
* $XConsortium: bsearch.C /main/4 1996/10/04 09:33:19 drk $
|
||||
*
|
||||
* Copyright (c) 1992 HaL Computer Systems, Inc. All rights reserved.
|
||||
* UNPUBLISHED -- rights reserved under the Copyright Laws of the United
|
||||
* States. Use of a copyright notice is precautionary only and does not
|
||||
* imply publication or disclosure.
|
||||
*
|
||||
* This software contains confidential information and trade secrets of HaL
|
||||
* Computer Systems, Inc. Use, disclosure, or reproduction is prohibited
|
||||
* without the prior express written permission of HaL Computer Systems, Inc.
|
||||
*
|
||||
* RESTRICTED RIGHTS LEGEND
|
||||
* Use, duplication, or disclosure by the Government is subject to
|
||||
* restrictions as set forth in subparagraph (c)(l)(ii) of the Rights in
|
||||
* Technical Data and Computer Software clause at DFARS 252.227-7013.
|
||||
* HaL Computer Systems, Inc.
|
||||
* 1315 Dell Avenue, Campbell, CA 95008
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#include <sys/time.h>
|
||||
#include <math.h>
|
||||
#include <fstream.h>
|
||||
#include <search.h>
|
||||
#include "dynhash/bucket.h"
|
||||
|
||||
/*
|
||||
extern "C" {
|
||||
int bsearch(char*, char*, int, int, int(*)());
|
||||
};
|
||||
*/
|
||||
|
||||
int compare(const void* vd1, const void* vd2)
|
||||
{
|
||||
data_t* d1 = (data_t*)vd1;
|
||||
data_t* d2 = (data_t*)vd2;
|
||||
|
||||
if ( d1 -> key < d2 -> key )
|
||||
return -1;
|
||||
else
|
||||
if ( d1 -> key == d2 -> key )
|
||||
return 0;
|
||||
else
|
||||
return 1;
|
||||
}
|
||||
|
||||
#define TBSIZE 1000
|
||||
|
||||
main( int argc, char** argv )
|
||||
{
|
||||
data_t *x = new data_t[TBSIZE];
|
||||
|
||||
srand(314159);
|
||||
for ( int i=0; i<TBSIZE; i++ ) {
|
||||
x[i].key = rand() % TBSIZE;
|
||||
//x[i].key = i;
|
||||
x[i].dt = voidPtr(i);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
for ( i=0; i<TBSIZE; i++ )
|
||||
debug(cerr, x[i]);
|
||||
*/
|
||||
|
||||
struct timeval sec1, sec2;
|
||||
struct timezone tz1, tz2;
|
||||
|
||||
gettimeofday(&sec1, &tz1);
|
||||
//debug(cerr, sec1.tv_sec);
|
||||
//debug(cerr, sec1.tv_usec);
|
||||
|
||||
qsort((char*)x, TBSIZE, sizeof(data_t), compare);
|
||||
|
||||
for ( i=0; i<TBSIZE; i++ ) {
|
||||
data_t key = x[i];
|
||||
void * ok = bsearch((char*)(&key),
|
||||
(char*)x, TBSIZE, sizeof(data_t), compare);
|
||||
if ( ok == 0 ) {
|
||||
debug(cerr, "member test failed");
|
||||
exit(-2);
|
||||
}
|
||||
}
|
||||
gettimeofday(&sec2, &tz2);
|
||||
//debug(cerr, sec2.tv_sec);
|
||||
//debug(cerr, sec2.tv_usec);
|
||||
|
||||
if ( sec1.tv_usec > sec2.tv_usec ) {
|
||||
printf("difference = %ld %6ld\n",
|
||||
(long)sec2.tv_sec-sec1.tv_sec-1,
|
||||
(long)1000000+sec2.tv_usec-sec1.tv_usec
|
||||
);
|
||||
} else {
|
||||
printf("difference = %ld %6ld\n",
|
||||
(long)sec2.tv_sec-sec1.tv_sec,
|
||||
(long)sec2.tv_usec-sec1.tv_usec
|
||||
);
|
||||
}
|
||||
}
|
||||
294
cde/programs/dtinfo/DtMmdb/dynhash/bucket.C
Normal file
294
cde/programs/dtinfo/DtMmdb/dynhash/bucket.C
Normal file
@@ -0,0 +1,294 @@
|
||||
/*
|
||||
* $XConsortium: bucket.cc /main/3 1996/06/11 17:18:55 cde-hal $
|
||||
*
|
||||
* Copyright (c) 1992 HaL Computer Systems, Inc. All rights reserved.
|
||||
* UNPUBLISHED -- rights reserved under the Copyright Laws of the United
|
||||
* States. Use of a copyright notice is precautionary only and does not
|
||||
* imply publication or disclosure.
|
||||
*
|
||||
* This software contains confidential information and trade secrets of HaL
|
||||
* Computer Systems, Inc. Use, disclosure, or reproduction is prohibited
|
||||
* without the prior express written permission of HaL Computer Systems, Inc.
|
||||
*
|
||||
* RESTRICTED RIGHTS LEGEND
|
||||
* Use, duplication, or disclosure by the Government is subject to
|
||||
* restrictions as set forth in subparagraph (c)(l)(ii) of the Rights in
|
||||
* Technical Data and Computer Software clause at DFARS 252.227-7013.
|
||||
* HaL Computer Systems, Inc.
|
||||
* 1315 Dell Avenue, Campbell, CA 95008
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#include "dynhash/bucket.h"
|
||||
|
||||
int bucket::upper_limit;
|
||||
|
||||
bucket::bucket(int new_Mj, int owj) : wj(0), Mj(new_Mj), old_wj(owj)
|
||||
{
|
||||
k = 19;
|
||||
data_array = new data_t[2*Mj*Mj];
|
||||
}
|
||||
|
||||
bucket::~bucket()
|
||||
{
|
||||
delete [2 * Mj * Mj] data_array;
|
||||
}
|
||||
|
||||
/***********************************************/
|
||||
// rehash the existing keys and the new key
|
||||
// 'data'
|
||||
/***********************************************/
|
||||
void bucket::rehash_all(data_t& data, shared_t& sh)
|
||||
{
|
||||
int j = 0;
|
||||
int ind = first();
|
||||
while ( ind != -1 ) {
|
||||
sh.internal_L[j++] = (*this)(ind);
|
||||
data_array[ind].marked = false;
|
||||
next(ind);
|
||||
}
|
||||
sh.internal_L[j] = data;
|
||||
|
||||
select_h_params(sh);
|
||||
|
||||
for ( ind = 0; ind <= j; ind++ ) {
|
||||
int hash = h(sh.internal_L[ind].key, sh);
|
||||
data_array[hash] = sh.internal_L[ind];
|
||||
data_array[hash].marked = true;
|
||||
}
|
||||
}
|
||||
|
||||
/****************************************/
|
||||
// select a proper value for parameter k
|
||||
// sh contains useful variables from the
|
||||
// first level hash table.
|
||||
/****************************************/
|
||||
void bucket::select_h_params(shared_t& sh)
|
||||
{
|
||||
Boolean injective = false;
|
||||
int loops = 0;
|
||||
|
||||
/******************************************/
|
||||
// loop until an injective mapping is found
|
||||
/******************************************/
|
||||
|
||||
while ( injective == false ) {
|
||||
k = sh.rand_generator.rand() % (sh.p - 1) + 1;
|
||||
injective = true;
|
||||
for ( int i=0; i<wj; i++ ) {
|
||||
int hash = h( sh.internal_L[i].key, sh );
|
||||
if ( data_array[hash].marked == false ) {
|
||||
data_array[hash].marked = true ;
|
||||
} else {
|
||||
for ( int j = 0; j<2*Mj*Mj; j++ )
|
||||
data_array[j].marked = false;
|
||||
injective = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
loops ++;
|
||||
if ( loops >= 20 ) { // supposedly loop twice
|
||||
debug(cerr, loops);
|
||||
debug(cerr, Mj);
|
||||
debug(cerr, wj);
|
||||
debug(cerr, k);
|
||||
for ( int i=0; i<wj; i++ ) {
|
||||
int hash = h( sh.internal_L[i].key, sh );
|
||||
debug(cerr, sh.internal_L[i]);
|
||||
debug(cerr, hash);
|
||||
}
|
||||
throw(boundaryException(1, 20, loops));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/************************************************/
|
||||
// insert
|
||||
/************************************************/
|
||||
Boolean bucket::insert(data_t& data, shared_t& sh)
|
||||
{
|
||||
wj++;
|
||||
int j = h(data.key, sh);
|
||||
|
||||
if ( wj <= Mj ) {
|
||||
|
||||
/**********************/
|
||||
// space is enough
|
||||
/**********************/
|
||||
|
||||
if ( data_array[j].marked == false ) {
|
||||
data_array[j] = data;
|
||||
data_array[j].marked = true;
|
||||
} else
|
||||
if ( data_array[j].key == data.key) {
|
||||
debug(cerr, data_array[j]);
|
||||
debug(cerr, data);
|
||||
MESSAGE(cerr, "key is in the set");
|
||||
return true;
|
||||
} else
|
||||
rehash_all(data, sh);
|
||||
|
||||
return true;
|
||||
} else {
|
||||
|
||||
/***************************/
|
||||
// need to double the space
|
||||
// debug(cerr, "rehash bucket");
|
||||
// debug(cerr, data.key);
|
||||
/***************************/
|
||||
|
||||
int old_contribute = 2 * old_wj * old_wj;
|
||||
int new_contribute = 2 * wj * wj;
|
||||
if ( sh.sum - old_contribute + new_contribute < sh.limit ) {
|
||||
|
||||
/**************************************/
|
||||
// if condition 4 holds, we just rehash
|
||||
// keys in this table
|
||||
/**************************************/
|
||||
sh.sum -= old_contribute;
|
||||
sh.sum += new_contribute;
|
||||
old_wj = wj;
|
||||
|
||||
data_t *x = new data_t[8*Mj*Mj];
|
||||
|
||||
int ind = first();
|
||||
|
||||
/********************/
|
||||
// collect records
|
||||
/********************/
|
||||
while ( ind != -1 ) {
|
||||
x[ind] = (*this)(ind);
|
||||
next(ind);
|
||||
}
|
||||
|
||||
/*****************************/
|
||||
// allocate new space
|
||||
/*****************************/
|
||||
delete [2*Mj*Mj] data_array;
|
||||
data_array = x;
|
||||
|
||||
Mj *= 2;
|
||||
|
||||
/*****************************/
|
||||
// re-hash keys in this bucket
|
||||
/*****************************/
|
||||
rehash_all(data, sh);
|
||||
|
||||
return true;
|
||||
|
||||
} else {
|
||||
/*******************************/
|
||||
// Condition 4 does not hold.
|
||||
// Return false to signal a
|
||||
// entire set re-hash.
|
||||
/*******************************/
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*******************************/
|
||||
// compute the hash value
|
||||
/*******************************/
|
||||
int bucket::h(int key, shared_t& sh)
|
||||
{
|
||||
return ( (abs( k * key )) % (sh.p) ) % (2 * Mj * Mj);
|
||||
}
|
||||
|
||||
/*******************************/
|
||||
// membership test
|
||||
/*******************************/
|
||||
Boolean bucket::member(data_t& data, shared_t& sh)
|
||||
{
|
||||
int pos = h( data.key, sh );
|
||||
if ( data_array[pos].marked == true ) {
|
||||
data.dt = data_array[pos].dt;
|
||||
|
||||
if ( data_array[pos].key == data.key )
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
|
||||
} else {
|
||||
data.key = -1;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/*******************************/
|
||||
// remove operation
|
||||
/*******************************/
|
||||
Boolean bucket::remove(data_t& data, shared_t& sh)
|
||||
{
|
||||
int pos = h( data.key, sh );
|
||||
|
||||
if ( data_array[pos].marked == true &&
|
||||
data_array[pos].key == data.key) {
|
||||
|
||||
data_array[pos].marked = false;
|
||||
wj--;
|
||||
return true;
|
||||
|
||||
} else {
|
||||
MESSAGE(cerr, "+++++++++++++++");
|
||||
debug(cerr, wj);
|
||||
debug(cerr, *this);
|
||||
debug(cerr, data);
|
||||
debug(cerr, data_array[pos]);
|
||||
MESSAGE(cerr, "data is not in the key set");
|
||||
MESSAGE(cerr, "+++++++++++++++");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/***********************************************/
|
||||
// iteration operations
|
||||
/***********************************************/
|
||||
int bucket::first()
|
||||
{
|
||||
upper_limit = 2 * Mj * Mj;
|
||||
if ( wj == 0 )
|
||||
return -1;
|
||||
else {
|
||||
int i=0;
|
||||
while ( data_array[i].marked == false ) {
|
||||
if ( i >= upper_limit ) {
|
||||
debug(cerr, i);
|
||||
debug(cerr, upper_limit);
|
||||
throw(stringException("hash table is in inconsistent status"));
|
||||
}
|
||||
i++;
|
||||
}
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
data_t& bucket::operator()(int ind)
|
||||
{
|
||||
return data_array[ind];
|
||||
}
|
||||
|
||||
void bucket::next(int& ind)
|
||||
{
|
||||
for ( int j = ind+1; j < upper_limit; j ++ )
|
||||
if ( data_array[j].marked == true ) {
|
||||
ind = j;
|
||||
return;
|
||||
}
|
||||
|
||||
ind = -1;
|
||||
}
|
||||
|
||||
/***********************************************/
|
||||
// print operation
|
||||
/***********************************************/
|
||||
ostream& operator<<(ostream& out, bucket& bt)
|
||||
{
|
||||
int ind = bt.first();
|
||||
while ( ind != -1 ) {
|
||||
debug(out, bt(ind));
|
||||
bt.next(ind);
|
||||
}
|
||||
return out;
|
||||
}
|
||||
109
cde/programs/dtinfo/DtMmdb/dynhash/bucket.h
Normal file
109
cde/programs/dtinfo/DtMmdb/dynhash/bucket.h
Normal file
@@ -0,0 +1,109 @@
|
||||
/*
|
||||
* $XConsortium: bucket.h /main/3 1996/06/11 17:19:00 cde-hal $
|
||||
*
|
||||
* Copyright (c) 1992 HaL Computer Systems, Inc. All rights reserved.
|
||||
* UNPUBLISHED -- rights reserved under the Copyright Laws of the United
|
||||
* States. Use of a copyright notice is precautionary only and does not
|
||||
* imply publication or disclosure.
|
||||
*
|
||||
* This software contains confidential information and trade secrets of HaL
|
||||
* Computer Systems, Inc. Use, disclosure, or reproduction is prohibited
|
||||
* without the prior express written permission of HaL Computer Systems, Inc.
|
||||
*
|
||||
* RESTRICTED RIGHTS LEGEND
|
||||
* Use, duplication, or disclosure by the Government is subject to
|
||||
* restrictions as set forth in subparagraph (c)(l)(ii) of the Rights in
|
||||
* Technical Data and Computer Software clause at DFARS 252.227-7013.
|
||||
* HaL Computer Systems, Inc.
|
||||
* 1315 Dell Avenue, Campbell, CA 95008
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
/***************************************************************/
|
||||
//
|
||||
//Implementation of the dynamic perfect hashing algorithm, based on:
|
||||
//
|
||||
// "Dynamic Perfect Hashing: Upper and Lower Bounds"
|
||||
//
|
||||
// By
|
||||
//
|
||||
// M. Dietzfelbinger, A. Karlin, K. Mehlhorn,
|
||||
// F. Meyer auf der Heider, H. Rohnert and
|
||||
// R. E. Tarjan
|
||||
// appearing in
|
||||
//
|
||||
// 1988 FOCS.
|
||||
//
|
||||
/***************************************************************/
|
||||
|
||||
|
||||
/***************************************************************/
|
||||
// Programmer: QiFan Chen
|
||||
// Date: June 14, 1992
|
||||
// Language: C++ (2.0)
|
||||
// Machine: SUN SPARCstation IPC
|
||||
/***************************************************************/
|
||||
|
||||
#ifndef _bucket_h
|
||||
#define _bucket_h
|
||||
|
||||
#include "utility/funcs.h"
|
||||
#include "utility/prandom.h"
|
||||
#include "dynhash/data.h"
|
||||
|
||||
|
||||
/**************************************************************/
|
||||
// define a data object that is shared by the first
|
||||
// and the second level hash functions
|
||||
/**************************************************************/
|
||||
|
||||
struct shared_t {
|
||||
prandom rand_generator; // rand generator
|
||||
int p; // prime number p
|
||||
int sum; // the value of the lhs of condition 4
|
||||
int limit; // the value of the rhs of condition 4
|
||||
data_t* internal_L; // the list representation
|
||||
};
|
||||
|
||||
/****************************/
|
||||
// A bucket object forms a
|
||||
// second level hash function
|
||||
/****************************/
|
||||
class bucket {
|
||||
|
||||
protected:
|
||||
static int upper_limit; // set to 2*Mj*Mj by first()
|
||||
// for fast iteration
|
||||
|
||||
int k; // valye k used in H_{{2M_j}^2}()
|
||||
int Mj; // size window
|
||||
int wj; // keys in the bucket
|
||||
int old_wj; // value of wj after a memory allocation
|
||||
data_tPtr data_array; // key array
|
||||
|
||||
void rehash_all(data_t& dt, shared_t&); // rehash all keys
|
||||
void select_h_params(shared_t&); // select the parameter k
|
||||
|
||||
public:
|
||||
bucket(int new_Mj, int old_wj);
|
||||
virtual ~bucket();
|
||||
|
||||
int h(int key, shared_t&); // hash function H_{{2M_j}^2}()
|
||||
int M_size() { return Mj; }; // the value of Mj
|
||||
int wj_size() { return wj; }; // the value of wj
|
||||
|
||||
Boolean insert(data_t& dt, shared_t&); // insert a key
|
||||
Boolean remove(data_t& dt, shared_t&); // remove a key
|
||||
Boolean member(data_t& dt, shared_t&); // member test
|
||||
|
||||
int first(); // iterate over all keys in
|
||||
data_t& operator()(int ind); // the bucket
|
||||
void next(int& ind); // terminate condition: -1
|
||||
|
||||
friend ostream& operator<<(ostream&, bucket&);
|
||||
};
|
||||
|
||||
typedef bucket* bucketPtr;
|
||||
|
||||
#endif
|
||||
332
cde/programs/dtinfo/DtMmdb/dynhash/data_t.C
Normal file
332
cde/programs/dtinfo/DtMmdb/dynhash/data_t.C
Normal file
@@ -0,0 +1,332 @@
|
||||
/*
|
||||
* $XConsortium: data_t.cc /main/4 1996/07/18 14:31:45 drk $
|
||||
*
|
||||
* Copyright (c) 1993 HAL Computer Systems International, Ltd.
|
||||
* All rights reserved. Unpublished -- rights reserved under
|
||||
* the Copyright Laws of the United States. USE OF A COPYRIGHT
|
||||
* NOTICE IS PRECAUTIONARY ONLY AND DOES NOT IMPLY PUBLICATION
|
||||
* OR DISCLOSURE.
|
||||
*
|
||||
* THIS SOFTWARE CONTAINS CONFIDENTIAL INFORMATION AND TRADE
|
||||
* SECRETS OF HAL COMPUTER SYSTEMS INTERNATIONAL, LTD. USE,
|
||||
* DISCLOSURE, OR REPRODUCTION IS PROHIBITED WITHOUT THE
|
||||
* PRIOR EXPRESS WRITTEN PERMISSION OF HAL COMPUTER SYSTEMS
|
||||
* INTERNATIONAL, LTD.
|
||||
*
|
||||
* RESTRICTED RIGHTS LEGEND
|
||||
* Use, duplication, or disclosure by the Government is subject
|
||||
* to the restrictions as set forth in subparagraph (c)(l)(ii)
|
||||
* of the Rights in Technical Data and Computer Software clause
|
||||
* at DFARS 252.227-7013.
|
||||
*
|
||||
* HAL COMPUTER SYSTEMS INTERNATIONAL, LTD.
|
||||
* 1315 Dell Avenue
|
||||
* Campbell, CA 95008
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#include "dynhash/data_t.h"
|
||||
|
||||
//memory_pool data_t::data_t_space_pool;
|
||||
|
||||
extern memory_pool g_memory_pool;
|
||||
|
||||
#ifdef C_API
|
||||
atoi_larson* data_t::larson_convertor_ptr;
|
||||
atoi_pearson* data_t::pearson_convertor_ptr;
|
||||
#else
|
||||
atoi_larson data_t::larson_convertor;
|
||||
atoi_pearson data_t::pearson_convertor(MAXSHORT, 256);
|
||||
#endif
|
||||
|
||||
data_t::data_t(data_t& d)
|
||||
{
|
||||
flag = d.flag;
|
||||
dt = d.dt;
|
||||
|
||||
switch ( flag ) {
|
||||
case INT:
|
||||
{
|
||||
key.int_key = d.key.int_key ;
|
||||
flag = INT;
|
||||
break;
|
||||
}
|
||||
case STRING:
|
||||
{
|
||||
int sz = strlen(d.key.str_key);
|
||||
key.str_key = new char[sz+1];
|
||||
strcpy(key.str_key, d.key.str_key);
|
||||
key.str_key[sz] = 0;
|
||||
|
||||
flag = STRING;
|
||||
break;
|
||||
}
|
||||
case VOID:
|
||||
flag = VOID;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* // inline
|
||||
data_t::data_t(int t, voidPtr d) : dt(d)
|
||||
{
|
||||
flag = data_t::INT;
|
||||
key.int_key = t;
|
||||
}
|
||||
*/
|
||||
|
||||
data_t::data_t(const char* str, int sz, voidPtr d) : dt(d)
|
||||
{
|
||||
flag = data_t::STRING;
|
||||
|
||||
key.str_key = new char[sz+1];
|
||||
|
||||
if ( sz > 0 )
|
||||
strcpy(key.str_key, str);
|
||||
|
||||
key.str_key[sz] = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
int data_t::size()
|
||||
{
|
||||
switch ( flag ) {
|
||||
case INT:
|
||||
case VOID:
|
||||
return 2 + strlen(form("%d", key.int_key)) + sizeof(dt);
|
||||
|
||||
case STRING:
|
||||
return 2 + strlen(key.str_key) + sizeof(dt);
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
int data_t::operator==(data_t& d)
|
||||
{
|
||||
if ( flag != d.flag ) {
|
||||
|
||||
debug(cerr, flag);
|
||||
debug(cerr, d.flag);
|
||||
|
||||
debug(cerr, *this);
|
||||
debug(cerr, d);
|
||||
|
||||
throw(stringException("data_t type mismatches in operator==()"));
|
||||
}
|
||||
|
||||
switch (flag) {
|
||||
case INT:
|
||||
return key.int_key == d.key.int_key ;
|
||||
case STRING:
|
||||
return strcmp(key.str_key, d.key.str_key) == 0 ;
|
||||
case VOID:
|
||||
throw(stringException("VOID type in operator==()"));
|
||||
}
|
||||
}
|
||||
|
||||
data_t& data_t::operator =(data_t& d)
|
||||
{
|
||||
flag = d.flag;
|
||||
dt = d.dt;
|
||||
|
||||
switch ( flag ) {
|
||||
case INT:
|
||||
key.int_key = d.key.int_key ;
|
||||
flag = INT;
|
||||
break;
|
||||
|
||||
case STRING:
|
||||
{
|
||||
int d_sz = strlen(d.key.str_key);
|
||||
if ( strlen(key.str_key) < d_sz ) {
|
||||
delete key.str_key;
|
||||
key.str_key = new char[d_sz+1];
|
||||
}
|
||||
strcpy(key.str_key, d.key.str_key);
|
||||
key.str_key[d_sz] = 0;
|
||||
flag = STRING;
|
||||
break;
|
||||
}
|
||||
case VOID:
|
||||
flag = VOID;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
data_t::~data_t()
|
||||
{
|
||||
switch ( flag ) {
|
||||
case INT:
|
||||
break;
|
||||
case STRING:
|
||||
delete key.str_key;
|
||||
break;
|
||||
case VOID:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static char buf[BUFSIZ];
|
||||
|
||||
istream& operator >>(istream& i, data_t& d)
|
||||
{
|
||||
if ( !i.getline(buf, BUFSIZ) || buf[0] == '\n' )
|
||||
return i;
|
||||
|
||||
char* key_ptr = strchr(buf, '\t');
|
||||
char* voidPtr_ptr = strrchr(buf, '\t');
|
||||
|
||||
*key_ptr = 0;
|
||||
*voidPtr_ptr = 0;
|
||||
|
||||
key_ptr++;
|
||||
voidPtr_ptr++;
|
||||
|
||||
//////////////////////////
|
||||
// delete the string
|
||||
//////////////////////////
|
||||
if ( d.flag == data_t::STRING )
|
||||
delete d.key.str_key;
|
||||
|
||||
d.flag = (data_t::flag_type)atoi(buf);
|
||||
d.dt = voidPtr(atoi(voidPtr_ptr));
|
||||
|
||||
if ( d.flag == data_t::INT )
|
||||
d.key.int_key = atoi(key_ptr);
|
||||
else
|
||||
if ( d.flag == data_t::STRING ) {
|
||||
int sz = strlen(key_ptr);
|
||||
d.key.str_key = new char[sz+1];
|
||||
strcpy(d.key.str_key, key_ptr);
|
||||
d.key.str_key[sz] = 0;
|
||||
}
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
ostream& operator <<(ostream& o, data_t& d)
|
||||
{
|
||||
if ( d.flag == data_t::VOID )
|
||||
return o;
|
||||
|
||||
o << d.flag << " ";
|
||||
|
||||
switch ( d.flag ) {
|
||||
case data_t::INT:
|
||||
o << d.key.int_key;
|
||||
break;
|
||||
case data_t::STRING:
|
||||
o << d.key.str_key;
|
||||
break;
|
||||
}
|
||||
|
||||
o << " " << (long)(d.dt);
|
||||
return o;
|
||||
}
|
||||
|
||||
Boolean data_t::binaryIn(buffer& buf)
|
||||
{
|
||||
char c; buf.get(c);
|
||||
flag = (data_t::flag_type)c;
|
||||
|
||||
unsigned int sz;
|
||||
|
||||
switch ( flag ) {
|
||||
case data_t::VOID:
|
||||
break;
|
||||
|
||||
case data_t::INT:
|
||||
buf.get(*(unsigned int*)&key.int_key);
|
||||
break;
|
||||
|
||||
case data_t::STRING:
|
||||
|
||||
buf.get(sz);
|
||||
key.str_key = new char[sz+1];
|
||||
buf.get(key.str_key, sz);
|
||||
key.str_key[sz] = 0;
|
||||
|
||||
break;
|
||||
}
|
||||
buf.get(*(long*)&dt);
|
||||
return true;
|
||||
}
|
||||
|
||||
Boolean data_t::binaryOut(buffer& buf)
|
||||
{
|
||||
buf.put((char)flag);
|
||||
unsigned int sz;
|
||||
|
||||
switch ( flag ) {
|
||||
case data_t::VOID:
|
||||
break;
|
||||
|
||||
case data_t::INT:
|
||||
buf.put((unsigned int)key.int_key);
|
||||
break;
|
||||
|
||||
case data_t::STRING:
|
||||
sz = strlen(key.str_key);
|
||||
|
||||
buf.put(sz);
|
||||
buf.put(key.str_key, sz);
|
||||
|
||||
|
||||
break;
|
||||
}
|
||||
buf.put((long)dt);
|
||||
return true;
|
||||
}
|
||||
|
||||
ostream& data_t::asciiOut(ostream& o, print_func_ptr_t print_f)
|
||||
{
|
||||
print_f(o, this);
|
||||
return o;
|
||||
}
|
||||
|
||||
int data_t::bucket_num(int k, int p, int M)
|
||||
{
|
||||
switch ( flag ) {
|
||||
case INT:
|
||||
return abs( key.int_key * k ) % p % M ;
|
||||
case STRING:
|
||||
//return abs( larson_convertor.atoi(key.str_key) * k ) % p % M ;
|
||||
//return abs( pearson_convertor.atoi(key.str_key, strlen(key.str_key), k
|
||||
return abs( pearson_convertor.atoi(key.str_key, strlen(key.str_key), k
|
||||
, p) ) % M ;
|
||||
default:
|
||||
throw(stringException("VOID type in bucket_num()"));
|
||||
}
|
||||
}
|
||||
|
||||
int data_t::slot_num(int k, int rotate, int prime, int M )
|
||||
{
|
||||
int x;
|
||||
switch ( flag ) {
|
||||
case INT:
|
||||
x = ( abs( k * key.int_key ) % prime + rotate ) % M ;
|
||||
break;
|
||||
case STRING:
|
||||
x = ( abs( pearson_convertor.atoi(key.str_key, strlen(key.str_key), k, prime)) + rotate ) % M ;
|
||||
break;
|
||||
default:
|
||||
throw(stringException("VOID type in slot_num()"));
|
||||
}
|
||||
return x;
|
||||
}
|
||||
|
||||
void* data_t::operator new( size_t x )
|
||||
{
|
||||
//return (void*)data_t_space_pool.alloc(x);
|
||||
return (void*)g_memory_pool.alloc(x);
|
||||
}
|
||||
|
||||
void data_t::operator delete( void* ptr )
|
||||
{
|
||||
//data_t_space_pool.free((char*)ptr);
|
||||
g_memory_pool.free((char*)ptr);
|
||||
}
|
||||
|
||||
105
cde/programs/dtinfo/DtMmdb/dynhash/data_t.h
Normal file
105
cde/programs/dtinfo/DtMmdb/dynhash/data_t.h
Normal file
@@ -0,0 +1,105 @@
|
||||
/*
|
||||
* $XConsortium: data_t.h /main/3 1996/06/11 17:19:11 cde-hal $
|
||||
*
|
||||
* Copyright (c) 1993 HAL Computer Systems International, Ltd.
|
||||
* All rights reserved. Unpublished -- rights reserved under
|
||||
* the Copyright Laws of the United States. USE OF A COPYRIGHT
|
||||
* NOTICE IS PRECAUTIONARY ONLY AND DOES NOT IMPLY PUBLICATION
|
||||
* OR DISCLOSURE.
|
||||
*
|
||||
* THIS SOFTWARE CONTAINS CONFIDENTIAL INFORMATION AND TRADE
|
||||
* SECRETS OF HAL COMPUTER SYSTEMS INTERNATIONAL, LTD. USE,
|
||||
* DISCLOSURE, OR REPRODUCTION IS PROHIBITED WITHOUT THE
|
||||
* PRIOR EXPRESS WRITTEN PERMISSION OF HAL COMPUTER SYSTEMS
|
||||
* INTERNATIONAL, LTD.
|
||||
*
|
||||
* RESTRICTED RIGHTS LEGEND
|
||||
* Use, duplication, or disclosure by the Government is subject
|
||||
* to the restrictions as set forth in subparagraph (c)(l)(ii)
|
||||
* of the Rights in Technical Data and Computer Software clause
|
||||
* at DFARS 252.227-7013.
|
||||
*
|
||||
* HAL COMPUTER SYSTEMS INTERNATIONAL, LTD.
|
||||
* 1315 Dell Avenue
|
||||
* Campbell, CA 95008
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#ifndef _record_h
|
||||
#define _record_h
|
||||
|
||||
#include "utility/types.h"
|
||||
#include "utility/funcs.h"
|
||||
#include "utility/buffer.h"
|
||||
#include "dstr/memory_pool.h"
|
||||
#include "utility/atoi_pearson.h"
|
||||
#include "utility/atoi_larson.h"
|
||||
#include "dstr/dlist_cell.h"
|
||||
|
||||
/****************************/
|
||||
// record class. A record
|
||||
// contains a key and a void*
|
||||
// pointer
|
||||
/****************************/
|
||||
|
||||
class data_t : public dlist_cell
|
||||
{
|
||||
|
||||
protected:
|
||||
|
||||
#ifdef C_API
|
||||
static atoi_pearson* pearson_convertor_ptr;
|
||||
static atoi_larson* larson_convertor_ptr;
|
||||
#define pearson_convertor (*pearson_convertor_ptr)
|
||||
#define larson_convertor (*larson_convertor_ptr)
|
||||
#else
|
||||
static atoi_pearson pearson_convertor;
|
||||
static atoi_larson larson_convertor;
|
||||
#endif
|
||||
|
||||
public:
|
||||
enum flag_type { INT=0, STRING=1, VOID=2 };
|
||||
|
||||
flag_type flag;
|
||||
union {
|
||||
int int_key;
|
||||
char* str_key;
|
||||
} key;
|
||||
voidPtr dt; // rest of information in the record
|
||||
|
||||
data_t(): dt(0), flag(data_t::VOID) {} ;
|
||||
data_t(data_t&) ;
|
||||
data_t(int int_key, voidPtr d = 0) : dt(d), flag(data_t::INT)
|
||||
{ key.int_key = int_key; };
|
||||
|
||||
data_t(const char* char_ptr_key, int char_ptr_key_sz, voidPtr d = 0) ;
|
||||
virtual ~data_t() ;
|
||||
|
||||
data_t& operator=(data_t&);
|
||||
int operator==(data_t&);
|
||||
|
||||
virtual int bucket_num(int k, int p, int M ) ;
|
||||
virtual int slot_num(int k, int rotate, int prime, int M ) ;
|
||||
|
||||
ostream& asciiOut(ostream& out, print_func_ptr_t print_f);
|
||||
|
||||
Boolean binaryIn(buffer&);
|
||||
Boolean binaryOut(buffer&);
|
||||
|
||||
void* operator new( size_t );
|
||||
void operator delete( void* );
|
||||
|
||||
friend ostream& operator <<(ostream& o, data_t& d);
|
||||
friend istream& operator >>(istream& i, data_t& d);
|
||||
|
||||
#ifdef C_API
|
||||
friend void initialize_MMDB();
|
||||
friend void quit_MMDB();
|
||||
#endif
|
||||
|
||||
};
|
||||
|
||||
typedef data_t* data_tPtr;
|
||||
|
||||
#endif
|
||||
104
cde/programs/dtinfo/DtMmdb/dynhash/imp_bucket.C
Normal file
104
cde/programs/dtinfo/DtMmdb/dynhash/imp_bucket.C
Normal file
@@ -0,0 +1,104 @@
|
||||
/*
|
||||
* $XConsortium: imp_bucket.cc /main/4 1996/07/18 14:32:05 drk $
|
||||
*
|
||||
* Copyright (c) 1993 HAL Computer Systems International, Ltd.
|
||||
* All rights reserved. Unpublished -- rights reserved under
|
||||
* the Copyright Laws of the United States. USE OF A COPYRIGHT
|
||||
* NOTICE IS PRECAUTIONARY ONLY AND DOES NOT IMPLY PUBLICATION
|
||||
* OR DISCLOSURE.
|
||||
*
|
||||
* THIS SOFTWARE CONTAINS CONFIDENTIAL INFORMATION AND TRADE
|
||||
* SECRETS OF HAL COMPUTER SYSTEMS INTERNATIONAL, LTD. USE,
|
||||
* DISCLOSURE, OR REPRODUCTION IS PROHIBITED WITHOUT THE
|
||||
* PRIOR EXPRESS WRITTEN PERMISSION OF HAL COMPUTER SYSTEMS
|
||||
* INTERNATIONAL, LTD.
|
||||
*
|
||||
* RESTRICTED RIGHTS LEGEND
|
||||
* Use, duplication, or disclosure by the Government is subject
|
||||
* to the restrictions as set forth in subparagraph (c)(l)(ii)
|
||||
* of the Rights in Technical Data and Computer Software clause
|
||||
* at DFARS 252.227-7013.
|
||||
*
|
||||
* HAL COMPUTER SYSTEMS INTERNATIONAL, LTD.
|
||||
* 1315 Dell Avenue
|
||||
* Campbell, CA 95008
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
|
||||
#include "dynhash/imp_bucket.h"
|
||||
|
||||
imp_bucket::imp_bucket() : k(19), rotate(0)
|
||||
{
|
||||
}
|
||||
|
||||
imp_bucket::~imp_bucket()
|
||||
{
|
||||
}
|
||||
|
||||
Boolean imp_bucket::empty()
|
||||
{
|
||||
return ( count() == 0 ) ? true : false;
|
||||
}
|
||||
|
||||
/************************************************/
|
||||
// insert
|
||||
/************************************************/
|
||||
Boolean imp_bucket::insert(data_t* data)
|
||||
{
|
||||
insert_as_tail(data);
|
||||
return true;
|
||||
}
|
||||
|
||||
/************************************************/
|
||||
// remove
|
||||
/************************************************/
|
||||
data_t* imp_bucket::remove_all()
|
||||
{
|
||||
data_t* x = (data_t*)v_head;
|
||||
v_head = v_tail = 0;
|
||||
return x;
|
||||
}
|
||||
|
||||
/*******************************/
|
||||
// compute the hash value
|
||||
/*******************************/
|
||||
int imp_bucket::h(int key, int prime, int M)
|
||||
{
|
||||
return ( abs( k * key ) % prime + rotate ) % M ;
|
||||
}
|
||||
|
||||
data_t* imp_bucket::operator()(long ind)
|
||||
{
|
||||
if ( ind == 0 ) {
|
||||
MESSAGE(cerr, "imp_bucket::operator(): zero index value");
|
||||
throw(boundaryException(1, MAXINT, ind));
|
||||
}
|
||||
|
||||
return (data_t*)ind;
|
||||
}
|
||||
|
||||
|
||||
/***********************************************/
|
||||
// print operation
|
||||
/***********************************************/
|
||||
ostream& operator<<(ostream& out, imp_bucket& bt)
|
||||
{
|
||||
long ind = bt.first();
|
||||
while ( ind != 0 ) {
|
||||
out << *bt(ind) << "\n";
|
||||
bt.next(ind);
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
ostream& imp_bucket::asciiOut(ostream& out, print_func_ptr_t print_f)
|
||||
{
|
||||
long ind = first();
|
||||
while ( ind != 0 ) {
|
||||
(*this)(ind) -> asciiOut(out, print_f);
|
||||
next(ind);
|
||||
}
|
||||
return out;
|
||||
}
|
||||
69
cde/programs/dtinfo/DtMmdb/dynhash/imp_bucket.h
Normal file
69
cde/programs/dtinfo/DtMmdb/dynhash/imp_bucket.h
Normal file
@@ -0,0 +1,69 @@
|
||||
/*
|
||||
* $XConsortium: imp_bucket.h /main/4 1996/07/18 14:32:27 drk $
|
||||
*
|
||||
* Copyright (c) 1993 HAL Computer Systems International, Ltd.
|
||||
* All rights reserved. Unpublished -- rights reserved under
|
||||
* the Copyright Laws of the United States. USE OF A COPYRIGHT
|
||||
* NOTICE IS PRECAUTIONARY ONLY AND DOES NOT IMPLY PUBLICATION
|
||||
* OR DISCLOSURE.
|
||||
*
|
||||
* THIS SOFTWARE CONTAINS CONFIDENTIAL INFORMATION AND TRADE
|
||||
* SECRETS OF HAL COMPUTER SYSTEMS INTERNATIONAL, LTD. USE,
|
||||
* DISCLOSURE, OR REPRODUCTION IS PROHIBITED WITHOUT THE
|
||||
* PRIOR EXPRESS WRITTEN PERMISSION OF HAL COMPUTER SYSTEMS
|
||||
* INTERNATIONAL, LTD.
|
||||
*
|
||||
* RESTRICTED RIGHTS LEGEND
|
||||
* Use, duplication, or disclosure by the Government is subject
|
||||
* to the restrictions as set forth in subparagraph (c)(l)(ii)
|
||||
* of the Rights in Technical Data and Computer Software clause
|
||||
* at DFARS 252.227-7013.
|
||||
*
|
||||
* HAL COMPUTER SYSTEMS INTERNATIONAL, LTD.
|
||||
* 1315 Dell Avenue
|
||||
* Campbell, CA 95008
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#ifndef _imp_bucket_h
|
||||
#define _imp_bucket_h
|
||||
|
||||
#include "utility/funcs.h"
|
||||
#include "utility/pm_random.h"
|
||||
#include "dstr/dlist.h"
|
||||
#include "dynhash/data_t.h"
|
||||
|
||||
|
||||
/*******************************/
|
||||
// An imp_bucket object forms
|
||||
// a second level hash function
|
||||
/*******************************/
|
||||
class imp_bucket : public dlist
|
||||
{
|
||||
|
||||
protected:
|
||||
int k; // valye k used in H_{{2M_j}^2}()
|
||||
int rotate; // rotate value for this key subset
|
||||
|
||||
public:
|
||||
imp_bucket();
|
||||
virtual ~imp_bucket();
|
||||
|
||||
data_t* operator()(long ind);
|
||||
|
||||
int h(int key, int prime, int M); //hash function H_{{2M_j}^2}()
|
||||
Boolean empty() ; //bucket empty?
|
||||
|
||||
Boolean insert(data_t*);
|
||||
data_t* remove_all();
|
||||
|
||||
ostream& asciiOut(ostream& out, print_func_ptr_t print_f);
|
||||
|
||||
friend ostream& operator<<(ostream&, imp_bucket&);
|
||||
friend class imp_die;
|
||||
};
|
||||
|
||||
typedef imp_bucket* imp_bucketPtr;
|
||||
|
||||
#endif
|
||||
606
cde/programs/dtinfo/DtMmdb/dynhash/imp_die.C
Normal file
606
cde/programs/dtinfo/DtMmdb/dynhash/imp_die.C
Normal file
@@ -0,0 +1,606 @@
|
||||
/*
|
||||
* $XConsortium: imp_die.C /main/5 1996/08/21 15:52:00 drk $
|
||||
*
|
||||
* Copyright (c) 1993 HAL Computer Systems International, Ltd.
|
||||
* All rights reserved. Unpublished -- rights reserved under
|
||||
* the Copyright Laws of the United States. USE OF A COPYRIGHT
|
||||
* NOTICE IS PRECAUTIONARY ONLY AND DOES NOT IMPLY PUBLICATION
|
||||
* OR DISCLOSURE.
|
||||
*
|
||||
* THIS SOFTWARE CONTAINS CONFIDENTIAL INFORMATION AND TRADE
|
||||
* SECRETS OF HAL COMPUTER SYSTEMS INTERNATIONAL, LTD. USE,
|
||||
* DISCLOSURE, OR REPRODUCTION IS PROHIBITED WITHOUT THE
|
||||
* PRIOR EXPRESS WRITTEN PERMISSION OF HAL COMPUTER SYSTEMS
|
||||
* INTERNATIONAL, LTD.
|
||||
*
|
||||
* RESTRICTED RIGHTS LEGEND
|
||||
* Use, duplication, or disclosure by the Government is subject
|
||||
* to the restrictions as set forth in subparagraph (c)(l)(ii)
|
||||
* of the Rights in Technical Data and Computer Software clause
|
||||
* at DFARS 252.227-7013.
|
||||
*
|
||||
* HAL COMPUTER SYSTEMS INTERNATIONAL, LTD.
|
||||
* 1315 Dell Avenue
|
||||
* Campbell, CA 95008
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#include "dynhash/imp_die.h"
|
||||
|
||||
#ifdef C_API
|
||||
#include "utility/c_iostream.h"
|
||||
#else
|
||||
#include <iostream.h>
|
||||
#endif
|
||||
|
||||
int steps[] = { 2, 3, 5, 7, 11, 13, 17, 21, 23, 29, 31, 37, 41, 43, 47, 51 };
|
||||
int no_steps;
|
||||
|
||||
#define PRIME_LEVLE_2 2147483647
|
||||
|
||||
imp_die::imp_die(int prime, int expected_n) :
|
||||
p(prime), H(0), B(0), n(0), bucket_array(0), hash_table(0),
|
||||
free_list_head(0), collected_records(0)
|
||||
{
|
||||
alloc_table(int(2.5*expected_n));
|
||||
init_table();
|
||||
|
||||
rand_generator.seed();
|
||||
k = rand_generator.rand();
|
||||
|
||||
no_steps = sizeof(steps) / sizeof(int);
|
||||
}
|
||||
|
||||
imp_die::~imp_die()
|
||||
{
|
||||
//debug(cerr, H);
|
||||
//debug(cerr, B);
|
||||
//debug(cerr, n);
|
||||
|
||||
for ( int i = 0; i<B; i++ ) {
|
||||
delete bucket_array[i];
|
||||
}
|
||||
|
||||
bucket_holder* x = free_list_head;
|
||||
while ( x ) {
|
||||
bucket_holder* y = x -> next;
|
||||
delete x;
|
||||
x = y ;
|
||||
}
|
||||
|
||||
x = collected_records;
|
||||
while ( x ) {
|
||||
bucket_holder* y = x -> next;
|
||||
delete x -> data_ptr;
|
||||
delete x;
|
||||
x = y ;
|
||||
}
|
||||
|
||||
delete hash_table;
|
||||
delete bucket_array ;
|
||||
}
|
||||
|
||||
//**********************************************************
|
||||
// allocate new memory for the bucket table and hash table.
|
||||
// H is the size of the bucket table before
|
||||
// expansion. new\_H is the new size.
|
||||
//**********************************************************
|
||||
void imp_die::alloc_table(int new_H)
|
||||
{
|
||||
if ( bucket_array ) {
|
||||
for ( int i = 0; i<B; delete bucket_array[i++] );
|
||||
delete bucket_array ;
|
||||
}
|
||||
|
||||
B = new_H/2;
|
||||
bucket_array = new imp_bucketPtr[B];
|
||||
|
||||
if ( hash_table ) {
|
||||
delete hash_table;
|
||||
}
|
||||
|
||||
hash_table = new data_tPtr[new_H];
|
||||
|
||||
H = new_H;
|
||||
}
|
||||
|
||||
void imp_die::init_table()
|
||||
{
|
||||
for ( int i = 0; i < B; i++ ) {
|
||||
bucket_array[i] = 0 ;
|
||||
}
|
||||
for ( i = 0; i < H; i++ ) {
|
||||
hash_table[i] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void imp_die::clean()
|
||||
{
|
||||
n = 0;
|
||||
collect_all_keys();
|
||||
|
||||
for ( int i=0; i<B; i++ ) {
|
||||
if ( bucket_array[i] ) {
|
||||
delete bucket_array[i];
|
||||
bucket_array[i] = 0 ;
|
||||
}
|
||||
}
|
||||
|
||||
for ( i=0; i<H; i++ )
|
||||
hash_table[i] = 0;
|
||||
}
|
||||
|
||||
/*****************************/
|
||||
// collect all keys into
|
||||
// bcuket_list_head
|
||||
/*****************************/
|
||||
void imp_die::collect_all_keys()
|
||||
{
|
||||
for ( int i = 0; i < B; i++ )
|
||||
if ( bucket_array[i] ) {
|
||||
|
||||
bucket_holder *x ;
|
||||
if ( free_list_head ) {
|
||||
x = free_list_head ;
|
||||
//debug(cerr, "get from free list");
|
||||
free_list_head = free_list_head -> next;
|
||||
} else {
|
||||
//debug(cerr, "get from new");
|
||||
x = new bucket_holder;
|
||||
}
|
||||
//debug(cerr, int(x));
|
||||
|
||||
x -> data_ptr = bucket_array[i] -> remove_all();
|
||||
|
||||
delete bucket_array[i];
|
||||
bucket_array[i] = 0;
|
||||
|
||||
x -> next = collected_records;
|
||||
collected_records = x;
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************/
|
||||
// rehash all keys
|
||||
/*****************************/
|
||||
Boolean imp_die::rehash()
|
||||
{
|
||||
while ( 1 ) {
|
||||
|
||||
collect_all_keys();
|
||||
|
||||
if ( 2*n > H ) alloc_table(2*H);
|
||||
|
||||
init_table();
|
||||
|
||||
k = rand_generator.rand();
|
||||
|
||||
bucket_holder *x = collected_records;
|
||||
while ( x ) {
|
||||
|
||||
data_t* y = x -> data_ptr;
|
||||
|
||||
while ( y ) {
|
||||
|
||||
data_t *z = (data_t*)(y -> v_succ);
|
||||
|
||||
y -> v_pred = 0;
|
||||
y -> v_succ = 0;
|
||||
|
||||
int hash = y -> bucket_num(k, p, B);
|
||||
|
||||
if ( bucket_array[hash] == 0 )
|
||||
bucket_array[hash] = new imp_bucket;
|
||||
|
||||
bucket_array[hash] -> insert(y);
|
||||
|
||||
y = z;
|
||||
}
|
||||
|
||||
x = x -> next;
|
||||
}
|
||||
|
||||
free_list_head = collected_records;
|
||||
collected_records = 0;
|
||||
|
||||
Boolean rehash_done = true;
|
||||
|
||||
for ( int i = 0; i < B; i++ )
|
||||
if ( bucket_array[i] ) {
|
||||
if ( bucket_rehash(i) == false ) {
|
||||
debug(cerr, i);
|
||||
debug(cerr, *bucket_array[i]);
|
||||
rehash_done = false;
|
||||
break;
|
||||
//throw(stringException("rehash() failed"));
|
||||
}
|
||||
}
|
||||
|
||||
if ( rehash_done == true )
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/************************************/
|
||||
// insert
|
||||
/************************************/
|
||||
Boolean imp_die::insert(data_t& v)
|
||||
{
|
||||
n++;
|
||||
|
||||
int hash = v.bucket_num(k, p, B);
|
||||
|
||||
if ( bucket_insert(hash, v) == false )
|
||||
rehash();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/******************************************/
|
||||
// remove operation
|
||||
/******************************************/
|
||||
Boolean imp_die::remove(data_t& v)
|
||||
{
|
||||
MESSAGE(cerr, "imp_die::remove(data_t& v)");
|
||||
int hash = v.bucket_num(k, p, B);
|
||||
|
||||
/*********************************/
|
||||
// assure the bucket is not empty
|
||||
/*********************************/
|
||||
if ( bucket_remove(hash, v) == false )
|
||||
return false;
|
||||
|
||||
n--;
|
||||
|
||||
/*********************************/
|
||||
// delete the bucket if it becomes
|
||||
// empty
|
||||
/*********************************/
|
||||
if ( bucket_array[hash] -> empty() == true ) {
|
||||
delete bucket_array[hash];
|
||||
bucket_array[hash] = 0;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/*******************************************************/
|
||||
// first level hash function
|
||||
/*******************************************************/
|
||||
int imp_die::h(int key) const
|
||||
{
|
||||
return abs( k * key ) % p % B;
|
||||
}
|
||||
|
||||
//static to_print = false;
|
||||
/****************************************/
|
||||
// select a proper value for parameter k
|
||||
/****************************************/
|
||||
Boolean imp_die::bucket_fix_k(int bucket_num)
|
||||
{
|
||||
int loops = 0;
|
||||
|
||||
Boolean injective = false;
|
||||
|
||||
imp_bucket& x = *bucket_array[bucket_num];
|
||||
|
||||
/*
|
||||
MESSAGE(cerr, "bucket_fix_k()");
|
||||
debug(cerr, x);
|
||||
|
||||
if ( bucket_num == 412 )
|
||||
to_print = true;
|
||||
else
|
||||
to_print = false;
|
||||
*/
|
||||
|
||||
while ( injective == false && loops < H ) {
|
||||
|
||||
injective = test_injective(x);
|
||||
if ( injective == false ) {
|
||||
loops ++;
|
||||
x.k = abs(rand_generator.rand()) % ( p - 1 ) + 1;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
Boolean imp_die::test_injective(imp_bucket& x)
|
||||
{
|
||||
//MESSAGE(cerr, "test_injective()");
|
||||
long ind_out = x.first();
|
||||
while ( ind_out != 0 ) {
|
||||
|
||||
data_t* out = x(ind_out);
|
||||
|
||||
/*
|
||||
if ( to_print == true ) {
|
||||
debug(cerr, x.k);
|
||||
debug(cerr, x.rotate);
|
||||
debug(cerr, p);
|
||||
debug(cerr, M);
|
||||
}
|
||||
*/
|
||||
int hash_out = out -> slot_num(x.k, x.rotate, PRIME_LEVLE_2, H);
|
||||
|
||||
long ind_in = ind_out;
|
||||
x.next(ind_in);
|
||||
|
||||
while ( ind_in != 0 ) {
|
||||
|
||||
data_t* in = x(ind_in);
|
||||
|
||||
int hash_in = in -> slot_num(x.k, x.rotate, PRIME_LEVLE_2, H);
|
||||
|
||||
if ( hash_out == hash_in ) {
|
||||
|
||||
/*
|
||||
if ( to_print == true )
|
||||
{
|
||||
debug(cerr, x);
|
||||
debug(cerr, ind_in);
|
||||
debug(cerr, ind_out);
|
||||
debug(cerr, hash_in);
|
||||
debug(cerr, hash_out);
|
||||
}
|
||||
*/
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
x.next(ind_in);
|
||||
}
|
||||
|
||||
x.next(ind_out);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
Boolean imp_die::bucket_rotate(int bucket_num)
|
||||
{
|
||||
imp_bucket& x = *bucket_array[bucket_num];
|
||||
|
||||
int loops = 0;
|
||||
|
||||
int z = rand_generator.rand();
|
||||
|
||||
x.rotate = z % (H - 1) + 1;
|
||||
int step = steps[z % no_steps];
|
||||
|
||||
Boolean all_fit = false;
|
||||
int hash;
|
||||
|
||||
while ( all_fit == false && loops < H ) {
|
||||
|
||||
long ind = x.first();
|
||||
while ( ind != 0 ) {
|
||||
|
||||
data_t* data_ptr = x(ind);
|
||||
hash = data_ptr -> slot_num(x.k, x.rotate, PRIME_LEVLE_2, H);
|
||||
|
||||
if ( hash_table[hash] != 0 ) {
|
||||
long ind1 = x.first();
|
||||
while ( ind1 != ind ) {
|
||||
|
||||
hash = x(ind1) -> slot_num(x.k, x.rotate, PRIME_LEVLE_2, H);
|
||||
|
||||
hash_table[hash] = 0;
|
||||
|
||||
x.next(ind1);
|
||||
}
|
||||
loops ++;
|
||||
x.rotate += step;
|
||||
break;
|
||||
}
|
||||
hash_table[hash] = data_ptr;
|
||||
x.next(ind);
|
||||
}
|
||||
all_fit = ( ind == 0 ) ? true : false;
|
||||
}
|
||||
|
||||
return all_fit ;
|
||||
}
|
||||
|
||||
Boolean imp_die::bucket_insert(int bucket_num, data_t& v)
|
||||
{
|
||||
if ( bucket_array[bucket_num] == 0 ) {
|
||||
bucket_array[bucket_num] = new imp_bucket();
|
||||
}
|
||||
|
||||
imp_bucketPtr x = bucket_array[bucket_num];
|
||||
|
||||
data_t* y = 0;
|
||||
|
||||
if ( collected_records ) {
|
||||
bucket_holder* first_list = collected_records;
|
||||
y = first_list -> data_ptr;
|
||||
|
||||
first_list -> data_ptr = (data_t*)(y -> v_succ);
|
||||
|
||||
if ( first_list -> data_ptr == 0 ) {
|
||||
collected_records = collected_records -> next;
|
||||
delete first_list;
|
||||
}
|
||||
|
||||
*y = v;
|
||||
|
||||
} else
|
||||
y = new data_t(v);
|
||||
|
||||
x -> insert(y);
|
||||
int hash = y -> slot_num(x->k, x->rotate, PRIME_LEVLE_2, H);
|
||||
|
||||
if ( hash_table[hash] == 0 ) {
|
||||
hash_table[hash] = y;
|
||||
return true;
|
||||
}
|
||||
|
||||
//*******************************
|
||||
// clear the hash table entries
|
||||
//*******************************
|
||||
long ind = x -> first();
|
||||
while ( ind ) {
|
||||
int hash = (*x)(ind) -> slot_num(x->k, x->rotate, PRIME_LEVLE_2, H);
|
||||
|
||||
if ( hash_table[hash] && *hash_table[hash] == *(*x)(ind) )
|
||||
hash_table[hash] = 0;
|
||||
x -> next(ind);
|
||||
}
|
||||
|
||||
return bucket_rehash(bucket_num);
|
||||
/*
|
||||
debug(cerr, bucket_num);
|
||||
debug(cerr, int(x));
|
||||
debug(cerr, int(bucket_array));
|
||||
debug(cerr, int(bucket_array[bucket_num]));
|
||||
*/
|
||||
|
||||
}
|
||||
|
||||
|
||||
//*******************************
|
||||
// rehash keys in the bucket
|
||||
//*******************************
|
||||
Boolean imp_die::bucket_rehash(int bucket_num)
|
||||
{
|
||||
bucket_fix_k(bucket_num);
|
||||
return bucket_rotate(bucket_num);
|
||||
}
|
||||
|
||||
Boolean imp_die::bucket_remove(int bucket_num, data_t& v)
|
||||
{
|
||||
imp_bucketPtr x = bucket_array[bucket_num];
|
||||
|
||||
if ( x == 0 ) return false;
|
||||
|
||||
int hash = v.slot_num(x->k, x->rotate, PRIME_LEVLE_2, H);
|
||||
|
||||
if ( hash_table[hash] && *hash_table[hash] == v ) {
|
||||
|
||||
x -> delete_cell(hash_table[hash]);
|
||||
delete hash_table[hash];
|
||||
hash_table[hash] = 0;
|
||||
|
||||
//MESSAGE(cerr, "afterremove the entry");
|
||||
//debug(cerr, *x);
|
||||
|
||||
return true;
|
||||
} else
|
||||
return false;
|
||||
}
|
||||
|
||||
Boolean imp_die::bucket_member(int bucket_num, data_t& v) const
|
||||
{
|
||||
/*
|
||||
debug(cerr, bucket_num);
|
||||
debug(cerr, v);
|
||||
*/
|
||||
|
||||
imp_bucketPtr x = bucket_array[bucket_num];
|
||||
|
||||
if ( x == 0 ) {
|
||||
//MESSAGE(cerr, "empty bucket");
|
||||
//debug(cerr, int(bucket_array));
|
||||
return false;
|
||||
}
|
||||
|
||||
int hash = v.slot_num(x->k, x->rotate, PRIME_LEVLE_2, H);
|
||||
|
||||
if ( hash_table[hash] ) {
|
||||
v.dt = hash_table[hash] -> dt;
|
||||
if ( *hash_table[hash] == v ) {
|
||||
/*
|
||||
MESSAGE(cerr, "hash table entry match");
|
||||
debug(cerr, int(this));
|
||||
debug(cerr, v);
|
||||
debug(cerr, *hash_table[hash]);
|
||||
*/
|
||||
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
int imp_die::first_bucket()
|
||||
{
|
||||
if ( B > 0 )
|
||||
return 0;
|
||||
else
|
||||
return -1;
|
||||
}
|
||||
|
||||
void imp_die::next_bucket(int& ind)
|
||||
{
|
||||
if ( ind >= B )
|
||||
ind = -1;
|
||||
else
|
||||
ind++;
|
||||
}
|
||||
|
||||
imp_bucket* imp_die::get_bucket(int& ind)
|
||||
{
|
||||
while ( ind < B && bucket_array[ind] == 0 )
|
||||
ind++;
|
||||
|
||||
if ( ind >= B )
|
||||
return 0;
|
||||
else
|
||||
return bucket_array[ind];
|
||||
}
|
||||
|
||||
/*******************************************************/
|
||||
// print operation
|
||||
/*******************************************************/
|
||||
ostream& imp_die::asciiOut(ostream& out)
|
||||
{
|
||||
int ind = first_bucket();
|
||||
|
||||
while ( ind != -1 ) {
|
||||
|
||||
imp_bucket* bucket = get_bucket(ind);
|
||||
|
||||
if ( bucket )
|
||||
out << *bucket;
|
||||
|
||||
next_bucket(ind);
|
||||
}
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
istream& imp_die::asciiIn(istream& in)
|
||||
{
|
||||
data_t actor;
|
||||
|
||||
while ( in >> actor ) {
|
||||
insert(actor);
|
||||
}
|
||||
|
||||
return in;
|
||||
}
|
||||
|
||||
ostream& imp_die::asciiOut(ostream& out, print_func_ptr_t print_f)
|
||||
{
|
||||
|
||||
int ind = first_bucket();
|
||||
|
||||
while ( ind != -1 ) {
|
||||
|
||||
imp_bucket* bucket = get_bucket(ind);
|
||||
|
||||
if ( bucket ) {
|
||||
bucket -> asciiOut(out, print_f);
|
||||
}
|
||||
|
||||
next_bucket(ind);
|
||||
}
|
||||
|
||||
return out;
|
||||
}
|
||||
132
cde/programs/dtinfo/DtMmdb/dynhash/imp_die.h
Normal file
132
cde/programs/dtinfo/DtMmdb/dynhash/imp_die.h
Normal file
@@ -0,0 +1,132 @@
|
||||
/*
|
||||
* $XConsortium: imp_die.h /main/3 1996/06/11 17:19:33 cde-hal $
|
||||
*
|
||||
* Copyright (c) 1993 HAL Computer Systems International, Ltd.
|
||||
* All rights reserved. Unpublished -- rights reserved under
|
||||
* the Copyright Laws of the United States. USE OF A COPYRIGHT
|
||||
* NOTICE IS PRECAUTIONARY ONLY AND DOES NOT IMPLY PUBLICATION
|
||||
* OR DISCLOSURE.
|
||||
*
|
||||
* THIS SOFTWARE CONTAINS CONFIDENTIAL INFORMATION AND TRADE
|
||||
* SECRETS OF HAL COMPUTER SYSTEMS INTERNATIONAL, LTD. USE,
|
||||
* DISCLOSURE, OR REPRODUCTION IS PROHIBITED WITHOUT THE
|
||||
* PRIOR EXPRESS WRITTEN PERMISSION OF HAL COMPUTER SYSTEMS
|
||||
* INTERNATIONAL, LTD.
|
||||
*
|
||||
* RESTRICTED RIGHTS LEGEND
|
||||
* Use, duplication, or disclosure by the Government is subject
|
||||
* to the restrictions as set forth in subparagraph (c)(l)(ii)
|
||||
* of the Rights in Technical Data and Computer Software clause
|
||||
* at DFARS 252.227-7013.
|
||||
*
|
||||
* HAL COMPUTER SYSTEMS INTERNATIONAL, LTD.
|
||||
* 1315 Dell Avenue
|
||||
* Campbell, CA 95008
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
|
||||
#ifndef _imp_die_h
|
||||
#define _imp_die_h
|
||||
|
||||
#include "dstr/index_agent.h"
|
||||
#include "dynhash/imp_bucket.h"
|
||||
|
||||
/***************************************************************/
|
||||
//
|
||||
// An improved version of Dietzfelbinger etc.'s algorithm.
|
||||
//
|
||||
// Goal: reducing the space consumption.
|
||||
//
|
||||
// By
|
||||
//
|
||||
// QiFan Chen (June 24, 1992)
|
||||
//
|
||||
/***************************************************************/
|
||||
|
||||
|
||||
#define COLLISION_BIT 0x2
|
||||
|
||||
extern int steps[];
|
||||
extern int no_steps;
|
||||
|
||||
class bucket_holder {
|
||||
|
||||
public:
|
||||
data_t* data_ptr;
|
||||
bucket_holder *next;
|
||||
|
||||
bucket_holder() : data_ptr(0), next(0) {};
|
||||
virtual ~bucket_holder() {};
|
||||
};
|
||||
|
||||
//extern data_t bad_record;
|
||||
|
||||
class imp_die : public index_agent
|
||||
{
|
||||
|
||||
protected:
|
||||
|
||||
int k; // parameter used in the 1st level hash function
|
||||
int p; // prime number p
|
||||
|
||||
int n; // current key set size
|
||||
int H; // current hash table size
|
||||
int B; // current bucket table size
|
||||
|
||||
data_tPtr* hash_table; // the hash table
|
||||
imp_bucketPtr* bucket_array; // bucket array
|
||||
|
||||
bucket_holder* free_list_head ; // free bucket holder list head
|
||||
bucket_holder* collected_records; // collected bucket list head
|
||||
|
||||
pm_random rand_generator; // rand generator
|
||||
|
||||
int h(int key) const; // h_{sM}() function
|
||||
void alloc_table(int new_M); // expand the hash tabel and bucket array
|
||||
void init_table(); // init hash table and bucket array
|
||||
void collect_all_keys(); // collect all keys into bcuket_list_head
|
||||
Boolean rehash(); // rehash all keys
|
||||
|
||||
Boolean bucket_insert(int bucket_num, data_t&);
|
||||
Boolean bucket_remove(int bucket_num, data_t&);
|
||||
Boolean bucket_member(int bucket_num, data_t&) const;
|
||||
Boolean bucket_rehash(int bucket_num) ;
|
||||
|
||||
Boolean bucket_fix_k(int bucket_num);
|
||||
Boolean bucket_rotate(int bucket_num);
|
||||
Boolean test_injective(imp_bucket& x);
|
||||
|
||||
public:
|
||||
imp_die(int prime = 32801, int expected_n = 100);
|
||||
// prime and expected
|
||||
// key set size
|
||||
virtual ~imp_die();
|
||||
|
||||
void clean() ; // remove all keys
|
||||
|
||||
Boolean insert(data_t& v); // insert a key
|
||||
Boolean remove(data_t& v); // remove a key
|
||||
Boolean member(data_t& v) {
|
||||
return bucket_member(v.bucket_num(k, p, B), v);
|
||||
}; // member test
|
||||
|
||||
|
||||
int no_keys() const { return n; }; // return key set size
|
||||
|
||||
// WARNING: -1 is the terminate condition!!!
|
||||
int first_bucket();
|
||||
imp_bucket* get_bucket(int&);
|
||||
void next_bucket(int&);
|
||||
|
||||
// output this with print_f handling the printing of whole data_t.
|
||||
// pointer to data_t as voidd* is passed to print_f
|
||||
ostream& asciiOut(ostream& out, print_func_ptr_t print_f);
|
||||
|
||||
ostream& asciiOut(ostream& out);
|
||||
istream& asciiIn(istream& in);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
24
cde/programs/dtinfo/DtMmdb/dynhash/linked_record.C
Normal file
24
cde/programs/dtinfo/DtMmdb/dynhash/linked_record.C
Normal file
@@ -0,0 +1,24 @@
|
||||
// $XConsortium: linked_record.cc /main/3 1996/06/11 17:19:38 cde-hal $
|
||||
|
||||
#include "dynhash/linked_record.h"
|
||||
|
||||
linked_record::linked_record()
|
||||
{
|
||||
next = 0;
|
||||
}
|
||||
|
||||
linked_record::linked_record(data_t& v) : data_t(v)
|
||||
{
|
||||
next = 0;
|
||||
}
|
||||
|
||||
linked_record& linked_record::operator = (linked_record& d)
|
||||
{
|
||||
data_t::operator =(d) ;
|
||||
next = d.next ;
|
||||
return *this;
|
||||
}
|
||||
|
||||
linked_record::~linked_record()
|
||||
{
|
||||
}
|
||||
48
cde/programs/dtinfo/DtMmdb/dynhash/linked_record.h
Normal file
48
cde/programs/dtinfo/DtMmdb/dynhash/linked_record.h
Normal file
@@ -0,0 +1,48 @@
|
||||
/*
|
||||
* $XConsortium: linked_record.h /main/3 1996/06/11 17:19:43 cde-hal $
|
||||
*
|
||||
* Copyright (c) 1992 HaL Computer Systems, Inc. All rights reserved.
|
||||
* UNPUBLISHED -- rights reserved under the Copyright Laws of the United
|
||||
* States. Use of a copyright notice is precautionary only and does not
|
||||
* imply publication or disclosure.
|
||||
*
|
||||
* This software contains confidential information and trade secrets of HaL
|
||||
* Computer Systems, Inc. Use, disclosure, or reproduction is prohibited
|
||||
* without the prior express written permission of HaL Computer Systems, Inc.
|
||||
*
|
||||
* RESTRICTED RIGHTS LEGEND
|
||||
* Use, duplication, or disclosure by the Government is subject to
|
||||
* restrictions as set forth in subparagraph (c)(l)(ii) of the Rights in
|
||||
* Technical Data and Computer Software clause at DFARS 252.227-7013.
|
||||
* HaL Computer Systems, Inc.
|
||||
* 1315 Dell Avenue, Campbell, CA 95008
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
|
||||
#ifndef _linked_record_h
|
||||
#define _linked_record_h
|
||||
|
||||
#include "dynhash/data.h"
|
||||
|
||||
/****************************/
|
||||
/****************************/
|
||||
|
||||
class linked_record : public data_t
|
||||
{
|
||||
|
||||
protected:
|
||||
|
||||
public:
|
||||
linked_record* next;
|
||||
|
||||
linked_record() ;
|
||||
linked_record(data_t&) ;
|
||||
linked_record& operator =(linked_record& d);
|
||||
virtual ~linked_record() ;
|
||||
};
|
||||
|
||||
typedef linked_record* linked_recordPtr;
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user