⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 winos.c

📁 在VC6环境下开发
💻 C
📖 第 1 页 / 共 2 页
字号:
	return osType==2;
}
/*
** Windows file locking notes:  [similar issues apply to MacOS]
**
** We cannot use LockFileEx() or UnlockFileEx() on Win95/98/ME because
** those functions are not available.  So we use only LockFile() and
** UnlockFile().
**
** LockFile() prevents not just writing but also reading by other processes.
** (This is a design error on the part of Windows, but there is nothing
** we can do about that.)  So the region used for locking is at the
** end of the file where it is unlikely to ever interfere with an
** actual read attempt.
**
** A database read lock is obtained by locking a single randomly-chosen 
** byte out of a specific range of bytes. The lock byte is obtained at 
** random so two separate readers can probably access the file at the 
** same time, unless they are unlucky and choose the same lock byte.
** A database write lock is obtained by locking all bytes in the range.
** There can only be one writer.
**
** A lock is obtained on the first byte of the lock range before acquiring
** either a read lock or a write lock.  This prevents two processes from
** attempting to get a lock at a same time.  The semantics of 
** eDbOsReadLock() require that if there is already a write lock, that
** lock is converted into a read lock atomically.  The lock on the first
** byte allows us to drop the old write lock and get the read lock without
** another process jumping into the middle and messing us up.  The same
** argument applies to eDbOsWriteLock().
**
** On WinNT/2K/XP systems, LockFileEx() and UnlockFileEx() are available,
** which means we can use reader/writer locks.  When reader writer locks
** are used, the lock is placed on the same range of bytes that is used
** for probabilistic locking in Win95/98/ME.  Hence, the locking scheme
** will support two or more Win95 readers or two or more WinNT readers.
** But a single Win95 reader will lock out all WinNT readers and a single
** WinNT reader will lock out all other Win95 readers.
**
** Note: On MacOS we use the resource fork for locking.
**
** The following #defines specify the range of bytes used for locking.
** N_LOCKBYTE is the number of bytes available for doing the locking.
** The first byte used to hold the lock while the lock is changing does
** not count toward this number.  FIRST_LOCKBYTE is the address of
** the first byte in the range of bytes used for locking.
*/
#define N_LOCKBYTE       10239
# define FIRST_LOCKBYTE   (0xffffffff - N_LOCKBYTE)

/*
** Change the status of the lock on the file "id" to be a readlock.
** If the file was write locked, then this reduces the lock to a read.
** If the file was read locked, then this acquires a new read lock.
**
** Return eDb_OK on success and eDb_BUSY on failure.  If this
** library was compiled with large file support (LFS) but LFS is not
** available on the host, then an eDb_NOLFS is returned.
*/
int eDbOsReadLock(OsFile *id){
	int rc;
	if( id->locked>0 ){
		rc = eDb_OK;
	}else{
		int lk;
		int res;
		int cnt = 100;
		eDbRandomness(sizeof(lk), &lk);
		lk = (lk & 0x7fffffff)%N_LOCKBYTE + 1;
		while( cnt-->0 && (res = LockFile(id->h, FIRST_LOCKBYTE, 0, 1, 0))==0 ){
			Sleep(1);
		}
		if( res ){
			UnlockFile(id->h, FIRST_LOCKBYTE+1, 0, N_LOCKBYTE, 0);
			if( isNT() ){
				OVERLAPPED ovlp;
				ovlp.Offset = FIRST_LOCKBYTE+1;
				ovlp.OffsetHigh = 0;
				ovlp.hEvent = 0;
				res = LockFileEx(id->h, LOCKFILE_FAIL_IMMEDIATELY, 
								  0, N_LOCKBYTE, 0, &ovlp);
			}else{
				res = LockFile(id->h, FIRST_LOCKBYTE+lk, 0, 1, 0);
			}
			UnlockFile(id->h, FIRST_LOCKBYTE, 0, 1, 0);
		}
		if( res ){
			id->locked = lk;
			rc = eDb_OK;
		}else{
			rc = eDb_BUSY;
		}
	}
	return rc;
}

