/****************************************************************************** * Copyright © 2014-2015 The SuperNET Developers. * * * * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * * the top-level directory of this distribution for the individual copyright * * holder information and the developer policies on copyright and licensing. * * * * Unless otherwise agreed in a custom licensing agreement, no part of the * * SuperNET software, including this file may be copied, modified, propagated * * or distributed except according to the terms contained in the LICENSE file * * * * Removal or modification of this copyright notice is prohibited. * * * ******************************************************************************/ #include "peggy.h" void ramkv777_lock(struct ramkv777 *kv) { if ( kv->threadsafe != 0 ) portable_mutex_lock(&kv->mutex); } void ramkv777_unlock(struct ramkv777 *kv) { if ( kv->threadsafe != 0 ) portable_mutex_unlock(&kv->mutex); } int32_t ramkv777_delete(struct ramkv777 *kv,void *key) { int32_t retval = -1; struct ramkv777_item *ptr = 0; if ( kv == 0 ) return(-1); ramkv777_lock(kv); HASH_FIND(hh,kv->table,key,kv->keysize,ptr); if ( ptr != 0 ) { HASH_DELETE(hh,kv->table,ptr); free(ptr); retval = 0; } ramkv777_lock(kv); return(retval); } void *ramkv777_read(int32_t *valuesizep,struct ramkv777 *kv,void *key) { struct ramkv777_item *item = 0; if ( kv == 0 ) { printf("ramkv777_read: null ramkv??\n"); return(0); } //printf("search for [%llx] keysize.%d\n",*(long long *)key,keysize); ramkv777_lock(kv); HASH_FIND(hh,kv->table,key,kv->keysize,item); ramkv777_unlock(kv); if ( item != 0 ) { if ( valuesizep != 0 ) *valuesizep = item->valuesize; return(ramkv777_itemvalue(kv,item)); } //else printf("cant find key.%llx keysize.%d\n",*(long long *)key,kv->keysize); if ( valuesizep != 0 ) *valuesizep = 0; return(0); } void *ramkv777_write(struct ramkv777 *kv,void *key,void *value,int32_t valuesize) { struct ramkv777_item *item = 0; int32_t keysize = kv->keysize; if ( kv == 0 ) return(0); ramkv777_lock(kv); HASH_FIND(hh,kv->table,key,keysize,item); if ( item != 0 ) { printf("item being added, already there\n"); if ( valuesize == item->valuesize ) { if ( memcmp(ramkv777_itemvalue(kv,item),value,valuesize) != 0 ) { vupdate_sha256(kv->sha256.bytes,&kv->state,key,kv->keysize); vupdate_sha256(kv->sha256.bytes,&kv->state,value,valuesize); memcpy(ramkv777_itemvalue(kv,item),value,valuesize); } ramkv777_unlock(kv); return(item); } HASH_DELETE(hh,kv->table,item); free(item); vupdate_sha256(kv->sha256.bytes,&kv->state,key,kv->keysize); } item = calloc(1,ramkv777_itemsize(kv,valuesize)); memcpy(item->keyvalue,key,kv->keysize); memcpy(ramkv777_itemvalue(kv,item),value,valuesize); item->valuesize = valuesize; item->rawind = (kv->numkeys++ * ACCTS777_MAXRAMKVS) | kv->kvind; //printf("add.(%s) kv->numkeys.%d keysize.%d valuesize.%d [%llx]\n",kv->name,kv->numkeys,keysize,valuesize,*(long long *)ramkv777_itemkey(item)); HASH_ADD_KEYPTR(hh,kv->table,ramkv777_itemkey(item),kv->keysize,item); vupdate_sha256(kv->sha256.bytes,&kv->state,key,kv->keysize); vupdate_sha256(kv->sha256.bytes,&kv->state,value,valuesize); ramkv777_unlock(kv); if ( kv->dispflag != 0 ) fprintf(stderr,"%016llx ramkv777_write numkeys.%d kv.%p table.%p write kep.%p key.%llx size.%d, value.(%08x) size.%d\n",(long long)kv->sha256.txid,kv->numkeys,kv,kv->table,key,*(long long *)key,keysize,calc_crc32(0,value,valuesize),valuesize); return(ramkv777_itemvalue(kv,item)); } void *ramkv777_iterate(struct ramkv777 *kv,void *args,void *(*iterator)(struct ramkv777 *kv,void *args,void *key,void *value,int32_t valuesize)) { struct ramkv777_item *item,*tmp; void *retval = 0; if ( kv == 0 ) return(0); ramkv777_lock(kv); HASH_ITER(hh,kv->table,item,tmp) { if ( (retval= (*iterator)(kv,args!=0?args:item,item->keyvalue,ramkv777_itemvalue(kv,item),item->valuesize)) != 0 ) { ramkv777_unlock(kv); return(retval); } } ramkv777_unlock(kv); return(0); } void *ramkv777_saveiterator(struct ramkv777 *kv,void *args,void *key,void *value,int32_t valuesize) { FILE *fp = args; if ( args != 0 ) { if ( fwrite(key,1,kv->keysize,fp) != kv->keysize ) { printf("Error saving key.[%d]\n",kv->keysize); return(key); } } return(0); } /*char *OS_mvstr() { #ifdef __WIN32 return("rename"); #else return("mv"); #endif }*/ char *OS_mvstr(); long ramkv777_save(struct ramkv777 *kv) { FILE *fp; long retval = -1; char fname[512],oldfname[512],cmd[512]; sprintf(fname,"%s.tmp",kv->name); if ( (fp= fopen(fname,"wb")) != 0 ) { if ( ramkv777_iterate(kv,fp,ramkv777_saveiterator) == 0 ) { printf("save %ld to HDD\n",ftell(fp)); retval = ftell(fp); } else printf("error saving item at %ld\n",ftell(fp)); fclose(fp); } else printf("error creating(%s)\n",fname); if ( retval > 0 ) { sprintf(oldfname,"%s.%u",kv->name,(uint32_t)time(NULL)); sprintf(cmd,"%s %s %s",OS_mvstr(),kv->name,oldfname); if ( system(cmd) != 0 ) printf("error issuing.(%s)\n",cmd); sprintf(cmd,"%s %s %s",OS_mvstr(),fname,kv->name); if ( system(cmd) != 0 ) printf("error issuing.(%s)\n",cmd); } return(retval); } struct ramkv777 *ramkv777_init(int32_t kvind,char *name,int32_t keysize,int32_t threadsafe) { struct ramkv777 *kv; printf("ramkv777_init.(%s)\n",name); kv = calloc(1,sizeof(*kv)); strcpy(kv->name,name); kv->threadsafe = threadsafe, kv->keysize = keysize, kv->kvind = kvind;//, kv->dispflag = 1; portable_mutex_init(&kv->mutex); vupdate_sha256(kv->sha256.bytes,&kv->state,0,0); return(kv); } int32_t ramkv777_disp(struct ramkv777 *kv) { struct ramkv777_item *item,*tmp; int32_t n = 0; printf("ramkv777_disp.(%s)\n",kv->name); if ( kv == 0 ) return(0); ramkv777_lock(kv); HASH_ITER(hh,kv->table,item,tmp) { n++; printf("%llx: %llx\n",*(long long *)ramkv777_itemkey(item),*(long long *)ramkv777_itemvalue(kv,item)); } ramkv777_unlock(kv); printf("ramkv777_disp.(%s) n.%d items\n",kv->name,n); return(n); } void ramkv777_free(struct ramkv777 *kv) { struct ramkv777_item *ptr,*tmp; if ( kv != 0 ) { HASH_ITER(hh,kv->table,ptr,tmp) { HASH_DEL(kv->table,ptr); free(ptr); } free(kv); } } int32_t ramkv777_clone(struct ramkv777 *clone,struct ramkv777 *kv) { struct ramkv777_item *item,*tmp; int32_t n = 0; if ( kv != 0 ) { HASH_ITER(hh,kv->table,item,tmp) { ramkv777_write(clone,item->keyvalue,ramkv777_itemvalue(kv,item),item->valuesize); n++; } } return(n); } struct ramkv777_item *ramkv777_itemptr(struct ramkv777 *kv,void *value) { struct ramkv777_item *item = 0; if ( kv != 0 && value != 0 ) { value = (void *)((long)value - (kv)->keysize); item = (void *)((long)value - ((long)item->keyvalue - (long)item)); } return(item); }