Buffered I/O for registry performance

git-svn-id: svn://10.0.0.236/trunk@47893 18797224-902f-48f8-a5cc-f745e15eee43
This commit is contained in:
dveditz%netscape.com
1999-09-17 01:32:00 +00:00
parent 4c7131a637
commit bf8a5b89ca
8 changed files with 773 additions and 223 deletions

View File

@@ -29,7 +29,7 @@ REQUIRES = libreg pref js
PROGRAM = vreg
CSRCS = reg.c VerReg.c vr_stubs.c
CSRCS = reg.c VerReg.c vr_stubs.c nr_bufio.c
BIN_SRCS = VerReg.c reg.c vr_stubs.c
PROGOBJS = $(addprefix R_,$(BIN_SRCS:.c=.o))
@@ -40,11 +40,12 @@ override NO_STATIC_LIB=
include $(topsrcdir)/config/config.mk
DEFINES += -DUSE_BUFFERED_REGISTRY_IO
# Memory mapped files are not supported under QNX, Neutrino, HP-UX and BeOS
ifeq (,$(filter BeOS HP-UX QNX,$(OS_ARCH)))
CSRCS += mmapio.c
DEFINES += -DUSE_MMAP_REGISTRY_IO
endif
#ifeq (,$(filter BeOS HP-UX QNX,$(OS_ARCH)))
#CSRCS += mmapio.c
#DEFINES += -DUSE_MMAP_REGISTRY_IO
#endif
include $(topsrcdir)/config/rules.mk

View File

@@ -31,11 +31,10 @@ DEPTH= ..\..\..
MAKE_OBJ_TYPE=DLL
#//------------------------------------------------------------------------
#//
#// Define any Public Make Variables here: (ie. PDFFILE, MAPFILE, ...)
#//
#//------------------------------------------------------------------------
#//--- pick at most one of the IO types. Commenting both of
#//--- them out gives you normal NSPR I/O
USE_BUFFERED_REGISTRY_IO=1
#USE_MMAP_REGISTRY_IO=1
#//------------------------------------------------------------------------
#//
@@ -47,7 +46,12 @@ OBJS= \
.\$(OBJDIR)\reg.obj \
.\$(OBJDIR)\VerReg.obj \
.\$(OBJDIR)\vr_stubs.obj \
# .\$(OBJDIR)\mmapio.obj \
!if defined(USE_MMAP_REGISTRY_IO)
.\$(OBJDIR)\mmapio.obj \
!endif
!if defined(USE_BUFFERED_REGISTRY_IO)
.\$(OBJDIR)\nr_bufio.obj \
!endif
$(NULL)
#//------------------------------------------------------------------------
@@ -69,7 +73,12 @@ DLL=$(OBJDIR)\$(DLLNAME).dll
#//
#//------------------------------------------------------------------------
#LCFLAGS= -DUSE_MMAP_REGISTRY_IO
!if defined(USE_MMAP_REGISTRY_IO)
LCFLAGS=$(LCFLAGS) -DUSE_MMAP_REGISTRY_IO
!endif
!if defined(USE_BUFFERED_REGISTRY_IO)
LCFLAGS=$(LCFLAGS) -DUSE_BUFFERED_REGISTRY_IO
!endif
LLIBS = \
$(LIBNSPR) \

View File

