#include #include #include const char* SEQUENTIAL_TEST = "sequential"; const char* INTERLACING_TEST = "interlacing"; const char* PERFORMANCE_TEST = "performance"; const char* COMMAND_FILE_PARAMETER = "COMMAND_FILE"; const char* LOOP_TIMES_PARAMETER = "LOOP_TIMES"; const char* SECONDS_TO_WAIT_PARAMETER = "SECONDS_TO_WAIT"; const char* TEST_SERVER_PORT_BASE_PARAMETER = "TEST_SERVER_PORT_BASE"; const char* SERVER_NAMES_PARAMETER = "SERVER_NAMES"; const char* FILE_TO_WRITE_PARAMETER = "FILE_TO_WRITE"; const char* NFS_FILE_TO_WRITE_PARAMETER = "NFS_FILE_TO_WRITE"; const char* FILE_TO_WRITE_SIZE_PARAMETER = "SIZE_FILE_TO_WRITE"; /* Function : generateSequentialTest * Arguments : commandFileBasePath - test servers command file path prefix * loopTimes - number of times, the main loop of the test is to be * repeated * testServerPortBase - to calculate the test servers command port * one must add the ordinal number of the * server to this parameter * serverNames - names of the test server machines * fileToWritePath - file to update * Return value: success/failure value * Description : creates a test, in which two test servers write sequentially to * the same file one after another (without races). The file * update repeats 'loopTimes' times by each server */ int generateSequentialTest(const char* commandFileBasePath, int loopTimes, int testServerPortBase, const char* serverNames[2], const char* fileToWritePath) { FILE* firstCommandFile = NULL; FILE* secondCommandFile = NULL; char firstCommandFilePath[BUFSIZ]; char secondCommandFilePath[BUFSIZ]; int firstServerPort = testServerPortBase + 1; int secondServerPort = testServerPortBase + 2; const char* firstServerName = serverNames[0]; const char* secondServerName = serverNames[1]; int loopIndex = 0; sprintf(firstCommandFilePath , "%s.1", commandFileBasePath); sprintf(secondCommandFilePath, "%s.2", commandFileBasePath); // Open both command files for writing if((firstCommandFile = fopen(firstCommandFilePath, "w")) == NULL) { fprintf(stderr, "Unable to open the command file %s\n", firstCommandFilePath); return 1; } if((secondCommandFile = fopen(secondCommandFilePath, "w")) == NULL) { fprintf(stderr, "Unable to open the command file %s\n", secondCommandFilePath); fclose(firstCommandFile); return 1; } // Bind both servers to specific ports fprintf(firstCommandFile, "bind %d\n", firstServerPort); fprintf(secondCommandFile, "bind %d\n", secondServerPort); // Prepare the main loops of the test for(loopIndex = 0; loopIndex < loopTimes; loopIndex ++) { fprintf(firstCommandFile, "read %s\n", fileToWritePath); fprintf(firstCommandFile, "writeSocket %s %d write %s SECOND\n", secondServerName, secondServerPort, fileToWritePath); // synchronization point - to verify that the previous write was // committed fprintf(firstCommandFile, "readSocket\n"); fprintf(firstCommandFile, "read %s\n", fileToWritePath); fprintf(firstCommandFile, "readSocket\n"); // returning acknowlegment to another server to verify that the write // was committed fprintf(firstCommandFile, "writeSocket %s %d nop\n", secondServerName, secondServerPort); fprintf(secondCommandFile, "read %s\n", fileToWritePath); fprintf(secondCommandFile, "readSocket\n"); // returning acknowlegment to another server to verify that the write // was committed fprintf(secondCommandFile, "writeSocket %s %d nop\n", firstServerName, firstServerPort); fprintf(secondCommandFile, "read %s\n", fileToWritePath); fprintf(secondCommandFile, "writeSocket %s %d write %s FIRST\n", firstServerName, firstServerPort, fileToWritePath); // synchronization point - to verify that the previous write was // committed fprintf(secondCommandFile, "readSocket\n"); } // Finalize everything in both servers fprintf(firstCommandFile, "exit"); fprintf(secondCommandFile, "exit"); fclose(secondCommandFile); fclose(firstCommandFile); return 0; } /* Function : generateInterlacingTest * Arguments : commandFileBasePath - test servers command file path prefix * loopTimes - number of times, the main loop of the test is to be * repeated * secondsToWait - number of seconds to wait in 'wait' commands * testServerPortBase - to calculate the test servers command port * one must add the ordinal number of the * server to this parameter * serverNames - names of the test server machines * fileToWritePath - Coda mounted file to update * Return value: success/failure value * Description : creates a test, in which two test servers write * to the same file in an interlacing manner (while one opens a * file and keeps it open, the second writes to the same file, * then the first writes its data to the file too and closes the * descriptor). The file update repeats 'loopTimes' times by * each server */ int generateInterlacingTest(const char* commandFileBasePath, int loopTimes, int secondsToWait, int testServerPortBase, const char* serverNames[2], const char* fileToWritePath) { FILE* firstCommandFile = NULL; FILE* secondCommandFile = NULL; char firstCommandFilePath[BUFSIZ]; char secondCommandFilePath[BUFSIZ]; int firstServerPort = testServerPortBase + 1; int secondServerPort = testServerPortBase + 2; const char* firstServerName = serverNames[0]; const char* secondServerName = serverNames[1]; int loopIndex = 0; sprintf(firstCommandFilePath , "%s.1", commandFileBasePath); sprintf(secondCommandFilePath, "%s.2", commandFileBasePath); // Open both command files for writing if((firstCommandFile = fopen(firstCommandFilePath, "w")) == NULL) { fprintf(stderr, "Unable to open the command file %s\n", firstCommandFilePath); return 1; } if((secondCommandFile = fopen(secondCommandFilePath, "w")) == NULL) { fprintf(stderr, "Unable to open the command file %s\n", secondCommandFilePath); fclose(firstCommandFile); return 1; } // Bind both servers to specific ports fprintf(firstCommandFile, "bind %d\n", firstServerPort); fprintf(secondCommandFile, "bind %d\n", secondServerPort); // Prepare the main loops of the test for(loopIndex = 0; loopIndex < loopTimes; loopIndex ++) { fprintf(firstCommandFile, "read %s\n", fileToWritePath); fprintf(firstCommandFile, "writeSocket %s %d open %s\n", secondServerName, secondServerPort, fileToWritePath); // synchronization point - to verify that the previous open was // committed fprintf(firstCommandFile, "readSocket\n"); fprintf(firstCommandFile, "write %s FIRST\n", fileToWritePath); fprintf(firstCommandFile, "read %s\n", fileToWritePath); fprintf(firstCommandFile, "writeSocket %s %d flush SECOND\n", secondServerName, secondServerPort); // synchronization point - to verify that the previous write was // committed fprintf(firstCommandFile, "readSocket\n"); fprintf(firstCommandFile, "read %s\n", fileToWritePath); fprintf(firstCommandFile, "readSocket\n"); // returning acknowlegment to another server to verify that the open // was committed fprintf(firstCommandFile, "writeSocket %s %d nop\n", secondServerName, secondServerPort); fprintf(firstCommandFile, "readSocket\n"); // returning acknowlegment to another server to verify that the flush // was committed fprintf(firstCommandFile, "writeSocket %s %d nop\n", secondServerName, secondServerPort); fprintf(secondCommandFile, "read %s\n", fileToWritePath); fprintf(secondCommandFile, "readSocket\n"); // returning acknowlegment to another server to verify that the open // was committed fprintf(secondCommandFile, "writeSocket %s %d nop\n", firstServerName, firstServerPort); fprintf(secondCommandFile, "readSocket\n"); // returning acknowlegment to another server to verify that the flush // was committed fprintf(secondCommandFile, "writeSocket %s %d nop\n", firstServerName, firstServerPort); fprintf(secondCommandFile, "read %s\n", fileToWritePath); fprintf(secondCommandFile, "writeSocket %s %d open %s\n", firstServerName, firstServerPort, fileToWritePath); // synchronization point - to verify that the previous open was // committed fprintf(secondCommandFile, "readSocket\n"); fprintf(secondCommandFile, "write %s SECOND\n", fileToWritePath); fprintf(secondCommandFile, "read %s\n", fileToWritePath); fprintf(secondCommandFile, "writeSocket %s %d flush FIRST\n", firstServerName, firstServerPort); // synchronization point - to verify that the previous flush was // committed fprintf(secondCommandFile, "readSocket\n"); } // Finalize everything in both servers fprintf(firstCommandFile, "exit"); fprintf(secondCommandFile, "exit"); fclose(secondCommandFile); fclose(firstCommandFile); return 0; } /* Function : generatePerformanceTest * Arguments : commandFileBasePath - test servers command file path prefix * loopTimes - number of times, the main loop of the test is to be * repeated * fileToWritePath - Coda mounted file to update * nfsFileToWritePath - NFS mounted file to update * fileToWriteSize - NFS mounted and Coda files size in bytes * Return value: success/failure value * Description : creates a test, in which NFS and Coda mounted files are updated * 'loopTimes' times and the time for the bunch of these updates * is measured for NFS and for Coda */ int generatePerformanceTest(const char* commandFileBasePath, int loopTimes, const char* fileToWritePath, const char* nfsFileToWritePath, int fileToWriteSize) { FILE* commandFile = NULL; char commandFilePath[BUFSIZ]; int loopIndex = 0; sprintf(commandFilePath, "%s.1", commandFileBasePath); if((commandFile = fopen(commandFilePath, "w")) == NULL) { fprintf(stderr, "Unable to open the command file %s\n", commandFilePath); return 1; } fprintf(commandFile, "date\n"); for(loopIndex = 0; loopIndex < loopTimes; loopIndex ++) { fprintf(commandFile, "write_bytes %s %d\n", fileToWritePath, fileToWriteSize); fprintf(commandFile, "read_silent %s\n", fileToWritePath); } fprintf(commandFile, "date\n"); for(loopIndex = 0; loopIndex < loopTimes; loopIndex ++) { fprintf(commandFile, "write_bytes %s %d\n", nfsFileToWritePath, fileToWriteSize); fprintf(commandFile, "read_silent %s\n", nfsFileToWritePath); } fprintf(commandFile, "date\n"); fclose(commandFile); return 0; } /* Function : main * Arguments : argv[1] - the type of test to generate: sequential, * interlacing or performance * Return value: success/failure value * Usage : GenerateCommandFile [sequential|interlacing|performance] * Description : this utility generates test cases for two test servers. It uses * configuration file GenerateCommandFile.conf, in which the * following parameters affect the way, the test servers * behave: * * COMMAND_FILE_PARAMETER - produced command files names for * the test servers will be preceded * with this string * LOOP_TIMES_PARAMETER - number of times, the main loop of the * test should repeat * SECONDS_TO_WAIT_PARAMETER - number of seconds, the servers * wait, when it is necessary * TEST_SERVER_PORT_BASE_PARAMETER - in order to calculate the * command port of the test * servers, one must add the * ordinal number of the * server to this parameter * SERVER_NAMES_PARAMETER - names of the test servers machines * FILE_TO_WRITE_PARAMETER - the path to the file to be updated * NFS_FILE_TO_WRITE_PARAMETER - the path to the NFS mounted * file to be updated * FILE_TO_WRITE_SIZE_PARAMETER - size of the NFS mounted and * Coda files in bytes * * For explanations about each one of the tests, see documentation * of the corresponding generating functions: * 'generateSequentialTest', 'generateInterlacingTest' or * 'generatePerformanceTest' */ int main(int argc, char* argv[]) { const char* usageString = "Usage: GenerateCommandFile [sequential|interlacing|performance]"; FILE* configurationFile = NULL; FILE* commandFile = NULL; char buffer[BUFSIZ]; // Configuration parameters variables char commandFileBasePath[BUFSIZ]; int loopTimes = -1; int secondsToWait = -1; int testServerPortBase = -1; char firstServerName[BUFSIZ], secondServerName[BUFSIZ]; char fileToWritePath[BUFSIZ]; char nfsFileToWritePath[BUFSIZ]; int fileToWriteSize = -1; int returnValue = 0; const char* serverNames[2] = {0}; if(argc != 2) { fprintf(stderr, "No test type specified\n%s\n", usageString); return 1; } if((configurationFile = fopen("GenerateCommandFile.conf", "r")) == NULL) { fprintf(stderr, "Unable to open the configuration file\n"); return 1; } // Interpreting the configuration file information while(fgets(buffer, BUFSIZ, configurationFile) != NULL) { char* valueBasePosition = strchr(buffer, '=') + 1; // 'COMMAND_FILE' parameter clause if(!strncasecmp(buffer, COMMAND_FILE_PARAMETER, strlen(COMMAND_FILE_PARAMETER)) && sscanf(valueBasePosition, "%s", commandFileBasePath) != 1) { fprintf(stderr, "Unable to read command file parameter\n"); return 1; } // 'LOOP_TIMES' parameter clause if(!strncasecmp(buffer, LOOP_TIMES_PARAMETER, strlen(LOOP_TIMES_PARAMETER)) && sscanf(valueBasePosition, "%d", &loopTimes) != 1) { fprintf(stderr, "Unable to read loop times parameter\n"); return 1; } // 'SECONDS_TO_WAIT' parameter clause if(!strncasecmp(buffer, SECONDS_TO_WAIT_PARAMETER, strlen(SECONDS_TO_WAIT_PARAMETER)) && sscanf(valueBasePosition, "%d", &secondsToWait) != 1) { fprintf(stderr, "Unable to read seconds to wait parameter\n"); return 1; } // 'TEST_SERVER_PORT' parameter clause if(!strncasecmp(buffer, TEST_SERVER_PORT_BASE_PARAMETER, strlen(TEST_SERVER_PORT_BASE_PARAMETER)) && sscanf(valueBasePosition, "%d", &testServerPortBase) != 1) { fprintf(stderr, "Unable to read test server port base parameter\n"); return 1; } // 'SERVER_NAMES' parameter clause if(!strncasecmp(buffer, SERVER_NAMES_PARAMETER, strlen(SERVER_NAMES_PARAMETER)) && sscanf(valueBasePosition, "%s %s", firstServerName, secondServerName) != 2) { fprintf(stderr, "Unable to read server names parameter\n"); return 1; } // 'FILE_TO_WRITE' parameter clause if(!strncasecmp(buffer, FILE_TO_WRITE_PARAMETER, strlen(FILE_TO_WRITE_PARAMETER)) && sscanf(valueBasePosition, "%s", fileToWritePath) != 1) { fprintf(stderr, "Unable to read file to write parameter\n"); return 1; } // 'NFS_FILE_TO_WRITE' parameter clause if(!strncasecmp(buffer, NFS_FILE_TO_WRITE_PARAMETER, strlen(NFS_FILE_TO_WRITE_PARAMETER)) && sscanf(valueBasePosition, "%s", nfsFileToWritePath) != 1) { fprintf(stderr, "Unable to read NFS file to write parameter %s\n", nfsFileToWritePath); return 1; } // 'FILE_TO_WRITE_SIZE' parameter clause if(!strncasecmp(buffer, FILE_TO_WRITE_SIZE_PARAMETER, strlen(FILE_TO_WRITE_SIZE_PARAMETER)) && sscanf(valueBasePosition, "%d", &fileToWriteSize) != 1) { fprintf(stderr, "Unable to read file to write size parameter %s\n", fileToWriteSize); return 1; } } fclose(configurationFile); serverNames[0] = firstServerName; serverNames[1] = secondServerName; // Generating a specific test if(!strcasecmp(argv[1], SEQUENTIAL_TEST)) // { // const char* serverNames[2] = {firstServerName, secondServerName}; returnValue = generateSequentialTest(commandFileBasePath, loopTimes, testServerPortBase, serverNames, fileToWritePath); // } else if(!strcasecmp(argv[1], INTERLACING_TEST)) returnValue = generateInterlacingTest(commandFileBasePath, loopTimes, secondsToWait, testServerPortBase, serverNames, fileToWritePath); else if(!strcasecmp(argv[1], PERFORMANCE_TEST)) returnValue = generatePerformanceTest(commandFileBasePath, loopTimes, fileToWritePath, nfsFileToWritePath, fileToWriteSize); else { fprintf(stderr, "The test type is incorrect\n%s\n", usageString); return 1; } return returnValue; }