Trying to get the OS abstraction layer to work. (CVS 256)

FossilOrigin-Name: abff526d005b3b46904de091753cc79548739ad8
This commit is contained in:
drh 2001-09-19 13:22:39 +00:00
parent db5ed6d55d
commit 8cfbf08ffa
9 changed files with 343 additions and 257 deletions

View File

@ -61,7 +61,7 @@ ENCODING = @ENCODING@
# Object files for the SQLite library.
#
LIBOBJ = btree.o build.o delete.o expr.o insert.o \
main.o pager.o parse.o printf.o random.o select.o table.o \
main.o os.o pager.o parse.o printf.o random.o select.o table.o \
tokenize.o update.o util.o vdbe.o where.o tclsqlite.o
# All of the source code files.
@ -134,6 +134,7 @@ lemon: $(TOP)/tool/lemon.c $(TOP)/tool/lempar.c
HDR = \
sqlite.h \
$(TOP)/src/btree.h \
$(TOP)/src/os.h \
$(TOP)/src/sqliteInt.h \
$(TOP)/src/vdbe.h \
parse.h
@ -150,6 +151,9 @@ main.o: $(TOP)/src/main.c $(HDR)
pager.o: $(TOP)/src/pager.c $(HDR) $(TOP)/src/pager.h
$(TCC) -c $(TOP)/src/pager.c
os.o: $(TOP)/src/os.c $(HDR)
$(TCC) -c $(TOP)/src/os.c
parse.o: parse.c $(HDR)
$(TCC) -c parse.c

View File

@ -1,6 +1,6 @@
C Fix\sa\sproblem\sin\sGROUP\sBY\swith\smultiple\scolumns.\s(CVS\s255)
D 2001-09-18T22:17:44
F Makefile.in a7053596881af6f2590a816ad4eb8fbbf20724a7
C Trying\sto\sget\sthe\sOS\sabstraction\slayer\sto\swork.\s(CVS\s256)
D 2001-09-19T13:22:39
F Makefile.in 1d9592c4aeedd3643b2e1dfa037ce5faf54805a3
F README 51f6a4e7408b34afa5bc1c0485f61b6a4efb6958
F VERSION 3861a21803fcd9eb92a403027b0da2bb7add4de1
F configure aad857a97ca28a584228869186eb4cd7dbebbb3a x
@ -14,15 +14,15 @@ F src/build.c 072d6cf5b894c47d3fb8c11580eaa1a24528bca8
F src/delete.c ca7ca9bf8b613730821c4a755030d1a020b5e067
F src/expr.c 343a515a4abaf60e9e26c7412aa8c43fd3eae97d
F src/insert.c b34860ea58525754f18bde652f74161295ca2455
F src/main.c 71ca839b90869c8c13db52fd08b0d0e80dae3288
F src/main.c 5e5794eea3316dd3a63c112ccdcc997b9118f345
F src/md5.c 52f677bfc590e09f71d07d7e327bd59da738d07c
F src/os.c 2e0daeca8a8c75f122d41f894698f5e1b258b69c
F src/os.h 3b21772e76df0f3998c5a968a2a0d23b9d4551fe
F src/pager.c c7db91e4e44bbf3e13ecea658e47b670d1f26e29
F src/os.c 6ed6f61915807b1b4578398b4e797e55b12db4ab
F src/os.h 2528414d4d441e86cf458b7520ed7f629d446d70
F src/pager.c 28c8a641601b81a11454de3015d3d796e31ea182
F src/pager.h a0d4c5ae271914aa07b62aee0707997d6932b6ca
F src/parse.y 2bcf47bb8e6afd8bc10aebd555fa07b73905bee4
F src/printf.c b1e22a47be8cdf707815647239991e08e8cb69f9
F src/random.c 707529bcda5c7382dc32bd0545e0217f90f70e29
F src/random.c b6a57e85288470b013ad584a8813e893b60e62fe
F src/select.c 7d90a6464906419fde96c0707a4cf4f3280db318
F src/shell.c 8e573138074e0b9526fca59b3eac22bdf18ecc03
F src/shell.tcl 27ecbd63dd88396ad16d81ab44f73e6c0ea9d20e
@ -35,7 +35,7 @@ F src/test2.c 0168b39225b768cfdadd534406f9dec58c27879e
F src/test3.c f46bad555db7a6a25be332a96ac99e4d68a1b0c5
F src/tokenize.c 2adf0568edf41b3d3c2fcb541ac49bd6e662da0c
F src/update.c a1952ad5d53379fa2b2d12efae5993ddb85a1ddb
F src/util.c 2cd0bb9693e1c538a5c6f152b7d45cc8567e6724
F src/util.c 2a3491fd761b64cca849b07095076f482d119f9c
F src/vdbe.c efe564f482c94d361843c5975e2a5724cf0ca8af
F src/vdbe.h 900b59b46afdfb9c048a2a31a4478f380ab8504e
F src/where.c cce952b6a2459ac2296e3432876a4252d2fe3b87
@ -96,7 +96,7 @@ F www/opcode.tcl cb3a1abf8b7b9be9f3a228d097d6bf8b742c2b6f
F www/sqlite.tcl cb0d23d8f061a80543928755ec7775da6e4f362f
F www/tclsqlite.tcl 06f81c401f79a04f2c5ebfb97e7c176225c0aef2
F www/vdbe.tcl 0c8aaa529dd216ccbf7daaabd80985e413d5f9ad
P 8f28a83abac59a2161d486c96386b8df726468d0
R 716384b1a17cd98ef2ff77fe086995d1
P 22132ce18cad31482cdb9b380cedc3f53bc532b8
R f2b9b288263979b8bf39b2aa8c086069
U drh
Z 8f168bc49c168254b9355cae69013087
Z a1f7206e19ddb2d1a7062a107b29fcdc