@@ -17,6 +17,7 @@
*
* Contributor(s): James L. Nance <jim_nance@yahoo.com>
*/
#include <string.h>
#include "mmapio.h"
#include "prmem.h"
#include "prlog.h"
@@ -38,16 +39,16 @@ PRStatus mmio_FileSeek(MmioFile *mmio, PRInt32 offset, PRSeekWhence whence)
switch(whence) {
case PR_SEEK_SET:
mmio->pos = offset;
break;
case PR_SEEK_END:
mmio->pos = mmio->fsize + offset;
break;
case PR_SEEK_CUR:
mmio->pos = mmio->pos + offset;
break;
default:
return PR_FAILURE;
mmio->pos = offset;
break;
case PR_SEEK_END:
mmio->pos = mmio->fsize + offset;
break;
case PR_SEEK_CUR:
mmio->pos = mmio->pos + offset;
break;
default:
return PR_FAILURE;
}
if(mmio->pos<0) {
@@ -75,28 +76,28 @@ PRInt32 mmio_FileRead(MmioFile *mmio, char *dest, PRInt32 count)
/* Check to see if we need to remap for this read */
if(mmio->pos+count > mmio->msize) {
if(mmio->addr && mmio->msize) {
PR_ASSERT(mmio->fileMap);
PR_MemUnmap(mmio->addr, mmio->msize);
PR_CloseFileMap(mmio->fileMap);
mmio->addr = NULL;
mmio->msize = 0;
}
if(mmio->addr && mmio->msize) {
PR_ASSERT(mmio->fileMap);
PR_MemUnmap(mmio->addr, mmio->msize);
PR_CloseFileMap(mmio->fileMap);
mmio->addr = NULL;
mmio->msize = 0;
}
LL_UI2L(fsize_l, mmio->fsize);
mmio->fileMap = PR_CreateFileMap(mmio->fd, fsize_l, prot);
LL_UI2L(fsize_l, mmio->fsize);
mmio->fileMap = PR_CreateFileMap(mmio->fd, fsize_l, prot);
if(!mmio->fileMap) {
return -1;
}
if(!mmio->fileMap) {
return -1;
}
mmio->addr = PR_MemMap(mmio->fileMap, 0, fsize_l);
mmio->addr = PR_MemMap(mmio->fileMap, 0, fsize_l);
if(!mmio->addr) {
return -1;
}
if(!mmio->addr) {
return -1;
}
mmio->msize = mmio->fsize;
mmio->msize = mmio->fsize;
}
memcpy(dest, mmio->addr+mmio->pos, count);
@@ -113,16 +114,16 @@ PRInt32 mmio_FileWrite(MmioFile *mmio, const char *src, PRInt32 count)
if(mmio->needSeek) {
PR_Seek(mmio->fd, mmio->pos, PR_SEEK_SET);
mmio->needSeek = PR_FALSE;
mmio->needSeek = PR_FALSE;
}
wcode = PR_Write(mmio->fd, src, count);
if(wcode>0) {
mmio->pos += wcode;
if(mmio->pos>mmio->fsize) {
mmio->fsize=mmio->pos;
}
if(mmio->pos>mmio->fsize) {
mmio->fsize=mmio->pos;
}
}
return wcode;
@@ -136,9 +137,9 @@ PRInt32 mmio_FileTell(MmioFile *mmio)
PRStatus mmio_FileClose(MmioFile *mmio)
{
if(mmio->addr && mmio->msize) {
PR_ASSERT(mmio->fileMap);
PR_ASSERT(mmio->fileMap);
PR_MemUnmap(mmio->addr, mmio->msize);
PR_CloseFileMap(mmio->fileMap);
PR_CloseFileMap(mmio->fileMap);
}
PR_Close(mmio->fd);
@@ -163,7 +164,7 @@ MmioFile *mmio_FileOpen(char *path, PRIntn flags, PRIntn mode)
mmio = PR_MALLOC(sizeof(MmioFile));
if(!mmio || PR_FAILURE==PR_GetOpenFileInfo(fd, &info)) {
PR_Close(fd);
PR_Close(fd);
return NULL;
}

View File

@@ -18,7 +18,7 @@
* Contributor(s): James L. Nance <jim_nance@yahoo.com>
*/
#include <prio.h>
#include "prio.h"
typedef struct MmioFileStruct MmioFile;

View File

@@ -0,0 +1,562 @@
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape Public License
* Version 1.1 (the "License"); you may not use this file except in
* compliance with the License. You may obtain a copy of the License at
* http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is Mozilla Communicator
*
* The Initial Developer of the Original Code is Netscape Communications
* Corporation. Portions created by Netscape are
* Copyright (C) 1999 Netscape Communications Corporation. All Rights
* Reserved.
*
* Contributors:
* Daniel Veditz <dveditz@netscape.com>
*/
/*------------------------------------------------------------------------
* nr_bufio
*
* Buffered I/O routines to improve registry performance
* the routines mirror fopen(), fclose() et al
*
* Inspired by the performance gains James L. Nance <jim_nance@yahoo.com>
* got using NSPR memory-mapped I/O for the registry. Unfortunately NSPR
* doesn't support mmapio on the Mac.
*-----------------------------------------------------------------------*/
#include <stdio.h>
#include <string.h>
#include <errno.h>
#if defined(XP_MAC)
#include <Errors.h>
#endif
#include "prerror.h"
#include "prlog.h"
#include "vr_stubs.h"
#include "nr_bufio.h"
#define STARTS_IN_BUF(f) ((f->fpos >= f->datastart) && \
(f->fpos < (f->datastart+f->datasize)))
#define ENDS_IN_BUF(f,c) (((f->fpos + c) > (PRUint32)f->datastart) && \
((f->fpos + c) <= (PRUint32)(f->datastart+f->datasize)))
#define BUFIO_BUFSIZE 0x10000
struct BufioBufStruct
{
PRInt32 datastart; /* The file position for the buffer start */
PRInt32 datasize; /* the amount of data in the buffer */
PRBool dirty; /* if the buffer has been written to */
PRInt32 dirtystart; /* lowest offset written to */
PRInt32 dirtyend; /* end of the written area */
} BufioBuf;
struct BufioFileStruct
{
FILE *fd; /* real file descriptor */
PRInt32 fsize; /* total size of file */
PRInt32 fpos; /* our logical position in the file */
PRInt32 datastart; /* the file position at which the buffer starts */
PRInt32 datasize; /* the amount of data actually in the buffer*/
PRBool bufdirty; /* whether the buffer been written to */
PRInt32 dirtystart;
PRInt32 dirtyend;
PRBool readOnly; /* whether the file allows writing or not */
char *data; /* the data buffer */
};
static PRBool _bufio_loadBuf( BufioFile* file, PRUint32 count );
static int _bufio_flushBuf( BufioFile* file );
/**
* like fopen() this routine takes *native* filenames, not NSPR names.
*/
BufioFile* bufio_Open(const char* name, const char* mode)
{
FILE *fd;
BufioFile *file = NULL;
PRBool cleanup = PR_FALSE;
fd = fopen( name, mode );
if ( fd )
{
/* file opened successfully, initialize the bufio structure */
file = PR_NEWZAP( BufioFile );
if ( file )
{
file->fd = fd;
file->data = (char*)PR_Malloc( BUFIO_BUFSIZE );
if ( file->data )
{
/* get file size to finish initialization of bufio */
if ( !fseek( fd, 0, SEEK_END ) )
{
file->fsize = ftell( fd );
file->readOnly = strcmp(mode,XP_FILE_READ) == 0 ||
strcmp(mode,XP_FILE_READ_BIN) == 0;
}
else
{
PR_Free( file->data );
PR_DELETE( file );
}
}
else
PR_DELETE( file );
}
/* close file if we couldn't create BufioFile */
if (!file)
{
fclose( fd );
PR_SetError( PR_OUT_OF_MEMORY_ERROR, 0 );
}
}
else
{
/* couldn't open file. Figure out why and set NSPR errors */
switch (errno)
{
/* file not found */
#ifdef XP_MAC
case fnfErr:
#else
case ENOENT:
#endif
PR_SetError(PR_FILE_NOT_FOUND_ERROR,0);
break;
/* file in use */
#ifdef XP_MAC
case opWrErr:
#else
case EACCES:
#endif
PR_SetError(PR_NO_ACCESS_RIGHTS_ERROR,0);
break;
default:
PR_SetError(PR_UNKNOWN_ERROR,0);
break;
}
}
return file;
}
/**
* close the buffered file and destroy BufioFile struct
*/
int bufio_Close(BufioFile* file)
{
int retval = -1;
if ( file )
{
if ( file->bufdirty )
_bufio_flushBuf( file );
retval = fclose( file->fd );
if ( file->data )
PR_Free( file->data );
PR_DELETE( file );
}
return retval;
}
/**
* change the logical position in the file. Equivalent to fseek()
*/
int bufio_Seek(BufioFile* file, PRInt32 offset, int whence)
{
if (!file)
return -1;
switch(whence)
{
case SEEK_SET:
file->fpos = offset;
break;
case SEEK_END:
file->fpos = file->fsize + offset;
break;
case SEEK_CUR:
file->fpos = file->fpos + offset;
break;
default:
return -1;
}
if ( file->fpos < 0 )
file->fpos = 0;
return 0;
}
/**
* like ftell() returns the current position in the file, or -1 for error
*/
PRInt32 bufio_Tell(BufioFile* file)
{
if (file)
return file->fpos;
else
return -1;
}
PRUint32 bufio_Read(BufioFile* file, char* dest, PRUint32 count)
{
PRInt32 startOffset;
PRInt32 endOffset;
PRInt32 leftover;
PRUint32 bytesCopied;
PRUint32 bytesRead;
PRUint32 retcount = 0;
/* sanity check arguments */
if ( !file || !dest || count == 0 || file->fpos >= file->fsize )
return 0;
/* Adjust amount to read if we're near EOF */
if ( (file->fpos + count) > (PRUint32)file->fsize )
count = file->fsize - file->fpos;
/* figure out how much of the data we want is already buffered */
startOffset = file->fpos - file->datastart;
endOffset = startOffset + count;
if ( startOffset >= 0 && startOffset < file->datasize )
{
/* The beginning of what we want is in the buffer */
/* so copy as much as is available of what we want */
if ( endOffset <= file->datasize )
bytesCopied = count;
else
bytesCopied = file->datasize - startOffset;
memcpy( dest, file->data + startOffset, bytesCopied );
retcount = bytesCopied;
file->fpos += bytesCopied;
/* Was that all we wanted, or do we need to get more? */
leftover = count - bytesCopied;
PR_ASSERT( leftover >= 0 ); /* negative left? something's wrong! */
if ( leftover )
{
/* need data that's not in the buffer */
/* if what's left fits in a buffer then load the buffer with the */
/* new area before giving the data, otherwise just read right */
/* into the user's dest buffer */
if ( _bufio_loadBuf( file, leftover ) )
{
startOffset = file->fpos - file->datastart;
/* we may not have been able to load as much as we wanted */
if ( startOffset+leftover <= file->datasize )
bytesRead = leftover;
else
bytesRead = file->datasize - startOffset;
memcpy( dest+bytesCopied, file->data+startOffset, bytesRead );
file->fpos += bytesRead;
retcount += bytesRead;
}
else
{
/* we need more than we could load into a buffer, so */
/* skip buffering and just read the data directly */
if ( fseek( file->fd, file->fpos, SEEK_SET ) == 0 )
{
bytesRead = fread(dest+bytesCopied, 1, leftover, file->fd);
file->fpos += bytesRead;
retcount += bytesRead;
}
else
{
/* XXX seek failed, couldn't load more data -- help! */
/* should we call PR_SetError() ? */
}
}
}
}
else
{
/* range doesn't start in the loaded buffer but it might end there */
if ( endOffset > 0 && endOffset <= file->datasize )
bytesCopied = endOffset;
else
bytesCopied = 0;
leftover = count - bytesCopied;
if ( bytesCopied )
{
/* the tail end of the range we want is already buffered */
/* first copy the buffered data to the dest area */
memcpy( dest+leftover, file->data, bytesCopied );
}
/* now pick up the part that's not already in the buffer */
if ( _bufio_loadBuf( file, leftover ) )
{
/* we were able to load some data */
startOffset = file->fpos - file->datastart;
/* we may not have been able to read as much as we wanted */
if ( startOffset+leftover <= file->datasize )
bytesRead = leftover;
else
bytesRead = file->datasize - startOffset;
memcpy( dest, file->data+startOffset, bytesRead );
}
else
{
/* leftover data doesn't fit so skip buffering */
if ( fseek( file->fd, file->fpos, SEEK_SET ) == 0 )
bytesRead = fread(dest, 1, leftover, file->fd);
else
bytesRead = 0;
}
/* if we couldn't read all the leftover, don't tell caller */
/* about the tail end we copied from the first buffer */
if ( bytesRead == (PRUint32)leftover )
retcount = bytesCopied + bytesRead;
else
retcount = bytesRead;
file->fpos += retcount;
}
return retcount;
}
/**
* write through to disk skipping buffering. This will change
*/
PRUint32 bufio_Write(BufioFile* file, const char* src, PRUint32 count)
{
PRInt32 startOffset;
PRInt32 endOffset;
PRUint32 retcount = 0;
PRUint32 bytesWritten = 0;
/* sanity check arguments */
if ( !file || !src || count == 0 || file->readOnly )
return 0;
/* Write to the current buffer if we can, otherwise load a new buffer */
startOffset = file->fpos - file->datastart;
endOffset = startOffset + count;
if ( startOffset >= 0 &&
startOffset < BUFIO_BUFSIZE &&
endOffset <= BUFIO_BUFSIZE )
{
/* the entire area we want to write is buffered */
bytesWritten = count;
memcpy( file->data + startOffset, src, bytesWritten );
file->bufdirty = PR_TRUE;
if ( endOffset > file->datasize )
file->datasize = endOffset;
file->dirtystart = PR_MIN( startOffset, file->dirtystart );
file->dirtyend = PR_MAX( endOffset, file->dirtyend );
}
else if ( count > BUFIO_BUFSIZE )
{
/* the data doesn't fit in a buffer, write w/out buffering. */
/* first check to see if it overlaps our current buffer */
if ( startOffset < BUFIO_BUFSIZE && endOffset > 0 )
{
/* this write overlaps at least part of the current buffer */
/* Flush any dirty data first */
if ( file->bufdirty )
_bufio_flushBuf( file );
/* then empty the buffer so stale data isn't used */
file->datasize = 0;
file->dirtystart = BUFIO_BUFSIZE;
file->dirtyend = 0;
}
/* now if is safe to do the write */
if ( fseek( file->fd, file->fpos, SEEK_SET ) == 0 )
{
bytesWritten = fwrite( src, 1, count, file->fd );
}
}
else
{
/* the data doesn't fit in the current buffer, so we'll just */
/* start a new buffer. Flush any dirty data first */
if ( file->bufdirty )
_bufio_flushBuf( file );
bytesWritten = count;
memcpy( file->data, src, bytesWritten );
file->bufdirty = PR_TRUE;
file->datastart = file->fpos; /* NB: original fpos! */
file->datasize = bytesWritten;
file->dirtystart = 0;
file->dirtyend = file->datasize;
}
file->fpos += bytesWritten;
if ( file->fpos > file->fsize )
{
file->fsize = file->fpos;
}
return bytesWritten;
}
int bufio_Flush(BufioFile* file)
{
if ( file->bufdirty )
_bufio_flushBuf( file );
return fflush(file->fd);
}
/*---------------------------------------------------------------------------*
* internal helper functions
*---------------------------------------------------------------------------*/
/**
* Attempts to load the buffer with the requested amount of data.
* Returns PR_TRUE if it was able to load *some* of the requested
* data, but not necessarily all. Returns PR_FALSE if the read fails
* or if the requested amount wouldn't fit in the buffer.
*/
static PRBool _bufio_loadBuf( BufioFile* file, PRUint32 count )
{
PRInt32 startBuf;
PRInt32 endPos;
PRInt32 endBuf;
PRUint32 bytesRead;
/* no point in buffering more than the physical buffer will hold */
if ( count > BUFIO_BUFSIZE )
return PR_FALSE;
/* Is caller asking for data we already have? */
if ( STARTS_IN_BUF(file) && ENDS_IN_BUF(file,count) )
{
PR_ASSERT(0);
return PR_TRUE;
}
/* if the buffer's dirty make sure we successfully flush it */
if ( file->bufdirty && _bufio_flushBuf(file) != 0 )
return PR_FALSE;
/* For now we're not trying anything smarter than simple paging. */
/* Slide over if necessary to fit the entire request */
startBuf = ( file->fpos / BUFIO_BUFSIZE ) * BUFIO_BUFSIZE;
endPos = file->fpos + count;
endBuf = startBuf + BUFIO_BUFSIZE;
if ( endPos > endBuf )
startBuf += (endPos - endBuf);
if ( fseek( file->fd, startBuf, SEEK_SET ) != 0 )
return PR_FALSE;
else
{
bytesRead = fread( file->data, 1, BUFIO_BUFSIZE, file->fd );
if (bytesRead)
{
file->datastart = startBuf;
file->datasize = bytesRead;
file->bufdirty = PR_FALSE;
file->dirtystart = BUFIO_BUFSIZE;
file->dirtyend = 0;
}
/* return true if we got *any* of the requested data */
if ( bytesRead > (PRUint32)(file->fpos - startBuf) )
return PR_TRUE;
else
return PR_FALSE;
}
}
static int _bufio_flushBuf( BufioFile* file )
{
PRUint32 written;
PRUint32 dirtyamt;
PRInt32 startpos;
PR_ASSERT(file);
if ( !file || !file->bufdirty )
return 0;
startpos = file->datastart + file->dirtystart;
if ( !fseek( file->fd, startpos, SEEK_SET ) )
{
dirtyamt = file->dirtyend - file->dirtystart;
written = fwrite( file->data+file->dirtystart, 1, dirtyamt, file->fd );
if ( written == dirtyamt )
return 0;
}
return -1;
}
/* EOF nr_bufio.c */

