Ignore generated files

Remove the checkpoint from the client - it is not the goal of this example
Fix the XML descriptions
Add a header for definitions common to the client and the master
Make the master periodically send messages until the result is received


git-svn-id: svn+ssh://cvs.lpds.sztaki.hu/var/lib/svn/szdg/dcapi/trunk@804 a7169a2c-3604-0410-bc95-c702d8d87f7a
This commit is contained in:
gombasg 2006-07-07 14:04:39 +00:00 committed by Adam Visegradi
parent 95a98aebae
commit 9948e538b5
6 changed files with 85 additions and 171 deletions

View File

@ -18,11 +18,11 @@ endif
CLEANFILES = message-example-client.xml message-example-master.xml
message_example_client_SOURCES = client.c
message_example_client_SOURCES = client.c common.h
message_example_client_CPPFLAGS = $(DCAPI_CLIENT_CFLAGS)
message_example_client_LDADD = $(DCAPI_CLIENT_LIBS)
message_example_master_SOURCES = master.c
message_example_master_SOURCES = master.c common.h
message_example_master_CPPFLAGS = $(DCAPI_MASTER_CFLAGS)
message_example_master_LDADD = $(DCAPI_MASTER_LIBS)

View File

@ -1,3 +1,7 @@
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <dc_client.h>
#include <unistd.h>
@ -5,80 +9,27 @@
#include <stdio.h>
#include <ctype.h>
/* The logical file names, used at sequencial application */
#define INPUT_NAME "in.txt"
#define OUTPUT_NAME "out.txt"
#include "common.h"
static FILE *infile;
static FILE *outfile;
/* Needed to report the percentage of the work already done */
static int frac_total_size;
static int frac_current_pos;
static int message_has_arrived = 0;
/* Save the value of frac_current_pos to the ckpt file */
static void do_checkpoint(void)
{
char *ckptfile_name;
FILE *ckptfile;
int retval;
/* Ensure that the output file is really on the disk before we create
* the checkpoint file */
retval = fflush(outfile);
if (retval)
{
perror("APP: flushing the output file has failed");
DC_finishClient(1);
}
ckptfile_name = DC_resolveFileName(DC_FILE_OUT, DC_CHECKPOINT_FILE);
if (!ckptfile_name)
{
fprintf(stderr, "APP: Could not resolve the checkpoint file "
"name\n");
DC_finishClient(1);
}
ckptfile = fopen(ckptfile_name, "w");
if (!ckptfile)
{
perror("APP: Could not create the checkpoint file");
DC_finishClient(1);
}
fprintf(ckptfile, "%d", frac_current_pos);
retval = fclose(ckptfile);
if (retval)
{
perror("APP: Closing the checkpoint file has failed");
DC_finishClient(1);
}
/* Tell the DC-API that the checkpoint is ready */
DC_checkpointMade(ckptfile_name);
/* Update the estimation about the work done */
DC_fractionDone(frac_current_pos/frac_total_size);
}
static int messages_received;
/* Open input and output files, and check is there is a checkpoint file */
static void init_files(void)
{
const char *outfile_openmode = "w";
char *file_name;
/* Open the input file */
file_name = DC_resolveFileName(DC_FILE_IN, INPUT_NAME);
file_name = DC_resolveFileName(DC_FILE_IN, INPUT_LABEL);
if (!file_name)
{
fprintf(stderr, "APP: Could not resolve the input file name\n");
DC_finishClient(1);
}
infile = fopen(file_name, "rb");
infile = fopen(file_name, "r");
if (!infile)
{
perror("APP: Could not open the input file");
@ -86,80 +37,38 @@ static void init_files(void)
}
free(file_name);
/* Determine the size of the input file */
fseek(infile, 0, SEEK_END);
frac_total_size = ftell(infile);
fseek(infile, 0, SEEK_SET);
/* Check the checkpoint file */
file_name = DC_resolveFileName(DC_FILE_IN, DC_CHECKPOINT_FILE);
if (file_name)
{
FILE *ckptfile;
int ret;
ckptfile = fopen(file_name, "r");
if (!ckptfile)
{
perror("APP: Could not open the initial checkpoint file");
DC_finishClient(1);
}
free(file_name);
/* ckpt file exists: read and set everything according to it */
ret = fscanf(ckptfile, "%d", &frac_current_pos);
if (ret != 1 || frac_current_pos < 0 ||
frac_current_pos > frac_total_size)
{
fprintf(stderr, "APP: Failed to parse the contents of "
"the checkpoint file, starting from the "
"beginning\n");
frac_current_pos = 0;
}
else
{
fprintf(stderr, "APP: Found checkpoint file, starting "
"from position %d.\n", frac_current_pos);
outfile_openmode = "r+";
}
fclose(ckptfile);
fseek(infile, frac_current_pos, SEEK_SET);
}
/* Open the output file */
file_name = DC_resolveFileName(DC_FILE_OUT, OUTPUT_NAME);
file_name = DC_resolveFileName(DC_FILE_OUT, OUTPUT_LABEL);
if (!file_name)
{
fprintf(stderr, "APP: Could not resolve the output file name\n");
DC_finishClient(1);
}
outfile = fopen(file_name, outfile_openmode);
outfile = fopen(file_name, "w");
if (!outfile)
{
perror("APP: Could not open/create the output file");
DC_finishClient(1);
}
free(file_name);
/* If we are starting from a checkpoint file, restore the state of
* the output file as well */
ftruncate(fileno(outfile), frac_current_pos);
fseek(outfile, 0, SEEK_END);
}
static void message_arrived(char *message)
static void message_arrived(const char *message)
{
fprintf(stderr, "APP: message: '%s' arrived\n", message);
DC_sendMessage("This is a sample reply message");
fprintf(stderr, "APP: message: 'This is a sample reply message' sent\n");
message_has_arrived = 1;
char reply[256];
fprintf(stderr, "APP: message: '%s' arrived, sending reply\n", message);
snprintf(reply, sizeof(reply), "Reply to: %s", message);
DC_sendMessage(reply);
messages_received++;
}
/* The real work */
static void do_work(void)
{
char buf[32];
int c;
while ((c = fgetc(infile)) != EOF)
@ -172,11 +81,16 @@ static void do_work(void)
perror("APP: fputc");
DC_finishClient(1);
}
frac_current_pos++;
/* Send the just-converted character to the master. This in
* turn also allows receiving messages from the master */
snprintf(buf, sizeof(buf), "Processed %c", c);
DC_sendMessage(buf);
/* Real applications do real computation that takes time. Here
* we just emulate it */
sleep(5);
* we just emulate it. We sleep for a long time to prevent
* sending messages too often. */
sleep(30);
/* Check if either the master or the BOINC core client asked
* us to do something */
@ -184,11 +98,12 @@ static void do_work(void)
if (!event)
continue;
/* If it is time, do a checkpoint */
if (event->type == DC_CLIENT_CHECKPOINT)
do_checkpoint();
if (event->type == DC_CLIENT_MESSAGE)
{
DC_log(LOG_INFO, "Checkpoint request received");
DC_checkpointMade(NULL);
}
else if (event->type == DC_CLIENT_MESSAGE)
message_arrived(event->message);
/* Make sure we do not leak memory */
@ -213,14 +128,14 @@ int main(int argc, char *argv[])
"value was %d\n", retval);
DC_finishClient(1);
}
fprintf(stderr, "APP: DC-API initialization was successful.\n");
fprintf(stdout, "APP: DC-API initialization was successful.\n");
init_files();
do_work();
fprintf(stderr, "APP: Work finished.\n");
if (!message_has_arrived)
fprintf(stderr, "APP: Hasn't receaved any message from the master !!!\n");
do_work();
fprintf(stdout, "APP: Work finished. Received %d messages from the "
"master.\n", messages_received);
DC_finishClient(0);
return(0); // Tho' we never reach this line
@ -230,13 +145,11 @@ int main(int argc, char *argv[])
int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrevInst, LPSTR Args, int WinMode)
{
LPSTR command_line;
char* argv[100];
char *argv[100];
int argc;
command_line = GetCommandLine();
argc = parse_command_line( command_line, argv );
argc = parse_command_line(command_line, argv);
return main(argc, argv);
}
#endif

View File

@ -0,0 +1,12 @@
/*
* Common definitions used by both the master and the client
*/
#ifndef COMMON_H
#define COMMON_H
/* Logical names of the input/output files */
#define INPUT_LABEL "in.txt"
#define OUTPUT_LABEL "out.txt"
#endif /* COMMON_H */

View File

@ -20,6 +20,10 @@
*
*****************************************************/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <dc.h>
#include <stdlib.h>
@ -29,13 +33,7 @@
#include <stdio.h>
#include <errno.h>
#define INPUT_LABEL "in.txt"
#define OUTPUT_LABEL "out.txt"
/* Number of WUs we have created */
static int created_wus;
/* Number of results we have received so far */
static int processed_wus;
#include "common.h"
/* Command line options */
static const struct option longopts[] =
@ -45,27 +43,22 @@ static const struct option longopts[] =
{ NULL }
};
static int do_exit;
static void process_result(DC_Workunit *wu, DC_Result *result)
{
char *tag;
/* Internal housekeeping of the number of results we have seen */
processed_wus++;
/* Extract our own private identifier */
tag = DC_getWUTag(wu);
DC_log(LOG_NOTICE, "Work unit %s has completed", tag);
/* We no longer need the work unit */
DC_destroyWU(wu);
free(tag);
}
static void process_subresult(DC_Workunit *wu, const char *logicalFileName, const char *path)
{
/* There is no subresult in this example */
/* This will cause the main loop to quit */
do_exit = 1;
}
static void process_message(DC_Workunit *wu, const char *message)
@ -78,9 +71,8 @@ static void process_message(DC_Workunit *wu, const char *message)
free(tag);
}
static void create_work(void)
static DC_Workunit *create_work(void)
{
char ch;
DC_Workunit *wu;
wu = DC_createWU("message-example", NULL, 0, "message-test");
@ -108,12 +100,7 @@ static void create_work(void)
exit(1);
}
created_wus++;
printf("Press ENTER, after this WU is downloaded by a BOINC client");
ch = getchar();
DC_sendWUMessage(wu, "This is a test message");
return wu;
}
static void print_help(const char *prog) __attribute__((noreturn));
@ -136,6 +123,7 @@ static void print_help(const char *prog)
int main(int argc, char *argv[])
{
char *config_file = NULL;
DC_Workunit *wu;
int c;
while ((c = getopt_long(argc, argv, "ch", longopts, NULL)) != -1)
@ -174,17 +162,23 @@ int main(int argc, char *argv[])
exit(1);
}
/* We need the result callback function only */
DC_setMasterCb(process_result, process_subresult, process_message);
/* Set the callbacks for receiving messages & the result */
DC_setMasterCb(process_result, NULL, process_message);
DC_log(LOG_NOTICE, "Master: Creating work unit");
create_work();
wu = create_work();
DC_log(LOG_NOTICE, "Master: Work unit has been created. Waiting "
"for result/message ...\n");
"for result/message");
/* Wait for the work units to finish */
while (processed_wus < created_wus)
DC_processMasterEvents(600);
while (!do_exit)
{
DC_processMasterEvents(60);
/* The result processing destroys the WU, so make sure we
* only try to send a message if the WU is still alive */
if (!do_exit)
DC_sendWUMessage(wu, "What's up?");
}
return 0;
}

View File

@ -1,10 +1,10 @@
<?xml version="1.0" standalone="no"?>
<client>
<!-- Application name -->
<name>uppercase-example</name>
<name>message-example</name>
<!-- User-friendly name for Boinc -->
<user_friendly_name>Uppercase Example Application with callback functions</user_friendly_name>
<user_friendly_name>Messaging example</user_friendly_name>
<!-- Application version. Boinc requirements:
- The version number must contain two components (major.minor)
@ -19,14 +19,9 @@
<!-- The name of the main client binary. It will be
automatically renamed to the name expected by Boinc -->
<binary>uppercase-example-client</binary>
<!-- Signature of the main binary, if the code signing key
is not present at the machine running the project -->
<!-- <signarute>@appdir@/search.sig</signature> -->
<binary>message-example-client</binary>
<!-- Additional files can also be installed -->
<!-- <lib>winlib.dll</lib> -->
<!-- <lib>winlib.dll.sig</lib> -->
</platform>
</client>

View File

@ -1,10 +1,10 @@
<?xml version="1.0" standalone="no"?>
<!--
Configuration template for the uppercase example application
Configuration template for the message example application
-->
<master>
<!-- Application name -->
<name>uppercase-example</name>
<name>message-example</name>
<!-- Application version. There are no restrictions for the format of
master version numbers -->
@ -17,7 +17,7 @@
<!-- Master daemon definition -->
<daemon>
<binary>uppercase-example-master</binary>
<binary>message-example-master</binary>
<arguments>
<arg>--config</arg>
<arg>${workdir}/dc-api.conf</arg>
@ -35,7 +35,7 @@
<arg>-d</arg>
<arg>3</arg>
<arg>-app</arg>
<arg>uppercase-example</arg>
<arg>message-example</arg>
</arguments>
</daemon>
</master>