BOOLEAN mergeRuns(FILE ** sorted, int pagesize, int availableBuffers, FileList currentFiles, int * passes, int * runs, int totalRecordCount){ RecordHeap rHeap; Buffer * bufferNodes; int bufferIndex; /*Determine max files that can be merged in a run*/ /*That is available buffers -1 for the output buffer*/ /*This is also the output buffer indes*/ int outputBuffIndex = availableBuffers -1; /*Buffer array (of buffer nodes) where size of which is the number of buffers available to store in memory*/ bufferNodes = calloc(availableBuffers, sizeof(Buffer)); if(!bufferNodes){ fprintf(stderr, "Error: Failed to allocate buffer array\n"); return FALSE; } /*Allocate memory for record arrays for each buffer*/ for(bufferIndex = 0; bufferIndex < availableBuffers; bufferIndex++){ initBuffer(&bufferNodes[bufferIndex], pagesize); } /*Initialise priority queue It's size is the amount of files that can be merged in a run*/ /*outputBuffIndex is the last index in the buffer array*/ if(initHeap(&rHeap, outputBuffIndex * pagesize) == FALSE){ return FALSE; } /*while more merging required, (more than 1 temporary file)*/ /*go through a pass*/ while(currentFiles.fileCount > 1){ int runCount = 0; /*Define first file to be the start of the file linked list*/ FileNode * firstFileForRun = currentFiles.fileHeadNode; /*Run file list, is the files to be merged in the next pass*/ FileList runFileList;/*= calloc(1, sizeof(FileList));*/ float runsInPassFloat = ((float)currentFiles.fileCount/(float)(availableBuffers-1)); int runsInPass = ceil(runsInPassFloat); initFileList(&runFileList); /*while still merging required for pass*/ /*go through a run*/ while(runCount < runsInPass){ int buffersInUse = 0; int bufferIndex = 0; int init = 0; FileNode * currentRunFile = firstFileForRun; FILE * outputFile; /*create new temp file for merge run, written to when output buffer is full*/ if((outputFile = tmpfile()) == NULL){ fprintf(stderr, "Error: Failed to create output temporary file for run\n"); return FALSE; } /*add file pointer to the file list for the next pass*/ addFile(&runFileList,outputFile); /*Read in pages from current files to buffers*/ for(bufferIndex = 0; bufferIndex < outputBuffIndex; bufferIndex++){ int recordPageIndex; /*fill buffer with records from file*/ if(currentRunFile->fp != NULL){ for(recordPageIndex = 0; recordPageIndex < pagesize; recordPageIndex++){ /*read in record*/ Record record; if(fread(&record, sizeof(Record), 1, currentRunFile->fp) == 1){ /*add record to page (records array)*/ init++; if(addRecord(&bufferNodes[bufferIndex], record, pagesize, recordPageIndex) == FALSE) return FALSE; /*add record index to heap*/ if(addToHeap(&rHeap, &bufferNodes[bufferIndex], recordPageIndex) == FALSE) return FALSE; } /*else reached file end*/ else{ /*temp file will be automatically deleted by the system*/ fclose(currentRunFile->fp); currentRunFile->fp = NULL; /*removeFile(currentFiles, currentRunFile);*/ /*add blank records*/ /*int blankRecordCount; for(blankRecordCount = recordCount; blankRecordCount < pagesize; blankRecordCount++){ int recordPageIndex = addBlankRecord(&bufferNodes[bufferIndex], pagesize); if(recordPageIndex < 0) return FALSE; }*/ break; } } bufferNodes[bufferIndex].fileNode = currentRunFile; buffersInUse++; currentRunFile = currentRunFile->nextFileNode; if (currentRunFile == NULL) break; } else break; } /*set firstFileForRun for next run*/ firstFileForRun = currentRunFile; /*while all buffers are not empty (there is still records in pages in some buffer not including the output buffer)*/ while(buffersInUse > 0 && rHeap.count > 0){ /*keep getting min record and writing to output buffer*/ /*get smallest record*/ RecordIndex minIndex = removeMinHeap(&rHeap); if(minIndex.guildID == 0) return FALSE; /*move smallest record from main buffer memory to output buffer*/ /*add record to output buffer*/ addRecord(&bufferNodes[outputBuffIndex], minIndex.buff->pageRecords[minIndex.pgIndex], pagesize, bufferNodes[outputBuffIndex].recordCount); /*remove the same record from original buffer*/ removeRecord(minIndex.buff, minIndex.pgIndex); /*if output buffer is full, write page to file*/ if(bufferNodes[outputBuffIndex].recordCount == pagesize){ /*write page to file*/ int written; written = fwrite(bufferNodes[outputBuffIndex].pageRecords, sizeof(Record), pagesize, outputFile); if(written !=pagesize){ fprintf(stderr, "Error: Failed to write to output file, wrote %i records\n",written); return FALSE; } /*clear page in output buffer*/ clearPage(&bufferNodes[outputBuffIndex], pagesize); } /*if original buffer is empty, read in another page*/ if(minIndex.buff->recordCount == 0){ int recordPageIndex; /*fill buffer with records from file*/ for(recordPageIndex = 0; recordPageIndex < pagesize; recordPageIndex++){ Record record; if(minIndex.buff->fileNode->fp != NULL){ if(fread(&record, sizeof(Record), 1, minIndex.buff->fileNode->fp) == 1){ /*add record to page (records array)*/ if(addRecord(minIndex.buff, record, pagesize, recordPageIndex) == FALSE) return FALSE; /*add record index to heap*/ if(addToHeap(&rHeap, minIndex.buff, recordPageIndex) == FALSE) return FALSE; } /*else reached file end*/ else{ /*temp file will be automatically deleted by the system*/ fclose(minIndex.buff->fileNode->fp); minIndex.buff->fileNode->fp = NULL; /*removeFile(currentFiles, minIndex.buff->fileNode);*/ break; } } } } /*if buffer is still empty, then 0 records were read in, therefore file is empty and the buffer is now free*/ if(minIndex.buff->recordCount == 0) /*decrement buffers in use counter*/ buffersInUse--; } /*All files for run have been fully read*/ /*Write out records still in output buffer*/ if(bufferNodes[outputBuffIndex].recordCount > 0){ /*Output buffer page was not full*/ int i = 0; for(i = 0; i < pagesize; i++){ if(bufferNodes[outputBuffIndex].pageRecords[i].GuildID != 0){ fwrite(&bufferNodes[outputBuffIndex].pageRecords[i], sizeof(Record), 1, outputFile); removeRecord(&bufferNodes[outputBuffIndex], i); } } } /*Rewind outfile for future merge*/ rewind(outputFile); runCount++; } /*set runFileListas new current file list*/ freeFileNode(¤tFiles); currentFiles = runFileList; *passes = *passes+1; *runs = *runs + runCount; printf("Pass %i resulted in %i runs\n",*passes,runCount); } /*FileList will contain link to only 1 temporary binary file*/ if(currentFiles.fileCount != 1){ fprintf(stderr, "Error: Number of files:%i is invalid\n",currentFiles.fileCount); return FALSE; } *sorted = currentFiles.fileHeadNode->fp; /*free allocated memory*/ for(bufferIndex = 0; bufferIndex < availableBuffers; bufferIndex++){ freeBuffer(&bufferNodes[bufferIndex]); } free(bufferNodes); freeHeap(&rHeap); freeFileNode(¤tFiles); /*free(currentFiles);*/ return TRUE; }
int main(int argc, char ** argv) { struct rec * head = NULL; int recNum, i, input; int menu = 0; char name[100]; char usrOption = 'y'; double wNum, hNum, bmi; printf("How many records would you like to create?\n"); scanf("%d",&recNum); for(i = 0; i < recNum; i++){ printf("Name: - "); scanf("%s", name); printf("Weight (kg): - "); scanf("%lf", &wNum); printf("Height (cm): - "); scanf("%lf", &hNum); bmi = calcBmi(wNum, hNum); insertEnd(&head, wNum, hNum, bmi, name, recNum); } while(menu == 0){ printf("\n1. Print Records\n2. Add a record\n3. Send to file\n4. Sort List\n5. Delete a Record\n6. Quit\n"); scanf("%d", &input); //If user would like to print the patient records if(input == 1){ printRecs(head); } //Add a new patient record else if(input == 2){ printf("Name: - "); scanf("%s", name); printf("Weight (kg): - "); scanf("%lf", &wNum); printf("Height (cm): - "); scanf("%lf", &hNum); bmi = calcBmi(wNum, hNum); recNum++; addRecord(&head, wNum, hNum, bmi, name, recNum); } //Send records to a file else if(input == 3){ toFile(head); } //Sorts the list alphabetically else if(input == 4){ printf("This feature is currently in development.\n"); sortList(&head); } //If user would like to delete records else if(input == 5){ if(head->next != NULL){ printf("Which record would you like to delete?\n"); scanf("%s", name); removeRecord(&head, name); } else{ printf("Sorry! There was a problem with deleting the record!\n"); } } //User wishes to quit program else if(input == 6){ printf("Closing Records.\n"); menu = 1; } else{ printf("Sorry! Please enter a valid input.\n"); } } destroy(&head); return(0); }
int clientUploadFile(BIO *conn, char *filename) { /* CALCULATE AND STORE ANY RECORDS OF THIS FILE WE NEED * BEFORE UPLOADING IT */ FILE *ifp = fopen(filename, "rb"); if ( ifp == NULL ) return NO_SUCH_FILE; //generate key and iv for encryption unsigned char *key = randomBytes(32); unsigned char *iv = randomBytes(32); //encrypt the file int status = encryptFile(filename, TEMP_ENCRYPTED_FILENAME, key, iv); if(status == -1) { fprintf(stderr, "Failed to encrypt %s in clientUploadFile()\n", filename); return -1; } //we need to store NUM_HASHES salts and digests for later verification unsigned char *salts[NUM_HASHES]; unsigned char *hashes[NUM_HASHES]; for(int i=0; i<NUM_HASHES; ++i) { //generate a random salt salts[i] = randomBytes(SALT_LENGTH); //compute the digest for the file with that salt hashes[i] = calculateMD5(TEMP_ENCRYPTED_FILENAME, salts[i], SALT_LENGTH); if(hashes[i] == NULL) { fprintf(stderr, "Failed to calculate digest in clientUploadFile()\n"); return -1; } } //store all this data for later status = addRecord(filename, 0, hashes, salts, key, iv); if(status == -1) { fprintf(stderr, "addRecord() failed for in clientUploadFile()\n"); return -1; } //free the memory we allocated above for(int i=0; i < NUM_HASHES; ++i) { free(salts[i]); free(hashes[i]); } free(key); free(iv); /* START THE ACTUAL COMMUNICATION WITH THE SERVER */ //send the code which causes the server to call serverUploadFile() if(writeInt(conn, UPLOAD_FILE_CODE) == -1) return -1; //send the fileSize int fileSize = sizeOfFile(TEMP_ENCRYPTED_FILENAME); if(writeInt(conn, fileSize) == -1) return -1; printf("NOTE: Original size: %f MB. Encrypted size: %f MB.\n", (double)sizeOfFile(filename)/MEGABYTE, (double)fileSize/MEGABYTE); //wait for an int telling us the balance owing unsigned int fee = readInt(conn); if(fee > 0) { printf("Purchase %d more cloud dollar(s) to upload this file.\n", fee); removeRecord(filename); return -1; } else if(fee < 0) return -1; //send the file if(writeFile(conn, TEMP_ENCRYPTED_FILENAME, filename) < 1) return -1; unlink( TEMP_ENCRYPTED_FILENAME ); printf("Succesfully uploaded the file.\n"); return 0; }