1f08c3bdfSopenharmony_ci/* ************************************************* 2f08c3bdfSopenharmony_ci * *********** README ****************************** 3f08c3bdfSopenharmony_ci * ************************************************* 4f08c3bdfSopenharmony_ci * 5f08c3bdfSopenharmony_ci * COMPILE : make 6f08c3bdfSopenharmony_ci * RUN : ./locktests -n <number of concurent process> -f <test file> [-P] 7f08c3bdfSopenharmony_ci * 8f08c3bdfSopenharmony_ci * GOAL : This test tries to stress the fcntl locking functions. A 9f08c3bdfSopenharmony_ci * master process sets a lock on a file region (this is called "byte 10f08c3bdfSopenharmony_ci * range locking"). Some slave processes try to perform operations on 11f08c3bdfSopenharmony_ci * this region, such as read, write, set a new lock ... The expected 12f08c3bdfSopenharmony_ci * results of these operations are known. If the operation result is 13f08c3bdfSopenharmony_ci * the same as the expected one, the test suceeds, else it fails. 14f08c3bdfSopenharmony_ci * 15f08c3bdfSopenharmony_ci * 16f08c3bdfSopenharmony_ci * 17f08c3bdfSopenharmony_ci * Slaves are concurent processes or thread. 18f08c3bdfSopenharmony_ci * -n <num> : Number of threads to use (mandatory). 19f08c3bdfSopenharmony_ci * -f <file> : Run the test on given test file defined by the -f option (mandatory). 20f08c3bdfSopenharmony_ci * -c <num> : Number of clients to connect before starting the tests. 21f08c3bdfSopenharmony_ci * 22f08c3bdfSopenharmony_ci * HISTORY : This program was written to stress NFSv4 locks. 23f08c3bdfSopenharmony_ci * EXAMPLE : ./locktests -n 50 -f /file/system/to/test 24f08c3bdfSopenharmony_ci * 25f08c3bdfSopenharmony_ci * 26f08c3bdfSopenharmony_ci * Vincent ROQUETA 2005 - vincent.roqueta@ext.bull.net 27f08c3bdfSopenharmony_ci * BULL S.A. 28f08c3bdfSopenharmony_ci */ 29f08c3bdfSopenharmony_ci 30f08c3bdfSopenharmony_ci#include "locktests.h" 31f08c3bdfSopenharmony_ci 32f08c3bdfSopenharmony_ciint MAXLEN = 64; 33f08c3bdfSopenharmony_ciint MAXTEST = 10; 34f08c3bdfSopenharmony_ciextern int maxClients; 35f08c3bdfSopenharmony_ciextern int fdServer; 36f08c3bdfSopenharmony_ci 37f08c3bdfSopenharmony_cichar message[M_SIZE]; 38f08c3bdfSopenharmony_ciint slaveReader; 39f08c3bdfSopenharmony_ciint masterReader; 40f08c3bdfSopenharmony_ciint slaveWriter; 41f08c3bdfSopenharmony_ci 42f08c3bdfSopenharmony_ci/* Which lock will be applied by the master process on test startup */ 43f08c3bdfSopenharmony_ciint LIST_LOCKS[] = { READLOCK, WRITELOCK, 44f08c3bdfSopenharmony_ci READLOCK, WRITELOCK, 45f08c3bdfSopenharmony_ci READLOCK, WRITELOCK, 46f08c3bdfSopenharmony_ci READLOCK, WRITELOCK, 47f08c3bdfSopenharmony_ci BYTELOCK_READ, BYTELOCK_WRITE 48f08c3bdfSopenharmony_ci}; 49f08c3bdfSopenharmony_ci 50f08c3bdfSopenharmony_ci/* The operations the slave processes will try to perform */ 51f08c3bdfSopenharmony_ciint LIST_TESTS[] = { WRONLY, WRONLY, 52f08c3bdfSopenharmony_ci RDONLY, RDONLY, 53f08c3bdfSopenharmony_ci READLOCK, WRITELOCK, 54f08c3bdfSopenharmony_ci WRITELOCK, READLOCK, 55f08c3bdfSopenharmony_ci BYTELOCK_READ, BYTELOCK_WRITE 56f08c3bdfSopenharmony_ci}; 57f08c3bdfSopenharmony_ci 58f08c3bdfSopenharmony_ci/* List of test names */ 59f08c3bdfSopenharmony_cichar *LIST_NAMES_TESTS[] = { "WRITE ON A READ LOCK", 60f08c3bdfSopenharmony_ci "WRITE ON A WRITE LOCK", 61f08c3bdfSopenharmony_ci "READ ON A READ LOCK", 62f08c3bdfSopenharmony_ci "READ ON A WRITE LOCK", 63f08c3bdfSopenharmony_ci "SET A READ LOCK ON A READ LOCK", 64f08c3bdfSopenharmony_ci "SET A WRITE LOCK ON A WRITE LOCK", 65f08c3bdfSopenharmony_ci "SET A WRITE LOCK ON A READ LOCK", 66f08c3bdfSopenharmony_ci "SET A READ LOCK ON A WRITE LOCK", 67f08c3bdfSopenharmony_ci "READ LOCK THE WHOLE FILE BYTE BY BYTE", 68f08c3bdfSopenharmony_ci "WRITE LOCK THE WHOLE FILE BYTE BY BYTE" 69f08c3bdfSopenharmony_ci}; 70f08c3bdfSopenharmony_ci 71f08c3bdfSopenharmony_ci/* List of expected test results, when slaves are processes */ 72f08c3bdfSopenharmony_ciint LIST_RESULTS_PROCESS[] = { SUCCES, SUCCES, 73f08c3bdfSopenharmony_ci SUCCES, SUCCES, 74f08c3bdfSopenharmony_ci SUCCES, ECHEC, 75f08c3bdfSopenharmony_ci ECHEC, ECHEC, 76f08c3bdfSopenharmony_ci SUCCES, SUCCES 77f08c3bdfSopenharmony_ci}; 78f08c3bdfSopenharmony_ci 79f08c3bdfSopenharmony_ci/* List of expected test results, when slaves are threads */ 80f08c3bdfSopenharmony_ciint LIST_RESULTS_THREADS[] = { SUCCES, SUCCES, 81f08c3bdfSopenharmony_ci SUCCES, SUCCES, 82f08c3bdfSopenharmony_ci SUCCES, SUCCES, 83f08c3bdfSopenharmony_ci SUCCES, SUCCES, 84f08c3bdfSopenharmony_ci ECHEC, ECHEC 85f08c3bdfSopenharmony_ci}; 86f08c3bdfSopenharmony_ci 87f08c3bdfSopenharmony_ciint *LIST_RESULTS = NULL; 88f08c3bdfSopenharmony_cichar *eType = NULL; 89f08c3bdfSopenharmony_ci 90f08c3bdfSopenharmony_ciint TOTAL_RESULT_OK[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; 91f08c3bdfSopenharmony_ci 92f08c3bdfSopenharmony_civoid *slave(void *data); 93f08c3bdfSopenharmony_ciint (*finish) (int a); 94f08c3bdfSopenharmony_ci 95f08c3bdfSopenharmony_ciint finishProcess(int a) 96f08c3bdfSopenharmony_ci{ 97f08c3bdfSopenharmony_ci exit(a); 98f08c3bdfSopenharmony_ci} 99f08c3bdfSopenharmony_ci 100f08c3bdfSopenharmony_ciint (*load) (void); 101f08c3bdfSopenharmony_ci 102f08c3bdfSopenharmony_cistruct dataPub dp; 103f08c3bdfSopenharmony_ci 104f08c3bdfSopenharmony_ci/* Functions to access tests/tests names/tests results*/ 105f08c3bdfSopenharmony_ciint testSuiv(int n) 106f08c3bdfSopenharmony_ci{ 107f08c3bdfSopenharmony_ci return LIST_TESTS[n]; 108f08c3bdfSopenharmony_ci} 109f08c3bdfSopenharmony_ci 110f08c3bdfSopenharmony_ciint resAttSuiv(int n) 111f08c3bdfSopenharmony_ci{ 112f08c3bdfSopenharmony_ci return LIST_RESULTS[n]; 113f08c3bdfSopenharmony_ci} 114f08c3bdfSopenharmony_ci 115f08c3bdfSopenharmony_cichar *nomTestSuiv(int n) 116f08c3bdfSopenharmony_ci{ 117f08c3bdfSopenharmony_ci return LIST_NAMES_TESTS[n]; 118f08c3bdfSopenharmony_ci} 119f08c3bdfSopenharmony_ci 120f08c3bdfSopenharmony_ciint lockSuiv(int n) 121f08c3bdfSopenharmony_ci{ 122f08c3bdfSopenharmony_ci return LIST_LOCKS[n]; 123f08c3bdfSopenharmony_ci} 124f08c3bdfSopenharmony_ci 125f08c3bdfSopenharmony_ci/* Verify the test result is the expected one */ 126f08c3bdfSopenharmony_ciint matchResult(int r, int n) 127f08c3bdfSopenharmony_ci{ 128f08c3bdfSopenharmony_ci 129f08c3bdfSopenharmony_ci P("r=%d\n", r); 130f08c3bdfSopenharmony_ci if (r == LIST_RESULTS[n]) 131f08c3bdfSopenharmony_ci return 1; 132f08c3bdfSopenharmony_ci else 133f08c3bdfSopenharmony_ci return 0; 134f08c3bdfSopenharmony_ci} 135f08c3bdfSopenharmony_ci 136f08c3bdfSopenharmony_ci/* Increments the number of process which have successfully passed the test */ 137f08c3bdfSopenharmony_civoid counter(int r, int n) 138f08c3bdfSopenharmony_ci{ 139f08c3bdfSopenharmony_ci TOTAL_RESULT_OK[n] += matchResult(r, n); 140f08c3bdfSopenharmony_ci} 141f08c3bdfSopenharmony_ci 142f08c3bdfSopenharmony_ci/* Special case for test 'lock file byte byte by byte'. 143f08c3bdfSopenharmony_ci * We ensure each byte is correctly locked. 144f08c3bdfSopenharmony_ci */ 145f08c3bdfSopenharmony_civoid validationResults(int n) 146f08c3bdfSopenharmony_ci{ 147f08c3bdfSopenharmony_ci int i, u, l, fsize; 148f08c3bdfSopenharmony_ci struct flock request; 149f08c3bdfSopenharmony_ci 150f08c3bdfSopenharmony_ci fsize = dp.nclnt * (maxClients + 1); 151f08c3bdfSopenharmony_ci TOTAL_RESULT_OK[n] = 0; 152f08c3bdfSopenharmony_ci l = FALSE; 153f08c3bdfSopenharmony_ci u = TRUE; 154f08c3bdfSopenharmony_ci 155f08c3bdfSopenharmony_ci /* If the expected operation result is a success, we will have to increase the number of correct results */ 156f08c3bdfSopenharmony_ci if (LIST_RESULTS[n]) { 157f08c3bdfSopenharmony_ci l = TRUE; 158f08c3bdfSopenharmony_ci u = FALSE; 159f08c3bdfSopenharmony_ci } 160f08c3bdfSopenharmony_ci 161f08c3bdfSopenharmony_ci for (i = 0; i < fsize; i++) { 162f08c3bdfSopenharmony_ci request.l_type = F_WRLCK; 163f08c3bdfSopenharmony_ci request.l_whence = SEEK_SET; 164f08c3bdfSopenharmony_ci request.l_start = i; 165f08c3bdfSopenharmony_ci request.l_len = 1; 166f08c3bdfSopenharmony_ci fcntl(dp.fd, F_GETLK, &request); 167f08c3bdfSopenharmony_ci /* Ensure the lock is correctly set */ 168f08c3bdfSopenharmony_ci if (request.l_type != F_UNLCK) 169f08c3bdfSopenharmony_ci TOTAL_RESULT_OK[n] += l; 170f08c3bdfSopenharmony_ci else 171f08c3bdfSopenharmony_ci TOTAL_RESULT_OK[n] += u; 172f08c3bdfSopenharmony_ci } 173f08c3bdfSopenharmony_ci} 174f08c3bdfSopenharmony_ci 175f08c3bdfSopenharmony_ciint initTest(void) 176f08c3bdfSopenharmony_ci{ 177f08c3bdfSopenharmony_ci 178f08c3bdfSopenharmony_ci P("Master opens %s\n", dp.fname); 179f08c3bdfSopenharmony_ci dp.fd = open(dp.fname, OPENFLAGS, MANDMODES); 180f08c3bdfSopenharmony_ci if (dp.fd < 0) { 181f08c3bdfSopenharmony_ci perror("lock test : can't open test file :"); 182f08c3bdfSopenharmony_ci finish(1); 183f08c3bdfSopenharmony_ci } 184f08c3bdfSopenharmony_ci P("fd=%d\n", dp.fd); 185f08c3bdfSopenharmony_ci return 0; 186f08c3bdfSopenharmony_ci} 187f08c3bdfSopenharmony_ci 188f08c3bdfSopenharmony_cistruct dataChild *initClientFork(int i) 189f08c3bdfSopenharmony_ci{ 190f08c3bdfSopenharmony_ci struct dataPriv *dpr; 191f08c3bdfSopenharmony_ci struct dataChild *df; 192f08c3bdfSopenharmony_ci 193f08c3bdfSopenharmony_ci /* Initialize private data fields */ 194f08c3bdfSopenharmony_ci dpr = malloc(sizeof(struct dataPriv)); 195f08c3bdfSopenharmony_ci df = malloc(sizeof(struct dataChild)); 196f08c3bdfSopenharmony_ci dpr->whoami = i; 197f08c3bdfSopenharmony_ci df->dp = &dp; 198f08c3bdfSopenharmony_ci df->dpr = dpr; 199f08c3bdfSopenharmony_ci /* Initialize master to client pipe */ 200f08c3bdfSopenharmony_ci dp.lclnt[i] = malloc(sizeof(int) * 2); 201f08c3bdfSopenharmony_ci if (pipe(dp.lclnt[i]) < 0) { 202f08c3bdfSopenharmony_ci perror("Impossible to create pipe\n"); 203f08c3bdfSopenharmony_ci exit(1); 204f08c3bdfSopenharmony_ci } 205f08c3bdfSopenharmony_ci P("Initialization %d\n", i); 206f08c3bdfSopenharmony_ci write(0, ".", 1); 207f08c3bdfSopenharmony_ci return df; 208f08c3bdfSopenharmony_ci} 209f08c3bdfSopenharmony_ci 210f08c3bdfSopenharmony_ciint initialize(int clnt) 211f08c3bdfSopenharmony_ci{ 212f08c3bdfSopenharmony_ci 213f08c3bdfSopenharmony_ci /* Initialize private data fields */ 214f08c3bdfSopenharmony_ci printf("Init\n"); 215f08c3bdfSopenharmony_ci dp.nclnt = clnt; 216f08c3bdfSopenharmony_ci dp.lclnt = malloc(sizeof(int *) * clnt); 217f08c3bdfSopenharmony_ci dp.lthreads = malloc(sizeof(pthread_t) * clnt); 218f08c3bdfSopenharmony_ci 219f08c3bdfSopenharmony_ci /* Initialize client to master pipe */ 220f08c3bdfSopenharmony_ci if (pipe(dp.master) < 0) { 221f08c3bdfSopenharmony_ci perror("Master pipe creation error\n"); 222f08c3bdfSopenharmony_ci exit(1); 223f08c3bdfSopenharmony_ci } 224f08c3bdfSopenharmony_ci printf("%s initialization\n", eType); 225f08c3bdfSopenharmony_ci load(); 226f08c3bdfSopenharmony_ci initTest(); 227f08c3bdfSopenharmony_ci 228f08c3bdfSopenharmony_ci return 0; 229f08c3bdfSopenharmony_ci} 230f08c3bdfSopenharmony_ci 231f08c3bdfSopenharmony_civoid cleanClient(struct dataChild *df) 232f08c3bdfSopenharmony_ci{ 233f08c3bdfSopenharmony_ci int i; 234f08c3bdfSopenharmony_ci i = df->dpr->whoami; 235f08c3bdfSopenharmony_ci free(dp.lclnt[i]); 236f08c3bdfSopenharmony_ci free(df->dpr); 237f08c3bdfSopenharmony_ci free(df); 238f08c3bdfSopenharmony_ci} 239f08c3bdfSopenharmony_ci 240f08c3bdfSopenharmony_civoid clean(void) 241f08c3bdfSopenharmony_ci{ 242f08c3bdfSopenharmony_ci free(dp.lthreads); 243f08c3bdfSopenharmony_ci free(dp.lclnt); 244f08c3bdfSopenharmony_ci} 245f08c3bdfSopenharmony_ci 246f08c3bdfSopenharmony_ciint loadProcess(void) 247f08c3bdfSopenharmony_ci{ 248f08c3bdfSopenharmony_ci int i; 249f08c3bdfSopenharmony_ci struct dataChild *df; 250f08c3bdfSopenharmony_ci for (i = 0; i < dp.nclnt; i++) { 251f08c3bdfSopenharmony_ci df = initClientFork(i); 252f08c3bdfSopenharmony_ci if (!fork()) { 253f08c3bdfSopenharmony_ci P("Running slave num: %d\n", df->dpr->whoami); 254f08c3bdfSopenharmony_ci write(0, ".", 1); 255f08c3bdfSopenharmony_ci slave((void *)df); 256f08c3bdfSopenharmony_ci cleanClient(df); 257f08c3bdfSopenharmony_ci exit(0); 258f08c3bdfSopenharmony_ci } 259f08c3bdfSopenharmony_ci } 260f08c3bdfSopenharmony_ci return 0; 261f08c3bdfSopenharmony_ci} 262f08c3bdfSopenharmony_ci 263f08c3bdfSopenharmony_civoid lockWholeFile(struct flock *request) 264f08c3bdfSopenharmony_ci{ 265f08c3bdfSopenharmony_ci request->l_whence = SEEK_SET; 266f08c3bdfSopenharmony_ci request->l_start = 0; 267f08c3bdfSopenharmony_ci /* Lock the whole file */ 268f08c3bdfSopenharmony_ci request->l_len = 0; 269f08c3bdfSopenharmony_ci} 270f08c3bdfSopenharmony_ci 271f08c3bdfSopenharmony_civoid selectTest(int n, struct s_test *test) 272f08c3bdfSopenharmony_ci{ 273f08c3bdfSopenharmony_ci 274f08c3bdfSopenharmony_ci test->test = testSuiv(n); 275f08c3bdfSopenharmony_ci test->resAtt = resAttSuiv(n); 276f08c3bdfSopenharmony_ci test->nom = nomTestSuiv(n); 277f08c3bdfSopenharmony_ci test->type = lockSuiv(n); 278f08c3bdfSopenharmony_ci} 279f08c3bdfSopenharmony_ci 280f08c3bdfSopenharmony_ci/* Final test report */ 281f08c3bdfSopenharmony_ciint report(int clnt) 282f08c3bdfSopenharmony_ci{ 283f08c3bdfSopenharmony_ci int rc = 0; 284f08c3bdfSopenharmony_ci int i; 285f08c3bdfSopenharmony_ci int totalClients; 286f08c3bdfSopenharmony_ci totalClients = clnt * (maxClients + 1); 287f08c3bdfSopenharmony_ci printf 288f08c3bdfSopenharmony_ci ("\n%s number : %d - Remote clients: %d local client 1 - Total client %d - Total concurent tests: %d\n", 289f08c3bdfSopenharmony_ci eType, clnt, maxClients, maxClients + 1, totalClients); 290f08c3bdfSopenharmony_ci printf("%s number running test successfully :\n", eType); 291f08c3bdfSopenharmony_ci for (i = 0; i < MAXTEST; i++) { 292f08c3bdfSopenharmony_ci if (TOTAL_RESULT_OK[i] != totalClients) 293f08c3bdfSopenharmony_ci rc = 1; 294f08c3bdfSopenharmony_ci 295f08c3bdfSopenharmony_ci printf("%d %s of %d successfully ran test : %s\n", 296f08c3bdfSopenharmony_ci TOTAL_RESULT_OK[i], eType, totalClients, 297f08c3bdfSopenharmony_ci LIST_NAMES_TESTS[i]); 298f08c3bdfSopenharmony_ci } 299f08c3bdfSopenharmony_ci return rc; 300f08c3bdfSopenharmony_ci} 301f08c3bdfSopenharmony_ci 302f08c3bdfSopenharmony_ciint serverSendLocal(void) 303f08c3bdfSopenharmony_ci{ 304f08c3bdfSopenharmony_ci int i; 305f08c3bdfSopenharmony_ci /* Synchronize slave processes */ 306f08c3bdfSopenharmony_ci /* Configure slaves for test */ 307f08c3bdfSopenharmony_ci 308f08c3bdfSopenharmony_ci for (i = 0; i < dp.nclnt; i++) 309f08c3bdfSopenharmony_ci write(dp.lclnt[i][1], message, M_SIZE); 310f08c3bdfSopenharmony_ci return 0; 311f08c3bdfSopenharmony_ci 312f08c3bdfSopenharmony_ci} 313f08c3bdfSopenharmony_ci 314f08c3bdfSopenharmony_civoid serverSendNet(void) 315f08c3bdfSopenharmony_ci{ 316f08c3bdfSopenharmony_ci writeToAllClients(message); 317f08c3bdfSopenharmony_ci} 318f08c3bdfSopenharmony_ci 319f08c3bdfSopenharmony_ciint serverReceiveNet(void) 320f08c3bdfSopenharmony_ci{ 321f08c3bdfSopenharmony_ci int i, c; 322f08c3bdfSopenharmony_ci for (c = 0; c < maxClients; c++) { 323f08c3bdfSopenharmony_ci for (i = 0; i < dp.nclnt; i++) { 324f08c3bdfSopenharmony_ci serverReceiveClient(c); 325f08c3bdfSopenharmony_ci } 326f08c3bdfSopenharmony_ci } 327f08c3bdfSopenharmony_ci return 0; 328f08c3bdfSopenharmony_ci} 329f08c3bdfSopenharmony_ci 330f08c3bdfSopenharmony_ciint serverReceiveLocal(void) 331f08c3bdfSopenharmony_ci{ 332f08c3bdfSopenharmony_ci int i; 333f08c3bdfSopenharmony_ci for (i = 0; i < dp.nclnt; i++) 334f08c3bdfSopenharmony_ci read(masterReader, message, M_SIZE); 335f08c3bdfSopenharmony_ci return 0; 336f08c3bdfSopenharmony_ci} 337f08c3bdfSopenharmony_ci 338f08c3bdfSopenharmony_ciint clientReceiveLocal(void) 339f08c3bdfSopenharmony_ci{ 340f08c3bdfSopenharmony_ci read(slaveReader, message, M_SIZE); 341f08c3bdfSopenharmony_ci return 0; 342f08c3bdfSopenharmony_ci} 343f08c3bdfSopenharmony_ci 344f08c3bdfSopenharmony_ciint clientSend(void) 345f08c3bdfSopenharmony_ci{ 346f08c3bdfSopenharmony_ci write(slaveWriter, message, M_SIZE); 347f08c3bdfSopenharmony_ci return 0; 348f08c3bdfSopenharmony_ci} 349f08c3bdfSopenharmony_ci 350f08c3bdfSopenharmony_ciint serverSend(void) 351f08c3bdfSopenharmony_ci{ 352f08c3bdfSopenharmony_ci serverSendNet(); 353f08c3bdfSopenharmony_ci serverSendLocal(); 354f08c3bdfSopenharmony_ci return 0; 355f08c3bdfSopenharmony_ci} 356f08c3bdfSopenharmony_ci 357f08c3bdfSopenharmony_ciint serverReceive(void) 358f08c3bdfSopenharmony_ci{ 359f08c3bdfSopenharmony_ci serverReceiveNet(); 360f08c3bdfSopenharmony_ci serverReceiveLocal(); 361f08c3bdfSopenharmony_ci return 0; 362f08c3bdfSopenharmony_ci} 363f08c3bdfSopenharmony_ci 364f08c3bdfSopenharmony_ci/* binary structure <-> ASCII functions used to ensure data will be correctly used over 365f08c3bdfSopenharmony_ci * the network, especially when multiples clients do not use the same hardware architecture. 366f08c3bdfSopenharmony_ci */ 367f08c3bdfSopenharmony_ciint serializeTLock(struct s_test *tLock) 368f08c3bdfSopenharmony_ci{ 369f08c3bdfSopenharmony_ci memset(message, 0, M_SIZE); 370f08c3bdfSopenharmony_ci sprintf(message, "T:%d:%d:%d::", tLock->test, tLock->type, 371f08c3bdfSopenharmony_ci tLock->resAtt); 372f08c3bdfSopenharmony_ci return 0; 373f08c3bdfSopenharmony_ci} 374f08c3bdfSopenharmony_ci 375f08c3bdfSopenharmony_civoid unSerializeTLock(struct s_test *tLock) 376f08c3bdfSopenharmony_ci{ 377f08c3bdfSopenharmony_ci sscanf(message, "T:%d:%d:%d::", &(tLock->test), &(tLock->type), 378f08c3bdfSopenharmony_ci &(tLock->resAtt)); 379f08c3bdfSopenharmony_ci memset(message, 0, M_SIZE); 380f08c3bdfSopenharmony_ci 381f08c3bdfSopenharmony_ci} 382f08c3bdfSopenharmony_ci 383f08c3bdfSopenharmony_civoid serializeFLock(struct flock *request) 384f08c3bdfSopenharmony_ci{ 385f08c3bdfSopenharmony_ci int len, pid, start; 386f08c3bdfSopenharmony_ci memset(message, 0, M_SIZE); 387f08c3bdfSopenharmony_ci len = (int)request->l_len; 388f08c3bdfSopenharmony_ci pid = (int)request->l_pid; 389f08c3bdfSopenharmony_ci start = (int)request->l_start; 390f08c3bdfSopenharmony_ci /* Beware to length of integer conversions ... */ 391f08c3bdfSopenharmony_ci sprintf(message, "L:%hd:%hd:%d:%d:%d::", 392f08c3bdfSopenharmony_ci request->l_type, request->l_whence, start, len, pid); 393f08c3bdfSopenharmony_ci} 394f08c3bdfSopenharmony_ci 395f08c3bdfSopenharmony_civoid serializeResult(int result) 396f08c3bdfSopenharmony_ci{ 397f08c3bdfSopenharmony_ci memset(message, 0, M_SIZE); 398f08c3bdfSopenharmony_ci sprintf(message, "R:%d::", result); 399f08c3bdfSopenharmony_ci 400f08c3bdfSopenharmony_ci} 401f08c3bdfSopenharmony_ci 402f08c3bdfSopenharmony_civoid unSerializeResult(int *result) 403f08c3bdfSopenharmony_ci{ 404f08c3bdfSopenharmony_ci sscanf(message, "R:%d::", result); 405f08c3bdfSopenharmony_ci} 406f08c3bdfSopenharmony_ci 407f08c3bdfSopenharmony_civoid unSerializeFLock(struct flock *request) 408f08c3bdfSopenharmony_ci{ 409f08c3bdfSopenharmony_ci int len, pid, start; 410f08c3bdfSopenharmony_ci sscanf(message, "L:%hd:%hd:%d:%d:%d::", 411f08c3bdfSopenharmony_ci &(request->l_type), &(request->l_whence), &start, &len, &pid); 412f08c3bdfSopenharmony_ci request->l_start = (off_t) start; 413f08c3bdfSopenharmony_ci request->l_len = (off_t) len; 414f08c3bdfSopenharmony_ci request->l_pid = (pid_t) pid; 415f08c3bdfSopenharmony_ci} 416f08c3bdfSopenharmony_ci 417f08c3bdfSopenharmony_ciint serverSendLockClient(struct flock *request, int client) 418f08c3bdfSopenharmony_ci{ 419f08c3bdfSopenharmony_ci serializeFLock(request); 420f08c3bdfSopenharmony_ci return serverSendClient(client); 421f08c3bdfSopenharmony_ci} 422f08c3bdfSopenharmony_ci 423f08c3bdfSopenharmony_ciint serverSendLockLocal(struct flock *request, int slave) 424f08c3bdfSopenharmony_ci{ 425f08c3bdfSopenharmony_ci serializeFLock(request); 426f08c3bdfSopenharmony_ci return write(dp.lclnt[slave][1], message, M_SIZE); 427f08c3bdfSopenharmony_ci} 428f08c3bdfSopenharmony_ci 429f08c3bdfSopenharmony_ciint getLockSection(struct flock *request) 430f08c3bdfSopenharmony_ci{ 431f08c3bdfSopenharmony_ci memset(message, 0, M_SIZE); 432f08c3bdfSopenharmony_ci clientReceiveLocal(); 433f08c3bdfSopenharmony_ci unSerializeFLock(request); 434f08c3bdfSopenharmony_ci return 0; 435f08c3bdfSopenharmony_ci} 436f08c3bdfSopenharmony_ci 437f08c3bdfSopenharmony_ciint sendLockTest(struct s_test *tLock) 438f08c3bdfSopenharmony_ci{ 439f08c3bdfSopenharmony_ci serializeTLock(tLock); 440f08c3bdfSopenharmony_ci serverSend(); 441f08c3bdfSopenharmony_ci return 0; 442f08c3bdfSopenharmony_ci} 443f08c3bdfSopenharmony_ci 444f08c3bdfSopenharmony_ciint getLockTest(struct s_test *tLock) 445f08c3bdfSopenharmony_ci{ 446f08c3bdfSopenharmony_ci clientReceiveLocal(); 447f08c3bdfSopenharmony_ci unSerializeTLock(tLock); 448f08c3bdfSopenharmony_ci return 0; 449f08c3bdfSopenharmony_ci} 450f08c3bdfSopenharmony_ci 451f08c3bdfSopenharmony_ciint sendResult(int result) 452f08c3bdfSopenharmony_ci{ 453f08c3bdfSopenharmony_ci serializeResult(result); 454f08c3bdfSopenharmony_ci clientSend(); 455f08c3bdfSopenharmony_ci return 0; 456f08c3bdfSopenharmony_ci} 457f08c3bdfSopenharmony_ci 458f08c3bdfSopenharmony_ciint getResults(int ntest) 459f08c3bdfSopenharmony_ci{ 460f08c3bdfSopenharmony_ci int i, c; 461f08c3bdfSopenharmony_ci int result = 0; 462f08c3bdfSopenharmony_ci /* Add remote test results */ 463f08c3bdfSopenharmony_ci for (c = 0; c < maxClients; c++) { 464f08c3bdfSopenharmony_ci for (i = 0; i < dp.nclnt; i++) { 465f08c3bdfSopenharmony_ci serverReceiveClient(c); 466f08c3bdfSopenharmony_ci unSerializeResult(&result); 467f08c3bdfSopenharmony_ci counter(result, ntest); 468f08c3bdfSopenharmony_ci 469f08c3bdfSopenharmony_ci } 470f08c3bdfSopenharmony_ci } 471f08c3bdfSopenharmony_ci /* Add local test results */ 472f08c3bdfSopenharmony_ci for (i = 0; i < dp.nclnt; i++) { 473f08c3bdfSopenharmony_ci read(masterReader, message, M_SIZE); 474f08c3bdfSopenharmony_ci unSerializeResult(&result); 475f08c3bdfSopenharmony_ci counter(result, ntest); 476f08c3bdfSopenharmony_ci } 477f08c3bdfSopenharmony_ci 478f08c3bdfSopenharmony_ci return 0; 479f08c3bdfSopenharmony_ci} 480f08c3bdfSopenharmony_ci 481f08c3bdfSopenharmony_ci#ifdef DEBUG 482f08c3bdfSopenharmony_ci#define P(a,b) memset(dbg,0,16);sprintf(dbg,a,b);write(0,dbg,16); 483f08c3bdfSopenharmony_ci#endif 484f08c3bdfSopenharmony_ci 485f08c3bdfSopenharmony_ci/* In the case of a network use, the master of the client application si only 486f08c3bdfSopenharmony_ci * a 'repeater' of information. It resends server-master instructions to its own slaves. 487f08c3bdfSopenharmony_ci */ 488f08c3bdfSopenharmony_civoid masterClient(void) 489f08c3bdfSopenharmony_ci{ 490f08c3bdfSopenharmony_ci fd_set fdread; 491f08c3bdfSopenharmony_ci struct timeval tv; 492f08c3bdfSopenharmony_ci int n, i, r, m, start; 493f08c3bdfSopenharmony_ci#ifdef DEBUG 494f08c3bdfSopenharmony_ci char dbg[16]; 495f08c3bdfSopenharmony_ci#endif 496f08c3bdfSopenharmony_ci struct flock lock; 497f08c3bdfSopenharmony_ci int t; 498f08c3bdfSopenharmony_ci 499f08c3bdfSopenharmony_ci masterReader = dp.master[0]; 500f08c3bdfSopenharmony_ci FD_ZERO(&fdread); 501f08c3bdfSopenharmony_ci tv.tv_sec = 50; 502f08c3bdfSopenharmony_ci tv.tv_usec = 0; 503f08c3bdfSopenharmony_ci n = fdServer > masterReader ? fdServer : masterReader; 504f08c3bdfSopenharmony_ci printf("Master Client - fdServer=%d\n", fdServer); 505f08c3bdfSopenharmony_ci while (1) { 506f08c3bdfSopenharmony_ci /* Add slave and server pipe file descriptors */ 507f08c3bdfSopenharmony_ci FD_ZERO(&fdread); 508f08c3bdfSopenharmony_ci FD_SET(fdServer, &fdread); 509f08c3bdfSopenharmony_ci FD_SET(masterReader, &fdread); 510f08c3bdfSopenharmony_ci r = select(n + 1, &fdread, NULL, NULL, &tv); 511f08c3bdfSopenharmony_ci if (r < 0) { 512f08c3bdfSopenharmony_ci perror("select:\n"); 513f08c3bdfSopenharmony_ci continue; 514f08c3bdfSopenharmony_ci } 515f08c3bdfSopenharmony_ci if (r == 0) { 516f08c3bdfSopenharmony_ci exit(0); 517f08c3bdfSopenharmony_ci } 518f08c3bdfSopenharmony_ci 519f08c3bdfSopenharmony_ci if (FD_ISSET(fdServer, &fdread)) { 520f08c3bdfSopenharmony_ci /* We just have received information from the server. 521f08c3bdfSopenharmony_ci * We repeat it to slaves. 522f08c3bdfSopenharmony_ci */ 523f08c3bdfSopenharmony_ci i = readFromServer(message); 524f08c3bdfSopenharmony_ci t = message[0]; 525f08c3bdfSopenharmony_ci switch (t) { 526f08c3bdfSopenharmony_ci case 'L': 527f08c3bdfSopenharmony_ci /* Lock instruction. We need to send a different section to lock to each process */ 528f08c3bdfSopenharmony_ci unSerializeFLock(&lock); 529f08c3bdfSopenharmony_ci start = lock.l_start; 530f08c3bdfSopenharmony_ci for (i = 0; i < dp.nclnt; i++) { 531f08c3bdfSopenharmony_ci lock.l_start = start + i; 532f08c3bdfSopenharmony_ci serializeFLock(&lock); 533f08c3bdfSopenharmony_ci write(dp.lclnt[i][1], message, M_SIZE); 534f08c3bdfSopenharmony_ci } 535f08c3bdfSopenharmony_ci printf("\n"); 536f08c3bdfSopenharmony_ci continue; 537f08c3bdfSopenharmony_ci case 'T': 538f08c3bdfSopenharmony_ci /* Test instruction. Ensure server is not sending the END(ish) instruction to end tests */ 539f08c3bdfSopenharmony_ci /* To be rewritten asap */ 540f08c3bdfSopenharmony_ci m = atoi(&(message[2])); 541f08c3bdfSopenharmony_ci if (m == END) 542f08c3bdfSopenharmony_ci break; 543f08c3bdfSopenharmony_ci if (m == CLEAN) 544f08c3bdfSopenharmony_ci printf("\n"); 545f08c3bdfSopenharmony_ci 546f08c3bdfSopenharmony_ci serverSendLocal(); 547f08c3bdfSopenharmony_ci continue; 548f08c3bdfSopenharmony_ci } 549f08c3bdfSopenharmony_ci break; 550f08c3bdfSopenharmony_ci } else { 551f08c3bdfSopenharmony_ci /* Else, we read information from slaves and repeat them to the server */ 552f08c3bdfSopenharmony_ci for (i = 0; i < dp.nclnt; i++) { 553f08c3bdfSopenharmony_ci r = read(masterReader, message, M_SIZE); 554f08c3bdfSopenharmony_ci r = write(fdServer, message, M_SIZE); 555f08c3bdfSopenharmony_ci if (r < 0) 556f08c3bdfSopenharmony_ci perror("write : "); 557f08c3bdfSopenharmony_ci 558f08c3bdfSopenharmony_ci } 559f08c3bdfSopenharmony_ci continue; 560f08c3bdfSopenharmony_ci } 561f08c3bdfSopenharmony_ci } 562f08c3bdfSopenharmony_ci 563f08c3bdfSopenharmony_ci /* Receive the END(ish) instruction */ 564f08c3bdfSopenharmony_ci 565f08c3bdfSopenharmony_ci /* Repeat it to the slaves */ 566f08c3bdfSopenharmony_ci printf("Exiting...\n"); 567f08c3bdfSopenharmony_ci serverSendLocal(); 568f08c3bdfSopenharmony_ci 569f08c3bdfSopenharmony_ci /* Ok, we can quit */ 570f08c3bdfSopenharmony_ci printf("Bye :)\n"); 571f08c3bdfSopenharmony_ci 572f08c3bdfSopenharmony_ci} 573f08c3bdfSopenharmony_ci 574f08c3bdfSopenharmony_ciint master(void) 575f08c3bdfSopenharmony_ci{ 576f08c3bdfSopenharmony_ci int i, n, bl; 577f08c3bdfSopenharmony_ci int clnt; 578f08c3bdfSopenharmony_ci char tmp[MAXLEN], *buf; 579f08c3bdfSopenharmony_ci#ifdef DEBUG 580f08c3bdfSopenharmony_ci char dbg[16]; 581f08c3bdfSopenharmony_ci#endif 582f08c3bdfSopenharmony_ci struct flock request; 583f08c3bdfSopenharmony_ci struct s_test tLock = { 0 }; 584f08c3bdfSopenharmony_ci enum state_t state; 585f08c3bdfSopenharmony_ci int offset; 586f08c3bdfSopenharmony_ci /* A test sentence written in the file */ 587f08c3bdfSopenharmony_ci char phraseTest[] = 588f08c3bdfSopenharmony_ci "Ceci est une phrase test ecrite par le maitre dans le fichier"; 589f08c3bdfSopenharmony_ci bl = -1; 590f08c3bdfSopenharmony_ci clnt = dp.nclnt; 591f08c3bdfSopenharmony_ci masterReader = dp.master[0]; 592f08c3bdfSopenharmony_ci state = SELECT; 593f08c3bdfSopenharmony_ci /* Start with the first test ;) */ 594f08c3bdfSopenharmony_ci n = 0; 595f08c3bdfSopenharmony_ci printf("\n--------------------------------------\n"); 596f08c3bdfSopenharmony_ci while (1) { 597f08c3bdfSopenharmony_ci switch (state) { 598f08c3bdfSopenharmony_ci case SELECT: 599f08c3bdfSopenharmony_ci /* Select the test to perform */ 600f08c3bdfSopenharmony_ci printf("\n"); 601f08c3bdfSopenharmony_ci E("Master: SELECT"); 602f08c3bdfSopenharmony_ci selectTest(n, &tLock); 603f08c3bdfSopenharmony_ci state = tLock.type; 604f08c3bdfSopenharmony_ci bl = 0; 605f08c3bdfSopenharmony_ci if (n < MAXTEST) { 606f08c3bdfSopenharmony_ci memset(tmp, 0, MAXLEN); 607f08c3bdfSopenharmony_ci sprintf(tmp, "TEST : TRY TO %s:", 608f08c3bdfSopenharmony_ci LIST_NAMES_TESTS[n]); 609f08c3bdfSopenharmony_ci write(0, tmp, strlen(tmp)); 610f08c3bdfSopenharmony_ci } else 611f08c3bdfSopenharmony_ci state = END; 612f08c3bdfSopenharmony_ci P("state=%d\n", state); 613f08c3bdfSopenharmony_ci n += 1; 614f08c3bdfSopenharmony_ci continue; 615f08c3bdfSopenharmony_ci 616f08c3bdfSopenharmony_ci case RDONLY: 617f08c3bdfSopenharmony_ci case WRONLY: 618f08c3bdfSopenharmony_ci 619f08c3bdfSopenharmony_ci case READLOCK: 620f08c3bdfSopenharmony_ci P("Read lock :%d\n", state); 621f08c3bdfSopenharmony_ci request.l_type = F_RDLCK; 622f08c3bdfSopenharmony_ci state = LOCK; 623f08c3bdfSopenharmony_ci continue; 624f08c3bdfSopenharmony_ci 625f08c3bdfSopenharmony_ci case WRITELOCK: 626f08c3bdfSopenharmony_ci P("Write lock :%d\n", state); 627f08c3bdfSopenharmony_ci request.l_type = F_WRLCK; 628f08c3bdfSopenharmony_ci state = LOCK; 629f08c3bdfSopenharmony_ci continue; 630f08c3bdfSopenharmony_ci 631f08c3bdfSopenharmony_ci case LOCK: 632f08c3bdfSopenharmony_ci /* Apply the wanted lock */ 633f08c3bdfSopenharmony_ci E("Master: LOCK"); 634f08c3bdfSopenharmony_ci write(dp.fd, phraseTest, strlen(phraseTest)); 635f08c3bdfSopenharmony_ci lockWholeFile(&request); 636f08c3bdfSopenharmony_ci if (fcntl(dp.fd, F_SETLK, &request) < 0) { 637f08c3bdfSopenharmony_ci perror("Master: can't set lock\n"); 638f08c3bdfSopenharmony_ci perror("Echec\n"); 639f08c3bdfSopenharmony_ci exit(0); 640f08c3bdfSopenharmony_ci } 641f08c3bdfSopenharmony_ci E("Master"); 642f08c3bdfSopenharmony_ci state = SYNC; 643f08c3bdfSopenharmony_ci continue; 644f08c3bdfSopenharmony_ci 645f08c3bdfSopenharmony_ci case BYTELOCK_READ: 646f08c3bdfSopenharmony_ci bl = 1; 647f08c3bdfSopenharmony_ci request.l_type = F_RDLCK; 648f08c3bdfSopenharmony_ci state = SYNC; 649f08c3bdfSopenharmony_ci continue; 650f08c3bdfSopenharmony_ci 651f08c3bdfSopenharmony_ci case BYTELOCK_WRITE: 652f08c3bdfSopenharmony_ci bl = 1; 653f08c3bdfSopenharmony_ci request.l_type = F_WRLCK; 654f08c3bdfSopenharmony_ci state = SYNC; 655f08c3bdfSopenharmony_ci continue; 656f08c3bdfSopenharmony_ci 657f08c3bdfSopenharmony_ci case BYTELOCK: 658f08c3bdfSopenharmony_ci /* The main idea is to lock all the bytes in a file. Each slave process locks one byte. 659f08c3bdfSopenharmony_ci * 660f08c3bdfSopenharmony_ci * We need : 661f08c3bdfSopenharmony_ci * - To create a file of a length equal to the total number of slave processes 662f08c3bdfSopenharmony_ci * - send the exact section to lock to each slave 663f08c3bdfSopenharmony_ci * - ensure locks have been correctly set 664f08c3bdfSopenharmony_ci */ 665f08c3bdfSopenharmony_ci 666f08c3bdfSopenharmony_ci /* Create a string to record in the test file. Length is exactly the number of sub process */ 667f08c3bdfSopenharmony_ci P("Master: BYTELOCK: %d\n", state); 668f08c3bdfSopenharmony_ci buf = malloc(clnt * (maxClients + 1)); 669f08c3bdfSopenharmony_ci memset(buf, '*', clnt); 670f08c3bdfSopenharmony_ci write(dp.fd, buf, clnt); 671f08c3bdfSopenharmony_ci free(buf); 672f08c3bdfSopenharmony_ci 673f08c3bdfSopenharmony_ci /* Each slave process re-writes its own field to lock */ 674f08c3bdfSopenharmony_ci request.l_whence = SEEK_SET; 675f08c3bdfSopenharmony_ci request.l_start = 0; 676f08c3bdfSopenharmony_ci request.l_len = 1; 677f08c3bdfSopenharmony_ci 678f08c3bdfSopenharmony_ci /* Start to send sections to lock to remote process (network clients) */ 679f08c3bdfSopenharmony_ci for (i = 0; i < maxClients; i++) { 680f08c3bdfSopenharmony_ci /* Set the correct byte to lock */ 681f08c3bdfSopenharmony_ci offset = (i + 1) * clnt; 682f08c3bdfSopenharmony_ci request.l_start = (off_t) offset; 683f08c3bdfSopenharmony_ci serverSendLockClient(&request, i); 684f08c3bdfSopenharmony_ci } 685f08c3bdfSopenharmony_ci 686f08c3bdfSopenharmony_ci /* Now send sections to local processes */ 687f08c3bdfSopenharmony_ci for (i = 0; i < clnt; i++) { 688f08c3bdfSopenharmony_ci request.l_start = i; 689f08c3bdfSopenharmony_ci serverSendLockLocal(&request, i); 690f08c3bdfSopenharmony_ci } 691f08c3bdfSopenharmony_ci state = RESULT; 692f08c3bdfSopenharmony_ci continue; 693f08c3bdfSopenharmony_ci 694f08c3bdfSopenharmony_ci case SYNC: 695f08c3bdfSopenharmony_ci sendLockTest(&tLock); 696f08c3bdfSopenharmony_ci if (bl) { 697f08c3bdfSopenharmony_ci state = BYTELOCK; 698f08c3bdfSopenharmony_ci continue; 699f08c3bdfSopenharmony_ci } 700f08c3bdfSopenharmony_ci 701f08c3bdfSopenharmony_ci if (n < MAXTEST + 1) 702f08c3bdfSopenharmony_ci state = RESULT; 703f08c3bdfSopenharmony_ci else 704f08c3bdfSopenharmony_ci state = END; 705f08c3bdfSopenharmony_ci continue; 706f08c3bdfSopenharmony_ci 707f08c3bdfSopenharmony_ci case RESULT: 708f08c3bdfSopenharmony_ci /* Read results by one */ 709f08c3bdfSopenharmony_ci getResults(n - 1); 710f08c3bdfSopenharmony_ci if (bl) 711f08c3bdfSopenharmony_ci validationResults(n - 1); 712f08c3bdfSopenharmony_ci state = CLEAN; 713f08c3bdfSopenharmony_ci continue; 714f08c3bdfSopenharmony_ci 715f08c3bdfSopenharmony_ci case CLEAN: 716f08c3bdfSopenharmony_ci /* Ask the clients to stop testing ... */ 717f08c3bdfSopenharmony_ci tLock.test = CLEAN; 718f08c3bdfSopenharmony_ci serializeTLock(&tLock); 719f08c3bdfSopenharmony_ci serverSend(); 720f08c3bdfSopenharmony_ci /* ... and wait for an ack before closing */ 721f08c3bdfSopenharmony_ci serverReceive(); 722f08c3bdfSopenharmony_ci /* Ignore message content : that is only an ack */ 723f08c3bdfSopenharmony_ci 724f08c3bdfSopenharmony_ci /* close and open file */ 725f08c3bdfSopenharmony_ci close(dp.fd); 726f08c3bdfSopenharmony_ci initTest(); 727f08c3bdfSopenharmony_ci state = SELECT; 728f08c3bdfSopenharmony_ci continue; 729f08c3bdfSopenharmony_ci case END: 730f08c3bdfSopenharmony_ci tLock.test = END; 731f08c3bdfSopenharmony_ci serializeTLock(&tLock); 732f08c3bdfSopenharmony_ci serverSend(); 733f08c3bdfSopenharmony_ci sleep(2); 734f08c3bdfSopenharmony_ci break; 735f08c3bdfSopenharmony_ci 736f08c3bdfSopenharmony_ci printf("(end)\n"); 737f08c3bdfSopenharmony_ci exit(0); 738f08c3bdfSopenharmony_ci 739f08c3bdfSopenharmony_ci } 740f08c3bdfSopenharmony_ci break; 741f08c3bdfSopenharmony_ci } 742f08c3bdfSopenharmony_ci 743f08c3bdfSopenharmony_ci return report(clnt); 744f08c3bdfSopenharmony_ci} 745f08c3bdfSopenharmony_ci 746f08c3bdfSopenharmony_ci/* Slave process/thread */ 747f08c3bdfSopenharmony_ci 748f08c3bdfSopenharmony_civoid *slave(void *data) 749f08c3bdfSopenharmony_ci{ 750f08c3bdfSopenharmony_ci struct dataChild *df; 751f08c3bdfSopenharmony_ci int i, a, result, ftest; 752f08c3bdfSopenharmony_ci struct s_test tLock; 753f08c3bdfSopenharmony_ci struct flock request; 754f08c3bdfSopenharmony_ci char tmp[16]; 755f08c3bdfSopenharmony_ci#ifdef DEBUG 756f08c3bdfSopenharmony_ci char dbg[16]; 757f08c3bdfSopenharmony_ci#endif 758f08c3bdfSopenharmony_ci char *phraseTest = "L'ecriture a reussi"; 759f08c3bdfSopenharmony_ci int len; 760f08c3bdfSopenharmony_ci enum state_t state; 761f08c3bdfSopenharmony_ci 762f08c3bdfSopenharmony_ci result = -1; 763f08c3bdfSopenharmony_ci ftest = -1; 764f08c3bdfSopenharmony_ci len = strlen(phraseTest); 765f08c3bdfSopenharmony_ci df = (struct dataChild *)data; 766f08c3bdfSopenharmony_ci i = df->dpr->whoami; 767f08c3bdfSopenharmony_ci P("Slave n=%d\n", i); 768f08c3bdfSopenharmony_ci slaveReader = dp.lclnt[i][0]; 769f08c3bdfSopenharmony_ci slaveWriter = dp.master[1]; 770f08c3bdfSopenharmony_ci state = SYNC; 771f08c3bdfSopenharmony_ci errno = 0; 772f08c3bdfSopenharmony_ci memset(tmp, 0, 16); 773f08c3bdfSopenharmony_ci while (1) { 774f08c3bdfSopenharmony_ci switch (state) { 775f08c3bdfSopenharmony_ci case SELECT: 776f08c3bdfSopenharmony_ci case SYNC: 777f08c3bdfSopenharmony_ci getLockTest(&tLock); 778f08c3bdfSopenharmony_ci state = tLock.test; 779f08c3bdfSopenharmony_ci P("Slave State=%d\n", state); 780f08c3bdfSopenharmony_ci 781f08c3bdfSopenharmony_ci continue; 782f08c3bdfSopenharmony_ci case RDONLY: 783f08c3bdfSopenharmony_ci /* Try to read a file */ 784f08c3bdfSopenharmony_ci P("TEST READ ONLY %d\n", RDONLY); 785f08c3bdfSopenharmony_ci if ((ftest = open(dp.fname, O_RDONLY | O_NONBLOCK)) < 0) { 786f08c3bdfSopenharmony_ci result = ECHEC; 787f08c3bdfSopenharmony_ci state = RESULT; 788f08c3bdfSopenharmony_ci if (dp.verbose) 789f08c3bdfSopenharmony_ci perror("Open:"); 790f08c3bdfSopenharmony_ci continue; 791f08c3bdfSopenharmony_ci } 792f08c3bdfSopenharmony_ci P("fd=%d\n", ftest); 793f08c3bdfSopenharmony_ci a = read(ftest, tmp, 16); 794f08c3bdfSopenharmony_ci if (a < 16) 795f08c3bdfSopenharmony_ci result = ECHEC; 796f08c3bdfSopenharmony_ci else 797f08c3bdfSopenharmony_ci result = SUCCES; 798f08c3bdfSopenharmony_ci state = RESULT; 799f08c3bdfSopenharmony_ci continue; 800f08c3bdfSopenharmony_ci 801f08c3bdfSopenharmony_ci case WRONLY: 802f08c3bdfSopenharmony_ci /* Try to write a file */ 803f08c3bdfSopenharmony_ci P("TEST WRITE ONLY %d\n", WRONLY); 804f08c3bdfSopenharmony_ci if ((ftest = open(dp.fname, O_WRONLY | O_NONBLOCK)) < 0) { 805f08c3bdfSopenharmony_ci result = ECHEC; 806f08c3bdfSopenharmony_ci state = RESULT; 807f08c3bdfSopenharmony_ci if (dp.verbose) 808f08c3bdfSopenharmony_ci perror("Open read only:"); 809f08c3bdfSopenharmony_ci continue; 810f08c3bdfSopenharmony_ci } 811f08c3bdfSopenharmony_ci P("fd=%d\n", ftest); 812f08c3bdfSopenharmony_ci if (write(ftest, phraseTest, len) < len) 813f08c3bdfSopenharmony_ci result = ECHEC; 814f08c3bdfSopenharmony_ci else 815f08c3bdfSopenharmony_ci result = SUCCES; 816f08c3bdfSopenharmony_ci state = RESULT; 817f08c3bdfSopenharmony_ci continue; 818f08c3bdfSopenharmony_ci 819f08c3bdfSopenharmony_ci case LOCK: 820f08c3bdfSopenharmony_ci 821f08c3bdfSopenharmony_ci case READLOCK: 822f08c3bdfSopenharmony_ci /* Try to read a read-locked section */ 823f08c3bdfSopenharmony_ci P("READ LOCK %d\n", F_RDLCK); 824f08c3bdfSopenharmony_ci if ((ftest = open(dp.fname, O_RDONLY | O_NONBLOCK)) < 0) { 825f08c3bdfSopenharmony_ci result = ECHEC; 826f08c3bdfSopenharmony_ci state = RESULT; 827f08c3bdfSopenharmony_ci if (dp.verbose) 828f08c3bdfSopenharmony_ci perror("Open read-write:"); 829f08c3bdfSopenharmony_ci continue; 830f08c3bdfSopenharmony_ci } 831f08c3bdfSopenharmony_ci 832f08c3bdfSopenharmony_ci P("fd=%d\n", ftest); 833f08c3bdfSopenharmony_ci /* Lock the whole file */ 834f08c3bdfSopenharmony_ci request.l_type = F_RDLCK; 835f08c3bdfSopenharmony_ci request.l_whence = SEEK_SET; 836f08c3bdfSopenharmony_ci request.l_start = 0; 837f08c3bdfSopenharmony_ci request.l_len = 0; 838f08c3bdfSopenharmony_ci 839f08c3bdfSopenharmony_ci if (fcntl(ftest, F_SETLK, &request) < 0) { 840f08c3bdfSopenharmony_ci if (dp.verbose || errno != EAGAIN) 841f08c3bdfSopenharmony_ci perror("RDONLY: fcntl"); 842f08c3bdfSopenharmony_ci result = ECHEC; 843f08c3bdfSopenharmony_ci } else 844f08c3bdfSopenharmony_ci result = SUCCES; 845f08c3bdfSopenharmony_ci state = RESULT; 846f08c3bdfSopenharmony_ci continue; 847f08c3bdfSopenharmony_ci 848f08c3bdfSopenharmony_ci case WRITELOCK: 849f08c3bdfSopenharmony_ci /* Try to write a file */ 850f08c3bdfSopenharmony_ci P("WRITE LOCK %d\n", F_WRLCK); 851f08c3bdfSopenharmony_ci if ((ftest = open(dp.fname, O_WRONLY | O_NONBLOCK)) < 0) { 852f08c3bdfSopenharmony_ci result = ECHEC; 853f08c3bdfSopenharmony_ci state = RESULT; 854f08c3bdfSopenharmony_ci if (dp.verbose) 855f08c3bdfSopenharmony_ci perror("\nOpen:"); 856f08c3bdfSopenharmony_ci continue; 857f08c3bdfSopenharmony_ci } 858f08c3bdfSopenharmony_ci /* Lock the whole file */ 859f08c3bdfSopenharmony_ci P("fd=%d\n", ftest); 860f08c3bdfSopenharmony_ci request.l_type = F_WRLCK; 861f08c3bdfSopenharmony_ci request.l_whence = SEEK_SET; 862f08c3bdfSopenharmony_ci request.l_start = 0; 863f08c3bdfSopenharmony_ci request.l_len = 0; 864f08c3bdfSopenharmony_ci 865f08c3bdfSopenharmony_ci if (fcntl(ftest, F_SETLK, &request) < 0) { 866f08c3bdfSopenharmony_ci if (dp.verbose || errno != EAGAIN) 867f08c3bdfSopenharmony_ci perror("\nWRONLY: fcntl"); 868f08c3bdfSopenharmony_ci result = ECHEC; 869f08c3bdfSopenharmony_ci } else 870f08c3bdfSopenharmony_ci result = SUCCES; 871f08c3bdfSopenharmony_ci state = RESULT; 872f08c3bdfSopenharmony_ci continue; 873f08c3bdfSopenharmony_ci 874f08c3bdfSopenharmony_ci case BYTELOCK_READ: 875f08c3bdfSopenharmony_ci P("BYTE LOCK READ: %d\n", state); 876f08c3bdfSopenharmony_ci state = BYTELOCK; 877f08c3bdfSopenharmony_ci continue; 878f08c3bdfSopenharmony_ci 879f08c3bdfSopenharmony_ci case BYTELOCK_WRITE: 880f08c3bdfSopenharmony_ci P("BYTE LOCK WRITE: %d\n", state); 881f08c3bdfSopenharmony_ci state = BYTELOCK; 882f08c3bdfSopenharmony_ci continue; 883f08c3bdfSopenharmony_ci 884f08c3bdfSopenharmony_ci case BYTELOCK: 885f08c3bdfSopenharmony_ci /* Wait for the exact section to lock. The whole file is sent by the master */ 886f08c3bdfSopenharmony_ci P("BYTE LOCK %d\n", state); 887f08c3bdfSopenharmony_ci getLockSection(&request); 888f08c3bdfSopenharmony_ci if ((ftest = open(dp.fname, O_RDWR | O_NONBLOCK)) < 0) { 889f08c3bdfSopenharmony_ci result = ECHEC; 890f08c3bdfSopenharmony_ci state = RESULT; 891f08c3bdfSopenharmony_ci if (dp.verbose) 892f08c3bdfSopenharmony_ci perror("\nOpen:"); 893f08c3bdfSopenharmony_ci continue; 894f08c3bdfSopenharmony_ci } 895f08c3bdfSopenharmony_ci 896f08c3bdfSopenharmony_ci if (fcntl(ftest, F_SETLK, &request) < 0) { 897f08c3bdfSopenharmony_ci if (dp.verbose || errno != EAGAIN) 898f08c3bdfSopenharmony_ci perror("\nBTLOCK: fcntl"); 899f08c3bdfSopenharmony_ci result = ECHEC; 900f08c3bdfSopenharmony_ci state = RESULT; 901f08c3bdfSopenharmony_ci continue; 902f08c3bdfSopenharmony_ci } 903f08c3bdfSopenharmony_ci /* Change the character at the given position for an easier verification */ 904f08c3bdfSopenharmony_ci a = lseek(ftest, request.l_start, SEEK_SET); 905f08c3bdfSopenharmony_ci write(ftest, "=", 1); 906f08c3bdfSopenharmony_ci result = SUCCES; 907f08c3bdfSopenharmony_ci state = RESULT; 908f08c3bdfSopenharmony_ci continue; 909f08c3bdfSopenharmony_ci 910f08c3bdfSopenharmony_ci case RESULT: 911f08c3bdfSopenharmony_ci if (result == SUCCES) 912f08c3bdfSopenharmony_ci write(0, "=", 1); 913f08c3bdfSopenharmony_ci else 914f08c3bdfSopenharmony_ci write(0, "x", 1); 915f08c3bdfSopenharmony_ci P("RESULT: %d\n", result); 916f08c3bdfSopenharmony_ci sendResult(result); 917f08c3bdfSopenharmony_ci state = SYNC; 918f08c3bdfSopenharmony_ci continue; 919f08c3bdfSopenharmony_ci 920f08c3bdfSopenharmony_ci case CLEAN: 921f08c3bdfSopenharmony_ci close(ftest); 922f08c3bdfSopenharmony_ci /* Send CLEAN Ack */ 923f08c3bdfSopenharmony_ci sendResult(result); 924f08c3bdfSopenharmony_ci state = SYNC; 925f08c3bdfSopenharmony_ci continue; 926f08c3bdfSopenharmony_ci 927f08c3bdfSopenharmony_ci case END: 928f08c3bdfSopenharmony_ci E("(End)\n"); 929f08c3bdfSopenharmony_ci finish(0); 930f08c3bdfSopenharmony_ci printf("Unknown command\n"); 931f08c3bdfSopenharmony_ci finish(1); 932f08c3bdfSopenharmony_ci 933f08c3bdfSopenharmony_ci } 934f08c3bdfSopenharmony_ci } 935f08c3bdfSopenharmony_ci 936f08c3bdfSopenharmony_ci} 937f08c3bdfSopenharmony_ci 938f08c3bdfSopenharmony_cichar *nextArg(int argc, char **argv, int *i) 939f08c3bdfSopenharmony_ci{ 940f08c3bdfSopenharmony_ci if (((*i) + 1) < argc) { 941f08c3bdfSopenharmony_ci (*i) += 1; 942f08c3bdfSopenharmony_ci return argv[(*i)]; 943f08c3bdfSopenharmony_ci } 944f08c3bdfSopenharmony_ci return NULL; 945f08c3bdfSopenharmony_ci} 946f08c3bdfSopenharmony_ci 947f08c3bdfSopenharmony_ciint usage(void) 948f08c3bdfSopenharmony_ci{ 949f08c3bdfSopenharmony_ci printf("locktest -n <number of process> -f <test file> [-T]\n"); 950f08c3bdfSopenharmony_ci printf("Number of child process must be higher than 1\n"); 951f08c3bdfSopenharmony_ci exit(0); 952f08c3bdfSopenharmony_ci return 0; 953f08c3bdfSopenharmony_ci} 954f08c3bdfSopenharmony_ci 955f08c3bdfSopenharmony_ciint main(int argc, char **argv) 956f08c3bdfSopenharmony_ci{ 957f08c3bdfSopenharmony_ci int rc = 0; 958f08c3bdfSopenharmony_ci int i, nThread = 0; 959f08c3bdfSopenharmony_ci char *tmp; 960f08c3bdfSopenharmony_ci int type = 0; 961f08c3bdfSopenharmony_ci int clients; 962f08c3bdfSopenharmony_ci type = PROCESS; 963f08c3bdfSopenharmony_ci dp.fname = NULL; 964f08c3bdfSopenharmony_ci dp.verbose = 0; 965f08c3bdfSopenharmony_ci int server = 1; 966f08c3bdfSopenharmony_ci char *host; 967f08c3bdfSopenharmony_ci 968f08c3bdfSopenharmony_ci host = NULL; 969f08c3bdfSopenharmony_ci clients = 0; 970f08c3bdfSopenharmony_ci 971f08c3bdfSopenharmony_ci for (i = 1; i < argc; i++) { 972f08c3bdfSopenharmony_ci 973f08c3bdfSopenharmony_ci if (!strcmp("-n", argv[i])) { 974f08c3bdfSopenharmony_ci if (!(tmp = nextArg(argc, argv, &i))) 975f08c3bdfSopenharmony_ci usage(); 976f08c3bdfSopenharmony_ci nThread = atoi(tmp); 977f08c3bdfSopenharmony_ci continue; 978f08c3bdfSopenharmony_ci } 979f08c3bdfSopenharmony_ci 980f08c3bdfSopenharmony_ci if (!strcmp("-f", argv[i])) { 981f08c3bdfSopenharmony_ci if (!(dp.fname = nextArg(argc, argv, &i))) 982f08c3bdfSopenharmony_ci usage(); 983f08c3bdfSopenharmony_ci continue; 984f08c3bdfSopenharmony_ci } 985f08c3bdfSopenharmony_ci if (!strcmp("-v", argv[i])) { 986f08c3bdfSopenharmony_ci dp.verbose = TRUE; 987f08c3bdfSopenharmony_ci continue; 988f08c3bdfSopenharmony_ci } 989f08c3bdfSopenharmony_ci if (!strcmp("-c", argv[i])) { 990f08c3bdfSopenharmony_ci if (!(clients = atoi(nextArg(argc, argv, &i)))) 991f08c3bdfSopenharmony_ci usage(); 992f08c3bdfSopenharmony_ci continue; 993f08c3bdfSopenharmony_ci } 994f08c3bdfSopenharmony_ci 995f08c3bdfSopenharmony_ci if (!strcmp("--server", argv[i])) { 996f08c3bdfSopenharmony_ci if (!(host = nextArg(argc, argv, &i))) 997f08c3bdfSopenharmony_ci usage(); 998f08c3bdfSopenharmony_ci server = 0; 999f08c3bdfSopenharmony_ci continue; 1000f08c3bdfSopenharmony_ci } 1001f08c3bdfSopenharmony_ci printf("Ignoring unknown option: %s\n", argv[i]); 1002f08c3bdfSopenharmony_ci } 1003f08c3bdfSopenharmony_ci 1004f08c3bdfSopenharmony_ci if (server) { 1005f08c3bdfSopenharmony_ci if (!(dp.fname && nThread)) 1006f08c3bdfSopenharmony_ci usage(); 1007f08c3bdfSopenharmony_ci if (clients > 0) { 1008f08c3bdfSopenharmony_ci configureServer(clients); 1009f08c3bdfSopenharmony_ci setupClients(type, dp.fname, nThread); 1010f08c3bdfSopenharmony_ci } 1011f08c3bdfSopenharmony_ci } else { 1012f08c3bdfSopenharmony_ci configureClient(host); 1013f08c3bdfSopenharmony_ci dp.fname = malloc(512); 1014f08c3bdfSopenharmony_ci memset(dp.fname, 0, 512); 1015f08c3bdfSopenharmony_ci getConfiguration(&type, dp.fname, &nThread); 1016f08c3bdfSopenharmony_ci } 1017f08c3bdfSopenharmony_ci 1018f08c3bdfSopenharmony_ci if (dp.verbose) 1019f08c3bdfSopenharmony_ci printf("By process.\n"); 1020f08c3bdfSopenharmony_ci load = loadProcess; 1021f08c3bdfSopenharmony_ci eType = "process"; 1022f08c3bdfSopenharmony_ci finish = finishProcess; 1023f08c3bdfSopenharmony_ci LIST_RESULTS = LIST_RESULTS_PROCESS; 1024f08c3bdfSopenharmony_ci initialize(nThread); 1025f08c3bdfSopenharmony_ci if (server) { 1026f08c3bdfSopenharmony_ci rc = master(); 1027f08c3bdfSopenharmony_ci } else { 1028f08c3bdfSopenharmony_ci masterClient(); 1029f08c3bdfSopenharmony_ci free(dp.fname); 1030f08c3bdfSopenharmony_ci } 1031f08c3bdfSopenharmony_ci clean(); 1032f08c3bdfSopenharmony_ci 1033f08c3bdfSopenharmony_ci return rc; 1034f08c3bdfSopenharmony_ci} 1035