/* Copyright (c) 1998-2018 University Corporation for Atmospheric Research/Unidata See LICENSE.txt for license information. */ #ifndef NCEXHASH_H #define NCEXHASH_H #if HAVE_CONFIG_H #include "config.h" #endif #include #include "netcdf.h" /* Implement extendible hashing as defined in: ```` R. Fagin, J. Nievergelt, N. Pippenger, and H. Strong, "Extendible Hashing — a fast access method for dynamic files", ACM Transactions on Database Systems, vol. 4, No. 3, pp. 315-344, 1979. ```` */ /*! Hashmap-related structs. NOTES: 1. 'data' is the an arbitrary uintptr_t integer or void* pointer. 2. hashkey is a crc64 hash of key -- it is assumed to be unique for keys. WARNINGS: 1. It is critical that |uintptr_t| == |void*| */ #define ncexhashkey_t unsigned long long #define NCEXHASHKEYBITS 64 typedef struct NCexentry { ncexhashkey_t hashkey; /* Hash id */ uintptr_t data; } NCexentry; typedef struct NCexleaf { int uid; /* primarily for debug */ struct NCexleaf* next; /* linked list of all leaves for cleanup */ int depth; /* local depth */ int active; /* index of the first emptry slot */ NCexentry* entries; /* |entries| == leaflen*/ } NCexleaf; /* Top Level Vector */ typedef struct NCexhashmap { int leaflen; /* # entries a leaf can store */ int depth; /* Global depth */ NCexleaf* leaves; /* head of the linked list of leaves */ int nactive; /* # of active entries in whole table */ NCexleaf** directory; /* |directory| == 2^depth */ int uid; /* unique id counter */ /* Allow a single iterator over the entries */ struct { int walking; /* 0=>not in use */ int index; /* index of current entry in leaf */ NCexleaf* leaf; /* leaf we are walking */ } iterator; } NCexhashmap; /** Creates a new exhash using LSB */ EXTERNL NCexhashmap* ncexhashnew(int leaflen); /** Reclaims the exhash structure. */ EXTERNL void ncexhashmapfree(NCexhashmap*); /** Returns the number of active elements. */ EXTERNL int ncexhashcount(NCexhashmap*); /* Hash key based API */ /* Lookup by Hash Key */ EXTERNL int ncexhashget(NCexhashmap*, ncexhashkey_t hkey, uintptr_t*); /* Insert by Hash Key */ EXTERNL int ncexhashput(NCexhashmap*, ncexhashkey_t hkey, uintptr_t data); /* Remove by Hash Key */ EXTERNL int ncexhashremove(NCexhashmap*, ncexhashkey_t hkey, uintptr_t* datap); /** Change the data for the specified key; takes hashkey. */ EXTERNL int ncexhashsetdata(NCexhashmap*, ncexhashkey_t hkey, uintptr_t newdata, uintptr_t* olddatap); /** Get map parameters */ EXTERNL int ncexhashinqmap(NCexhashmap* map, int* leaflenp, int* depthp, int* nactivep, int* uidp, int* walkingp); /* Return the hash key for specified key; takes key+size*/ EXTERNL ncexhashkey_t ncexhashkey(const unsigned char* key, size_t size); /* Walk the entries in some order */ /* @return NC_NOERR if keyp and datap are valid @return NC_ERANGE if iteration is finished @return NC_EINVAL for all other errors */ EXTERNL int ncexhashiterate(NCexhashmap* map, ncexhashkey_t* keyp, uintptr_t* datap); /* Debugging */ EXTERNL void ncexhashprint(NCexhashmap*); EXTERNL void ncexhashprintstats(NCexhashmap*); EXTERNL void ncexhashprintdir(NCexhashmap*, NCexleaf** dir); EXTERNL void ncexhashprintleaf(NCexhashmap*, NCexleaf* leaf); EXTERNL void ncexhashprintentry(NCexhashmap* map, NCexentry* entry); EXTERNL char* ncexbinstr(ncexhashkey_t hkey, int depth); /* Macro defined functions */ /** Get map parameters */ #define ncexhashmaplength(map) ((map)==NULL?0:(map)->nactive) #endif /*NCEXHASH_H*/