package Client; use strict; #===========================================================# # NOTE: Users of this package (the main package) are # # required to implement two routines: # # rcvd_msg_from_server ($serverConn, $msg, $err) = @_; # # which is called as a default server message handler # # if blocking reply code is not supplied after a given# # message is sent to a server. # # prompt (no parameters) # # which is called on the main package after processing# # a local request (one not sent to a socket server) # #===========================================================# #-----------------------------------------------# # INITIAL SETUP # #-----------------------------------------------# BEGIN { use Exporter(); our ($VERSION, @ISA, @EXPORT, @EXPORT_OK, %EXPORT_TAGS); # $VERSION=1.00; # if using RCS/CVS, this may be preferred # must be all one line, for MakeMaker $VERSION = do { my @r = (q$Revision: 1.53 $ =~ /\d+/g); sprintf "%d."."%02d" x $#r, @r }; @ISA = qw(Exporter); @EXPORT = qw($col_delim); %EXPORT_TAGS = (); # your exported package globals go here, # as well as any optionally exported functions @EXPORT_OK = (); } use Msg; our $col_delim; $col_delim = pack("c",29); # nonalphanumeric column data separator my $ssn = 0; # session number; overridden if passed in URL # otherwise obtained new from Cacher my $temp_ssn = 0; my $retrieve_timeout = 60; my $test_mode = 1; my ($Cconn); my (%cmd_dest) = ( "strc" => "c", "strp" => "c", "retc" => "c", "retp" => "c", "delc" => "c", "delp" => "c", "listc" => "c", "ccount" => "c", "cdata" => "c", "strq" => "c", "retq" => "c", "delq" => "c", "getq" => "c", "listfifo" => "c", "listq" => "c", "findq" => "c", "flushq" => "c", "qcount" => "c", "getcto" => "c", "setcto" => "c", "getqmax" => "c", "getcmax" => "c", "newssn" => "c", "getmaxssn" => "c", "setmaxssn" => "c", "savedata" => "c", "killc" => "c", # kill cacher to test die reporting "testmode" => "l", "getssn" => "l", "setssn" => "l", "grepc" => "l", "help" => "l", "close" => "l", "execsql" => "l", "alterssn" => "l", "resssn" => "l", "setdbalias" => "l", "setdefaultdbalias" => "l", "getdbaliases" => "l", "getdefaultdbalias" => "l", "getrestricts" => "l", "monitorsql" => "l", ); # c : Cacher # l : Local my (%cmd_help) = ( "strc" => "Store Client Data (strc:42)", "strp" => "Store Client Data at Checkpoint (strp:ALPHA:42)", "retc" => "Retrieve Client Data (retc)", "retp" => "Retrieve Client Data from Checkpoint (retp:ALPHA)", "grepc" => "grep for pattern in client data", "delc" => "Delete Client Data for Client (delc:1)", "delp" => "Delete Checkpoint for Client (delp:1:ALPHA)", "resssn" => "Restore Client ID (resc)", "listc" => "List Clients (listc)", "ccount" => "Client Count (ccount)", "cdata" => "Client Data (cdata:1)", "strq" => "Store Query (strq:select distinct...)", "retq" => "Retrieve Query (retq:select distinct...)", "delq" => "Delete Query (delq:select distinct...)", "getq" => "Get Query by number (getq:1)", "listfifo" => "List contents of query list (listfifo)", "listq" => "List Queries (listq)", "findq" => "Find Query (same as retq ???)", "flushq" => "Flush Queries (flushq)", "qcount" => "Query Count (qcount)", "testmode" => "Test Mode (testmode:on/off)", "getcto" => "Get Client Time-Out (getcto)", "setcto" => "Set Client Time-Out in seconds (setcto:1800)", "getqmax" => "Get Max-Size for Query Storage in KB (getqmax)", "setqmax" => "Set Max-Size for Query Storage in KB (setqmax:65000)", "getcmax" => "Get Max-Size for Client Data Storage in KB (getcmax)", "setcmax" => "Set Max-Size for Client Data Storage in KB (setcmax:65000)", "alterssn" => "Temporarily change the Client ID (alterssn:10)", "setssn" => "Permanently change the Client ID (setssn:10)", "newssn" => "Create a new Client ID for this session (newssn)", "savedata" => "Save Cached client data to specified file (savedata:filename)", "killc" => "Kill Cacher (for test of crash reporting)", "help" => "List Available Commands (help)", "close" => "Close Client (close)", "getssn" => "Get Client ID (getssn)", ); # open (LOG,">Client.log") or die "Can't open Client.log for writing\n"; #============================================================== sub make_socket_connections { #-----------------------------------# # Connect to CACHER # #-----------------------------------# $Cconn = Msg->connect('localhost', 8190, \&::rcvd_msg_from_server); if (!$Cconn) { print q/ Web Server Error: Could not connect to Cacher process.
Please inform Jeffrey Hook (jeffhook@essentialbits.com) (650) 269-7231 /; die; } my $ack = receive_msg($Cconn); testprint ("$ack\n"); } #=============================================================== sub close_socket_connections { my $cmd = "close"; send_cmd($Cconn,$cmd); # ... and don't bother waiting for the replies ... } #=============================================================== sub delete_cached_client_data { send_cmd($Cconn,"delc"); my $ack = receive_msg($Cconn); } #=============================================================== sub flushq # clear Cacher of query cache { send_cmd($Cconn,"flushq"); my $ack = receive_msg($Cconn); return($ack); } #=============================================================== sub kbd_input { } #====================================================== sub send_cmd { my ($conn, $cmd) = @_; if ($conn == $Cconn) { if ($temp_ssn == 0) { $conn->send_now("$ssn$;$cmd"); } else { $conn->send_now("$temp_ssn$;$cmd"); } } else { $conn->send_now($cmd); } } #===================================================== sub receive_msg { my ($conn) = @_; my ($timeout); if ($conn == $Cconn) { $timeout = $retrieve_timeout; } else { $timeout = 10; } my ($msg, $err) = $conn->rcv_with_timeout($conn,$timeout); print STDERR "Client receive_msg error: $err\n" if length($err); return wantarray ? ($msg,$err) : $msg; } #====================================================== sub create_ssn { send_cmd($Cconn,"newssn"); my ($cmd,$msg) = split("$;",receive_msg($Cconn),2); $ssn = $msg; } #====================================================== sub set_ssn { my ($newssn) = @_; $ssn = $newssn; $temp_ssn = 0; } #====================================================== sub store_client_data { my ($data) = @_; send_cmd($Cconn,"strc" . "$;" . $data); # receive acknowledgement of the store from Cacher my ($cmd,$msg) = split("$;",receive_msg($Cconn),2); die "Expecting 'strc' from Cacher.\n" unless $cmd eq "strc"; } #====================================================== sub store_client_data_cp # Stores client data in a checkpoint. { my ($checkpoint, $data) = @_; send_cmd($Cconn,"strp" . "$;" . $checkpoint . ":" . $data); # receive acknowledgement of the store from Cacher my ($cmd,$msg) = split("$;",receive_msg($Cconn),2); die "Expecting 'strp' from Cacher.\n" unless $cmd eq "strp"; } #====================================================== sub retrieve_client_data { send_cmd($Cconn,"retc"); my ($msg) = receive_msg($Cconn); my ($cmd,$data) = split("$;",$msg,2); return $data; } #====================================================== sub retrieve_client_data_cp # Retrieves client data from a checkpoint. { my ($checkpoint) = @_; send_cmd($Cconn,"retp$;$checkpoint"); my ($msg) = receive_msg($Cconn); my ($cmd,$data) = split("$;",$msg,2); return $data; } #====================================================== sub store_to_query_cache { # my ($query,$dbalias,$query_results) = @_; my @args = @_; unshift (@args,"strq"); # add command; send_cmd($Cconn,join($;,@args)); # receive acknowledgement of the store from Cacher my ($cmd,$msg) = split("$;",receive_msg($Cconn),2); die "Expecting 'strq' from Cacher\n" unless $cmd eq "strq"; } #====================================================== sub retrieve_cached_query { # my ($query,$dbalias) = @_; my @args = @_; unshift (@args,"retq"); # add command send_cmd($Cconn,join($;,@args)); my ($msg) = receive_msg($Cconn); my ($cmd,$query_results) = split("$;",$msg,2); return $query_results; } #====================================================== sub testmode_on { $test_mode = 1; print "Test Mode is ON.\n"; } #====================================================== sub testmode_off { $test_mode = 0; print "Test Mode is OFF.\n"; } #====================================================== sub send_to_server # this routine to be used only by TestClient.pl { Msg::time_check("Client Begin"); my ($cmd,$data) = @_; my ($connection, $results); if ($cmd_dest{$cmd} eq "c") { send_cmd($Cconn,$cmd . $; . $data); # rcvd_msg_from_server handles response } elsif ($cmd_dest{$cmd} eq "l") { execute_local_cmd($cmd,$data); } else # Unknown destination, aborting. { testprint ("Unknown destination for command. Not processed.\n"); &::prompt(); } Msg::time_check("Client End"); } #====================================================== sub execute_local_cmd { my ($cmd, $data) = @_; if ($cmd =~ /^testmode/i) { if ($data =~ /^on/i) { testmode_on(); } elsif ($data =~ /^off/i) { testmode_off(); } } elsif ($cmd =~ /^help/i) { if ($test_mode) { print ("\nAVAILABLE COMMANDS:\n"); my ($key); foreach $key (sort keys %cmd_help) { print ("$key: $cmd_help{$key}\n"); } } } elsif ($cmd =~ /^getssn/i) { if ($temp_ssn == 0) { print ("Client ID: $ssn."); } else { print ("Client ID: $temp_ssn."); } } elsif ($cmd =~ /^setssn/i) { $ssn = $data; } elsif ($cmd =~ /^getmsgto/i) { print ("Message Timeout: $retrieve_timeout seconds."); } elsif ($cmd =~ /^setmsgto/i) { $retrieve_timeout = $data; } elsif ($cmd =~ /^grepc/i) { my $pattern = $data; my $cldata = retrieve_client_data(); my @cldata = split("\n",$cldata); my @results = grep /$pattern/,@cldata; my $reply = join("\n",@results); testprint ("Reply: \n" . $reply); } elsif ($cmd =~ /^execsql/i) { my ($querytype, $query,$dbalias) = split(":",$data,3); Msg::time_check("execute_sql begin"); my $reply = execute_sql($querytype,$query,$dbalias); testprint ("Reply: \n" . $reply); Msg::time_check("execute_sql end"); } elsif ($cmd =~ /^close/i) { close_socket_connections(); exit; } elsif ($cmd =~ /^setssn/i) { $temp_ssn = $data; testprint ("Client ID has temporarily been set to $temp_ssn."); } elsif ($cmd =~ /^resssn/i) { $temp_ssn = 0; testprint ("Client ID has been restored to $ssn."); } &::prompt(); } #====================================================== sub testprint { my ($text) = @_; if ($test_mode) { $text =~ s/$::col_delim/ \| /g; $text =~ s/$;/\n/g; print STDERR $text; } } #====================================================== 1;