netcdf-c/unit_test/tst_xcache.c
2024-03-12 16:13:41 +00:00

196 lines
4.1 KiB
C

/*********************************************************************
* Copyright 2018, UCAR/Unidata
* See netcdf/COPYRIGHT file for copying and redistribution conditions.
*********************************************************************/
/**
Test the NCxcache data structure
*/
#include "config.h"
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <assert.h>
#include "netcdf.h"
#include "ncexhash.h"
#include "ncxcache.h"
#include "timer_utils.h"
#ifdef _WIN32
#define srandom srand
#define random (long)rand
#endif
#define DEBUG 0
/* Approximate average times; if we get out of this range, then
something is drastically wrong */
static const struct TimeRange insertrange = {0,50000};
static const struct TimeRange readrange = {0,5000};
static Nanotime inserttime[2];
static Nanotime readtime[2];
#define CHECK(expr) check((expr),__LINE__)
void check(int stat, int line)
{
if(stat) {
fprintf(stderr,"%d: (%d)%s\n",line,stat,nc_strerror(stat));
fflush(stderr);
exit(1);
}
}
/*
Test set 1:
- insert string with obj
- lookup by various methods
- remove
- verify remove
*/
#define MAXSTRLEN 25
#define DEFAULTSEED 1
typedef struct NC_OBJ {
int sort;
char* name;
size_t id;
} NC_OBJ;
typedef struct NCXSTR {
void* next;
void* prev;
void* ptr;
char* string;
} NCXSTR;
//static int N[] = {10, 100, 1000, 0};
static int N[] = {4,0};
/* Generate random ascii strings */
static NCXSTR* strings = NULL;
static void
generatestrings(int n, unsigned seed)
{
int i,k;
long rnd;
int len;
char* s = NULL;
srandom(seed);
strings = (NCXSTR*)calloc(sizeof(NCXSTR),((size_t)n+1));
if(strings == NULL) abort();
for(i=0;i<n;i++) {
/* Generate one random string */
if((s = (char*)malloc(1+MAXSTRLEN))==NULL) abort();
rnd = random();
len = (int)rnd % MAXSTRLEN;
/* generate the characters */
for(k=0;k<len;k++) {
do {rnd = random() % 127;} while(rnd <= ' ');
assert(rnd > ' ' && rnd < 127);
s[k] = (char)rnd;
}
s[len] = '\0';
strings[i].string = s;
#if DEBUG >= 3
fprintf(stderr,"strings[%d] = |%s|\n",i,strings[i].string);
#endif
}
}
static void
freestrings(void)
{
if(strings) {
NCXSTR* p = strings;
for(;p->string;p++) {nullfree(p->string);}
nullfree(strings);
strings = NULL;
}
}
int
main(int argc, char** argv)
{
int stat = NC_NOERR;
NCxcache* cache = NULL;
ncexhashkey_t hkey;
int* np = NULL;
void* content = NULL;
NCT_inittimer();
for(np=N;*np;np++) {
int ns,i;
ns = *np;
generatestrings(ns,DEFAULTSEED);
fprintf(stderr,"insert:\n");
if((stat = ncxcachenew(2,&cache))) goto done;
NCT_marktime(&inserttime[0]);
for(i=0;i<ns;i++) {
hkey = ncexhashkey((unsigned char*)strings[i].string,strlen(strings[i].string));
if((stat=ncxcacheinsert(cache,hkey,&strings[i]))) goto done;
}
assert(ncxcachecount(cache) == ns);
NCT_marktime(&inserttime[1]);
#if DEBUG > 0
ncxcacheprint(cache);
#endif
NCT_reporttime((unsigned int)ns, inserttime, insertrange, "insert");
/* Try to touch and extract all the entries */
fprintf(stderr,"read:\n");
NCT_marktime(&readtime[0]);
for(i=0;i<ns;i++) {
void* top = NULL;
hkey = ncexhashkey((unsigned char*)strings[i].string,strlen(strings[i].string));
if((stat=ncxcachelookup(cache,hkey,&content))) goto done;
if((stat=ncxcachetouch(cache,hkey))) goto done;
top = ncxcachefirst(cache);
if(top != content) {stat = NC_EINTERNAL; goto done;}
}
NCT_marktime(&readtime[1]);
#if DEBUG > 0
ncxcacheprint(cache);
#endif
NCT_reporttime((unsigned int)ns, readtime, readrange, "read");
for(i=0;i<ns;i++) {
void* top = NULL;
hkey = ncexhashkey((unsigned char*)strings[i].string,strlen(strings[i].string));
if((stat=ncxcachetouch(cache,hkey))) goto done;
top = ncxcachefirst(cache);
if(top != &strings[i])
fprintf(stderr,"touch failure: top=%p strings[%d]=%p\n",top,i,&strings[i]);
}
fprintf(stderr,"touch: passed\n");
freestrings();
ncxcachefree(cache);
}
done:
if(stat) fprintf(stderr,"***fail: %s\n",nc_strerror(stat));
return 0;
}