View File

@ -1 +1 @@
22132ce18cad31482cdb9b380cedc3f53bc532b8
abff526d005b3b46904de091753cc79548739ad8

View File

@ -14,12 +14,10 @@
** other files are for internal use by SQLite and should not be
** accessed by users of the library.
**
** $Id: main.c,v 1.38 2001/09/17 20:25:58 drh Exp $
** $Id: main.c,v 1.39 2001/09/19 13:22:40 drh Exp $
*/
#include "sqliteInt.h"
#if defined(HAVE_USLEEP) && HAVE_USLEEP
#include <unistd.h>
#endif
#include "os.h"
/*
** This is the callback routine for the code that initializes the
@ -428,8 +426,8 @@ static int sqliteDefaultBusyCallback(
const char *NotUsed, /* The name of the table that is busy */
int count /* Number of times table has been busy */
){
#if defined(HAVE_USLEEP) && HAVE_USLEEP
int delay = 10000;
#if SQLITE_MIN_SLEEP_MS==1
int delay = 10;
int prior_delay = 0;
int timeout = (int)Timeout;
int i;
@ -437,9 +435,9 @@ static int sqliteDefaultBusyCallback(
for(i=1; i<count; i++){
prior_delay += delay;
delay = delay*2;
if( delay>=1000000 ){
delay = 1000000;
prior_delay += 1000000*(count - i - 1);
if( delay>=1000 ){
delay = 1000;
prior_delay += 1000*(count - i - 1);
break;
}
}
@ -447,14 +445,14 @@ static int sqliteDefaultBusyCallback(
delay = timeout*1000 - prior_delay;
if( delay<=0 ) return 0;
}
usleep(delay);
sqliteOsSleep(delay);
return 1;
#else
int timeout = (int)Timeout;
if( (count+1)*1000 > timeout ){
return 0;
}
sleep(1);
sqliteOsSleep(1000);
return 1;
#endif
}

235
src/os.c
View File

@ -17,6 +17,16 @@
#include "sqliteInt.h"
#include "os.h"
#ifndef OS_UNIX
# ifndef OS_WIN
# define OS_UNIX 1
# else
# define OS_UNIX 0
# endif
#endif
#ifndef OS_WIN
# define OS_WIN 0
#endif
#if OS_UNIX
# include <fcntl.h>
# include <sys/stat.h>
@ -27,6 +37,44 @@
# include <winbase.h>
#endif
/*
** Delete the named file
*/
int sqliteOsDelete(const char *zFilename){
#if OS_UNIX
unlink(zFilename);
#endif
#if OS_WIN
DeleteFile(zFilename);
#endif
return SQLITE_OK;
}
/*
** Return TRUE if the named file exists.
*/
int sqliteOsFileExists(const char *zFilename){
#if OS_UNIX
return access(zFilename, 0)==0;
#endif
#if OS_WIN
HANDLE h;
h = CreateFile(zBuf,
GENERIC_READ,
0,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL | FILE_FLAG_RANDOM_ACCESS,
NULL
);
if( h!=INVALID_FILE_HANDLE ){
CloseHandle(h);
return 1;
}
return 0;
#endif
}
/*
** Attempt to open a file for both reading and writing. If that
@ -41,7 +89,11 @@
** On failure, the function returns SQLITE_CANTOPEN and leaves
** *pResulst and *pReadonly unchanged.
*/
int sqliteOsOpenReadWrite(char *zFilename, OsFile *pResult, int *pReadonly){
int sqliteOsOpenReadWrite(
const char *zFilename,
OsFile *pResult,
int *pReadonly
){
#if OS_UNIX
int fd = open(zFilename, O_RDWR|O_CREAT, 0644);
if( fd<0 ){
@ -84,6 +136,7 @@ int sqliteOsOpenReadWrite(char *zFilename, OsFile *pResult, int *pReadonly){
*pResult = h;
return SQLITE_OK;
#endif
}
/*
@ -97,10 +150,8 @@ int sqliteOsOpenReadWrite(char *zFilename, OsFile *pResult, int *pReadonly){
**
** On failure, return SQLITE_CANTOPEN.
*/
int sqliteOsOpenExclusive(char *zFilename, OsFile *pResult){
int sqliteOsOpenExclusive(const char *zFilename, OsFile *pResult){
#if OS_UNIX
struct stat buf;
time_t now;
int fd;
if( access(zFilename, 0)==0 ){
return SQLITE_CANTOPEN;
@ -150,7 +201,7 @@ int sqliteOsTempFileName(char *zBuf){
"0123456789";
int i, j;
struct stat buf;
char *zDir = ".";
const char *zDir = ".";
for(i=0; i<sizeof(azDirs)/sizeof(azDirs[0]); i++){
if( stat(azDirs[i], &buf) ) continue;
if( !S_ISDIR(buf.st_mode) ) continue;
@ -181,19 +232,7 @@ int sqliteOsTempFileName(char *zBuf){
zBuf[j++] = zChars[n];
}
zBuf[j] = 0;
h = CreateFile(zBuf,
GENERIC_READ,
0,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL | FILE_FLAG_RANDOM_ACCESS,
NULL
);
if( h!=INVALID_FILE_HANDLE ){
CloseHandle(h);
continue;
}
break;
if( !sqliteOsFileExists(zBuf) ) break;
}
#endif
return SQLITE_OK;
@ -214,37 +253,183 @@ int sqliteOsClose(OsFile id){
}
/*
** Read data from a file into a buffer
** Read data from a file into a buffer. Return the number of
** bytes actually read.
*/
int sqliteOsRead(OsFile id, void *pBuf, int amt){
#if OS_UNIX
int got;
got = read(id, pBuf, amt);
if( got<0 ) got = 0;
return got==amt ? SQLITE_OK : SQLITE_IOERR;
#endif
#if OS_WIN
int got;
if( !ReadFile(id, pBuf, amt, &got, 0) ){
got = 0;
}
return got==amt ? SQLITE_OK : SQLITE_IOERR;
#endif
}
/*
** Write data from a buffer into a file
** Write data from a buffer into a file. Return SQLITE_OK on success
** or some other error code on failure.
*/
int sqliteOsWrite(OsFile id, const void *pBuf, int amt){
#if OS_UNIX
int wrote;
wrote = write(id, pBuf, amt);
if( wrote<amt ) return SQLITE_FULL;
return SQLITE_OK;
#endif
#if OS_WIN
int wrote;
if( !WriteFile(id, pBuf, amt, &wrote, 0) || wrote<amt ){
return SQLITE_FULL;
}
return SQLITE_OK;
#endif
}
/*
** Move the read/write pointer in a file.
*/
int sqliteOsSeek(OsFile id, int offset){
#if OS_UNIX
lseek(id, offset, SEEK_SET);
return SQLITE_OK;
#endif
#if OS_WIN
SetFilePointer(id, offset, 0, FILE_BEGIN);
return SQLITE_OK;
#endif
}
/*
** Make sure all writes to a particular file are committed to disk.
*/
int sqliteOsSync(OsFile id){
#if OS_UNIX
return fsync(id)==0 ? SQLITE_OK : SQLITE_IOERR;
#endif
#if OS_WIN
return FlushFileBuffers(id) ? SQLITE_OK : SQLITE_IOERR;
#endif
}
/*
** Truncate an open file to a specified size
*/
int sqliteOsTruncate(OsFile id, int nByte){
#if OS_UNIX
return ftruncate(id, nByte)==0 ? SQLITE_OK : SQLITE_IOERR;
#endif
#if OS_WIN
SetFilePointer(id, nByte, 0, FILE_BEGIN);
SetEndOfFile(id);
return SQLITE_OK;
#endif
}
/*
** Determine the current size of a file in bytes
*/
int sqliteOsFileSize(OsFile id, int *pSize){
#if OS_UNIX
struct stat buf;
if( fstat(id, &buf)!=0 ){
return SQLITE_IOERR;
}
*pSize = buf.st_size;
return SQLITE_OK;
#endif
#if OS_WIN
*pSize = GetFileSize(id, 0);
return SQLITE_OK;
#endif
}
/*
** Get a read or write lock on a file.
*/
int sqliteOsLock(OsFile id, int wrlock){
#if OS_UNIX
int rc;
struct flock lock;
memset(&lock, 0, sizeof(lock));
lock.l_type = wrlock ? F_WRLCK : F_RDLCK;
lock.l_whence = SEEK_SET;
lock.l_start = 0L;
lock.l_len = 1024L;
printf("LOCK %s %d\n",wrlock?"WRITE":"READ",id);
rc = fcntl(id, F_SETLK, &lock);
fcntl(id, F_GETLK, &lock);
printf("rc=%d why=%d\n",rc,lock.l_type);
return rc==0 ? SQLITE_OK : SQLITE_BUSY;
#endif
#if OS_WIN
if( !LockFile(id, 0, 0, 1024, 0) ){
return SQLITE_BUSY;
}
return SQLITE_OK;
#endif
}
/*
** Release the read or write lock from a file.
*/
int sqliteOsUnlock(OsFile id){
#if OS_UNIX
int rc;
struct flock lock;
lock.l_type = F_UNLCK;
lock.l_whence = SEEK_SET;
lock.l_start = 0L;
lock.l_len = 1L;
printf("UNLOCK %d\n",id);
rc = fcntl(id, F_SETLK, &lock);
return rc==0 ? SQLITE_OK : SQLITE_IOERR;
#endif
#if OS_WIN
return UnlockFile(id, 0, 0, 1024, 0) ? SQLITE_OK : SQLITE_IOERR;
#endif
}
/*
** Get information to seed the random number generator.
*/
int sqliteOsRandomSeed(char *zBuf){
#if OS_UNIX
int pid;
time((time_t*)zBuf);
zBuf += sizeof(time_t);
pid = getpid();
memcpy(zBuf, &pid, sizeof(pid));
zBuf += pid;
return SQLITE_OK;
#endif
#if OS_WIN
GetSystemTime((LPSYSTEMTIME)zBuf);
return SQLITE_OK;
#endif
}
/*
** Sleep for a little while.
** Sleep for a little while. Return the amount of time slept.
*/
#endif /* OS_WIN */
int sqliteOsSleep(int ms){
#if OS_UNIX
#if defined(HAVE_USLEEP) && HAVE_USLEEP
usleep(ms*1000);
return ms;
#else
sleep((ms+999)/1000);
return 1000*((ms+999)/1000);
#endif
#endif
#if OS_WIN
Sleep(ms);
return ms;
#endif
}

View File

@ -23,27 +23,35 @@
#if OS_UNIX
typedef int OsFile;
# define SQLITE_TEMPNAME_SIZE 200
# if defined(HAVE_USLEEP) && HAVE_USLEEP
# define SQLITE_MIN_SLEEP_MS 1
# else
# define SQLITE_MIN_SLEEP_MS 1000
# endif
#endif
#if OS_WIN
typedef HANDLE OsFile;
# define SQLITE_TEMPNAME_SIZE (MAX_PATH+1)
# define SQLITE_TEMPNAME_SIZE (MAX_PATH+50)
# deifne SQLITE_MIN_SLEEP_MS 1
#endif
int sqliteOsOpenReadWrite(char*, OsFile*, int*);
int sqliteOsOpenExclusive(char*, OsFile*);
int sqliteOsDelete(const char*);
int sqliteOsFileExists(const char*);
int sqliteOsOpenReadWrite(const char*, OsFile*, int*);
int sqliteOsOpenExclusive(const char*, OsFile*);
int sqliteOsTempFileName(char*);
int sqliteOsClose(OsFile);
int sqliteOsRead(OsFile, int amt, void*);
int sqliteOsWrite(OsFile, int amt, void*);
int sqliteOsRead(OsFile, void*, int amt);
int sqliteOsWrite(OsFile, const void*, int amt);
int sqliteOsSeek(OsFile, int offset);
int sqliteOsSync(OsFile);
int sqliteOsTruncate(OsFile, int size);
int sqliteOsFileSize(OsFile, int *pSize);
int sqliteOsLock(OsFile, int wrlock);
int sqliteOsUnlock(OsFile);
int sqliteOsRandomSeed(int amt, char*);
int sqliteSleep(int ms);
int sqliteOsRandomSeed(char*);
int sqliteOsSleep(int ms);

View File

@ -18,13 +18,11 @@
** file simultaneously, or one process from reading the database while
** another is writing.
**
** @(#) $Id: pager.c,v 1.21 2001/09/18 02:02:23 drh Exp $
** @(#) $Id: pager.c,v 1.22 2001/09/19 13:22:40 drh Exp $
*/
#include "sqliteInt.h"
#include "pager.h"
#include <fcntl.h>
#include <sys/stat.h>
#include <unistd.h>
#include "os.h"
#include <assert.h>
#include <string.h>
@ -102,7 +100,8 @@ struct PgHdr {
struct Pager {
char *zFilename; /* Name of the database file */
char *zJournal; /* Name of the journal file */
int fd, jfd; /* File descriptors for database and journal */
OsFile fd, jfd; /* File descriptors for database and journal */
int journalOpen; /* True if journal file descriptors is valid */
int dbSize; /* Number of pages in the file */
int origDbSize; /* dbSize before the current change */
int nExtra; /* Add this many bytes to each in-memory page */
@ -172,93 +171,6 @@ static const unsigned char aJournalMagic[] = {
# define REFINFO(X)
#endif
/*
** Attempt to acquire a read lock (if wrlock==0) or a write lock (if wrlock==1)
** on the database file. Return 0 on success and non-zero if the lock
** could not be acquired.
*/
static int pager_lock(int fd, int wrlock){
int rc;
struct flock lock;
lock.l_type = wrlock ? F_WRLCK : F_RDLCK;
lock.l_whence = SEEK_SET;
lock.l_start = lock.l_len = 0L;
rc = fcntl(fd, F_SETLK, &lock);
return rc!=0;
}
/*
** Unlock the database file.
*/
static int pager_unlock(fd){
int rc;
struct flock lock;
lock.l_type = F_UNLCK;
lock.l_whence = SEEK_SET;
lock.l_start = lock.l_len = 0L;
rc = fcntl(fd, F_SETLK, &lock);
return rc!=0;
}
/*
** Move the cursor for file descriptor fd to the point whereto from
** the beginning of the file.
*/
static int pager_seek(int fd, off_t whereto){
/*printf("SEEK to page %d\n", whereto/SQLITE_PAGE_SIZE + 1);*/
lseek(fd, whereto, SEEK_SET);
return SQLITE_OK;
}
/*
** Truncate the given file so that it contains exactly mxPg pages
** of data.
*/
static int pager_truncate(int fd, Pgno mxPg){
int rc;
rc = ftruncate(fd, mxPg*SQLITE_PAGE_SIZE);
return rc!=0 ? SQLITE_IOERR : SQLITE_OK;
}
/*
** Read nBytes of data from fd into pBuf. If the data cannot be
** read or only a partial read occurs, then the unread parts of
** pBuf are filled with zeros and this routine returns SQLITE_IOERR.
** If the read is completely successful, return SQLITE_OK.
*/
static int pager_read(int fd, void *pBuf, int nByte){
int rc;
/* printf("READ\n");*/
rc = read(fd, pBuf, nByte);
if( rc<0 ){
memset(pBuf, 0, nByte);
return SQLITE_IOERR;
}
if( rc<nByte ){
memset(&((char*)pBuf)[rc], 0, nByte - rc);
rc = SQLITE_IOERR;
}else{
rc = SQLITE_OK;
}
return rc;
}
/*
** Write nBytes of data into fd. If any problem occurs or if the
** write is incomplete, SQLITE_IOERR is returned. SQLITE_OK is
** returned upon complete success.
*/
static int pager_write(int fd, const void *pBuf, int nByte){
int rc;
/*printf("WRITE\n");*/
rc = write(fd, pBuf, nByte);
if( rc<nByte ){
return SQLITE_FULL;
}else{
return SQLITE_OK;
}
}
/*
** Convert the bits in the pPager->errMask into an approprate
** return code.
@ -304,10 +216,11 @@ static void pager_reset(Pager *pPager){
if( pPager->state==SQLITE_WRITELOCK ){
sqlitepager_rollback(pPager);
}
pager_unlock(pPager->fd);
sqliteOsUnlock(pPager->fd);
pPager->state = SQLITE_UNLOCK;
pPager->dbSize = -1;
pPager->nRef = 0;
assert( pPager->journalOpen==0 );
}
/*
@ -331,11 +244,11 @@ static int pager_unwritelock(Pager *pPager){
int rc;
PgHdr *pPg;
if( pPager->state!=SQLITE_WRITELOCK ) return SQLITE_OK;
pager_unlock(pPager->fd);
rc = pager_lock(pPager->fd, 0);
unlink(pPager->zJournal);
close(pPager->jfd);
pPager->jfd = -1;
sqliteOsUnlock(pPager->fd);
rc = sqliteOsLock(pPager->fd, 0);
sqliteOsClose(pPager->jfd);
pPager->journalOpen = 0;
sqliteOsDelete(pPager->zJournal);
sqliteFree( pPager->aInJournal );
pPager->aInJournal = 0;
for(pPg=pPager->pAll; pPg; pPg=pPg->pNextAll){
@ -380,7 +293,6 @@ static int pager_playback(Pager *pPager){
int nRec; /* Number of Records */
int i; /* Loop counter */
Pgno mxPg = 0; /* Size of the original file in pages */
struct stat statbuf; /* Used to size the journal */
PgHdr *pPg; /* An existing page in the cache */
PageRecord pgRec;
unsigned char aMagic[sizeof(aJournalMagic)];
@ -389,26 +301,26 @@ static int pager_playback(Pager *pPager){
/* Read the beginning of the journal and truncate the
** database file back to its original size.
*/
assert( pPager->jfd>=0 );
pager_seek(pPager->jfd, 0);
rc = pager_read(pPager->jfd, aMagic, sizeof(aMagic));
assert( pPager->journalOpen );
sqliteOsSeek(pPager->jfd, 0);
rc = sqliteOsRead(pPager->jfd, aMagic, sizeof(aMagic));
if( rc!=SQLITE_OK || memcmp(aMagic,aJournalMagic,sizeof(aMagic))!=0 ){
return SQLITE_PROTOCOL;
}
rc = pager_read(pPager->jfd, &mxPg, sizeof(mxPg));
rc = sqliteOsRead(pPager->jfd, &mxPg, sizeof(mxPg));
if( rc!=SQLITE_OK ){
return SQLITE_PROTOCOL;
}
pager_truncate(pPager->fd, mxPg);
sqliteOsTruncate(pPager->fd, mxPg*SQLITE_PAGE_SIZE);
pPager->dbSize = mxPg;
/* Begin reading the journal beginning at the end and moving
** toward the beginning.
*/
if( fstat(pPager->jfd, &statbuf)!=0 ){
if( sqliteOsFileSize(pPager->jfd, &nRec)!=SQLITE_OK ){
return SQLITE_OK;
}
nRec = (statbuf.st_size - (sizeof(aMagic)+sizeof(Pgno))) / sizeof(PageRecord);
nRec = (nRec - (sizeof(aMagic)+sizeof(Pgno))) / sizeof(PageRecord);
/* Process segments beginning with the last and working backwards
** to the first.
@ -417,9 +329,9 @@ static int pager_playback(Pager *pPager){
/* Seek to the beginning of the segment */
off_t ofst;
ofst = i*sizeof(PageRecord) + sizeof(aMagic) + sizeof(Pgno);
rc = pager_seek(pPager->jfd, ofst);
rc = sqliteOsSeek(pPager->jfd, ofst);
if( rc!=SQLITE_OK ) break;
rc = pager_read(pPager->jfd, &pgRec, sizeof(pgRec));
rc = sqliteOsRead(pPager->jfd, &pgRec, sizeof(pgRec));
if( rc!=SQLITE_OK ) break;
/* Sanity checking on the page */
@ -436,9 +348,9 @@ static int pager_playback(Pager *pPager){
memcpy(PGHDR_TO_DATA(pPg), pgRec.aData, SQLITE_PAGE_SIZE);
memset(PGHDR_TO_EXTRA(pPg), 0, pPager->nExtra);
}
rc = pager_seek(pPager->fd, (pgRec.pgno-1)*SQLITE_PAGE_SIZE);
rc = sqliteOsSeek(pPager->fd, (pgRec.pgno-1)*SQLITE_PAGE_SIZE);
if( rc!=SQLITE_OK ) break;
rc = pager_write(pPager->fd, pgRec.aData, SQLITE_PAGE_SIZE);
rc = sqliteOsWrite(pPager->fd, pgRec.aData, SQLITE_PAGE_SIZE);
if( rc!=SQLITE_OK ) break;
}
if( rc!=SQLITE_OK ){
@ -451,30 +363,6 @@ static int pager_playback(Pager *pPager){
return rc;
}
/*
** Locate a directory where we can potentially create a temporary
** file.
*/
static const char *findTempDir(void){
static const char *azDirs[] = {
".",
"/var/tmp",
"/usr/tmp",
"/tmp",
"/temp",
"./temp",
};
int i;
struct stat buf;
for(i=0; i<sizeof(azDirs)/sizeof(azDirs[0]); i++){
if( stat(azDirs[i], &buf) ) continue;
if( !S_ISDIR(buf.st_mode) ) continue;
if( access(azDirs[i], 07) ) continue;
return azDirs[i];
}
return 0;
}
/*
** Change the maximum number of in-memory pages that are allowed.
*/
@ -498,41 +386,37 @@ int sqlitepager_open(
){
Pager *pPager;
int nameLen;
int fd;
OsFile fd;
int rc;
int tempFile;
int readOnly = 0;
char zTemp[300];
char zTemp[SQLITE_TEMPNAME_SIZE];
*ppPager = 0;
if( sqlite_malloc_failed ){
return SQLITE_NOMEM;
}
if( zFilename ){
fd = open(zFilename, O_RDWR|O_CREAT, 0644);
if( fd<0 ){
fd = open(zFilename, O_RDONLY, 0);
readOnly = 1;
}
rc = sqliteOsOpenReadWrite(zFilename, &fd, &readOnly);
tempFile = 0;
}else{
int cnt = 8;
const char *zDir = findTempDir();
if( zDir==0 ) return SQLITE_CANTOPEN;
sqliteOsTempFileName(zTemp);
do{
cnt--;
sprintf(zTemp,"%s/_sqlite_%u", zDir, (unsigned)sqliteRandomInteger());
fd = open(zTemp, O_RDWR|O_CREAT|O_EXCL, 0600);
}while( cnt>0 && fd<0 );
sqliteOsTempFileName(zTemp);
rc = sqliteOsOpenExclusive(zTemp, &fd);
}while( cnt>0 && rc!=SQLITE_OK );
zFilename = zTemp;
tempFile = 1;
}
if( fd<0 ){
if( rc!=SQLITE_OK ){
return SQLITE_CANTOPEN;
}
nameLen = strlen(zFilename);
pPager = sqliteMalloc( sizeof(*pPager) + nameLen*2 + 30 );
if( pPager==0 ){
close(fd);
sqliteOsClose(fd);
return SQLITE_NOMEM;
}
pPager->zFilename = (char*)&pPager[1];
@ -541,7 +425,7 @@ int sqlitepager_open(
strcpy(pPager->zJournal, zFilename);
strcpy(&pPager->zJournal[nameLen], "-journal");
pPager->fd = fd;
pPager->jfd = -1;
pPager->journalOpen = 0;
pPager->nRef = 0;
pPager->dbSize = -1;
pPager->nPage = 0;
@ -577,16 +461,14 @@ void sqlitepager_set_destructor(Pager *pPager, void (*xDesc)(void*)){
*/
int sqlitepager_pagecount(Pager *pPager){
int n;
struct stat statbuf;
assert( pPager!=0 );
if( pPager->dbSize>=0 ){
return pPager->dbSize;
}
if( fstat(pPager->fd, &statbuf)!=0 ){
n = 0;
}else{
n = statbuf.st_size/SQLITE_PAGE_SIZE;
if( sqliteOsFileSize(pPager->fd, &n)!=SQLITE_OK ){
return 0;
}
n /= SQLITE_PAGE_SIZE;
if( pPager->state!=SQLITE_UNLOCK ){
pPager->dbSize = n;
}
@ -607,11 +489,12 @@ int sqlitepager_close(Pager *pPager){
switch( pPager->state ){
case SQLITE_WRITELOCK: {
sqlitepager_rollback(pPager);
pager_unlock(pPager->fd);
sqliteOsUnlock(pPager->fd);
assert( pPager->journalOpen==0 );
break;
}
case SQLITE_READLOCK: {
pager_unlock(pPager->fd);
sqliteOsUnlock(pPager->fd);
break;
}
default: {
@ -623,10 +506,10 @@ int sqlitepager_close(Pager *pPager){
pNext = pPg->pNextAll;
sqliteFree(pPg);
}
if( pPager->fd>=0 ) close(pPager->fd);
assert( pPager->jfd<0 );
sqliteOsClose(pPager->fd);
assert( pPager->journalOpen==0 );
if( pPager->tempFile ){
unlink(pPager->zFilename);
sqliteOsDelete(pPager->zFilename);
}
sqliteFree(pPager);
return SQLITE_OK;
@ -690,14 +573,14 @@ static int syncAllPages(Pager *pPager){
PgHdr *pPg;
int rc = SQLITE_OK;
if( pPager->needSync ){
rc = fsync(pPager->jfd);
rc = sqliteOsSync(pPager->jfd);
if( rc!=0 ) return rc;
pPager->needSync = 0;
}
for(pPg=pPager->pFirst; pPg; pPg=pPg->pNextFree){
if( pPg->dirty ){
pager_seek(pPager->fd, (pPg->pgno-1)*SQLITE_PAGE_SIZE);
rc = pager_write(pPager->fd, PGHDR_TO_DATA(pPg), SQLITE_PAGE_SIZE);
sqliteOsSeek(pPager->fd, (pPg->pgno-1)*SQLITE_PAGE_SIZE);
rc = sqliteOsWrite(pPager->fd, PGHDR_TO_DATA(pPg), SQLITE_PAGE_SIZE);
if( rc!=SQLITE_OK ) break;
pPg->dirty = 0;
}
@ -744,7 +627,7 @@ int sqlitepager_get(Pager *pPager, Pgno pgno, void **ppPage){
** on the database file.
*/
if( pPager->nRef==0 ){
if( pager_lock(pPager->fd, 0)!=0 ){
if( sqliteOsLock(pPager->fd, 0)!=SQLITE_OK ){
*ppPage = 0;
return SQLITE_BUSY;
}
@ -752,28 +635,35 @@ int sqlitepager_get(Pager *pPager, Pgno pgno, void **ppPage){
/* If a journal file exists, try to play it back.
*/
if( access(pPager->zJournal,0)==0 ){
int rc;
if( sqliteOsFileExists(pPager->zJournal) ){
int rc, readOnly;
/* Open the journal for exclusive access. Return SQLITE_BUSY if
** we cannot get exclusive access to the journal file
*/
pPager->jfd = open(pPager->zJournal, O_RDONLY, 0);
if( pPager->jfd<0 || pager_lock(pPager->jfd, 1)!=0 ){
if( pPager->jfd>=0 ){ close(pPager->jfd); pPager->jfd = -1; }
pager_unlock(pPager->fd);
rc = sqliteOsOpenReadWrite(pPager->zJournal, &pPager->jfd, &readOnly);
if( rc==SQLITE_OK ){
pPager->journalOpen = 1;
}
if( rc!=SQLITE_OK || sqliteOsLock(pPager->jfd, 1)!=SQLITE_OK ){
if( pPager->journalOpen ){
sqliteOsClose(pPager->jfd);
pPager->journalOpen = 0;
}
sqliteOsUnlock(pPager->fd);
*ppPage = 0;
return SQLITE_BUSY;
}
/* Get a write lock on the database */
pager_unlock(pPager->fd);
if( pager_lock(pPager->fd, 1)!=0 ){
close(pPager->jfd);
pPager->jfd = -1;
sqliteOsUnlock(pPager->fd);
if( sqliteOsLock(pPager->fd, 1)!=SQLITE_OK ){
sqliteOsClose(pPager->jfd);
pPager->journalOpen = 0;
*ppPage = 0;
return SQLITE_PROTOCOL;
}
pPager->state = SQLITE_WRITELOCK;
/* Playback and delete the journal. Drop the database write
** lock and reacquire the read lock.
@ -892,8 +782,8 @@ int sqlitepager_get(Pager *pPager, Pgno pgno, void **ppPage){
if( pPager->dbSize<pgno ){
memset(PGHDR_TO_DATA(pPg), 0, SQLITE_PAGE_SIZE);
}else{
pager_seek(pPager->fd, (pgno-1)*SQLITE_PAGE_SIZE);
pager_read(pPager->fd, PGHDR_TO_DATA(pPg), SQLITE_PAGE_SIZE);
sqliteOsSeek(pPager->fd, (pgno-1)*SQLITE_PAGE_SIZE);
sqliteOsRead(pPager->fd, PGHDR_TO_DATA(pPg), SQLITE_PAGE_SIZE);
}
if( pPager->nExtra>0 ){
memset(PGHDR_TO_EXTRA(pPg), 0, pPager->nExtra);
@ -1023,20 +913,21 @@ int sqlitepager_write(void *pData){
if( pPager->aInJournal==0 ){
return SQLITE_NOMEM;
}
pPager->jfd = open(pPager->zJournal, O_RDWR|O_CREAT, 0644);
if( pPager->jfd<0 ){
rc = sqliteOsOpenExclusive(pPager->zJournal, &pPager->jfd);
if( rc!=SQLITE_OK ){
return SQLITE_CANTOPEN;
}
pPager->journalOpen = 1;
pPager->needSync = 0;
if( pager_lock(pPager->jfd, 1) ){
close(pPager->jfd);
pPager->jfd = -1;
if( sqliteOsLock(pPager->jfd, 1)!=SQLITE_OK ){
sqliteOsClose(pPager->jfd);
pPager->journalOpen = 0;
return SQLITE_BUSY;
}
pager_unlock(pPager->fd);
if( pager_lock(pPager->fd, 1) ){
close(pPager->jfd);
pPager->jfd = -1;
sqliteOsUnlock(pPager->fd);
if( sqliteOsLock(pPager->fd, 1)!=SQLITE_OK ){
sqliteOsClose(pPager->jfd);
pPager->journalOpen = 0;
pPager->state = SQLITE_UNLOCK;
pPager->errMask |= PAGER_ERR_LOCK;
return SQLITE_PROTOCOL;
@ -1044,9 +935,9 @@ int sqlitepager_write(void *pData){
pPager->state = SQLITE_WRITELOCK;
sqlitepager_pagecount(pPager);
pPager->origDbSize = pPager->dbSize;
rc = pager_write(pPager->jfd, aJournalMagic, sizeof(aJournalMagic));
rc = sqliteOsWrite(pPager->jfd, aJournalMagic, sizeof(aJournalMagic));
if( rc==SQLITE_OK ){
rc = pager_write(pPager->jfd, &pPager->dbSize, sizeof(Pgno));
rc = sqliteOsWrite(pPager->jfd, &pPager->dbSize, sizeof(Pgno));
}
if( rc!=SQLITE_OK ){
rc = pager_unwritelock(pPager);
@ -1055,11 +946,11 @@ int sqlitepager_write(void *pData){
}
}
assert( pPager->state==SQLITE_WRITELOCK );
assert( pPager->jfd>=0 );
assert( pPager->journalOpen );
if( pPg->pgno <= pPager->origDbSize ){
rc = pager_write(pPager->jfd, &pPg->pgno, sizeof(Pgno));
rc = sqliteOsWrite(pPager->jfd, &pPg->pgno, sizeof(Pgno));
if( rc==SQLITE_OK ){
rc = pager_write(pPager->jfd, pData, SQLITE_PAGE_SIZE);
rc = sqliteOsWrite(pPager->jfd, pData, SQLITE_PAGE_SIZE);
}
if( rc!=SQLITE_OK ){
sqlitepager_rollback(pPager);
@ -1110,18 +1001,18 @@ int sqlitepager_commit(Pager *pPager){
if( pPager->state!=SQLITE_WRITELOCK ){
return SQLITE_ERROR;
}
assert( pPager->jfd>=0 );
if( pPager->needSync && fsync(pPager->jfd) ){
assert( pPager->journalOpen );
if( pPager->needSync && sqliteOsSync(pPager->jfd)!=SQLITE_OK ){
goto commit_abort;
}
for(pPg=pPager->pAll; pPg; pPg=pPg->pNextAll){
if( pPg->dirty==0 ) continue;
rc = pager_seek(pPager->fd, (pPg->pgno-1)*SQLITE_PAGE_SIZE);
rc = sqliteOsSeek(pPager->fd, (pPg->pgno-1)*SQLITE_PAGE_SIZE);
if( rc!=SQLITE_OK ) goto commit_abort;
rc = pager_write(pPager->fd, PGHDR_TO_DATA(pPg), SQLITE_PAGE_SIZE);
rc = sqliteOsWrite(pPager->fd, PGHDR_TO_DATA(pPg), SQLITE_PAGE_SIZE);
if( rc!=SQLITE_OK ) goto commit_abort;
}
if( fsync(pPager->fd) ) goto commit_abort;
if( sqliteOsSync(pPager->fd)!=SQLITE_OK ) goto commit_abort;
rc = pager_unwritelock(pPager);
pPager->dbSize = -1;
return rc;

View File

@ -15,10 +15,10 @@
** Random numbers are used by some of the database backends in order
** to generate random integer keys for tables or random filenames.
**
** $Id: random.c,v 1.5 2001/09/16 00:13:27 drh Exp $
** $Id: random.c,v 1.6 2001/09/19 13:22:40 drh Exp $
*/
#include "sqliteInt.h"
#include <time.h>
#include "os.h"
/*
** Get a single 8-bit random value from the RC4 PRNG.
@ -48,9 +48,9 @@ int sqliteRandomByte(void){
*/
if( !prng_state.isInit ){
int i;
static char seed[] = " sqlite random seed";
static char seed[] = " sqlite random seed abcdefghijklmnop";
char k[256];
time((time_t*)seed);
sqliteOsRandomSeed(seed);
prng_state.j = 0;
prng_state.i = 0;
for(i=0; i<256; i++){

View File

@ -14,7 +14,7 @@
** This file contains functions for allocating memory, comparing
** strings, and stuff like that.
**
** $Id: util.c,v 1.26 2001/09/18 22:17:44 drh Exp $
** $Id: util.c,v 1.27 2001/09/19 13:22:40 drh Exp $
*/
#include "sqliteInt.h"
#include <stdarg.h>
@ -392,7 +392,7 @@ int sqliteHashNoCase(const char *z, int n){
int h = 0;
if( n<=0 ) n = strlen(z);
while( n > 0 ){
h = (h<<3) ^ h ^ UpperToLower[*z++];
h = (h<<3) ^ h ^ UpperToLower[(unsigned char)*z++];
n--;
}
if( h<0 ) h = -h;