Inter-process communication (8)

Source: Internet
Author: User

Search databases

Searching on the CD keyword is complex. Function users want to start a search once called. In Chapter 7th, we set * first_call_ptr on the first call to true and the function returns the first matching result to meet this requirement. In the next search function call, * Set first_call_ptr to false to return more matches. Each call returns a matching result.

Now we have divided the program into two processes. We can no longer search for an entity at a time on the server, because another client may request a different search by the server, however, our search is still being processed. We cannot make the server store the search content separately for each client (where the search has been done), because when a user finds the key value of the CD they are looking for or the client encounters a problem, the client can simply stop searching.

We can also change the method of search execution, or, as we have chosen here, hide complexity in interface routines. What we do is to make the server return all possible search matches and store them in a temporary file until the client requests them.

Test-search

1 This function is more complex, because it calls the three pipeline functions we will discuss in the next section: send_mess_to_server, start_resp_from_server and read_resp_from_server.

Cdc_entry search_cdc_entry (const char * cd_catalog_ptr, int * first_call_ptr)
{
Message_db_t mess_send;
Message_db_t mess_ret;
Static file * work_file = (File *) 0;
Static int entries_matching = 0;
Cdc_entry ret_val;
Ret_val.catalog [0] = '/0 ';
If (! Work_file & (* first_call_ptr = 0) Return (ret_val );

2. The first call to search is shown below. Here * first_call_ptr is set to true. To prevent us from forgetting, set it to false immediately. Create a work_file in this function and initialize the client message structure.

If (* first_call_ptr ){
* First_call_ptr = 0;
If (work_file) fclose (work_file );
Work_file = tmpfile ();
If (! Work_file) Return (ret_val );
Mess_send.client_pid = mypid;
Mess_send.request = s_find_cdc_entry;
Strcpy (mess_send.cdc_entry_data.catalog, cd_catalog_ptr );

3. Next is a three-tier conditional test. If a message is successfully sent to the server, the client waits for the response from the server. When the server's read operation is successful, search matching will be recorded in work_file, and the corresponding entries_matching will also increase.

If (send_mess_to_server (mess_send )){
If (start_resp_from_server ()){
While (read_resp_from_server (& mess_ret )){
If (mess_ret.response = r_success ){
Fwrite (& mess_ret.cdc_entry_data, sizeof (cdc_entry), 1, work_file );
Entries_matching ++;
} Else {
Break;
}
}/* While */
} Else {
Fprintf (stderr, "server not responding/N ");
}
} Else {
Fprintf (stderr, "server not accepting requests/N ");
}

4. The following test checks whether the search is successful. Then, the fseek call sets work_file to the next location where data is to be written.

If (entries_matching = 0 ){
Fclose (work_file );
Work_file = (File *) 0;
Return (ret_val );
}
(Void) fseek (work_file, 0l, seek_set );

5. If this is not the first time you use a specific search mode to call a search function, the following code checks whether there are any remaining matches. Finally, the next match will be read into the ret_val structure. The previous check considers that there is a matching item.

} Else {
/* Not * first_call_ptr */
If (entries_matching = 0 ){
Fclose (work_file );
Work_file = (File *) 0;
Return (ret_val );
}
}
Fread (& ret_val, sizeof (cdc_entry), 1, work_file );
Entries_matching -;
Return (ret_val );
}

Server Interface

Just as the client has an interface for the app_ui.c program, the server also needs a program to control (rename) cd_access.c. Now it is cd_dbm.c. The main function of the server is as follows.

Test -- server. c

1. At the beginning of the program, we declared several global variables, a prototype of the process_command function, and a signal capture function to ensure a clean exit.

# Include <unistd. h>
# Include <stdlib. h>
# Include <stdio. h>
# Include <fcntl. h>
# Include <limits. h>
# Include <signal. h>
# Include <string. h>
# Include <errno. h>
# Include <sys/types. h>
# Include <sys/STAT. h>
# Include "cd_data.h"
# Include "cliserv. h"
Int save_errno;
Static int server_running = 1;
Static void process_command (const message_db_t mess_command );
Void catch_signals ()
{
Server_running = 0;
}

2. Now let's take a look at the main function. After the detection signal capture routine is correct, the program checks whether a-I option is passed in the command line. If it is passed, the program will create a new database. If the database_initialize routine in cd_dbm.c fails, an error message is displayed. If everything is normal and the server is running, requests from the client will be passed to the process_command function. We will introduce this function later.

Int main (INT argc, char * argv []) {
Struct sigaction new_action, old_action;
Message_db_t mess_command;
Int database_init_type = 0;
New_action.sa_handler = catch_signals;
Sigemptyset (& new_action.sa_mask );
New_action.sa_flags = 0;
If (sigaction (SIGINT, & new_action, & old_action )! = 0) |
(Sigaction (sighup, & new_action, & old_action )! = 0) |
(Sigaction (sigterm, & new_action, & old_action )! = 0 )){
Fprintf (stderr, "server startup error, signal catching failed/N ");
Exit (exit_failure );
}
If (argc> 1 ){
Argv ++;
If (strncmp ("-I", * argv, 2) = 0) database_init_type = 1;
}
If (! Database_initialize (database_init_type )){
Fprintf (stderr, "server error :-/
Cocould not initialize database/N ");
Exit (exit_failure );
}
If (! Server_starting () Exit (exit_failure );
While (server_running ){
If (read_request_from_client (& mess_command )){
Process_command (mess_command );
} Else {
If (server_running) fprintf (stderr, "server ended-Can not/
Read pipe/N ");
Server_running = 0;
}
}/* While */
Server_ending ();
Exit (exit_success );
}

3. All client messages will be passed to the process_command function, where they will be passed to a case statement to execute the correct call in cd_dbm.c.

Static void process_command (const message_db_t comm)
{
Message_db_t resp;
Int first_time = 1;
Resp = comm;/* Copy command back, then change resp as required */
If (! Start_resp_to_client (RESP )){
Fprintf (stderr, "server warning :-/
Start_resp_to_client % d failed/N ", resp. client_pid );
Return;
}
Resp. Response = r_success;
Memset (resp. error_text, '/0', sizeof (resp. error_text ));
Save_errno = 0;
Switch (resp. Request ){
Case s_create_new_database:
If (! Database_initialize (1) resp. Response = r_failure;
Break;
Case s_get_cdc_entry:
Resp. cdc_entry_data =
Get_cdc_entry (Comm. cdc_entry_data.catalog );
Break;
Case s_get_cdt_entry:
Resp. cdt_entry_data =
Get_cdt_entry (Comm. cdt_entry_data.catalog,
Comm. cdt_entry_data.track_no );
Break;
Case s_add_cdc_entry:
If (! Add_cdc_entry (Comm. cdc_entry_data) resp. Response =
R_failure;
Break;
Case s_add_cdt_entry:
If (! Add_cdt_entry (Comm. cdt_entry_data) resp. Response =
R_failure;
Break;
Case s_del_cdc_entry:
If (! Del_cdc_entry (Comm. cdc_entry_data.catalog) resp. Response
= R_failure;
Break;
Case s_del_cdt_entry:
If (! Del_cdt_entry (Comm. cdt_entry_data.catalog,
Comm. cdt_entry_data.track_no) resp. Response = r_failure;
Break;
Case s_find_cdc_entry:
Do {
Resp. cdc_entry_data =
Search_cdc_entry (Comm. cdc_entry_data.catalog,
& First_time );
If (resp. cdc_entry_data.catalog [0]! = 0 ){
Resp. Response = r_success;
If (! Send_resp_to_client (RESP )){
Fprintf (stderr, "server warning :-/
Failed to respond to % d/N ", resp. client_pid );
Break;
}
} Else {
Resp. Response = r_find_no_more;
}
} While (resp. Response = r_success );
Break;
Default:
Resp. Response = r_failure;
Break;
}/* Switch */
Sprintf (resp. error_text, "command failed:/n/T % s/n ",
Strerror (save_errno ));
If (! Send_resp_to_client (RESP )){
Fprintf (stderr, "server warning :-/
Failed to respond to % d/N ", resp. client_pid );
}
End_resp_to_client ();
Return;
}

Before learning about the actual pipeline implementation, let's discuss the sequence of events that need to occur when data is transmitted between client and server processes. Figure 13-9 shows the client and server processes started and how the two sides cyclically process commands and responses.

In this implementation, the situation has some difficulties, because for a search request, the client sends a single command to the server and then wants the server to receive one or more responses. This causes other extra complexity, mainly on the client.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.