Threaded version 0.7
This commit is contained in:
@@ -14,8 +14,8 @@
|
||||
#endif
|
||||
typedef struct { int fd;uint8_t rx[260],tx[260];size_t received,needed,sent,length;uint64_t deadline; } as_peer;
|
||||
typedef struct {
|
||||
int used,enabled,listener,running,error,os_error;uint32_t generation,received,replied,exceptions,retry;
|
||||
uint32_t ip;uint16_t port,base[4],count[4],values[4][AS_ITEMS];uint64_t retry_at;
|
||||
int used,enabled,suspended,listener,running,error,os_error;uint32_t generation,received,replied,exceptions,retry;
|
||||
uint32_t ip;uint16_t port,base[4],count[4],values[4][AS_ITEMS];uint64_t retry_at,heartbeat; uint8_t dirty[4][AS_ITEMS];
|
||||
as_peer peers[AS_PEERS];
|
||||
} as_server;
|
||||
static as_server as_slots[AS_POOL];
|
||||
@@ -46,13 +46,13 @@ static void as_reply(as_server *s,as_peer *p){
|
||||
table=f==5?0:2;
|
||||
if(p->needed!=12 || (f==5 && q!=0 && q!=0xff00)){exception=3;break;}
|
||||
if(!as_range(s,table,address,1)){exception=2;break;}
|
||||
s->values[table][address-s->base[table]]=f==5?(q!=0):q;memcpy(p->tx+8,p->rx+8,4);n=12;break;
|
||||
s->values[table][address-s->base[table]]=f==5?(q!=0):q;s->dirty[table][address-s->base[table]]=1;memcpy(p->tx+8,p->rx+8,4);n=12;break;
|
||||
case 15:case 16:
|
||||
table=f==15?0:2;
|
||||
if(!q || q>(f==15?1968:123) || p->needed<13 || p->rx[12]!=(f==15?(q+7u)/8u:2u*q) || p->needed!=(size_t)(13+p->rx[12])){exception=3;break;}
|
||||
if(!as_range(s,table,address,q)){exception=2;break;}
|
||||
index=address-s->base[table];
|
||||
for(unsigned i=0;i<q;i++)s->values[table][index+i]=f==15?(uint16_t)((p->rx[13+i/8]>>(i%8))&1):as_get16(p->rx+13+2*i);
|
||||
for(unsigned i=0;i<q;i++){s->values[table][index+i]=f==15?(uint16_t)((p->rx[13+i/8]>>(i%8))&1):as_get16(p->rx+13+2*i);s->dirty[table][index+i]=1;}
|
||||
memcpy(p->tx+8,p->rx+8,4);n=12;break;
|
||||
default:exception=1;break;
|
||||
}
|
||||
@@ -103,7 +103,7 @@ uint32_t as_call(uint32_t cmd,uint32_t h,uint32_t ip,uint16_t port,uint8_t table
|
||||
memset(out,0,24*sizeof(*out));if(!port || !retry)return AM_ARGUMENT;
|
||||
for(i=0;i<AS_POOL;i++)if(!as_slots[i].used && as_slots[i].generation<0xffffffu)break;
|
||||
if(i==AS_POOL)return 257;
|
||||
s=&as_slots[i];uint32_t generation=s->generation+1;memset(s,0,sizeof(*s));s->generation=generation;s->used=1;s->listener=-1;s->ip=ip;s->port=port;s->retry=retry;
|
||||
s=&as_slots[i];uint32_t generation=s->generation+1;memset(s,0,sizeof(*s));s->generation=generation;s->used=1;s->listener=-1;s->ip=ip;s->port=port;s->retry=retry;s->heartbeat=now;
|
||||
for(unsigned j=0;j<AS_PEERS;j++){s->peers[j].fd=-1;as_peer_close(&s->peers[j]);}
|
||||
h=(generation<<8)|(i+65u);as_snapshot(s,h,out);return 0;
|
||||
}
|
||||
@@ -112,20 +112,32 @@ uint32_t as_call(uint32_t cmd,uint32_t h,uint32_t ip,uint16_t port,uint8_t table
|
||||
s=&as_slots[i-1];
|
||||
switch(cmd){
|
||||
case AS_CLOSE:as_stop(s);s->used=0;as_snapshot(s,0,out);return 0;
|
||||
case AS_ENABLE:s->enabled=1;break;
|
||||
case AS_DISABLE:s->enabled=0;as_stop(s);break;
|
||||
case AS_TICK:as_tick(s,now);break;
|
||||
case AS_ENABLE:s->enabled=1;s->suspended=0;s->heartbeat=now;break;
|
||||
case AS_DISABLE:s->suspended=0;s->enabled=0;as_stop(s);break;
|
||||
case AS_TICK:s->heartbeat=now;if(s->suspended){s->suspended=0;s->enabled=1;s->retry_at=now;}break;
|
||||
case AS_PUSH:case AS_PULL:
|
||||
if(table>3 || !q || q>AS_ITEMS || (uint32_t)addr+q>65536u)result=AM_ARGUMENT;
|
||||
else if(!data || cap<q)result=258;
|
||||
else if(cmd==AS_PUSH){
|
||||
if(table<2){for(unsigned j=0;j<q;j++)if(data[j]>1){result=AM_ARGUMENT;break;}}
|
||||
if(!result){s->base[table]=addr;s->count[table]=q;memcpy(s->values[table],data,q*sizeof(*data));}
|
||||
if(!result){
|
||||
if(s->count[table] && (s->base[table]!=addr || s->count[table]!=q)) { result=AM_ARGUMENT;break; }
|
||||
s->base[table]=addr;s->count[table]=q;
|
||||
for(unsigned j=0;j<q;j++)if(!s->dirty[table][j])s->values[table][j]=data[j];
|
||||
}
|
||||
}else if(s->base[table]!=addr || s->count[table]!=q)result=AM_ARGUMENT;
|
||||
else memcpy(data,s->values[table],q*sizeof(*data));
|
||||
else {memcpy(data,s->values[table],q*sizeof(*data));memset(s->dirty[table],0,q);}
|
||||
break;
|
||||
default:result=259;break;
|
||||
}
|
||||
as_snapshot(s,h,out);return result;
|
||||
}
|
||||
void as_shutdown(void){for(unsigned i=0;i<AS_POOL;i++)if(as_slots[i].used){as_stop(&as_slots[i]);as_slots[i].used=0;}}
|
||||
|
||||
void as_pump(uint64_t now,uint32_t watchdog_ms){
|
||||
for(unsigned i=0;i<AS_POOL;i++)if(as_slots[i].used){
|
||||
as_server *s=&as_slots[i];
|
||||
if(s->enabled && now-s->heartbeat>=watchdog_ms){as_stop(s);s->enabled=0;s->suspended=1;}
|
||||
as_tick(s,now);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user