View File

@@ -0,0 +1,46 @@
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape Public License
* Version 1.1 (the "License"); you may not use this file except in
* compliance with the License. You may obtain a copy of the License at
* http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is Mozilla Communicator
*
* The Initial Developer of the Original Code is Netscape Communications
* Corporation. Portions created by Netscape are
* Copyright (C) 1999 Netscape Communications Corporation. All Rights
* Reserved.
*
* Contributors:
* Daniel Veditz <dveditz@netscape.com>
*/
/* nr_bufio.h
* Buffered I/O routines to improve registry performance
*
* the routines mirror fopen(), fclose() et al
*
* __NOTE__: the filenames are *native* filenames, not NSPR names.
*/
#ifndef _NR_BUFIO_H_
#define _NR_BUFIO_H_
typedef struct BufioFileStruct BufioFile;
BufioFile* bufio_Open(const char* name, const char* mode);
int bufio_Close(BufioFile* file);
int bufio_Seek(BufioFile* file, PRInt32 offset, int whence);
PRUint32 bufio_Read(BufioFile* file, char* dest, PRUint32 count);
PRUint32 bufio_Write(BufioFile* file, const char* src, PRUint32 count);
PRInt32 bufio_Tell(BufioFile* file);
int bufio_Flush(BufioFile* file);
#endif /* _NR_BUFIO_H_ */