/*
** Change the lock status to be an exclusive or write lock.  Return
** eDb_OK on success and eDb_BUSY on a failure.  If this
** library was compiled with large file support (LFS) but LFS is not
** available on the host, then an eDb_NOLFS is returned.
*/
int eDbOsWriteLock(OsFile *id){
	int rc;
	if( id->locked<0 ){
		rc = eDb_OK;
	}else{
		int res;
		int cnt = 100;
		while( cnt-->0 && (res = LockFile(id->h, FIRST_LOCKBYTE, 0, 1, 0))==0 ){
			Sleep(1);
		}
		if( res ){
			if( id->locked>0 ){
				if( isNT() ){
					UnlockFile(id->h, FIRST_LOCKBYTE+1, 0, N_LOCKBYTE, 0);
				}else{
					res = UnlockFile(id->h, FIRST_LOCKBYTE + id->locked, 0, 1, 0);
				}
			}
			if( res ){
				res = LockFile(id->h, FIRST_LOCKBYTE+1, 0, N_LOCKBYTE, 0);
			}else{
				res = 0;
			}
			UnlockFile(id->h, FIRST_LOCKBYTE, 0, 1, 0);
		}
		if( res ){
			id->locked = -1;
			rc = eDb_OK;
		}else{
			rc = eDb_BUSY;
		}
	}
	return rc;
}

/*
** Unlock the given file descriptor.  If the file descriptor was
** not previously locked, then this routine is a no-op.  If this
** library was compiled with large file support (LFS) but LFS is not
** available on the host, then an eDb_NOLFS is returned.
*/
int eDbOsUnlock(OsFile *id){
	int rc;
	if( id->locked==0 ){
	rc = eDb_OK;
	}else if( isNT() || id->locked<0 ){
		UnlockFile(id->h, FIRST_LOCKBYTE+1, 0, N_LOCKBYTE, 0);
		rc = eDb_OK;
		id->locked = 0;
	}else{
		UnlockFile(id->h, FIRST_LOCKBYTE+id->locked, 0, 1, 0);
		rc = eDb_OK;
		id->locked = 0;
	}
	return rc;
}

/*
** Get information to seed the random number generator.  The seed
** is written into the buffer zBuf[256].  The calling function must
** supply a sufficiently large buffer.
*/
int eDbOsRandomSeed(char *zBuf){
  /* We have to initialize zBuf to prevent valgrind from reporting
  ** errors.  The reports issued by valgrind are incorrect - we would
  ** prefer that the randomness be increased by making use of the
  ** uninitialized space in zBuf - but valgrind errors tend to worry
  ** some users.  Rather than argue, it seems easier just to initialize
  ** the whole array and silence valgrind, even if that means less randomness
  ** in the random seed.
  **
  ** When testing, initializing zBuf[] to zero is all we do.  That means
  ** that we always use the same random number sequence.* This makes the
  ** tests repeatable.
  */
	memset(zBuf, 0, 256);
#if !defined(eDb_TEST)
	GetSystemTime((LPSYSTEMTIME)zBuf);
#endif
	return eDb_OK;
}

/*
** Sleep for a little while.  Return the amount of time slept.
*/
int eDbOsSleep(int ms){
	Sleep(ms);
	return ms;
}

/*
** Static variables used for thread synchronization
*/
static int inMutex = 0;
#ifdef eDb_W32_THREADS
  static CRITICAL_SECTION cs;
#endif
/*
** The following pair of routine implement mutual exclusion for
** multi-threaded processes.  Only a single thread is allowed to
** executed code that is surrounded by EnterMutex() and LeaveMutex().
**
** eDb uses only a single Mutex.  There is not much critical
** code and what little there is executes quickly and without blocking.
*/
void eDbOsEnterMutex(){
#ifdef eDb_W32_THREADS
	static int isInit = 0;
	while( !isInit ){
		static long lock = 0;
		if( InterlockedIncrement(&lock)==1 ){
			InitializeCriticalSection(&cs);
			isInit = 1;
		}else{
			Sleep(1);
		}
	}
	EnterCriticalSection(&cs);
#endif
	assert( !inMutex );
	inMutex = 1;
}
void eDbOsLeaveMutex(){
	assert( inMutex );
	inMutex = 0;
#ifdef eDb_W32_THREADS
	LeaveCriticalSection(&cs);
#endif
}

