/* File: lab2.c Author: Xiuwen Liu Purpose: a tool to sort email messages based on keywords Command to complie: see makefile */ #include #include #include #include #include #include #include #include #include #include #include #include #include "type-def.h" #include "util.h" #include "mythreads.h" int verbose; int main(int argc, char *argv[]) { int i, sum; extern char *optarg; extern int optind; thread_t *tid; /* array of thread IDs */ CONSUMER_INFO consumer_info; PRODUCER_INFO producer_info; char c; int fd; struct stat stat_buf; int seed; char comm[2048]; /* Initialization here */ nextc = 0; nextp = 0; done = 0; verbose = 0; mutex_lock_flag = 0; seed = 0; producer_info.mailbox[0] = '\0'; strcpy(consumer_info.filterwordsFile,"filterwords.dat"); strcpy(consumer_info.categoryFile,"categorylist.dat"); NUM_THREADS = 2; while ((c = getopt(argc, argv, "ms:v:f:c:t:")) != EOF) { switch(c) { case 'm': mutex_lock_flag = 1; break; case 'f': strcpy(consumer_info.filterwordsFile,optarg); break; case 'c': strcpy(consumer_info.categoryFile,optarg); break; case 'v': verbose = atoi(optarg); break; case 't': NUM_THREADS= atoi(optarg); break; case 's': seed = atoi(optarg); break; default: printf("%c is not valid option.\n", c); } } if (optind == (argc-1)) { strcpy(producer_info.mailbox,argv[optind]); } else { fprintf(stderr,"Usage: %s [-m] [-f filterwordfile] [-c categoryfile] ", argv[0]); fprintf(stderr,"[-v verbose-level] [-t numberthreads] mailbox\n"); return -1; } srandom(seed); if (verbose >= 1) { printf("Number of consumer threads is %d\n", NUM_THREADS); printf("The mailbox to be searched is \"%s\"\n",producer_info.mailbox); printf("The words to be checked are given in \"%s\".\n", consumer_info.filterwordsFile); printf("The folders for each category are given in \"%s\".\n", consumer_info.categoryFile); printf("The synchronizatoin is "); if (mutex_lock_flag ==0) { printf("DISABLED.\n"); } else { printf("ENABLED.\n"); } } /* Read the words from the filterwordsFile */ consumer_info.nwords = Count_Item_InFile(consumer_info.filterwordsFile); if (consumer_info.nwords <= 0) { fprintf(stderr,"There is no filter word read from \"%s\".\n", consumer_info.filterwordsFile); return -1; } consumer_info.words = (WORD_INFO *)malloc(sizeof(WORD_INFO) * consumer_info.nwords); Read_Items_FromFile(consumer_info.filterwordsFile, consumer_info.words, consumer_info.nwords); // We initilize the total occurrence for (i=0; i < consumer_info.nwords; i++) { consumer_info.words[i].saved_messages = 0; } /* Read the categories from the categoryFile */ consumer_info.ncategories = Count_Item_InFile(consumer_info.categoryFile); if (consumer_info.ncategories <= 0) { fprintf(stderr,"There is no category read from \"%s\".\n", consumer_info.categoryFile); return -1; } consumer_info.categories = (WORD_INFO *)malloc(sizeof(WORD_INFO) * consumer_info.ncategories); Read_Items_FromFile(consumer_info.categoryFile, consumer_info.categories, consumer_info.ncategories); if (verbose >= 1) { printf("There are %d filtering words to be used and they are\n", consumer_info.nwords); for (i=0; i < consumer_info.nwords; i++) { printf("\t%s (%d)\n",consumer_info.words[i].word, consumer_info.words[i].category); } printf("There are %d categories to be used and they are\n", consumer_info.ncategories); for (i=0; i < consumer_info.ncategories; i++) { printf("\t%s (%d)\n",consumer_info.categories[i].word, consumer_info.categories[i].category); } } for (i=0; i < consumer_info.ncategories; i++) { consumer_info.categories[i].saved_messages = 0; // We also need to truncate the file every time // Note in real life we may not need to do this as // normally only check new messages fd = open(consumer_info.categories[i].word,O_WRONLY|O_CREAT|O_TRUNC, S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH); if (fd > 0) { fchmod(fd, S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH); close(fd); } else { fprintf(stderr,"Cannot open file \"%s\" for writing the first time.\n", consumer_info.categories[i].word); if (chmod(consumer_info.categories[i].word, S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH) < 0) { printf("Cannot change the permission of file \"%s\".\n", consumer_info.categories[i].word); exit(0-1); } fd = open(consumer_info.categories[i].word,O_WRONLY|O_CREAT|O_TRUNC, S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH); if (fd > 0) { fchmod(fd, S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH); close(fd); fprintf(stderr,"The problem was fixed for file \"%s\".\n", consumer_info.categories[i].word); } else { fprintf(stderr,"Cannot open file \"%s\" for writing second time.\n", consumer_info.categories[i].word); exit(-1); } } } fd = open(producer_info.mailbox,O_RDONLY); if (fd < 0) { fprintf(stderr,"Cannot open the mailbox \"%s\" to be searched.\n", producer_info.mailbox); return -1; } fstat(fd, &stat_buf); mailbox = (char *)malloc(sizeof(char)*(stat_buf.st_size+1)); mailbox_len = (int)read(fd, (void *)mailbox, stat_buf.st_size); if (mailbox_len != (int)stat_buf.st_size) { fprintf(stderr,"Something is wrong with mailbox \"%s\".\n", producer_info.mailbox); fprintf(stderr,"We should read %d bytes but %d were read.\n", stat_buf.st_size, mailbox_len); close(fd); return -1; } close(fd); // Add '\0' at the end to avoid segmentation problems mailbox[mailbox_len] = '\0'; if (verbose >= 1) { printf("%d bytes were read from mailbox \"%s\".\n", mailbox_len, producer_info.mailbox); } tid = (thread_t *)malloc(sizeof(thread_t)*(NUM_THREADS+1)); message_buf_size = NUM_THREADS * 2; if (NUM_THREADS == 1) { // We make this one as a special case so that we can test our program // without synchronization // In this case, we have a buffer with an unlimited capacibity // Here the capacity is estimated based on the length of the mailbox // and that each message will have at least 100 bytes message_buf_size = (int)(mailbox_len/100); } shared_buf = (MESSAGE_INFO *)malloc(sizeof(MESSAGE_INFO) * message_buf_size); for (i=0; i < message_buf_size; i++) { shared_buf[i].message_id = -1; } /* Create the producer thread here */ if (thr_create(NULL, (int)0, Producer, (void *)(&producer_info), THR_SUSPENDED, &(tid[0])) <0) { perror("create thread: "); return -1; } /* Create the consumer thread here */ for (i=0; i < NUM_THREADS; i++) { if (thr_create(NULL, (int)0, Consumer, (void *)(&consumer_info), THR_SUSPENDED, &(tid[i+1])) <0) { perror("create thread: "); return -1; } } for (i=0; i < (NUM_THREADS+1); i++) thr_continue(tid[i]); while (thr_join(NULL, NULL, NULL) == 0); // Free all the allocated memory spaces // Print the total saved messages in each category printf("Total messages saved in each folder\n"); for (i=0; i < consumer_info.ncategories; i++) { printf("\t%s (%d): %d\n", consumer_info.categories[i].word, consumer_info.categories[i].category, consumer_info.categories[i].saved_messages); } printf("Total occurrences of the filtered words in mailbox \"%s.\n", producer_info.mailbox); for (i=0; i < consumer_info.nwords; i++) { printf("\t%s (%d):\t\t%d\n", consumer_info.words[i].word, consumer_info.words[i].category, consumer_info.words[i].saved_messages); } for (i=0; i < consumer_info.nwords; i++) { free(consumer_info.words[i].word); } free(consumer_info.words); for (i=0; i < consumer_info.ncategories; i++) { free(consumer_info.categories[i].word); } free(consumer_info.categories); free(tid); free(mailbox); free(shared_buf); // Destroy_Mutex(); return 0; }