Mercurial > hg > Game > Cerium
changeset 392:96200cf9a0d0 draft
added lindaapi.cpp and lindaapi.h to test_render
author | kazz@kazzone.cr.ie.u-ryukyu.ac.jp |
---|---|
date | Mon, 31 Aug 2009 19:04:24 +0900 |
parents | 492e60453124 |
children | cb06748ba6cf |
files | TaskManager/Test/test_render/lindaapi.cpp TaskManager/Test/test_render/lindaapi.h |
diffstat | 2 files changed, 712 insertions(+), 0 deletions(-) [+] |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/TaskManager/Test/test_render/lindaapi.cpp Mon Aug 31 19:04:24 2009 +0900 @@ -0,0 +1,626 @@ +// $Id: lindaapi.c,v 1.9 2006/04/03 08:17:11 kono Exp $ +// + +/*---------------------------------------------------------------------- + インクルードファイル読み込み +----------------------------------------------------------------------*/ +#include <sys/file.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <fcntl.h> +#include <sys/uio.h> +#include <sys/time.h> +#include <sys/select.h> +#include <sys/stat.h> +#include <sys/types.h> +#include <sys/socket.h> +#include <sys/un.h> +#include <netinet/in.h> +#include <netinet/tcp.h> +#include <signal.h> +#include <termios.h> +#include <netdb.h> +#include <errno.h> +#include <sys/select.h> + +#include "lindaapi.h" + +#define TIMEDELTA 10 +#if 0 +#define PSX_Debug(deb) (putchar(PS_DEB)),\ + (printf deb ),\ + (putchar(PS_DEB)) +#define DEB(a) +#else +#define PSX_Debug(deb) +#define DEB(a) /* a */ +#endif + +COMMAND *q_top, *q_end; +REPLY *reply, *r_end; + +int qsize, ps; +unsigned short seq; + +#ifdef COUNT_PACKET +// print packet count message per PRINT_INTERVAL sec +#define PRINT_INTERVAL 4 + +/*-------------------------------------------------------------------/ + void + count_packet (char type): + パケットの送受信カウントする + + 引き数: + type - 送信、受信 (char型: s,r) +/-------------------------------------------------------------------*/ +void count_packet(char type) +{ + static int send_packet=-1,receive_packet=0; + static struct timeval start,now,previous; + + if (out_packet == -1) { + gettimeofday(&start,NULL); + gettimeofday(&previous,NULL); + send_packet = 0; + printf("packet\tout\tread\t\ttime\n"); + } + + if (type == 's') { + send_packet++; + } else if (type == 'r') { + receive_packet++; + } else { + fprintf(stderr,"No type in count_packet function\n"); + return; + } + + gettimeofday(&now,NULL); + if ((now.tv_sec-previous.tv_sec) > PRINT_INTERVAL) { + printf("log\t%d\t%d\t%ld\n", + send_packet,receive_packet,now.tv_sec-start.tv_sec); + fflush(stdout); + + previous.tv_sec = now.tv_sec; + send_packet = receive_packet = 0; + } +} +#endif + + +#define unix_open open +#define unix_read_w read +/*-------------------------------------------------------------------/ + int + unix_read (int fd, char *buf, unsigned int size): + サーバからTUPLEを読みこむ。 + 現在は使われていない。 + + 引き数: + fd - サーバのファイルディスクリプタ + buf - 受け取るデータの格納場所(TUPLEヘッダ含む) + size - bufのbyte数 + 返り値: + 読みこんだbyte数 +/-------------------------------------------------------------------*/ +int +unix_read(int fd,char *buf,unsigned int size) { + int len,a,i; + if(read(fd,buf,INT_SIZE)!=INT_SIZE) { // INT_SIZE is sizeof(int) + fprintf(stderr, "read error! on fd:%d len=%d %s\n", fd, + *(unsigned int*)&buf[0], + strerror(errno)); + exit(1); + } + len = ntohl(*(unsigned int*)&buf[0]); + if((unsigned int)len>size) len=(int)size; + for(a=0;a<len;a+=i) { + if((i=read(fd,buf+a,len-a))<0) { + fprintf(stderr, "ldserv: client read error! on i=%d len= %d %s\n", + i, len, strerror(errno)); + exit(1); + } + } + return len; +} + +/*-------------------------------------------------------------------/ + int + unix_write (int fd, unsigned char *buf, unsigned int size): + サーバへTUPLEを送る。 + + 引き数: + fd - サーバのファイルディスクリプタ + buf - サーバへ送るデータ(TUPLEヘッダ含む) + size - bufのbyte数 + 返り値: + 送った(書きこんだ)データのbyte数 +/-------------------------------------------------------------------*/ +int +unix_write(int fd,unsigned char *buf,unsigned int size) { + int i,nsize; + nsize = htonl(size); + i = write(fd,&nsize,INT_SIZE); + i += write(fd,buf,size); // size == datasize + LINDA_HEADER_SIZE +#ifdef COUNT_PACKET + count_packet('s'); +#endif + return(i); +} + +#define unix_write_w unix_write + +#define SERV_NAME unix_port +#define PROTO_NAME "tcp" +#define SERVER_NAME hostname +#define MAX_REQ 16 + +int fd,paddrlen; +struct hostent *hoste; +struct sockaddr_in serv_addr; +struct sockaddr_un serv_addr_un; +unsigned char ipaddr[4]; + + +/*-------------------------------------------------------------------/ + int + start_linda (char * hostname): + サーバとのコネクションを確立し、COMMANDキューとREPLYキューの + 初期化を行なう。 + + 引き数: + hostname - サーバのホスト名 + 返り値: + コネクション確立が成功するとそのファイルディスクリプタを返す。 + 失敗すると -1 を返す。 +/-------------------------------------------------------------------*/ +int +start_linda(char * hostname){ + char *p; + + if (! hostname) { + hostname = "/tmp/ldserv"; + } + if (hostname[0]=='/') { + /* Unix domain */ + if ((fd = socket(AF_UNIX, SOCK_STREAM, 0)) == FAIL){ + fprintf(stderr, "socket open error! errno :%d %s\n", errno, + strerror(errno)); + return(-1); + } + serv_addr_un.sun_family = AF_UNIX; + strcpy(serv_addr_un.sun_path, hostname); + fprintf(stdout,"connecting ... %d\n", ntohs(serv_addr.sin_port)); + if (connect(fd, (struct sockaddr *)&serv_addr_un,sizeof(serv_addr_un)) == FAIL){ + fprintf(stderr,"connection error! errno :%d %s\n", errno, + strerror(errno)); + close(fd); + return(-1); + } + + } else { + /* INET domain */ + if ((fd = socket(AF_INET, SOCK_STREAM, 0)) == FAIL){ + fprintf(stderr, "socket open error! errno :%d %s\n", errno, + strerror(errno)); + return(-1); + } + /* check optional port number */ + serv_addr.sin_port = htons(10000); + p = (char *)malloc(strlen(hostname)); + strcpy(p,hostname); + hostname = p; + while(*p) { + if (*p==':') { + serv_addr.sin_port = htons(atoi(p+1)); + *p = 0; + break; + } + p++; + } + if ((hoste = gethostbyname(hostname)) == NULL){ + fprintf(stderr,"hostname error\n"); + close(fd); + return(-1); + } + free(hostname); hostname=0; + serv_addr.sin_family = AF_INET; + serv_addr.sin_addr.s_addr = ((struct in_addr *)(hoste->h_addr))->s_addr; + if (serv_addr.sin_family == AF_INET) { + int tmp = 1; + setsockopt (fd, IPPROTO_TCP, TCP_NODELAY, + (char *) &tmp, sizeof (int)); + } + fprintf(stdout,"connecting ... %d\n", ntohs(serv_addr.sin_port)); + if (connect(fd, (struct sockaddr *)&serv_addr,sizeof(serv_addr)) == FAIL){ + fprintf(stderr,"connection error! errno :%d %s\n", errno, + strerror(errno)); + close(fd); + return(-1); + } + } + + ps = fd; + fprintf(stdout," connect middle server %d\n", fd); + q_end = q_top = NULL; + r_end = reply = NULL; + qsize = seq = 0; + seq = 120; + return ps; +} + +/*-------------------------------------------------------------------/ + int + psx_out (unsigned int id, unsigned char *data, unsigned int size): + outコマンドをCOMMANDキューへ溜める。 + + 引き数: + id - TUPLE SpaceのID + data - 送信するデータ + size - dataのサイズ + 返り値: + シーケンス番号 +/-------------------------------------------------------------------*/ +int +psx_out(unsigned int id, unsigned char *data, unsigned int size){ + if (psx_queue(id, size, data, 'o', NULL, NULL) == FAIL){ + return(FAIL); + } + DEB( fprintf(stdout, "psx_out: size = %d, command = %s\n", + q_end->size, q_end->command+LINDA_HEADER_SIZE)); + return(seq); +} + +/*-------------------------------------------------------------------/ + int + psx_ld (unsigned int id, char mode, void(*callback)(char*,void*), + void * obj): + in,read,waitなどの受信コマンドをCOMMANDキューへ溜める。 + psx_in,psx_rd,psx_wait_rdなどに置き換えられている。 + + 引き数: + id - TUPLE SpaceのID + mode - i,r,w の文字を取り、各々in,read,waitを表している。 + callback - コールバックを使用する場合の関数へのポインタ。 + 使用しない場合はNULLをいれる。 + obj - コールバックで用いる関数の引き数。 + 返り値: + psx_queue内でmallocされたREPLY構造体へのポインタ +/-------------------------------------------------------------------*/ +int +psx_ld(unsigned int id, char mode,void(*callback)(char *,void *),void * obj){ + int r; + if ((r=psx_queue(id, 0, NULL, mode, callback, obj)) == FAIL){ + return(FAIL); + } + return(r); +} + +/*-------------------------------------------------------------------/ + unsigned char * + psx_reply (int seq): + サーバから答えが来たデータを返す。 + + 引き数: + seq - psx_ld()が返した値。 + 返り値: + seqに対応したデータを返す。データをまだ受信していない場合は + NULLを返す。 +/-------------------------------------------------------------------*/ +unsigned char * +psx_reply(int seq){ + REPLY *p, *q; + char *ans; + + DEB(fprintf(stdout, "psx_reply: search of seq = %d\n", seq)); + PSX_Debug(("psx_reply: seq %d", seq)); + for(q = NULL,p = reply;p;q = p,p = p->next){ + if (p->seq == (unsigned)seq){ + DEB(fprintf(stdout, "psx_reply: match of seq = %d\n", seq)); + if (p->mode == '!'){ + ans = (char *)p->answer; + if (q == NULL){ + reply = p->next; + if(p==r_end) { + r_end = p->next; + } + } else { + q->next = p->next; + if(p==r_end) { + r_end = q; + } + } + PSX_Debug(("psx_reply: reply %x r_end %x p %x q %x",reply,r_end,p,q)); + free(p); + DEB( for(p=reply;p;p=p->next) { PSX_Debug(("psx_queue dump: seq %d mode %c %x %x",p->seq,p->mode,p,p->next))}); + DEB( fprintf(stdout, "psx_reply: returned answer = %s\n", ans)); + PSX_Debug(("psx_reply: answer %s",ans)); + return((unsigned char *)ans); + } else { + if (p->mode == '?'){ + DEB(fprintf(stdout, "psx_reply: don't accept anser\n")); + return(NULL); + } + } + } + + } + PSX_Debug(("psx_reply: no match seq %d",seq)); + DEB(fprintf(stdout, "psx_reply: no match of seq\n")); + return(NULL); +} + +/*-------------------------------------------------------------------/ + void + psx_sync_n (): + サーバとデータの送受信をする。COMMANDキューに溜まったデータを + 送信し、サーバから送られて来たデータを対応するREPLYへいれる。 +/-------------------------------------------------------------------*/ +void +psx_sync_n(){ + int acount; + COMMAND *c, *t; + + fd_set tmp, fds; + struct timeval timeout; + timeout.tv_sec=0; + timeout.tv_usec=TIMEDELTA * 1000; + + acount = 0; + while (q_top != NULL){ + c = q_top; + unix_write_w(ps, c->command, c->size); + free(c->command); + t = c->next; + free(c); + q_top = c = t;qsize--; + } + FD_ZERO(&fds); + FD_SET(ps, &fds); + tmp = fds; + while(select(32, &tmp, NULL, NULL, &timeout) > 0) { + if(FD_ISSET(ps, &tmp)) { + unix_chkserv(); + } + } +} + +/*-------------------------------------------------------------------/ + int + psx_queue (unsigned int id, unsigned int size, unsigned char *data, + char mode, void(*callback)(char*,void*), void * obj): + out,in,read,waitなどのコマンドをCOMMANDキューに溜める。データを + 受信するコマンド(in,read,wait)のときは受け取ったときにデータを + 格納するREPLY構造体を作る。 + + 引き数: + id - アクセスするTUPLE SpaceのID + size - dataのサイズ + data - 送信するデータ。受信時はNULL。 + mode - コマンドのモード(out,in,read,wait は各々char型: o,i,r,w) + callback - コールバックを使用する場合の関数へのポインタ。 + 使用しない場合はNULL。 + obj - コールバックで用いる関数に引き渡すデータ。 + 返り値: + 成功した場合 - mallocしたREPLY構造体へのポインタ。outの場合は + 0が返る。 + 失敗した場合 - FAIL(-1)が返る。 +/-------------------------------------------------------------------*/ +int +psx_queue(unsigned int id, unsigned int size, unsigned char *data, char mode, + void(*callback)(char *,void *), void * obj){ + REPLY *p; + COMMAND *c; + + seq++; + if (qsize >= MAX_QUEUE){ +// PSX_Debug(("max queue: qsize=%d",qsize)); + psx_sync_n(); + } + + for(p=reply;p;p=p->next){ + if(p->seq == seq){ + printf("same seq number: %d\n",seq); + } + } + + if (q_top == NULL){ + if ((q_top = (COMMAND *) malloc (sizeof(COMMAND))) == NULL){ + return(FAIL); + } + c = q_end = q_top; + } else { + if ((q_end->next = (COMMAND *) malloc (sizeof(COMMAND))) == NULL){ + return(FAIL); + } + c = q_end; + q_end = q_end->next; + } + + // size は DATASIZE + if ((q_end->command = (unsigned char *) malloc(size+LINDA_HEADER_SIZE)) == NULL){ + free(q_end); + c->next = NULL; + return(FAIL); + } + + if (mode != 'o'){ + if (reply == NULL){ + if ((reply = (REPLY *) malloc (sizeof(REPLY))) == NULL){ + return(FAIL); + } + p = r_end = reply; p->next = NULL; + } else { + if ((r_end->next = (REPLY *) malloc (sizeof(REPLY))) == NULL){ + return(FAIL); + } + p = r_end->next; r_end = p; p->next = NULL; + } + p->mode = '?'; + p->seq = (int)p; // 構造体のアドレスで識別 + p->callback = callback; + p->obj = obj; + PSX_Debug(("psx_queue: seq %d reply %x p %x r_end %x",seq,reply,p,r_end)); + }else{ + p=0; + } + q_end->command[LINDA_MODE_OFFSET] = mode; + + q_end->command[LINDA_ID_OFFSET] = id >> 8; + q_end->command[LINDA_ID_OFFSET+1] = id & 0xff; + + q_end->command[LINDA_SEQ_OFFSET] = ((int)p>>24) & 0xff; + q_end->command[LINDA_SEQ_OFFSET+1] = ((int)p>>16) & 0xff; + q_end->command[LINDA_SEQ_OFFSET+2] = ((int)p>>8) & 0xff; + q_end->command[LINDA_SEQ_OFFSET+3] = ((int)p) & 0xff; + + q_end->command[LINDA_DATA_LENGTH_OFFSET] = (size>>24) & 0xff; + q_end->command[LINDA_DATA_LENGTH_OFFSET+1] = (size>>16) & 0xff; + q_end->command[LINDA_DATA_LENGTH_OFFSET+2] = (size>>8) & 0xff; + q_end->command[LINDA_DATA_LENGTH_OFFSET+3] = (size) & 0xff; + + q_end->size = size+LINDA_HEADER_SIZE; /* command size */ + q_end->next = NULL; qsize++; + if (data && size>0) memcpy(q_end->command+LINDA_HEADER_SIZE, data, size); + return((int)p); +} + +/*-------------------------------------------------------------------/ + void + unix_chkserv (): + サーバからデータ(TUPLE)を受け取る。REPLY構造体にコールバック関数 + が指定されていればその関数を実行し、REPLY構造体をキューから取り + 除く。コールバック関数が指定されていなければREPLY構造体にデータ + を引き渡す。 +/-------------------------------------------------------------------*/ +void +unix_chkserv(){ + int i,k,pkt,npkt; + REPLY *r,*prev; + int a; + unsigned char * tuple = 0; + + if((i=read(ps,&npkt,INT_SIZE))<0) { + fprintf(stderr, "size read error! on fd:%d %s\n", ps, + strerror(errno)); + exit(1); + } + pkt = ntohl(npkt); + DEB(printf("pkt: %d\n",pkt)); + DEB(fprintf(stdout, "psx_chkserv: queue number: %d , size = %d\n", i, pkt)); + if((tuple = (unsigned char *)malloc(pkt))==NULL){ + fprintf(stderr,"allocate error! errno :%d %s",errno,strerror(errno)); + exit(1); + } + for(a=0;a<pkt;a+=i) { + if((i=unix_read_w(ps,tuple+a,pkt-a))<0) { + fprintf(stderr, "psx_chkserv: read error! on i=%d pkt=%d %s\n", + i, pkt, strerror(errno)); + exit(1);//close(ps); + } + } + +#ifdef COUNT_PACKET + count_packet('r'); +#endif + + i = tuple[LINDA_ID_OFFSET] * 256 + tuple[LINDA_ID_OFFSET+1]; /* id */ + k = (tuple[LINDA_SEQ_OFFSET] <<24) + + (tuple[LINDA_SEQ_OFFSET+1]<<16) + + (tuple[LINDA_SEQ_OFFSET+2]<<8) + + (tuple[LINDA_SEQ_OFFSET+3]); /* seq */ + PSX_Debug(("psx_chkserv: anser packet size = %d id %d seq %d", pkt,i,k)); + DEB(fprintf(stdout, "psx_chkserv: data from server: %s id=%d seq = %d\n", tuple, i, k)); + DEB ( + for(p=reply;p;p=p->next) { + PSX_Debug(printf("psx_queue dump: seq %d mode %c %x %x",p->seq,p->mode,p,p->next)); + }) + + for(prev = NULL,r = reply; r; prev = r,r = r->next){ + DEB(fprintf(stdout,"seq: %d\n",r->seq);) + if (r->seq == (unsigned int)k){ + if(r->callback){ // call callback function + (*r->callback)((char *)tuple,r->obj); + if (prev == NULL){ + reply = r->next; + if(r == r_end) { + r_end = r->next; + } + } else { + prev->next = r->next; + if(r == r_end) { + r_end = prev; + } + } + free(r); + }else{ // normal reply + PSX_Debug(("psx_chkserv: copy answer r %x seq %d",r,k)); + r->answer = tuple; + r->mode = '!'; + } + break; + } + } + tuple = 0; + if (!r){ + DEB(fprintf(stdout, "unix_chkserv: accepted seq %d does not match. \n",k)); + } +} + +void psx_free(char * tuple) +{ +// free(tuple - LINDA_HEADER_SIZE); + free(tuple); +} + +/*-------------------------------------------------------------------/ + int + get_int(unsigned char * tuple, int offset): + TUPLEのヘッダに格納された int型 のデータを得るための関数 + psx_get_datalength() と psx_get_seq() から呼ばれる。 + + 引き数: + tuple - ヘッダ情報も含んだTUPLE。psx_reply()で得たものでもいい。 + offset - 取りだすデータのオフセット。LINDA_DATA_LENGTH_OFFSET + か LINDA_SEQ_OFFSET。 + + 返り値: + 指定したオフセットに格納されていた数値(int型) +/-------------------------------------------------------------------*/ +static +int get_int(unsigned char * tuple, int offset){ + int i; + i = (tuple[offset] <<24) + + (tuple[offset+1]<<16) + + (tuple[offset+2]<<8) + + (tuple[offset+3]); + return i; +} + +int psx_get_datalength(unsigned char * tuple){ + return get_int(tuple,LINDA_DATA_LENGTH_OFFSET); +} + +unsigned char *psx_get_data(unsigned char * tuple){ + return tuple+LINDA_HEADER_SIZE; +} + +int psx_get_seq(unsigned char * tuple){ + return get_int(tuple,LINDA_SEQ_OFFSET); +} + +short psx_get_id(unsigned char * tuple){ + short s; + s = tuple[LINDA_ID_OFFSET] * 256 + + tuple[LINDA_ID_OFFSET+1]; + return s; +} + +char psx_get_mode(unsigned char * tuple){ + return tuple[LINDA_MODE_OFFSET]; +} + + +/* end */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/TaskManager/Test/test_render/lindaapi.h Mon Aug 31 19:04:24 2009 +0900 @@ -0,0 +1,86 @@ +// $Id: lindaapi.h,v 1.8 2005/12/21 07:29:38 yasumura Exp $ +// + +/*---------------------------------------------------------------------- + マクロ定義 +----------------------------------------------------------------------*/ + +#define FAIL (-1) + +#define PS_DEB 0xf8 + +#define MAX_QUEUE 1024 + +#define INT_SIZE 4 // Byte = sizeof(int) + +/*---------------------------------------------------------------------- + パケットフォーマット + char short int int + Mode + ID + Seq + Data_len + Padding + Data + 0 1 3 7 11 12 +----------------------------------------------------------------------*/ + +#define LINDA_MODE_OFFSET 0 +#define LINDA_ID_OFFSET 1 +#define LINDA_SEQ_OFFSET 3 +#define LINDA_DATA_LENGTH_OFFSET 7 +#define LINDA_TID_OFFSET 11 +#define LINDA_HEADER_SIZE 12 + +/*---------------------------------------------------------------------- + 構造体定義 +----------------------------------------------------------------------*/ +typedef struct psx_reply{ + unsigned char *answer; + unsigned int seq; + struct psx_reply *next; + char mode; + void(*callback)(char * tuple, void * obj); + void * obj; +} REPLY, *REPLY_PTR; + +typedef struct command_queue{ + unsigned char *command; + struct command_queue *next; + unsigned int size; +} COMMAND, *COMMAND_PTR; + +/*---------------------------------------------------------------------- + 静的関数テンプレート +----------------------------------------------------------------------*/ + +int start_linda(char *hostname); +void unix_chkserv(); +extern void psx_free(char *tuple); + +int psx_out(unsigned int id, unsigned char *data, unsigned int size); +int psx_ld(unsigned int id, char mode, void(*callback)(char *,void *),void * obj); + +#define psx_in(id) psx_ld(id, 'i', NULL, NULL) +#define psx_rd(id) psx_ld(id, 'r', NULL, NULL) +#define psx_ck(id) psx_ld(id, 'c', NULL, NULL) +#define psx_wait_rd(id) psx_ld(id, 'w', NULL, NULL) + +#define psx_callback_in(id,callback,obj) psx_ld(id, 'i', callback, obj) +#define psx_callback_rd(id,callback,obj) psx_ld(id, 'r', callback, obj) +#define psx_callback_ck(id,callback,obj) psx_ld(id, 'c', callback, obj) +#define psx_callback_wait_rd(id,callback,obj) psx_ld(id, 'w', callback, obj) + +unsigned char *psx_reply(int seq); +void psx_sync_n(); +//void psx_free(unsigned char *); +int psx_queue(unsigned int id, unsigned int size, unsigned char *data, char mode, + void(*callback)(char *,void *),void * obj); +int psx_get_datalength(unsigned char *); +unsigned char *psx_get_data(unsigned char *); +int psx_get_seq(unsigned char *); +short psx_get_id(unsigned char *); +char psx_get_mode(unsigned char *); + +int unix_open(); /* UNIX 通信を開設する */ +int unix_read(int,char *,unsigned int); /* UNIX から読み込む */ +int unix_read_w(int,char *,int); /* UNIX から読み込む(non wait) */ +int unix_write(int,unsigned char *,unsigned int);/* UNIX へ書き込む */ +int unix_write_w(int,unsigned char *,unsigned int);/* UNIX へ書き込む(non wait) */ +int send_able(); /* 読み書きできるパケット数を求める */ +