From: J. A. H. <j_...@us...> - 2002-12-31 21:30:49
|
Update of /cvsroot/slashem/slashem/win/proxy In directory sc8-pr-cvs1:/tmp/cvs-serv27698/win/proxy Modified Files: callback.c compxdr.c ext_protocol.html proxycb.c prxyconn.c Log Message: Proxy: optimize player selection query to reduce start-up delay. Index: callback.c =================================================================== RCS file: /cvsroot/slashem/slashem/win/proxy/callback.c,v retrieving revision 1.12 retrieving revision 1.13 diff -C2 -r1.12 -r1.13 *** callback.c 30 Dec 2002 20:00:26 -0000 1.12 --- callback.c 31 Dec 2002 21:30:44 -0000 1.13 *************** *** 33,37 **** static void FDECL(callback_get_player_choices, \ (unsigned short, NhExtXdr *, NhExtXdr *)); ! static void FDECL(callback_is_valid_selection, \ (unsigned short, NhExtXdr *, NhExtXdr *)); static void FDECL(callback_quit_game, \ --- 33,37 ---- static void FDECL(callback_get_player_choices, \ (unsigned short, NhExtXdr *, NhExtXdr *)); ! static void FDECL(callback_get_valid_selections, \ (unsigned short, NhExtXdr *, NhExtXdr *)); static void FDECL(callback_quit_game, \ *************** *** 309,353 **** } ! /* ! * If s is negative, then iterate i over 0 <= i < n, otherwise do just one ! * iteration at i == s. Early exit as soon as we find a valid combination. ! */ ! ! #define ITERATE(i, s, n) for((i) = (s) >= 0 ? (s) : 0; \ ! !valid && ((s) >= 0 ? (i) == (s) : (i) < (n)); \ ! (i)++) static void ! callback_is_valid_selection(id, request, reply) unsigned short id; NhExtXdr *request, *reply; { - int valid = 0; int role, race, gend, align; ! int irole, irace, igend, ialign; ! int nrole, nrace; ! nhext_rpc_params(request, 4, EXT_INT_P(role), EXT_INT_P(race), ! EXT_INT_P(gend), EXT_INT_P(align)); ! if (role < 0) ! for(nrole = 0; roles[nrole].name.m; nrole++) ! ; ! if (race < 0) ! for(nrace = 0; races[nrace].noun; nrace++) ! ; ! ITERATE(irole, role, nrole) ! if (validrole(irole)) ! ITERATE(irace, race, nrace) ! if (validrace(irole, irace)) { ! ITERATE(igend, gend, ROLE_GENDERS) ! if (validgend(irole, irace, igend)) ! valid = 1; ! ITERATE(ialign, align, ROLE_ALIGNS) ! if (validalign(irole, irace, ialign)) ! valid = 1; ! } ! nhext_rpc_params(reply, 1, EXT_INT(valid)); } ! #undef ITERATE static void --- 309,368 ---- } ! #define SKIP(n) do { \ ! i += (n) / pack; \ ! k += ((n) % pack) * ROLE_GENDERS; \ ! if (k >= pack * ROLE_GENDERS) { \ ! i++; \ ! k -= pack * ROLE_GENDERS; \ ! } \ ! } while(0) static void ! callback_get_valid_selections(id, request, reply) unsigned short id; NhExtXdr *request, *reply; { int role, race, gend, align; ! const int pack = 32 / ROLE_GENDERS; /* No. masks packed in each element */ ! int i, k; ! struct proxycb_get_valid_selections_res vs; ! for(vs.no_roles = 0; roles[vs.no_roles].name.m; vs.no_roles++) ! ; ! for(vs.no_races = 0; races[vs.no_races].noun; vs.no_races++) ! ; ! vs.no_aligns = ROLE_ALIGNS; ! vs.no_genders = ROLE_GENDERS; ! vs.n_masks = (vs.no_roles * vs.no_races * ROLE_ALIGNS + pack - 1) / pack; ! vs.masks = (unsigned long *)alloc(vs.n_masks * sizeof(unsigned long)); ! memset((genericptr_t)vs.masks, 0, vs.n_masks * sizeof(unsigned long)); ! for(role = 0, i = 0, k = 0; role < vs.no_roles; role++) ! if (!validrole(role)) ! SKIP(vs.no_races * ROLE_ALIGNS); ! else ! for(race = 0; race < vs.no_races; race++) ! if (!validrace(role, race)) ! SKIP(ROLE_ALIGNS); ! else ! for(align = 0; align < ROLE_ALIGNS; align++) { ! if (!validalign(role, race, align)) ! k += ROLE_GENDERS; ! else ! for(gend = 0; gend < ROLE_GENDERS; gend++, k++) ! if (validgend(role, race, gend)) ! vs.masks[i] |= 1L << k; ! if (k >= pack * ROLE_GENDERS) { ! i++; ! k = 0; ! } ! } ! if (i != (k ? vs.n_masks - 1 : vs.n_masks)) ! panic("callback_get_valid_selections: Bad packing (%d, %d, %d)", ! i, k, vs.n_masks); ! nhext_rpc_params(reply, 1, ! EXT_XDRF(proxycb_xdr_get_valid_selections_res, &vs)); ! free(vs.masks); } ! #undef SKIP static void *************** *** 512,516 **** EXT_CID_GET_OPTION, callback_get_option, EXT_CID_GET_PLAYER_CHOICES, callback_get_player_choices, ! EXT_CID_IS_VALID_SELECTION, callback_is_valid_selection, EXT_CID_QUIT_GAME, callback_quit_game, EXT_CID_DISPLAY_SCORE, callback_display_score, --- 527,531 ---- EXT_CID_GET_OPTION, callback_get_option, EXT_CID_GET_PLAYER_CHOICES, callback_get_player_choices, ! EXT_CID_GET_VALID_SELECTIONS, callback_get_valid_selections, EXT_CID_QUIT_GAME, callback_quit_game, EXT_CID_DISPLAY_SCORE, callback_display_score, Index: compxdr.c =================================================================== RCS file: /cvsroot/slashem/slashem/win/proxy/compxdr.c,v retrieving revision 1.10 retrieving revision 1.11 diff -C2 -r1.10 -r1.11 *** compxdr.c 29 Dec 2002 21:34:52 -0000 1.10 --- compxdr.c 31 Dec 2002 21:30:44 -0000 1.11 *************** *** 108,111 **** --- 108,123 ---- } + nhext_xdr_bool_t proxycb_xdr_get_valid_selections_res(xdr, datum) + NhExtXdr *xdr; + struct proxycb_get_valid_selections_res *datum; + { + return nhext_xdr_int(xdr, &datum->no_roles) & + nhext_xdr_int(xdr, &datum->no_races) & + nhext_xdr_int(xdr, &datum->no_aligns) & + nhext_xdr_int(xdr, &datum->no_genders) & + nhext_xdr_array(xdr, (char **)&datum->masks, &datum->n_masks, + (unsigned int)-1, sizeof(unsigned long), nhext_xdr_u_long); + } + nhext_xdr_bool_t proxycb_xdr_get_extended_commands_res(xdr, datum) NhExtXdr *xdr; Index: ext_protocol.html =================================================================== RCS file: /cvsroot/slashem/slashem/win/proxy/ext_protocol.html,v retrieving revision 1.11 retrieving revision 1.12 diff -C2 -r1.11 -r1.12 *** ext_protocol.html 29 Dec 2002 21:34:52 -0000 1.11 --- ext_protocol.html 31 Dec 2002 21:30:44 -0000 1.12 *************** *** 1031,1035 **** <tr><td>get_option</td><td>0x0A</td></tr> <tr><td>get_player_choices</td><td>0x0B</td></tr> ! <tr><td>is_valid_selection</td><td>0x0C</td></tr> <tr><td>quit_game</td><td>0x0D</td></tr> <tr><td>display_score</td><td>0x0E</td></tr> --- 1031,1035 ---- <tr><td>get_option</td><td>0x0A</td></tr> <tr><td>get_player_choices</td><td>0x0B</td></tr> ! <tr><td>get_valid_selections</td><td>0x0C</td></tr> <tr><td>quit_game</td><td>0x0D</td></tr> <tr><td>display_score</td><td>0x0E</td></tr> *************** *** 1210,1232 **** player_selection procedure can be used as indices into these arrays. ! <h3>is_valid_selction</h3> <pre> ! struct is_valid_selection_req { ! int role; ! int race; ! int gend; ! int align; ! }; ! ! struct is_valid_selection_res { ! int retval; }; </pre> ! <p>Check if the specified combination of role, race, gender and alignment ! forms a valid player selection. Any or all of role, race, gend and align ! may be passed as -1 in which case all possible values will be checked. ! ! <p>Returns 0 if the selection is invalid. <h3>quit_game</h3> --- 1210,1240 ---- player_selection procedure can be used as indices into these arrays. ! <h3>get_valid_selctions</h3> <pre> ! struct get_valid_selections_res { ! int no_roles; ! int no_races; ! int no_aligns; ! int no_genders; ! unsigned long masks<>; }; </pre> ! <p>Get a packed array of masks of combinations of role, race, gender ! and alignment which form a valid player selection. ! ! <p>When unpacked, the array contains no_roles * no_races * no_aligns ! elements each of which is a mask of the valid genders for this ! combination of role, race, alignment. If there are no valid genders ! then this mask will be zero, otherwise it will be the bitwise-OR of ! (1<<gender) for each gender that is valid. ! ! <p>The array is packed by copying no_gender bits from the next mask ! in the unpacked array into the least significant unused bits of the ! current element in the packed array (the order of bits within each ! mask is unchanged during this process). A new element in the packed ! array is started when there is not enough room for a complete mask ! to be stored (masks are not split across array elements). The final ! element in the packed array may only be partially filled. <h3>quit_game</h3> Index: proxycb.c =================================================================== RCS file: /cvsroot/slashem/slashem/win/proxy/proxycb.c,v retrieving revision 1.12 retrieving revision 1.13 diff -C2 -r1.12 -r1.13 *** proxycb.c 1 Dec 2002 17:23:38 -0000 1.12 --- proxycb.c 31 Dec 2002 21:30:44 -0000 1.13 *************** *** 161,174 **** } ! int ! proxy_cb_is_valid_selection(role, race, gender, alignment) ! int role, race, gender, alignment; { ! int retval; ! if (!nhext_rpc(EXT_CID_IS_VALID_SELECTION, ! 4, EXT_INT(role), EXT_INT(race), EXT_INT(gender), EXT_INT(alignment), ! 1, EXT_INT_P(retval))) ! retval = -1; return retval; } --- 161,236 ---- } ! struct proxycb_get_valid_selections_res * ! proxy_cb_get_valid_selections() { ! struct proxycb_get_valid_selections_res *retval; ! retval=(struct proxycb_get_valid_selections_res *)alloc(sizeof(*retval)); ! memset(retval, 0, sizeof(*retval)); ! if (!nhext_rpc(EXT_CID_GET_VALID_SELECTIONS, 0, 1, ! EXT_XDRF(proxycb_xdr_get_valid_selections_res, retval))) { ! free(retval); ! return (struct proxycb_get_valid_selections_res *)0; ! } return retval; + } + + void + proxy_cb_free_valid_selections(vs) + struct proxycb_get_valid_selections_res *vs; + { + nhext_xdr_free(proxycb_xdr_get_valid_selections_res, (char *)vs); + free(vs); + } + + static struct proxycb_get_valid_selections_res *valid_selections; + + void + proxy_cb_valid_selection_open() + { + if (!valid_selections) + valid_selections = proxy_cb_get_valid_selections(); + } + + /* + * If s is negative, then iterate i over 0 <= i < n, otherwise do just one + * iteration at i == s. Early exit as soon as we find a valid combination. + */ + + #define ITERATE(i, s, n) for((i) = (s) >= 0 ? (s) : 0; \ + !valid && ((s) >= 0 ? (i) == (s) : (i) < (n)); \ + (i)++) + + int + proxy_cb_valid_selection_check(role, race, gend, align) + int role, race, gend, align; + { + int valid = 0; + int pack; /* No. masks packed in each element */ + int i, k, n; + int irole, irace, igend, ialign; + pack = 32 / valid_selections->no_genders; + ITERATE(irole, role, valid_selections->no_roles) + ITERATE(irace, race, valid_selections->no_races) + ITERATE(ialign, align, valid_selections->no_aligns) { + n = (irole * valid_selections->no_races + irace) * + valid_selections->no_aligns + ialign; + i = n / pack; + k = (n % pack) * valid_selections->no_genders; + ITERATE(igend, gend, valid_selections->no_genders) + if (valid_selections->masks[i] & 1L << k + igend) + valid = 1; + } + return valid; + } + + #undef ITERATE + + void + proxy_cb_valid_selection_close() + { + if (valid_selections) { + proxy_cb_free_valid_selections(valid_selections); + valid_selections = (struct proxycb_get_valid_selections_res *)0; + } } Index: prxyconn.c =================================================================== RCS file: /cvsroot/slashem/slashem/win/proxy/prxyconn.c,v retrieving revision 1.2 retrieving revision 1.3 diff -C2 -r1.2 -r1.3 *** prxyconn.c 29 Dec 2002 21:31:57 -0000 1.2 --- prxyconn.c 31 Dec 2002 21:30:44 -0000 1.3 *************** *** 178,211 **** #endif /* WIN32 */ void proxy_start_server(char *prgname, void *read_h, void *write_h) { int nb; char *s; ! if (!win_proxy_svr_init(read_h, write_h)) ! panic("%s: Failed to start sub-protocol1", prgname); ! while(win_proxy_svr_iteration() >= 0) ; ! fprintf(stderr, "%s: Proxy interface failed; switching to text mode\n", ! prgname); ! /* ! * Most likely cause of failing to start the proxy interface is that ! * either the game executable we called doesn't support proxy interfaces ! * or that an error occured during initialisation. The assumption is ! * that the output from the game is actually a message intended for the ! * user. In either case, we are best to retrieve the failed packet from ! * the nhext module and display it. Then we can connect the games's ! * standard I/O to the user for them to interpret and take appropriate ! * action. ! */ ! s = win_proxy_svr_get_failed_packet(&nb); ! if (s) ! write(1, s, nb); ! connect_pipe(read_h, write_h); } #ifdef WIN32 ! static void proxy_connect_file(char *address, int *argcp, char **argv) { --- 178,222 ---- #endif /* WIN32 */ + static int exit_server; + void + proxy_exit_server() + { + exit_server = 1; + } + + int proxy_start_server(char *prgname, void *read_h, void *write_h) { int nb; char *s; ! if (!win_proxy_svr_init(read_h, write_h)) { ! fprintf(stderr, "%s: Proxy interface failed; switching to text mode\n", ! prgname); ! /* ! * Most likely cause of failing to start the proxy interface is that ! * either the game executable we called doesn't support proxy interfaces ! * or that an error occured during initialisation. The assumption is ! * that the output from the game is actually a message intended for the ! * user. In either case, we are best to retrieve the failed packet from ! * the nhext module and display it. Then we can connect the games's ! * standard I/O to the user for them to interpret and take appropriate ! * action. ! */ ! s = win_proxy_svr_get_failed_packet(&nb); ! if (s) ! write(1, s, nb); ! connect_pipe(read_h, write_h); ! return 1; ! } ! exit_server = 0; ! while(win_proxy_svr_iteration() >= 0 && !exit_server) ; ! return 0; } #ifdef WIN32 ! static int proxy_connect_file(char *address, int *argcp, char **argv) { *************** *** 221,264 **** if (!pipe_create(to_game_h, 1) || !pipe_create(from_game_h, 0)) { fprintf(stderr, "%s: Failed to create pipes\n", argv[0]); ! return; } save_stdin = dup_osf(0); if (save_stdin == INVALID_HANDLE_VALUE) { fprintf(stderr, "%s: Failed to save stdin\n", argv[0]); ! return; } if (!redirect_to_osf(STD_INPUT_HANDLE, to_game_h[0])) { fprintf(stderr, "%s: Failed to redirect stdin\n", argv[0]); ! return; } save_stdout = dup_osf(1); if (save_stdout == INVALID_HANDLE_VALUE) { fprintf(stderr, "%s: Failed to save stdout\n", argv[0]); ! return; } if (!redirect_to_osf(STD_OUTPUT_HANDLE, from_game_h[1])) { fprintf(stderr, "%s: Failed to redirect stdout\n", argv[0]); ! return; } pid = spawnv(P_NOWAIT, nargv[0], nargv); if (pid < 0) { perror(nargv[0]); ! return; } free(nargv); if (!redirect_to_osf(STD_INPUT_HANDLE, save_stdin)) { fprintf(stderr, "%s: Failed to restore stdin\n", argv[0]); ! return; } if (!redirect_to_osf(STD_OUTPUT_HANDLE, save_stdout)) { fprintf(stderr, "%s: Failed to restore stdout\n", argv[0]); ! return; } ! proxy_start_server(argv[0], (void *)from_game_h[0], (void *)to_game_h[1]); } #else /* WIN32 */ ! static void proxy_connect_file(char *address, int *argcp, char **argv) { --- 232,276 ---- if (!pipe_create(to_game_h, 1) || !pipe_create(from_game_h, 0)) { fprintf(stderr, "%s: Failed to create pipes\n", argv[0]); ! return 1; } save_stdin = dup_osf(0); if (save_stdin == INVALID_HANDLE_VALUE) { fprintf(stderr, "%s: Failed to save stdin\n", argv[0]); ! return 1; } if (!redirect_to_osf(STD_INPUT_HANDLE, to_game_h[0])) { fprintf(stderr, "%s: Failed to redirect stdin\n", argv[0]); ! return 1; } save_stdout = dup_osf(1); if (save_stdout == INVALID_HANDLE_VALUE) { fprintf(stderr, "%s: Failed to save stdout\n", argv[0]); ! return 1; } if (!redirect_to_osf(STD_OUTPUT_HANDLE, from_game_h[1])) { fprintf(stderr, "%s: Failed to redirect stdout\n", argv[0]); ! return 1; } pid = spawnv(P_NOWAIT, nargv[0], nargv); if (pid < 0) { perror(nargv[0]); ! return 1; } free(nargv); if (!redirect_to_osf(STD_INPUT_HANDLE, save_stdin)) { fprintf(stderr, "%s: Failed to restore stdin\n", argv[0]); ! return 1; } if (!redirect_to_osf(STD_OUTPUT_HANDLE, save_stdout)) { fprintf(stderr, "%s: Failed to restore stdout\n", argv[0]); ! return 1; } ! return proxy_start_server(argv[0], (void *)from_game_h[0], ! (void *)to_game_h[1]); } #else /* WIN32 */ ! static int proxy_connect_file(char *address, int *argcp, char **argv) { *************** *** 285,295 **** close(to_game[0]); close(from_game[1]); ! proxy_start_server(argv[0], (void *)from_game[0], (void *)to_game[1]); } } #endif /* WIN32 */ ! static void proxy_connect_tcp(char *address, char *prgname) { --- 297,310 ---- close(to_game[0]); close(from_game[1]); ! return proxy_start_server(argv[0], (void *)from_game[0], ! (void *)to_game[1]); } + /*NOTREACHED*/ + return 1; } #endif /* WIN32 */ ! static int proxy_connect_tcp(char *address, char *prgname) { *************** *** 342,346 **** } free(s); ! proxy_start_server(prgname, (void *)skt, (void *)skt); } --- 357,361 ---- } free(s); ! return proxy_start_server(prgname, (void *)skt, (void *)skt); } *************** *** 354,365 **** */ ! void proxy_connect(char *scheme, char *address, int *argcp, char **argv) { if (!strcmp(scheme, "file")) ! proxy_connect_file(address, argcp, argv); else if (!strcmp(scheme, "tcp")) ! proxy_connect_tcp(address, argv[0]); else panic("proxy_connect: Unsupported scheme: %s", scheme); } --- 369,382 ---- */ ! int proxy_connect(char *scheme, char *address, int *argcp, char **argv) { if (!strcmp(scheme, "file")) ! return proxy_connect_file(address, argcp, argv); else if (!strcmp(scheme, "tcp")) ! return proxy_connect_tcp(address, argv[0]); else panic("proxy_connect: Unsupported scheme: %s", scheme); + /*NOTREACHED*/ + return 1; } |