View File

@@ -35,8 +35,8 @@
/* Preprocessor Defines
* STANDALONE_REGISTRY - define if not linking with Navigator
* NOCACHE_HDR - define if multi-threaded access to registry
* SELF_REPAIR - define to skip header update on open
* NOCACHE_HDR - define if multi-process access to registry
* SELF_REPAIR - undefine to skip header update on open
* VERIFY_READ - define TRUE to double-check short reads
*
#define NOCACHE_HDR 1
@@ -51,7 +51,6 @@
#ifdef STANDALONE_REGISTRY
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include <errno.h>
@@ -74,16 +73,6 @@
#include "reg.h"
#include "NSReg.h"
#if !defined(STANDALONE_REGISTRY) && defined(SEEK_SET)
/* Undo the damage caused by xp_core.h, which is included by NSReg.h */
#undef SEEK_SET
#undef SEEK_CUR
#undef SEEK_END
#define SEEK_SET PR_SEEK_SET
#define SEEK_CUR PR_SEEK_CUR
#define SEEK_END PR_SEEK_END
#endif
#if defined(XP_UNIX)
#ifndef MAX_PATH
#define MAX_PATH 1024
@@ -384,20 +373,26 @@ static REGERR nr_OpenFile(char *path, FILEHANDLE *fh)
PR_ASSERT( fh != NULL );
/* Open the file for exclusive random read/write */
(*fh) = XP_FileOpen(path, PR_RDWR|PR_CREATE_FILE, 00644);
*fh = XP_FileOpen(path, XP_FILE_UPDATE_BIN);
if ( !VALID_FILEHANDLE(*fh) )
{
switch (PR_GetError())
{
case PR_FILE_NOT_FOUND_ERROR: /* file not found */
return REGERR_NOFILE;
case PR_FILE_NOT_FOUND_ERROR:
/* file not found, try to create it */
*fh = XP_FileOpen(path, XP_FILE_TRUNCATE_BIN);
if ( VALID_FILEHANDLE(*fh) )
return REGERR_OK;
else
return REGERR_NOFILE;
case PR_FILE_IS_BUSY_ERROR: /* file in use */
case PR_FILE_IS_LOCKED_ERROR:
case PR_ILLEGAL_ACCESS_ERROR:
case PR_NO_ACCESS_RIGHTS_ERROR:
/* try read only */
(*fh) = XP_FileOpen(path, PR_RDONLY, 00644);
(*fh) = XP_FileOpen(path, XP_FILE_READ_BIN);
if ( VALID_FILEHANDLE(*fh) )
return REGERR_READONLY;
else
@@ -472,7 +467,7 @@ static REGERR nr_ReadFile(FILEHANDLE fh, REGOFF offset, int32 len, void *buffer)
/* If buffer has new data beyond what PR_READ() says it got */
/* we'll assume the read was OK--this is a gamble but */
/* missing errors will cause fewer problems than too many. */
p = (unsigned char*)buffer+readlen;
p = (unsigned char*)buffer + readlen;
while ( (*p == (unsigned char)FILLCHAR) && (p < dbgend) ) {
p++;
}
@@ -1239,14 +1234,6 @@ static REGERR nr_CatName(REGFILE *reg, REGOFF node, char *path, uint32 bufsize,
REGDESC *desc);
static REGERR nr_ReplaceName(REGFILE *reg, REGOFF node, char *path,
uint32 bufsize, REGDESC *desc);
#if 0 /* old interface */
static char * nr_LastDelim(char *pPath);
static XP_Bool nr_IsQualifiedEntry(char *pPath);
static REGERR nr_SplitEntry(char *pPath, char **name, char **value);
static REGERR nr_CatNameValue(char *path, int bufsize, REGDESC *desc);
static REGERR nr_ReplaceNameValue(char *path, int bufsize, REGDESC *desc);
#endif
/* -------------------------------------------------------------------- */
@@ -1694,111 +1681,6 @@ static REGERR nr_CreateEntry(REGFILE *reg, REGDESC *pParent, char *name,
#if 0 /* old interface */
VR_INTERFACE(REGERR) NR_RegRename(RKEY key, char *path, char *newname)
{
REGDESC desc;
REGERR err;
if ( !VALID_FILEHANDLE(gReg.fh) )
return REGERR_FAIL;
/* Okay to Update to "", but names must not be null */
if (!newname || !*newname)
return REGERR_PARAM;
err = nr_Lock(&gReg);
if (err != REGERR_OK)
return err;
/* Find the key or entry to rename (and validate the
incoming parameters) */
err = nr_Find((REGOFF)key, path, &desc, 0, 0, FALSE);
if (err != REGERR_OK)
goto cleanup;
/* Write the new name string to the file and update
the key or entry's pointer */
err = nr_AppendName(&gReg, newname, &desc);
if (err != REGERR_OK)
goto cleanup;
/* Write the key or entry back to the disk and return */
err = nr_WriteDesc(&gReg, &desc);
cleanup:
nr_Unlock(&gReg);
return err;
} /* RegRename */
VR_INTERFACE(REGERR) NR_RegPack(char *newfilename)
{
REGFILE dstReg;
char *path = NULL;
int err = REGERR_OK;
dstReg.fh = NULL;
if (!newfilename || !*newfilename)
return REGERR_PARAM;
if ( !VALID_FILEHANDLE(gReg.fh) )
return REGERR_FAIL;
/* open it & create a header by trying to read */
err = nr_OpenFile(newfilename, &dstReg.fh);
if (err != REGERR_OK)
goto cleanup;
err = nr_ReadHdr(&dstReg);
if (err != REGERR_OK)
goto cleanup;
/* read records from the current registry file and
add them to 'dstReg' */
path = XP_ALLOC(PACKBUFFERSIZE);
if (path == NULL)
{
err = REGERR_FAIL;
goto cleanup;
}
XP_STRCPY(path, "/");
err = nr_Lock(&gReg);
if (err != REGERR_OK)
goto cleanup;
while (NR_RegNext( 0, PACKBUFFERSIZE, path ) == REGERR_OK)
{
err = nr_RegGenericAdd(&dstReg, 0, path);
if (err != REGERR_OK)
break;
}
nr_Unlock(&gReg);
cleanup:
XP_FREEIF(path);
if ( VALID_FILEHANDLE(dstReg.fh) )
{
/* even if not caching headers it could be dirty due to an error */
if (dstReg.hdrDirty) {
nr_WriteHdr(&dstReg);
}
nr_CloseFile(&dstReg.fh);
}
return err;
} /* RegPack */
#endif /* old interface */
/* ---------------------------------------------------------------------
* Intermediate API
@@ -3356,8 +3238,10 @@ VR_INTERFACE(REGERR) NR_RegEnumSubkeys( HREG hReg, RKEY key, REGENUM *state,
key = nr_TranslateKey( reg, key );
if ( key == 0 )
err = REGERR_PARAM;
else
else if ( *state == 0 )
err = nr_ReadDesc( reg, key, &desc);
else
err = REGERR_OK;
if ( err == REGERR_OK )
{
@@ -3750,6 +3634,7 @@ static REGERR nr_addNodesToNewReg( HREG hReg, RKEY rootkey, HREG hRegNew, void *
}
/* ---------------------------------------------------------------------
* NR_RegPack - Pack an open registry.
* Registry is locked the entire time.
@@ -3760,6 +3645,8 @@ static REGERR nr_addNodesToNewReg( HREG hReg, RKEY rootkey, HREG hRegNew, void *
*/
VR_INTERFACE(REGERR) NR_RegPack( HREG hReg, void *userData, nr_RegPackCallbackFunc fn)
{
return REGERR_FAIL; /* XXX resurrect after mozilla beta 1 */
#if RESURRECT_LATER
XP_File fh;
REGFILE* reg;
HREG hRegTemp;
@@ -3860,9 +3747,10 @@ safe_exit:
PR_Unlock( reglist_lock );
nr_Unlock(reg);
return err;
#endif /* RESURRECT_LATER */
}
#ifdef XP_MAC
#pragma export reset
#endif

View File

@@ -81,20 +81,7 @@
#ifdef STANDALONE_REGISTRY
#define XP_FILE_READ "r"
#define XP_FILE_READ_BIN "rb"
#define XP_FILE_WRITE "w"
#define XP_FILE_WRITE_BIN "wb"
#define XP_FILE_UPDATE "r+"
#define XP_FILE_TRUNCATE "w+"
#ifdef SUNOS4
/* XXX SunOS4 hack -- make this universal by using r+b and w+b */
#define XP_FILE_UPDATE_BIN "r+"
#define XP_FILE_TRUNCATE_BIN "w+"
#else
#define XP_FILE_UPDATE_BIN "rb+"
#define XP_FILE_TRUNCATE_BIN "wb+"
#endif
#define USE_STDIO_MODES
#define XP_FileSeek(file,offset,whence) fseek((file), (offset), (whence))
#define XP_FileRead(dest,count,file) fread((dest), 1, (count), (file))
@@ -132,29 +119,19 @@
typedef FILE * XP_File;
#else /* if not standalone, use NSPR */
#else /* not standalone, use NSPR */
#define XP_FILE_READ PR_RDONLY, 0644
#define XP_FILE_READ_BIN PR_RDONLY, 0644
#define XP_FILE_WRITE PR_WRONLY, 0644
#define XP_FILE_WRITE_BIN PR_WRONLY, 0644
#define XP_FILE_UPDATE PR_RDWR|PR_CREATE_FILE, 0644
#define XP_FILE_TRUNCATE (PR_WRONLY | PR_TRUNCATE), 0644
#define XP_FILE_UPDATE_BIN PR_RDWR|PR_CREATE_FILE, 0644
#define XP_FILE_TRUNCATE_BIN (PR_RDWR | PR_TRUNCATE), 0644
#ifdef SEEK_SET
#undef SEEK_SET
#undef SEEK_CUR
#undef SEEK_END
#define SEEK_SET PR_SEEK_SET
#define SEEK_CUR PR_SEEK_CUR
#define SEEK_END PR_SEEK_END
#endif
/*-------------------------------------*/
/* Alternate fileI/O function mappings */
/*-------------------------------------*/
#if USE_MMAP_REGISTRY_IO
/*-----------------------------------------------*/
/* NSPR mememory-mapped I/O (write through) */
/* unfortunately this isn't supported on the Mac */
/*-----------------------------------------------*/
#define USE_NSPR_MODES
#include "mmapio.h"
#define XP_FileSeek(file,offset,whence) mmio_FileSeek((file),(offset),(whence))
@@ -162,12 +139,36 @@ typedef FILE * XP_File;
#define XP_FileWrite(src,count,file) mmio_FileWrite((file), (src), (count))
#define XP_FileTell(file) mmio_FileTell(file)
#define XP_FileClose(file) mmio_FileClose(file)
#define XP_FileOpen(path, flags, mode) mmio_FileOpen((path), (flags), (mode))
#define XP_FileOpen(path, mode) mmio_FileOpen((path), mode )
#define XP_FileFlush(file) ((void)1)
typedef MmioFile* XP_File;
#else /*USE_MMAP_REGISTRY_IO*/
#elif USE_BUFFERED_REGISTRY_IO
/*-----------------------------------------------*/
/* home-grown XP buffering */
/* writes are buffered too so use flush! */
/*-----------------------------------------------*/
#define USE_STDIO_MODES
#include "nr_bufio.h"
#define XP_FileSeek(file,offset,whence) bufio_Seek((file),(offset),(whence))
#define XP_FileRead(dest,count,file) bufio_Read((file), (dest), (count))
#define XP_FileWrite(src,count,file) bufio_Write((file), (src), (count))
#define XP_FileTell(file) bufio_Tell(file)
#define XP_FileClose(file) bufio_Close(file)
#define XP_FileOpen(path, mode) bufio_Open((path), (mode))
#define XP_FileFlush(file) ((void)1)
typedef BufioFile* XP_File;
#else
/*-----------------------------------------------*/
/* standard NSPR file I/O */
/*-----------------------------------------------*/
#define USE_NSPR_MODES
/*
** Note that PR_Seek returns the offset (if successful) and -1 otherwise. So
** to make this code work
@@ -178,7 +179,7 @@ typedef MmioFile* XP_File;
#define XP_FileRead(dest,count,file) PR_Read((file), (dest), (count))
#define XP_FileWrite(src,count,file) PR_Write((file), (src), (count))
#define XP_FileTell(file) PR_Seek(file, 0, PR_SEEK_CUR)
#define XP_FileOpen(path, flags, mode) PR_Open((path), (flags), (mode))
#define XP_FileOpen(path, mode) PR_Open((path), mode )
#define XP_FileClose(file) PR_Close(file)
#ifdef XP_MAC
#define XP_FileFlush(file) PR_Sync(file)
@@ -190,6 +191,8 @@ typedef PRFileDesc* XP_File;
#endif /*USE_MMAP_REGISTRY_IO*/
#define XP_ASSERT(x) PR_ASSERT((x))
#define XP_STRCAT(a,b) PL_strcat((a),(b))
@@ -212,19 +215,59 @@ typedef PRFileDesc* XP_File;
#endif /*STANDALONE_REGISTRY*/
/*--- file open modes for stdio ---*/
#ifdef USE_STDIO_MODES
#define XP_FILE_READ "r"
#define XP_FILE_READ_BIN "rb"
#define XP_FILE_WRITE "w"
#define XP_FILE_WRITE_BIN "wb"
#define XP_FILE_UPDATE "r+"
#define XP_FILE_TRUNCATE "w+"
#ifdef SUNOS4
/* XXX SunOS4 hack -- make this universal by using r+b and w+b */
#define XP_FILE_UPDATE_BIN "r+"
#define XP_FILE_TRUNCATE_BIN "w+"
#else
#define XP_FILE_UPDATE_BIN "rb+"
#define XP_FILE_TRUNCATE_BIN "wb+"
#endif
#endif /* USE_STDIO_MODES */
/*--- file open modes for NSPR file I/O ---*/
#ifdef USE_NSPR_MODES
#define XP_FILE_READ PR_RDONLY, 0644
#define XP_FILE_READ_BIN PR_RDONLY, 0644
#define XP_FILE_WRITE PR_WRONLY, 0644
#define XP_FILE_WRITE_BIN PR_WRONLY, 0644
#define XP_FILE_UPDATE (PR_RDWR|PR_CREATE_FILE), 0644
#define XP_FILE_TRUNCATE (PR_RDWR | PR_TRUNCATE), 0644
#define XP_FILE_UPDATE_BIN PR_RDWR|PR_CREATE_FILE, 0644
#define XP_FILE_TRUNCATE_BIN (PR_RDWR | PR_TRUNCATE), 0644
#ifdef SEEK_SET
#undef SEEK_SET
#undef SEEK_CUR
#undef SEEK_END
#define SEEK_SET PR_SEEK_SET
#define SEEK_CUR PR_SEEK_CUR
#define SEEK_END PR_SEEK_END
#endif
#endif /* USE_NSPR_MODES */
#ifdef STANDALONE_REGISTRY /* included from prmon.h otherwise */
#include "prtypes.h"
#endif /*STANDALONE_REGISTRY*/
typedef int XP_Bool;
#ifdef XP_PC
typedef struct _stat XP_StatStruct;
#define XP_Stat(file,data,type) _stat((file),(data))
#else
typedef struct stat XP_StatStruct;
#define XP_Stat(file,data,type) stat((file),(data))
#endif /*XP_PC*/
typedef struct stat XP_StatStruct;
#define XP_Stat(file,data) stat((file),(data))
#ifdef XP_MAC
extern int nr_RenameFile(char *from, char *to);