?? ucos.c
字號(hào):
/*
** This file contains code that is specific to particular operating
** systems. The purpose of this file is to provide a uniform abstraction
** on which the rest of eDb can operate.
*/
#include "eDbInit.h"
/*
** Macros for performance tracing. Normally turned off
*/
#define TIMER_START
#define TIMER_END
#define SEEK(X)
#define TRACE1(X)
#define TRACE2(X,Y)
#define TRACE3(X,Y,Z)
#define TRACE4(X,Y,Z,A)
#define TRACE5(X,Y,Z,A,B)
/*
** If we compile with the eDb_TEST macro set, then the following block
** of code will give us the ability to simulate a disk I/O error. This
** is used for testing the I/O recovery logic.
*/
#ifdef eDb_TEST
int eDb_io_error_pending = 0;
#define SimulateIOError(A) \
if( eDb_io_error_pending ) \
if( eDb_io_error_pending-- == 1 ){ local_ioerr(); return A; }
static void local_ioerr(){
eDb_io_error_pending = 0; /* Really just a place to set a breakpoint */
}
#else
#define SimulateIOError(A)
#endif
/*
** When testing, keep a count of the number of open files.
*/
#ifdef eDb_TEST
int eDb_open_file_count = 0;
#define OpenCounter(X) eDb_open_file_count+=(X)
#else
#define OpenCounter(X)
#endif
/*
** Delete the named file
*/
int eDbOsDelete(const char *zFilename){
DeleteFile((char *)zFilename);
return eDb_OK;
}
/*
** Return TRUE if the named file exists.
*/
int eDbOsFileExists(const char *zFilename){
return FileExist((char *)zFilename);
}
/*
** Attempt to open a file for both reading and writing. If that
** fails, try opening it read-only. If the file does not exist,
** try to create it.
**
** On success, a handle for the open file is written to *id
** and *pReadonly is set to 0 if the file was opened for reading and
** writing or 1 if the file was opened read-only. The function returns
** eDb_OK.
**
** On failure, the function returns eDb_CANTOPEN and leaves
** *id and *pReadonly unchanged.
*/
int eDbOsOpenReadWrite(const char *zFilename,OsFile *id,int *pReadonly){
if(FileExist((char *)zFilename) == 0){
CreateFile((char *)zFilename);
}
id->h = OpenFile((char *)zFilename,FILEMODE_READ|FILEMODE_WRITE);
id->locked = 0;
*pReadonly = 0;
return eDb_OK;
}
/*
** Attempt to open a new file for exclusive access by this process.
** The file will be opened for both reading and writing. To avoid
** a potential security problem, we do not allow the file to have
** previously existed. Nor do we allow the file to be a symbolic
** link.
**
** If delFlag is true, then make arrangements to automatically delete
** the file when it is closed.
**
** On success, write the file handle into *id and return eDb_OK.
**
** On failure, return eDb_CANTOPEN.
*/
int eDbOsOpenExclusive(const char *zFilename, OsFile *id, int delFlag){
if(FileExist((char *)zFilename) == 0){
CreateFile((char *)zFilename);
}
id->h = OpenFile((char *)zFilename,FILEMODE_READ|FILEMODE_WRITE);
id->locked = 0;
delFlag = delFlag;
return eDb_OK;
}
/*
** Attempt to open a new file for read-only access.
**
** On success, write the file handle into *id and return eDb_OK.
**
** On failure, return eDb_CANTOPEN.
*/
int eDbOsOpenReadOnly(const char *zFilename, OsFile *id){
if(FileExist((char *)zFilename) == 0){
CreateFile((char *)zFilename);
}
id->h = OpenFile((char *)zFilename,FILEMODE_READ);
id->locked = 0;
return eDb_OK;
}
/*
** Attempt to open a file descriptor for the directory that contains a
** file. This file descriptor can be used to fsync() the directory
** in order to make sure the creation of a new file is actually written
** to disk.
**
** This routine is only meaningful for Unix. It is a no-op under
** windows since windows does not support hard links.
**
** On success, a handle for a previously open file is at *id is
** updated with the new directory file descriptor and eDb_OK is
** returned.
**
** On failure, the function returns eDb_CANTOPEN and leaves
** *id unchanged.
*/
int eDbOsOpenDirectory(const char *zDirname,OsFile *id){
return eDb_OK;
}
/*
** Create a temporary file name in zBuf. zBuf must be big enough to
** hold at least eDb_TEMPNAME_SIZE characters.
*/
void eDbRandomness(int N, void *pBuf);
int eDbOsTempFileName(char *zBuf){
return eDb_OK;
}
/*
** Close a file.
*/
int eDbOsClose(OsFile *id){
CloseFile(id->h);
id->locked = 0;
return eDb_OK;
}
/*
** Read data from a file into a buffer. Return eDb_OK if all
** bytes were read successfully and eDb_IOERR if anything goes
** wrong.
*/
int eDbOsRead(OsFile *id, void *pBuf, int amt){
int n = ReadFile(id->h,(u8 *)pBuf,amt);
if(n == amt)
return eDb_OK;
else
return eDb_ERROR;
}
/*
** Write data from a buffer into a file. Return eDb_OK on success
** or some other error code on failure.
*/
int eDbOsWrite(OsFile *id, const void *pBuf, int amt){
int n = WriteFile(id->h,(u8 *)pBuf,amt);
if(n == amt)
return eDb_OK;
else
return eDb_ERROR;
}
/*
** Move the read/write pointer in a file.
*/
int eDbOsSeek(OsFile *id, off_t offset){
SeekFile(id->h,offset,FILESEEK_SET);
return eDb_OK;
}
/*
** Make sure all writes to a particular file are committed to disk.
**
** Under Unix, also make sure that the directory entry for the file
** has been created by fsync-ing the directory that contains the file.
** If we do not do this and we encounter a power failure, the directory
** entry for the journal might not exist after we reboot. The next
** eDb to access the file will not know that the journal exists (because
** the directory entry for the journal was never created) and the transaction
** will not roll back - possibly leading to database corruption.
*/
int eDbOsSync(OsFile *id){
FlushFile(id->h);
return eDb_OK;
}
/*
** Truncate an open file to a specified size
*/
int eDbOsTruncate(OsFile *id, off_t nByte){
return eDb_OK;
}
/*
** Determine the current size of a file in bytes
*/
int eDbOsFileSize(OsFile *id, off_t *pSize){
*pSize = FileSize(id->h);
return eDb_OK;
}
int eDbOsReadLock(OsFile *id){
return eDb_OK;
}
/*
** 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){
return eDb_OK;
}
/*
** 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){
return eDb_OK;
}
/*
** 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){
int i;
for(i=0;i<256;i++)
zBuf[i] = i%128;
return eDb_OK;
}
/*
** Sleep for a little while. Return the amount of time slept.
*/
int eDbOsSleep(int ms){
return ms;
}
/*
** Static variables used for thread synchronization
*/
static int inMutex = 0;
void eDbOsEnterMutex(){
inMutex = 1;
}
void eDbOsLeaveMutex(){
inMutex = 0;
}
/*
** 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 *pName = eDbStrDup(zRelative);
return pName;
}
/*
** 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){
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();
}
#ifndef itoa
char *itoa(int n, char *str,int rad){
extern int sprintf(char *str,const char *format,...);
switch(rad){
case 10:
sprintf(str,"%d",n);
break;
case 16:
sprintf(str,"%x",n);
break;
case 8:
sprintf(str,"%o",n);
break;
default:
sprintf(str,"%d",n);
}
return 0;
}
#endif
?? 快捷鍵說(shuō)明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號(hào)
Ctrl + =
減小字號(hào)
Ctrl + -