///////////////////////////////////////////////////////////////////////////// // Rev 11/12/2003 // // // LOCK.C // ------ // // // Sylvain MARECHAL - sylvain.marechal1@libertysurf.fr ///////////////////////////////////////////////////////////////////////////// // // Sample to show file lock usage under Win32 and Unix // // ///////////////////////////////////////////////////////////////////////////// #ifdef _WIN32 #include #include #include #include #include #include #else #include #include #include #define O_BINARY 0 #endif #include #include #include #include #include #include // If you link with ../tools/semaphore, define it to 1 #define SEMAPHORE_DEFINED 0 #if SEMAPHORE_DEFINED #include "semaphore.h" #endif ///////////////////////////////////////////////////////////////////////////// // // CHANGEFILESIZE ///////////////////////////////////////////////////////////////////////////// // // DESCRIPTION // --ChangeFileSize-- // // Change file size // // ARGUMENTS // Argument1: int hFile // Argument2: size_t cbSize // RETOUR/RESULTAT // int // REMARQUE // Rev 11/12/2003 ////////////////////////////////////////////////////////////////////////////// int ChangeFileSize(int hFile, size_t cbSize) { #if _WIN32 chsize(hFile, cbSize); #else ftruncate(hFile, cbSize); #endif return 0; } ///////////////////////////////////////////////////////////////////////////// // // GETCLOCKCOUNT ///////////////////////////////////////////////////////////////////////////// // // DESCRIPTION // --GetClockCount-- // // Return a relative current time in milliseconds // // ARGUMENTS // Argument1: void // RETOUR/RESULTAT // long // REMARQUE // Rev 11/12/2003 ////////////////////////////////////////////////////////////////////////////// long GetClockCount(void) { #ifdef _WIN32 return clock () ; #else static struct timeval ClockCount; struct timeval Now; static long diff; if( ClockCount.tv_sec != 0 ) { gettimeofday(&Now, NULL); diff += (Now.tv_sec - ClockCount.tv_sec) * 1000L; diff += (Now.tv_usec - ClockCount.tv_usec) / 1000L; ClockCount.tv_sec = Now.tv_sec ; ClockCount.tv_usec = Now.tv_usec ; return diff; } else { gettimeofday(&ClockCount, NULL); diff = 0 ; return 0; } #endif } ///////////////////////////////////////////////////////////////////////////// // // MYLOCKFILE ///////////////////////////////////////////////////////////////////////////// // // DESCRIPTION // --myLockFile-- // Lock file // ARGUMENTS // Argument1: int iFileHandle File handle given by open(), creat // RETOUR/RESULTAT // int // REMARQUE // Rev 11/12/2003 ////////////////////////////////////////////////////////////////////////////// int myLockFile(int iFileHandle) { int iRet = 0; #ifndef _WIN32 struct flock lock; int iLockMode = F_WRLCK; #else int iLockMode = LK_LOCK; //LK_NBLCK #endif #ifndef _WIN32 /*on lock*/ lock.l_type = iLockMode; lock.l_whence = 0; lock.l_start = 0; lock.l_len = 0; iRet = fcntl(iFileHandle, F_SETLKW, &lock); #else lseek( iFileHandle, 0, SEEK_SET ); if( (iRet = locking( iFileHandle, iLockMode, 1 )) == 0 ) lseek( iFileHandle, 0, SEEK_END ); #endif return iRet; } ///////////////////////////////////////////////////////////////////////////// // // MYUNLOCKFILE ///////////////////////////////////////////////////////////////////////////// // // DESCRIPTION // --myUnLockFile-- // Unlock file // ARGUMENTS // Argument1: int iFileHandle file handle // RETOUR/RESULTAT // static int // REMARQUE // Rev 11/12/2003 ////////////////////////////////////////////////////////////////////////////// static int myUnLockFile(int iFileHandle) { int iRet = 0; #ifndef _WIN32 struct flock lock; #endif #ifndef _WIN32 /*on lock*/ lock.l_type = F_UNLCK; lock.l_whence = 0; lock.l_start = 0; lock.l_len = 0; iRet = fcntl(iFileHandle, F_SETLKW, &lock); #else lseek( iFileHandle, 0, SEEK_SET ); iRet = locking( iFileHandle, LK_UNLCK , 1 ); #endif if(iRet == -1) iRet = errno; return iRet; } ///////////////////////////////////////////////////////////////////////////// // // MAIN ///////////////////////////////////////////////////////////////////////////// // // DESCRIPTION // --main-- // // Show how lock works // // ARGUMENTS // Argument1: int argc // Argument2: char * argv[] // RETOUR/RESULTAT // int // REMARQUE // Rev 11/12/2003 ////////////////////////////////////////////////////////////////////////////// int main( int argc, char * argv[] ) { int fd; char * pszFile; char pBuffer[] = "coucouaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\n"; int cbBuffer = strlen(pBuffer); Semaphore * hSemaphore; int nRet; int fLockWithSemaphore; long clockCount; int fChild; int i; int pid; int nbWrites = 100000; /* basic parsing */ if( argc < 3 ) { printf( "Usage %s \n", argv[0] ); exit(1); } pszFile = argv[1]; fLockWithSemaphore = atoi(argv[2]); fChild = argc == 4 ? 1 : 0; #if ! SEMAPHORE_DEFINED fLockWithSemaphore = 0; #endif /* How many time does it take ? */ if( ! fChild ) { clockCount = GetClockCount(); } /* destroy last file */ unlink( pszFile ); /* What do we do ? */ printf( "Using %s ...\n", fLockWithSemaphore ? "semaphore" : "file lock" ); /* Create one child */ if( ! fChild ) { #ifdef _WIN32 /* Create a child process */ pid = spawnl( P_NOWAIT, argv[0], argv[0], argv[1], argv[2], "child", NULL ); #else pid = fork(); if( pid == 0 ) { execle( argv[0], argv[0], argv[1], argv[2], "child", NULL ); return; } else if( pid == -1 ) { printf( "fork() error %d\n", errno ); } #endif } /* try to open the file */ fd = open(pszFile, O_RDWR | O_BINARY); if( fd < 0 ) { /* Creat it */ fd = creat(pszFile, 0664); if( fd < 0 ) { printf( "Can't open file '%s' (errno=%d)\n", pszFile, errno ); exit(2); } } #ifdef _WIN32 setmode( fd, O_BINARY ); #endif #if SEMAPHORE_DEFINED if( fLockWithSemaphore ) { /* Create a semaphore instead of locking file */ hSemaphore = semCreate("./", fChild ? SEM_OPEN : SEM_CREAT ); if( hSemaphore == NULL ) { printf( "SemaphoreCreate() error (%d)\n", errno ); return 0; } } #endif for(i = 0; i < nbWrites; i ++) { int nPos; #if SEMAPHORE_DEFINED if( fLockWithSemaphore ) { /* ** Lock the semaphore, so that only one process try to ** enlarge the file */ nRet = semAcquire( hSemaphore ); if( nRet < 0 ) { printf( "SemaphoreBeginCritical() error (%d)\n", errno ); return 0; } /* Enlarge the file from size that will be written */ nPos = lseek( fd, 0, SEEK_END ); ChangeFileSize( fd, nPos + cbBuffer ); /* ** Unlock the semaphore */ nRet = semRelease( hSemaphore ); if( nRet < 0 ) { printf( "SemaphoreEndCritical() error (%d)\n", errno ); return 0; } } else #endif //SEMAPHORE_DEFINED { /* ** Lock the file */ myLockFile(fd); lseek( fd, 0, SEEK_END ); } /* ** Write data in the file : We are sure not to overwrite ** data */ write( fd, pBuffer, cbBuffer ); if( ! fLockWithSemaphore ) { /* ** Unlock the file */ myUnLockFile(fd); } } #ifdef _WIN32 WaitForSingleObject( (HANDLE)pid, INFINITE ); #else { int status; wait( &status ); } #endif /* How many time does it take ? */ if( ! fChild ) { printf( "File size = %d, Time elapsed : %d ms\n", lseek( fd, 0, SEEK_END), GetClockCount() - clockCount ); } #ifndef _WIN32 if( ! fChild ) #endif { #if SEMAPHORE_DEFINED /* Destroy semaphore */ if( fLockWithSemaphore ) { nRet = semDestroy( hSemaphore ); if( nRet < 0 ) { printf( "SemaphoreDestroy() error (%d)\n", errno ); return 0; } } #endif } close( fd ); if( fChild ) { printf( "Child exiting ...\n" ); } return 0; }