/*
** Turn a relative pathname into a full pathname.  Return a pointer
** to the full pathname stored in space obtained from eDbMalloc().
** The calling function is responsible for freeing this space once it
** is no longer needed.
*/
char *eDbOsFullPathname(const char *zRelative){
	char *zNotUsed;
	char *zFull;
	int nByte;
	nByte = GetFullPathName(zRelative, 0, 0, &zNotUsed) + 1;
	zFull = eDbMalloc( nByte );
	if( zFull==0 ) return 0;
	GetFullPathName(zRelative, nByte, zFull, &zNotUsed);
	return zFull;
}

/*
** The following variable, if set to a now-zero value, become the result
** returned from eDbOsCurrentTime().  This is used for testing.
*/
#ifdef eDb_TEST
	int eDb_current_time = 0;
#endif

/*
** Find the current time (in Universal Coordinated Time).  Write the
** current time and date as a Julian Day number into *prNow and
** return 0.  Return 1 if the time and date cannot be found.
*/
int eDbOsCurrentTime(double *prNow){
	FILETIME ft;
	/* FILETIME structure is a 64-bit value representing the number of 
	 100-nanosecond intervals since January 1, 1601 (= JD 2305813.5). 
	*/
	double now;
	GetSystemTimeAsFileTime( &ft );
	now = ((double)ft.dwHighDateTime) * 4294967296.0; 
	*prNow = (now + ft.dwLowDateTime)/864000000000.0 + 2305813.5;
	return 0;
}


/*
** Get a single 8-bit random value from the RC4 PRNG.  The Mutex
** must be held while executing this routine.
**
** Why not just use a library random generator like lrand48() for this?
** Because the OP_NewRecno opcode in the VDBE depends on having a very
** good source of random numbers.  The lrand48() library function may
** well be good enough.  But maybe not.  Or maybe lrand48() has some
** subtle problems on some systems that could cause problems.  It is hard
** to know.  To minimize the risk of problems due to bad lrand48()
** implementations, eDb uses this random number generator based
** on RC4, which we know works very well.
*/
static int randomByte(){
	unsigned char t;

  /* All threads share a single random number generator.
  ** This structure is the current state of the generator.
  */
	static struct {
		unsigned char isInit;          /* True if initialized */
		unsigned char i, j;            /* State variables */
		unsigned char s[256];          /* State variables */
	} prng;

  /* Initialize the state of the random number generator once,
  ** the first time this routine is called.  The seed value does
  ** not need to contain a lot of randomness since we are not
  ** trying to do secure encryption or anything like that...
  **
  ** Nothing in this file or anywhere else in eDb does any kind of
  ** encryption.  The RC4 algorithm is being used as a PRNG (pseudo-random
  ** number generator) not as an encryption device.
  */
	if( !prng.isInit ){
		int i;
		char k[256];
		prng.j = 0;
		prng.i = 0;
		eDbOsRandomSeed(k);
		for(i=0; i<256; i++){
			prng.s[i] = i;
		}
		for(i=0; i<256; i++){
			prng.j += prng.s[i] + k[i];
			t = prng.s[prng.j];
			prng.s[prng.j] = prng.s[i];
			prng.s[i] = t;
		}
		prng.isInit = 1;
	}

	/* Generate and return single random byte
	*/
	prng.i++;
	t = prng.s[prng.i];
	prng.j += t;
	prng.s[prng.i] = prng.s[prng.j];
	prng.s[prng.j] = t;
	t += prng.s[prng.i];
	return prng.s[t];
}

/*
** Return N random bytes.
*/
void eDbRandomness(int N, void *pBuf){
	unsigned char *zBuf = pBuf;
	eDbOsEnterMutex();
	while( N-- ){
		*(zBuf++) = randomByte();
	}
	eDbOsLeaveMutex();

}
/*
** get a random between 0 and 59
** 
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
*/

int  getRandom(int i)
{
/*
  int re;
  PstructTime timePtr;
  InitRtc();
  Get_Rtc(timePtr);
  re=timePtr->second%i;
  return re;
*/
	return 0;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -