From 8595854a0829dd0b1341fa0f4370c2f575b0ece0 Mon Sep 17 00:00:00 2001 From: jl777 Date: Mon, 5 Sep 2016 00:23:51 -0300 Subject: [PATCH] jsonQ separated into global and coin specific queues MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit using a mutex to serialize all API requests causes unacceptable latency in some cases. Not serialized can lead to queries into a dataset with unstable state. To fix this, all JSON requests are split into coin specific queues whenever possible and the global queue is only used when the coin can’t be determined from the JSON request. Each coin’s main thread calls the iguana_jsonQ to process that coin’s queue of requests only after all the dataset updates are complete to assure only valid data is returned. Since any previous large latencies were when a specific coin was updating its dataset and the dataset can’t be safely accessed during that time, the delay in processing that coin’s request doesn’t create any additional latency this bug fix is in response to @pbca26 report of “iguana_pkhashbalance: unexpected non-ptr lastpt” which is an error that is most likely caused by accessing the dataset at the wrong time. --- iguana/iguana_init.c | 3 ++ iguana/iguana_recv.c | 1 + iguana/iguana_rpc.c | 92 ++++++++++++++++++++++----------------- iguana/main.c | 68 +++++++++++++++++------------ includes/iguana_funcs.h | 8 ++-- includes/iguana_globals.h | 2 +- includes/iguana_structs.h | 2 +- 7 files changed, 101 insertions(+), 75 deletions(-) diff --git a/iguana/iguana_init.c b/iguana/iguana_init.c index c9e2bfa04..62de02e5b 100755 --- a/iguana/iguana_init.c +++ b/iguana/iguana_init.c @@ -36,6 +36,8 @@ void iguana_initQs(struct iguana_info *coin) iguana_initQ(&coin->msgrequestQ,"msgrequestQ"); iguana_initQ(&coin->cacheQ,"cacheQ"); iguana_initQ(&coin->recvQ,"recvQ"); + iguana_initQ(&coin->jsonQ,"jsonQ"); + iguana_initQ(&coin->finishedQ,"finishedQ"); if ( coin->MAXPEERS > 0 && coin->peers != 0 ) { for (i=0; iblocks_mutex); portable_mutex_init(&coin->special_mutex); portable_mutex_init(&coin->allcoins_mutex); + portable_mutex_init(&coin->allcoins_mutex); coin->txfee = 10000; iguana_meminit(&coin->blockMEM,"blockMEM",coin->blockspace,coin->blockspacesize,0); iguana_initQs(coin); diff --git a/iguana/iguana_recv.c b/iguana/iguana_recv.c index e0dccfb78..a6c931c77 100755 --- a/iguana/iguana_recv.c +++ b/iguana/iguana_recv.c @@ -1868,6 +1868,7 @@ int32_t iguana_processrecv(struct supernet_info *myinfo,struct iguana_info *coin flag += iguana_processrecvQ(myinfo,coin,&newhwm); if ( coin->RTheight == 0 || (rand() % 30) == 0 ) flag += iguana_reqblocks(myinfo,coin); + iguana_jsonQ(myinfo,coin); if ( time(NULL) > coin->laststats+30 ) { flag += iguana_reqhdrs(coin); diff --git a/iguana/iguana_rpc.c b/iguana/iguana_rpc.c index 32dd36668..2d30cf1c9 100755 --- a/iguana/iguana_rpc.c +++ b/iguana/iguana_rpc.c @@ -32,7 +32,7 @@ char *sglue(GLUEARGS,char *agent,char *method) jaddstr(json,"coin",coin->symbol); if ( myinfo->expiration != 0 && time(NULL) > myinfo->expiration ) iguana_walletlock(myinfo,0); - if ( (retstr= SuperNET_JSON(myinfo,json,remoteaddr,port)) != 0 ) + if ( (retstr= SuperNET_JSON(myinfo,coin,json,remoteaddr,port)) != 0 ) { if ( (retjson= cJSON_Parse(retstr)) != 0 ) { @@ -195,7 +195,7 @@ static char *sendalert(RPCARGS) static char *SuperNET(RPCARGS) { - return(SuperNET_JSON(myinfo,json,remoteaddr,port)); + return(SuperNET_JSON(myinfo,coin,json,remoteaddr,port)); } static char *getrawmempool(RPCARGS) @@ -669,48 +669,54 @@ char *iguana_bitcoinrpc(struct supernet_info *myinfo,uint16_t port,struct iguana } return(clonestr("{\"error\":\"invalid coin address\"}")); } - -char *iguana_bitcoinRPC(struct supernet_info *myinfo,char *method,cJSON *json,char *remoteaddr,uint16_t port) +struct iguana_info *iguana_coinchoose(struct supernet_info *myinfo,char *symbol,cJSON *json,uint16_t port) { - cJSON *params[16],*array; struct iguana_info *tmp,*coin = 0; char symbol[16]; int32_t i,c,n; char *retstr = 0; - symbol[0] = 0; - memset(params,0,sizeof(params)); - //printf("bitcoinRPC\n"); - if ( json != 0 ) + int32_t i,c; struct iguana_info *tmp,*coin = 0; + if ( port == myinfo->rpcport ) { - if ( port == myinfo->rpcport ) + if ( jstr(json,"coin") == 0 ) { - if ( jstr(json,"coin") == 0 ) - { - strcpy(symbol,myinfo->rpcsymbol); - if ( symbol[0] == 0 ) - { - c = 'B'; - sprintf(symbol,"%c%c%c%c",c,'T',c+1,c+2); - } - } - else + strcpy(symbol,myinfo->rpcsymbol); + if ( symbol[0] == 0 ) { - safecopy(symbol,jstr(json,"coin"),sizeof(symbol)); - for (i=0; symbol[i]!=0; i++) - symbol[i] = toupper((int32_t)symbol[i]); + c = 'B'; + sprintf(symbol,"%c%c%c%c",c,'T',c+1,c+2); } - if ( myinfo->rpcsymbol[0] == 0 ) - strcpy(myinfo->rpcsymbol,symbol); } else { - //portable_mutex_lock(&myinfo->allcoins_mutex); - HASH_ITER(hh,myinfo->allcoins,coin,tmp) - { - if ( coin->chain->rpcport == port ) - break; - else coin = 0; - } - //portable_mutex_unlock(&myinfo->allcoins_mutex); + safecopy(symbol,jstr(json,"coin"),sizeof(symbol)); + for (i=0; symbol[i]!=0; i++) + symbol[i] = toupper((int32_t)symbol[i]); + } + } + else + { + //portable_mutex_lock(&myinfo->allcoins_mutex); + HASH_ITER(hh,myinfo->allcoins,coin,tmp) + { + if ( coin->chain->rpcport == port ) + break; + else coin = 0; } - if ( coin == 0 && symbol[0] != 0 ) - coin = iguana_coinfind(symbol); + //portable_mutex_unlock(&myinfo->allcoins_mutex); + } + if ( coin == 0 && symbol[0] != 0 ) + coin = iguana_coinfind(symbol); + return(coin); +} + +char *iguana_bitcoinRPC(struct supernet_info *myinfo,char *method,cJSON *json,char *remoteaddr,uint16_t port) +{ + cJSON *params[16],*array; struct iguana_info *coin = 0; char symbol[16]; int32_t i,n; char *retstr = 0; + symbol[0] = 0; + memset(params,0,sizeof(params)); + //printf("bitcoinRPC\n"); + if ( json != 0 ) + { + coin = iguana_coinchoose(myinfo,symbol,json,port); + if ( myinfo->rpcsymbol[0] == 0 ) + strcpy(myinfo->rpcsymbol,symbol); if ( coin != 0 ) safecopy(symbol,coin->symbol,sizeof(symbol)); //printf("method.(%s) (%s) remote.(%s) symbol.(%s)\n",method,jprint(json,0),remoteaddr,symbol); @@ -829,8 +835,8 @@ cJSON *SuperNET_urlconv(char *value,int32_t bufsize,char *urlstr) char *SuperNET_rpcparse(struct supernet_info *myinfo,char *retbuf,int32_t bufsize,int32_t *jsonflagp,int32_t *postflagp,char *urlstr,char *remoteaddr,char *filetype,uint16_t port) { - cJSON *tokens,*argjson,*origargjson,*json = 0; long filesize; - char symbol[16],buf[4096],urlmethod[16],*data,url[1024],furl[1024],*retstr,*filestr,*token = 0; int32_t i,j,n,num=0; + cJSON *tokens,*argjson,*origargjson,*json = 0; long filesize; struct iguana_info *coin = 0; + char symbol[64],buf[4096],urlmethod[16],*data,url[1024],furl[1024],*retstr,*filestr,*token = 0; int32_t i,j,n,num=0; //printf("rpcparse.(%s)\n",urlstr); for (i=0; ifinishedQ; + jsonQ = &coin->jsonQ; + } if ( COMMANDLINE_ARGFILE != 0 ) { ptr = calloc(1,sizeof(*ptr) + strlen(COMMANDLINE_ARGFILE) + 1); - ptr->myinfo = SuperNET_MYINFO(0); + ptr->myinfo = myinfo;//SuperNET_MYINFO(0); strcpy(ptr->jsonstr,COMMANDLINE_ARGFILE); free(COMMANDLINE_ARGFILE); COMMANDLINE_ARGFILE = 0; if ( (ptr->retjsonstr= SuperNET_jsonstr(ptr->myinfo,ptr->jsonstr,ptr->remoteaddr,ptr->port)) == 0 ) ptr->retjsonstr = clonestr("{\"error\":\"null return from iguana_jsonstr\"}"); printf("COMMANDLINE_ARGFILE.(%s) -> (%s) %.0f\n",ptr->jsonstr,ptr->retjsonstr!=0?ptr->retjsonstr:"null return",OS_milliseconds()); - queue_enqueue("finishedQ",&finishedQ,&ptr->DL,0); + queue_enqueue("finishedQ",finishedQ,&ptr->DL,0); return(1); } - if ( (ptr= queue_dequeue(&finishedQ,0)) != 0 ) + if ( (ptr= queue_dequeue(finishedQ,0)) != 0 ) { if ( ptr->expired != 0 ) { @@ -192,20 +202,20 @@ int32_t iguana_jsonQ() } printf("garbage collection: expired.(%s)\n",ptr->jsonstr); myfree(ptr,ptr->allocsize); - } else queue_enqueue("finishedQ",&finishedQ,&ptr->DL,0); + } else queue_enqueue("finishedQ",finishedQ,&ptr->DL,0); } - if ( (ptr= queue_dequeue(&jsonQ,0)) != 0 ) + if ( (ptr= queue_dequeue(jsonQ,0)) != 0 ) { if ( (ptr->retjsonstr= SuperNET_jsonstr(ptr->myinfo,ptr->jsonstr,ptr->remoteaddr,ptr->port)) == 0 ) ptr->retjsonstr = clonestr("{\"error\":\"null return from iguana_jsonstr\"}"); printf("finished.(%s) -> (%s) %.0f\n",ptr->jsonstr,ptr->retjsonstr!=0?ptr->retjsonstr:"null return",OS_milliseconds()); - queue_enqueue("finishedQ",&finishedQ,&ptr->DL,0); + queue_enqueue("finishedQ",finishedQ,&ptr->DL,0); return(1); } return(0); } -char *iguana_blockingjsonstr(struct supernet_info *myinfo,char *jsonstr,uint64_t tag,int32_t maxmillis,char *remoteaddr,uint16_t port) +char *iguana_blockingjsonstr(struct supernet_info *myinfo,struct iguana_info *coin,char *jsonstr,uint64_t tag,int32_t maxmillis,char *remoteaddr,uint16_t port) { struct iguana_jsonitem *ptr; int32_t len,allocsize; double expiration; expiration = OS_milliseconds() + maxmillis; @@ -219,14 +229,14 @@ char *iguana_blockingjsonstr(struct supernet_info *myinfo,char *jsonstr,uint64_t ptr->retjsonstr = 0; safecopy(ptr->remoteaddr,remoteaddr,sizeof(ptr->remoteaddr)); memcpy(ptr->jsonstr,jsonstr,len+1); - queue_enqueue("jsonQ",&jsonQ,&ptr->DL,0); + queue_enqueue("jsonQ",coin != 0 ? &coin->jsonQ : &JSON_Q,&ptr->DL,0); while ( OS_milliseconds() < expiration ) { usleep(100); if ( ptr->retjsonstr != 0 ) { //printf("got blocking retjsonstr.(%s) delete allocsize.%d:%d\n",retjsonstr,allocsize,ptr->allocsize); - queue_delete(&finishedQ,&ptr->DL,ptr->allocsize,1); + queue_delete(coin != 0 ? &coin->finishedQ : &FINISHED_Q,&ptr->DL,ptr->allocsize,1); return(ptr->retjsonstr); } usleep(1000); @@ -236,7 +246,7 @@ char *iguana_blockingjsonstr(struct supernet_info *myinfo,char *jsonstr,uint64_t return(clonestr("{\"error\":\"iguana jsonstr expired\"}")); } -char *SuperNET_processJSON(struct supernet_info *myinfo,cJSON *json,char *remoteaddr,uint16_t port) +char *SuperNET_processJSON(struct supernet_info *myinfo,struct iguana_info *coin,cJSON *json,char *remoteaddr,uint16_t port) { cJSON *retjson; uint64_t tag; uint32_t timeout; char *jsonstr,*retjsonstr,*retstr = 0; //*hexmsg,*method, //char str[65]; printf("processJSON %p %s\n",&myinfo->privkey,bits256_str(str,myinfo->privkey)); @@ -259,7 +269,7 @@ char *SuperNET_processJSON(struct supernet_info *myinfo,cJSON *json,char *remote //printf("RPC? (%s)\n",jsonstr); if ( jstr(json,"immediate") != 0 || ((remoteaddr == 0 || remoteaddr[0] == 0) && port == IGUANA_RPCPORT) ) retjsonstr = SuperNET_jsonstr(myinfo,jsonstr,remoteaddr,port); - else retjsonstr = iguana_blockingjsonstr(myinfo,jsonstr,tag,timeout,remoteaddr,port); + else retjsonstr = iguana_blockingjsonstr(myinfo,coin,jsonstr,tag,timeout,remoteaddr,port); if ( retjsonstr != 0 ) { if ( (retjsonstr[0] == '{' || retjsonstr[0] == '[') && (retjson= cJSON_Parse(retjsonstr)) != 0 ) @@ -286,7 +296,7 @@ char *SuperNET_processJSON(struct supernet_info *myinfo,cJSON *json,char *remote return(retstr); } -char *SuperNET_JSON(struct supernet_info *myinfo,cJSON *json,char *remoteaddr,uint16_t port) +char *SuperNET_JSON(struct supernet_info *myinfo,struct iguana_info *coin,cJSON *json,char *remoteaddr,uint16_t port) { int32_t autologin = 0; uint32_t timestamp; char *retstr=0,*agent=0,*method=0,*jsonstr=0; uint64_t tag; //printf("SuperNET_JSON.(%s)\n",jprint(json,0)); @@ -313,7 +323,7 @@ char *SuperNET_JSON(struct supernet_info *myinfo,cJSON *json,char *remoteaddr,ui OS_randombytes((uint8_t *)&tag,sizeof(tag)); jadd64bits(json,"tag",tag); } - if ( (retstr= SuperNET_processJSON(myinfo,json,remoteaddr,port)) == 0 ) + if ( (retstr= SuperNET_processJSON(myinfo,coin,json,remoteaddr,port)) == 0 ) printf("null retstr from SuperNET_JSON\n"); if ( jsonstr != 0 ) free(jsonstr); @@ -422,7 +432,7 @@ void mainloop(struct supernet_info *myinfo) counter++; coin = 0; depth = 0; - if ( 0 ) + if ( 1 ) { HASH_ITER(hh,myinfo->allcoins,coin,tmp) { @@ -431,9 +441,9 @@ void mainloop(struct supernet_info *myinfo) } } //printf("check jsonQ\n"); - while ( iguana_jsonQ() != 0 ) + while ( iguana_jsonQ(myinfo,0) != 0 ) ; - if ( 0 ) + if ( 1 ) { if ( depth > 0 ) { @@ -532,16 +542,16 @@ void iguana_appletests(struct supernet_info *myinfo) bitcoin_sharedsecret(myinfo->ctx,hash2,pubkey,33); printf("secp256k1 elapsed %.3f for %d iterations\n",OS_milliseconds() - startmillis,i); getchar();**/ - if ( 1 && (str= SuperNET_JSON(myinfo,cJSON_Parse("{\"protover\":70002,\"RELAY\":1,\"VALIDATE\":1,\"portp2p\":14631,\"rpc\":14632,\"agent\":\"iguana\",\"method\":\"addcoin\",\"startpend\":512,\"endpend\":512,\"services\":129,\"maxpeers\":8,\"newcoin\":\"BTCD\",\"active\":1,\"numhelpers\":1,\"poll\":100}"),0,myinfo->rpcport)) != 0 ) + if ( 1 && (str= SuperNET_JSON(myinfo,iguana_coinfind("BTCD"),cJSON_Parse("{\"protover\":70002,\"RELAY\":1,\"VALIDATE\":1,\"portp2p\":14631,\"rpc\":14632,\"agent\":\"iguana\",\"method\":\"addcoin\",\"startpend\":512,\"endpend\":512,\"services\":129,\"maxpeers\":8,\"newcoin\":\"BTCD\",\"active\":1,\"numhelpers\":1,\"poll\":100}"),0,myinfo->rpcport)) != 0 ) { free(str); - if ( 1 && (str= SuperNET_JSON(myinfo,cJSON_Parse("{\"portp2p\":8333,\"RELAY\":0,\"VALIDATE\":0,\"agent\":\"iguana\",\"method\":\"addcoin\",\"startpend\":1,\"endpend\":1,\"services\":128,\"maxpeers\":8,\"newcoin\":\"BTC\",\"active\":0,\"numhelpers\":1,\"poll\":100}"),0,myinfo->rpcport)) != 0 ) + if ( 1 && (str= SuperNET_JSON(myinfo,iguana_coinfind("BTC"),cJSON_Parse("{\"portp2p\":8333,\"RELAY\":0,\"VALIDATE\":0,\"agent\":\"iguana\",\"method\":\"addcoin\",\"startpend\":1,\"endpend\":1,\"services\":128,\"maxpeers\":8,\"newcoin\":\"BTC\",\"active\":0,\"numhelpers\":1,\"poll\":100}"),0,myinfo->rpcport)) != 0 ) { free(str); - if ( 0 && (str= SuperNET_JSON(myinfo,cJSON_Parse("{\"agent\":\"SuperNET\",\"method\":\"login\",\"handle\":\"alice\",\"password\":\"alice\",\"passphrase\":\"alice\"}"),0,myinfo->rpcport)) != 0 ) + if ( 0 && (str= SuperNET_JSON(myinfo,iguana_coinfind("BTCD"),cJSON_Parse("{\"agent\":\"SuperNET\",\"method\":\"login\",\"handle\":\"alice\",\"password\":\"alice\",\"passphrase\":\"alice\"}"),0,myinfo->rpcport)) != 0 ) { free(str); - if ( (str= SuperNET_JSON(myinfo,cJSON_Parse("{\"agent\":\"SuperNET\",\"method\":\"login\",\"handle\":\"bob\",\"password\":\"bob\",\"passphrase\":\"bob\"}"),0,myinfo->rpcport)) != 0 ) + if ( (str= SuperNET_JSON(myinfo,iguana_coinfind("BTCD"),cJSON_Parse("{\"agent\":\"SuperNET\",\"method\":\"login\",\"handle\":\"bob\",\"password\":\"bob\",\"passphrase\":\"bob\"}"),0,myinfo->rpcport)) != 0 ) free(str); } } @@ -591,13 +601,13 @@ int32_t iguana_commandline(struct supernet_info *myinfo,char *arg) printf("GLOBAL tmpdir.(%s)\n",GLOBAL_TMPDIR); } printf("call argv JSON.(%s)\n",(char *)arg); - SuperNET_JSON(myinfo,argjson,0,myinfo->rpcport); + SuperNET_JSON(myinfo,0,argjson,0,myinfo->rpcport); if ( (coinargs= SuperNET_keysinit(myinfo,arg)) != 0 ) iguana_launch(0,"iguana_coins",iguana_coins,coinargs,IGUANA_PERMTHREAD); if ( (array= jarray(&n,argjson,"commands")) != 0 ) { for (i=0; irpcport)) != 0 ) + if ( (str= SuperNET_JSON(myinfo,0,jitem(array,i),0,myinfo->rpcport)) != 0 ) free(str); } free_json(argjson); @@ -641,8 +651,8 @@ void iguana_ensuredirs() void iguana_Qinit() { iguana_initQ(&helperQ,"helperQ"); - iguana_initQ(&jsonQ,"jsonQ"); - iguana_initQ(&finishedQ,"finishedQ"); + iguana_initQ(&JSON_Q,"jsonQ"); + iguana_initQ(&FINISHED_Q,"finishedQ"); iguana_initQ(&bundlesQ,"bundlesQ"); iguana_initQ(&emitQ,"emitQ"); //iguana_initQ(&TerminateQ,"TerminateQ"); @@ -651,7 +661,7 @@ void iguana_Qinit() void iguana_helpinit(struct supernet_info *myinfo) { char *tmpstr = 0; - if ( (tmpstr= SuperNET_JSON(myinfo,cJSON_Parse("{\"agent\":\"SuperNET\",\"method\":\"help\"}"),0,myinfo->rpcport)) != 0 ) + if ( (tmpstr= SuperNET_JSON(myinfo,0,cJSON_Parse("{\"agent\":\"SuperNET\",\"method\":\"help\"}"),0,myinfo->rpcport)) != 0 ) { if ( (API_json= cJSON_Parse(tmpstr)) != 0 && (API_json= jobj(API_json,"result")) != 0 ) API_json = jobj(API_json,"API"); diff --git a/includes/iguana_funcs.h b/includes/iguana_funcs.h index 559673299..70d51ac90 100755 --- a/includes/iguana_funcs.h +++ b/includes/iguana_funcs.h @@ -138,7 +138,7 @@ double dxblend(double *destp,double val,double decay); // json int32_t iguana_processjsonQ(struct iguana_info *coin); // reentrant, can be called during any idletime -char *iguana_JSON(char *,uint16_t port); +char *iguana_JSON(struct supernet_info *myinfo,struct iguana_info *coin,char *,uint16_t port); char *SuperNET_p2p(struct iguana_info *coin,struct iguana_peer *addr,int32_t *delaymillisp,char *ipaddr,uint8_t *data,int32_t datalen,int32_t compressed); char *mbstr(char *str,double); @@ -262,7 +262,7 @@ cJSON *iguana_peersjson(struct iguana_info *coin,int32_t addronly); //int32_t btc_pub2rmd(uint8_t rmd160[20],uint8_t pubkey[33]); int32_t iguana_launchcoin(struct supernet_info *myinfo,char *symbol,cJSON *json,int32_t virtcoin); int32_t iguana_bundleinitmap(struct iguana_info *coin,struct iguana_bundle *bp,int32_t height,bits256 hash2,bits256 hash1); -int32_t iguana_jsonQ(); +int32_t iguana_jsonQ(struct supernet_info *myinfo,struct iguana_info *coin); int32_t is_bitcoinrpc(struct supernet_info *myinfo,char *method,char *remoteaddr); char *iguana_bitcoinRPC(struct supernet_info *myinfo,char *method,cJSON *json,char *remoteaddr,uint16_t port); cJSON *iguana_pubkeyjson(struct iguana_info *coin,char *pubkeystr); @@ -271,7 +271,7 @@ int32_t iguana_bundleiters(struct supernet_info *myinfo,struct iguana_info *coin void ramcoder_test(void *data,int64_t len); void iguana_exit(); int32_t iguana_pendingaccept(struct iguana_info *coin); -char *iguana_blockingjsonstr(struct supernet_info *myinfo,char *jsonstr,uint64_t tag,int32_t maxmillis,char *remoteaddr,uint16_t port); +char *iguana_blockingjsonstr(struct supernet_info *myinfo,struct iguana_info *coin,char *jsonstr,uint64_t tag,int32_t maxmillis,char *remoteaddr,uint16_t port); void iguana_iAkill(struct iguana_info *coin,struct iguana_peer *addr,int32_t markflag); cJSON *SuperNET_bits2json(uint8_t *serialized,int32_t datalen); int32_t SuperNET_sendmsg(struct supernet_info *myinfo,struct iguana_info *coin,struct iguana_peer *addr,bits256 destpub,bits256 mypriv,bits256 mypub,uint8_t *msg,int32_t len,uint8_t *data,int32_t delaymillis); @@ -519,7 +519,7 @@ bits256 calc_categoryhashes(bits256 *subhashp,char *category,char *subcategory); struct gecko_chain *category_find(bits256 categoryhash,bits256 subhash); void *category_subscribe(struct supernet_info *myinfo,bits256 category,bits256 keyhash); char *bitcoin_address(char *coinaddr,uint8_t addrtype,uint8_t *pubkey_or_rmd160,int32_t len); -char *SuperNET_JSON(struct supernet_info *myinfo,cJSON *json,char *remoteaddr,uint16_t port); +char *SuperNET_JSON(struct supernet_info *myinfo,struct iguana_info *coin,cJSON *json,char *remoteaddr,uint16_t port); struct supernet_info *SuperNET_accountfind(cJSON *json); cJSON *SuperNET_rosettajson(struct supernet_info *myinfo,bits256 privkey,int32_t showprivs); double instantdex_aveprice(struct supernet_info *myinfo,struct exchange_quote *sortbuf,int32_t max,double *totalvolp,char *base,char *rel,double basevolume,cJSON *argjson); diff --git a/includes/iguana_globals.h b/includes/iguana_globals.h index 8ff140ae9..d11069dc4 100755 --- a/includes/iguana_globals.h +++ b/includes/iguana_globals.h @@ -66,7 +66,7 @@ CONDEXTERN struct iguana_info *Allcoins; CONDEXTERN char Userhome[512]; CONDEXTERN int32_t USE_JAY,FIRST_EXTERNAL,IGUANA_disableNXT,Debuglevel,IGUANA_BIGENDIAN; CONDEXTERN uint32_t prices777_NXTBLOCK; -CONDEXTERN queue_t helperQ,jsonQ,finishedQ,bundlesQ,emitQ; +CONDEXTERN queue_t helperQ,JSON_Q,FINISHED_Q,bundlesQ,emitQ; CONDEXTERN struct supernet_info MYINFO,**MYINFOS; CONDEXTERN int32_t MAIN_initflag,MAX_DEPTH; CONDEXTERN int32_t HDRnet,netBLOCKS; diff --git a/includes/iguana_structs.h b/includes/iguana_structs.h index 1223095e8..cc40c7666 100755 --- a/includes/iguana_structs.h +++ b/includes/iguana_structs.h @@ -443,7 +443,7 @@ struct iguana_info void *ctx; struct iguana_bitmap *screen; struct OS_memspace TXMEM,MEM,MEMB[IGUANA_MAXBUNDLESIZE]; - queue_t acceptQ,hdrsQ,blocksQ,priorityQ,possibleQ,cacheQ,recvQ,msgrequestQ; + queue_t acceptQ,hdrsQ,blocksQ,priorityQ,possibleQ,cacheQ,recvQ,msgrequestQ,jsonQ,finishedQ; double parsemillis,avetime; uint32_t Launched[8],Terminated[8]; portable_mutex_t peers_mutex,blocks_mutex,special_mutex,RTmutex,allcoins_mutex; char changeaddr[64];