diff --git a/Makefile b/Makefile index d8e22b9..c29361e 100644 --- a/Makefile +++ b/Makefile @@ -59,7 +59,7 @@ ASRC=src/app/preferences$(SRCEXT) \ src/app/file-menu$(SRCEXT) LIBRARIES=libbang.so $(MODULES) -MODULES=test-module.so matrix-mult-module.so +MODULES=fractal-module.so #test-module.so matrix-mult-module.so .PHONY: doc modules commit @@ -88,6 +88,9 @@ test-module.so: src/modules/test-module.c matrix-mult-module.so: src/modules/matrix-mult-module.c $(CC) -shared -Wl,-soname,$@ $(COPTS) $(GTKOPTS) $^ -o $@ +fractal-module.so: src/modules/fractal-module.c + $(CC) -shared -Wl,-soname,$@ $(COPTS) $(GTKOPTS) $^ -o $@ + doc: cd doc && doxygen Doxygen diff --git a/src/modules/fractal-module.c b/src/modules/fractal-module.c index d5c7734..e72eb50 100644 --- a/src/modules/fractal-module.c +++ b/src/modules/fractal-module.c @@ -6,22 +6,21 @@ * A module to compute a series of frames of zooming in Mandelbrot fractals. */ -//TODO: initialize totalJobs, jobsLeft - #include #include #include +#include #include"../base/bang-module-api.h" +#define JOB_FINISHED -1 +#define JOB_FREE -2 +#define HAS_NO_FRAME -1 + char BANG_module_name[8] = "fractal"; unsigned char BANG_module_version[] = {0,0,1}; BANG_api *api; -int totalJobs; -int jobsLeft; -int totalPeers; -int peerArrSize; -typedef struct { +typedef struct _peerContainer{ int frame; int needsState; } peerContainer; @@ -34,71 +33,104 @@ typedef struct { } fractalState; typedef struct { - int job; + int frame; int x; int y; int color; } pixelStruct; -fractalState fractalStateData; - -static BANG_callbacks* BANG_module_init(BANG_api *get_api) { - api = get_api; - BANG_callbacks* callbacks = (BANG_callbacks*)malloc(sizeof(BANG_callbacks)); - memset(callbacks,0,sizeof(BANG_callbacks)); - return callbacks; -} - -static void BANG_module_run(BANG_module_info *info) { - api->BANG_debug_on_all_peers(info,"!\n"); -} - -static void GUI_init(GtkWidget** panel, GtkWidget** tabLabel) { - - -} - -/** - * Callback for when jobs are available for you to request - * \param int The id of the peer with jobs available. - */ -static void jobs_available_callback(BANG_module_info* mod, int authority) { - api->BANG_request_job(mod, authority); -} +static void job_done_callback(BANG_module_info* mod, BANG_job* job); +static void incoming_job_callback(BANG_module_info* mod, BANG_job* job); +static void jobs_available_callback(BANG_module_info* mod, int authority); +static void outgoing_job_callback(BANG_module_info* mod, int peer); +static void peer_removed_callback(BANG_module_info* mod, int peer); +static pixelStruct* process_frames(int numFrames, int *frame, int *numPixels); +static int mapIterToColor(int iter, int maxIter); + +static fractalState fractalStateData = { 0, 0, 0, 0 }; +static int totalJobs = 0; +static int jobsLeft = -1; +static int peerArrSize = 0; +static int *jobArr = NULL; +static peerContainer **peerArr = NULL; /** * Callback for when a finished job is sent to you. * \param BANG_job* The job that has been finished. */ -static void job_done_callback(BANG_module_info* mod, BANG_job* job) { +static void job_done_callback(BANG_module_info* info, BANG_job* job) { buffer(job); //Decommission job jobArr[job->job_number] = -1; --jobsLeft; if (jobsLeft) - api->BANG_assert_authority_to_peer(mod, job->authority, job->peer); + api->BANG_assert_authority_to_peer(info, job->authority, job->peer); - free(mod); } /** - * Callback for when a peer requests a job from you. - * \param int The id of peer requesting a job. + * Callback for when the authority sends a job to you. + * \param BANG_job* the job that is sent to you. */ -static void outgoing_jobs_callback(BANG_module_info* mod, int peer) { - if (peerArr[peer] = NULL || jobsLeft == 0) +static void incoming_job_callback(BANG_module_info* info, BANG_job* job) { + //Packet: [1B state flag][4B x][4B y][4B frames]* + + int offset = sizeof(char); //Pretend it's already looked at the first byte + + //Read state flag + //If authority is pushing state data on us + if (((char*)job->data)[0] == 1) { + //Read x/y coords + fractalStateData.x = ((int *)((job->data)+1))[0]; + fractalStateData.y = ((int *)((job->data)+1))[1]; + fractalStateData.winX = ((int *)((job->data)+1))[2]; + fractalStateData.winY = ((int *)((job->data)+1))[3]; + offset += 4*sizeof(int); + } + + //Read number of frames + int numFrames = (job->length - offset)/sizeof(int); + offset += sizeof(char); + + //Read frames + int *frame = (int *)malloc(numFrames*sizeof(int)); + int i; + for (i=0; idata)+offset))[0]; + offset += sizeof(int); + } + + free(job->data); + int numPixels; + job->data = (void *)process_frames(numFrames, frame, &numPixels); + job->length = numPixels; + api->BANG_finished_request(info, job); +} + +/** + * Callback for when jobs are available for you to request + * \param int The id of the peer with jobs available. + */ +static void jobs_available_callback(BANG_module_info* info, int authority) { + api->BANG_request_job(info, authority); +} + +static void outgoing_job_callback(BANG_module_info* info, int peer) { + if (peerArr == NULL || peerArr[peer] == NULL || jobsLeft == 0) return; - //If next job has been finished or is being worked on + int i, nextJob = 0; + + /* If next job has been finished or is being worked on */ if (jobArr[nextJob] != -1) { - //Search for next available job + /* Search for next available job */ for (i = nextJob+1; jobArr[i] != 0; ++i) { if (i == nextJob) - //No more active jobs, don't do anything + /* No more active jobs, don't do anything */ return; if (i+1 >= totalJobs) - //Reset i to the beginning of the jobArr + /* Reset i to the beginning of the jobArr */ i = -1; } nextJob = i; @@ -106,29 +138,67 @@ static void outgoing_jobs_callback(BANG_module_info* mod, int peer) { //Sign job with peer's ID jobArr[nextJob] = peer; - peerArr[peer].job = nextJob; - - BANG_job *job = (BANG_job *)malloc(sizeof(BANG_job)); - if (peerArr[peer].needsState) { - job->data = (void *)malloc(13); - ((char *)(job->data))[0] = 1; - ((int *)(job->data)+1)[0] = fractalStateData.x; - ((int *)(job->data)+1)[1] = fractalStateData.y; - ((int *)(job0>data)+1)[2] = nextJob; + peerArr[peer]->frame = nextJob; + + BANG_job *job = malloc(sizeof(BANG_job)); + int ref; + + if (peerArr[peer]->needsState) { + ref = 1; + + job->data = malloc(13); + memcpy(job->data,&ref,1); + memcpy(job->data + 1, &fractalStateData.x, 4); + memcpy(job->data + 5, &fractalStateData.y, 4); + memcpy(job->data + 9, &nextJob, 4); job->length = 13; - } - else { + + } else { + ref = 0; + job->data = (void *)malloc(5); - job->data[0] = 0; - ((int *)(job->data)+1)[0] = nextJob; + memcpy(job->data,&ref,1); + memcpy(job->data + 1, &nextJob, 4); job->length = 5; } - BANG_send_job(mod, job); + BANG_send_job(info, job); } +/** + * Callback for when a peer is added. + * \param int The id of the added peer. + */ +static void peer_added_callback(BANG_module_info* info, int peer) { + + if (peer >= peerArrSize) + peerArr = realloc(peerArr, peerArrSize *= 2); + + peerArr[peer] = malloc(sizeof(peerContainer)); + peerArr[peer]->frame = HAS_NO_FRAME; + peerArr[peer]->needsState = 1; + + if (jobsLeft) + api->BANG_assert_authority_to_peer(info, api->BANG_get_my_id(info), peer); +} + +/** + * Callback for when a peer is removed. + * \param int The id of the removed peer. + */ +static void peer_removed_callback(BANG_module_info* info, int peer) { + //Put their job back up for someone else to do + jobArr[peerArr[peer]->frame] = JOB_FREE; + //Remove them from the peer array + free(peerArr[peer]); + peerArr[peer] = NULL; + +} + + + static int mapIterToColor(int iter, int maxIter) { - #define COL_MAX 256 +#define COL_MAX 256 int retCol = 0; if (iter > (maxIter/2)) { @@ -140,19 +210,18 @@ static int mapIterToColor(int iter, int maxIter) { retCol = (iter*COL_MAX/maxIter) << 20; //low = black, high = red } - - #undef COL_MAX + +#undef COL_MAX return retCol; } -static pixelStruct *processFrames(int numFrames, int *frame, int *numPixels) { - - pixelStruct *data = (pixelStruct *)calloc((numFrames+1) * winX * winY * sizeof(pixelStruct)); +static pixelStruct* process_frames(int numFrames, int *frame, int *numPixels) { + pixelStruct *data = calloc((numFrames+1) * winX * winY, sizeof(pixelStruct)); *numPixels = 0; int i; - for (i=0; idata)[0] == 1) { - //Read x/y coords - fractalStateData.x = ((int *)((job->data)+1))[0]; - fractalStateData.y = ((int *)((job->data)+1))[1]; - fractalStateData.winX = ((int *)((job->data)+1))[2]; - fractalStateData.winY = ((int *)((job->data)+1))[3]; - offset += 4*sizeof(int); - } - -//Read number of frames - int numFrames = (job->length - offset)/sizeof(int); - offset += sizeof(char); - -//Read frames - int *frame = (int *)malloc(numFrames*sizeof(int)); - int i; - for (i=0; idata)+offset))[0]; - offset += sizeof(int); - } - - free(job->data); - int numPixels; - job->data = (void *)processFrames(numFrames, frame, &numPixels); - job->length = numPixels; - api->BANG_finished_request(mod, job); +static void GUI_init(GtkWidget** panel, GtkWidget** panel_label) { } -/** - * Callback for when a peer is added. - * \param int The id of the added peer. - */ -static void peer_added_callback(BANG_module_info* mod, int peer) { +static BANG_callbacks* BANG_module_init(BANG_api *get_api) { + api = get_api; + BANG_callbacks *callbacks = malloc(sizeof(BANG_callbacks)); - if (peer >= peerArrSize) - peerArr = (peerContainer *)realloc(peerArr, peerArrSize *= 2); - peerArr[peer] = (peerContainer *)malloc(sizeof(peerContainer)); - peerArr[peer].job = -1; - peerArr[needsState] = 1; + callbacks->job_done = &job_done_callback; + callbacks->jobs_available = &jobs_available_callback; + callbacks->incoming_job = &incoming_job_callback; + callbacks->outgoing_jobs = &outgoing_job_callback; + callbacks->peer_added = &peer_added_callback; + callbacks->peer_removed = &peer_removed_callback; - if (jobsLeft) - api->BANG_assert_authority_to_peer(mod, api->BANG_get_my_id(mod), peer); + return callbacks; } -/** - * Callback for when a peer is removed. - * \param int The id of the removed peer. - */ -static void peer_removed_callback(BANG_module_info* mod, int peer) { - //Put their job back up for someone else to do - jobArr[peerArr[peer].job] = -2; - //Remove them from the peer array - free(peerArr[peer]); - peerArr[peer] = NULL; - - free(mod); +static void BANG_module_run(BANG_module_info *info) { }