Compare commits

..

24 Commits

Author SHA1 Message Date
law%netscape.com
dd7437a096 Add libplc21.lib to get PL_ functions
git-svn-id: svn://10.0.0.236/branches/LIBREG990212_BRANCH@21544 18797224-902f-48f8-a5cc-f745e15eee43
1999-02-23 02:29:32 +00:00
mcmullen%netscape.com
a6041e3d9e Bringing nsCOMPtr.cpp from trunk.
git-svn-id: svn://10.0.0.236/branches/LIBREG990212_BRANCH@21538 18797224-902f-48f8-a5cc-f745e15eee43
1999-02-23 02:06:14 +00:00
mcmullen%netscape.com
467456baed Added nsRegistry::GetFactory()
git-svn-id: svn://10.0.0.236/branches/LIBREG990212_BRANCH@21537 18797224-902f-48f8-a5cc-f745e15eee43
1999-02-23 02:05:28 +00:00
law%netscape.com
07adb3fa4c Pull changes on tip to branch
git-svn-id: svn://10.0.0.236/branches/LIBREG990212_BRANCH@21526 18797224-902f-48f8-a5cc-f745e15eee43
1999-02-23 01:11:27 +00:00
law%netscape.com
9f7a44c3e2 Deal with nsIEnumerator.h changes
git-svn-id: svn://10.0.0.236/branches/LIBREG990212_BRANCH@21525 18797224-902f-48f8-a5cc-f745e15eee43
1999-02-23 01:10:10 +00:00
mcmullen%netscape.com
99153e23c5 Brought change over from trunk.
git-svn-id: svn://10.0.0.236/branches/LIBREG990212_BRANCH@21505 18797224-902f-48f8-a5cc-f745e15eee43
1999-02-23 00:02:18 +00:00
mcmullen%netscape.com
509501efbf Brought some more of the changes over from the trunk (needed the changes in xcDll.h/cpp).
git-svn-id: svn://10.0.0.236/branches/LIBREG990212_BRANCH@21501 18797224-902f-48f8-a5cc-f745e15eee43
1999-02-22 23:24:03 +00:00
law%netscape.com
249c9a91cc Adding registry to DIRS
git-svn-id: svn://10.0.0.236/branches/LIBREG990212_BRANCH@21491 18797224-902f-48f8-a5cc-f745e15eee43
1999-02-22 22:29:33 +00:00
law%netscape.com
6100d0195f Pulling tip changes onto branch
git-svn-id: svn://10.0.0.236/branches/LIBREG990212_BRANCH@21490 18797224-902f-48f8-a5cc-f745e15eee43
1999-02-22 22:27:12 +00:00
mcmullen%netscape.com
2b0897f6b5 Bringing nsCOMPtr.cpp from trunk.
git-svn-id: svn://10.0.0.236/branches/LIBREG990212_BRANCH@21361 18797224-902f-48f8-a5cc-f745e15eee43
1999-02-20 00:00:07 +00:00
law%netscape.com
9b7b41f2e2 Win32 build changes
git-svn-id: svn://10.0.0.236/branches/LIBREG990212_BRANCH@21360 18797224-902f-48f8-a5cc-f745e15eee43
1999-02-19 23:54:05 +00:00
law%netscape.com
acaf468169 Win32 build changes
git-svn-id: svn://10.0.0.236/branches/LIBREG990212_BRANCH@21358 18797224-902f-48f8-a5cc-f745e15eee43
1999-02-19 23:44:01 +00:00
mcmullen%netscape.com
37c847e5d4 Rework previous changes, so that libreg (standalone) still builds on Windows. Also, add standalone target to the Macintosh project.
git-svn-id: svn://10.0.0.236/branches/LIBREG990212_BRANCH@20885 18797224-902f-48f8-a5cc-f745e15eee43
1999-02-17 05:16:27 +00:00
mcmullen%netscape.com
4397f139f4 First Checked In.
git-svn-id: svn://10.0.0.236/branches/LIBREG990212_BRANCH@20870 18797224-902f-48f8-a5cc-f745e15eee43
1999-02-17 03:26:51 +00:00
(no author)
07af9a116d This commit was manufactured by cvs2svn to create branch
'LIBREG990212_BRANCH'.

git-svn-id: svn://10.0.0.236/branches/LIBREG990212_BRANCH@20863 18797224-902f-48f8-a5cc-f745e15eee43
1999-02-17 03:12:04 +00:00
mcmullen%netscape.com
601c209b84 Reverting these to the original form, prior to reworking to support the STANDALONE_REGISTRY version.
git-svn-id: svn://10.0.0.236/branches/LIBREG990212_BRANCH@20842 18797224-902f-48f8-a5cc-f745e15eee43
1999-02-17 01:32:45 +00:00
mcmullen%netscape.com
70f44c60cd Fix use of stat() for windows.
git-svn-id: svn://10.0.0.236/branches/LIBREG990212_BRANCH@20828 18797224-902f-48f8-a5cc-f745e15eee43
1999-02-16 22:52:10 +00:00
mcmullen%netscape.com
8d0d948e0a Added libreg, etc to make nsRegistry work.
git-svn-id: svn://10.0.0.236/branches/LIBREG990212_BRANCH@20652 18797224-902f-48f8-a5cc-f745e15eee43
1999-02-13 03:52:29 +00:00
mcmullen%netscape.com
bdc8aa3c5c Added nsRegistry::GetFactory()
git-svn-id: svn://10.0.0.236/branches/LIBREG990212_BRANCH@20651 18797224-902f-48f8-a5cc-f745e15eee43
1999-02-13 03:51:43 +00:00
mcmullen%netscape.com
ffccab09a0 Made it work.
git-svn-id: svn://10.0.0.236/branches/LIBREG990212_BRANCH@20650 18797224-902f-48f8-a5cc-f745e15eee43
1999-02-13 03:50:42 +00:00
mcmullen%netscape.com
fc3851269e Hard-coded some command-line arguments for Macintosh.
git-svn-id: svn://10.0.0.236/branches/LIBREG990212_BRANCH@20649 18797224-902f-48f8-a5cc-f745e15eee43
1999-02-13 03:50:16 +00:00
mcmullen%netscape.com
66a57a8d4a Remove the illegal semicolon after extern "C" {}
git-svn-id: svn://10.0.0.236/branches/LIBREG990212_BRANCH@20648 18797224-902f-48f8-a5cc-f745e15eee43
1999-02-13 03:49:41 +00:00
mcmullen%netscape.com
faddf412e6 LIBREG990212_BRANCH checkin to check that my port of libreg to NSPR is still working on win and unix.
git-svn-id: svn://10.0.0.236/branches/LIBREG990212_BRANCH@20646 18797224-902f-48f8-a5cc-f745e15eee43
1999-02-13 03:45:23 +00:00
(no author)
d95ce0280d This commit was manufactured by cvs2svn to create branch
'LIBREG990212_BRANCH'.

git-svn-id: svn://10.0.0.236/branches/LIBREG990212_BRANCH@20631 18797224-902f-48f8-a5cc-f745e15eee43
1999-02-13 00:58:55 +00:00
253 changed files with 57793 additions and 8908 deletions

View File

@@ -0,0 +1,28 @@
#!gmake
#
# The contents of this file are subject to the Netscape Public License
# Version 1.0 (the "NPL"); you may not use this file except in
# compliance with the NPL. You may obtain a copy of the NPL at
# http://www.mozilla.org/NPL/
#
# Software distributed under the NPL is distributed on an "AS IS" basis,
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
# for the specific language governing rights and limitations under the
# NPL.
#
# The Initial Developer of this code under the NPL is Netscape
# Communications Corporation. Portions created by Netscape are
# Copyright (C) 1998 Netscape Communications Corporation. All Rights
# Reserved.
DEPTH = ../..
topsrcdir = @top_srcdir@
VPATH = @srcdir@
srcdir = @srcdir@
include $(DEPTH)/config/autoconf.mk
DIRS = include src
include $(topsrcdir)/config/rules.mk

View File

@@ -0,0 +1,6 @@
#
# This is a list of local files which get copied to the mozilla:dist directory
#
VerReg.h
NSReg.h

View File

@@ -0,0 +1,30 @@
#!gmake
#
# The contents of this file are subject to the Netscape Public License
# Version 1.0 (the "NPL"); you may not use this file except in
# compliance with the NPL. You may obtain a copy of the NPL at
# http://www.mozilla.org/NPL/
#
# Software distributed under the NPL is distributed on an "AS IS" basis,
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
# for the specific language governing rights and limitations under the
# NPL.
#
# The Initial Developer of this code under the NPL is Netscape
# Communications Corporation. Portions created by Netscape are
# Copyright (C) 1998 Netscape Communications Corporation. All Rights
# Reserved.
DEPTH = ../../..
topsrcdir = @top_srcdir@
VPATH = @srcdir@
srcdir = @srcdir@
include $(DEPTH)/config/autoconf.mk
MODULE = libreg
EXPORTS = VerReg.h NSReg.h
EXPORTS := $(addprefix $(srcdir)/, $(EXPORTS))
include $(topsrcdir)/config/rules.mk

View File

@@ -0,0 +1,249 @@
/* -*- 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.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
* Reserved.
*/
/* NSReg.h
*/
#ifndef _NSREG_H_
#define _NSREG_H_
#include "xp_core.h"
typedef void (*nr_RegPackCallbackFunc) (void *userData, int32 bytes, int32 totalBytes);
typedef int32 REGERR;
typedef int32 RKEY;
typedef uint32 REGENUM;
typedef void * HREG;
typedef struct _reginfo
{
uint16 size; /* must be initialized to sizeof(REGINFO) */
uint16 entryType;
uint32 entryLength;
} REGINFO;
#define REGERR_OK (0)
#define REGERR_FAIL (1)
#define REGERR_NOMORE (2)
#define REGERR_NOFIND (3)
#define REGERR_BADREAD (4)
#define REGERR_BADLOCN (5)
#define REGERR_PARAM (6)
#define REGERR_BADMAGIC (7)
#define REGERR_BADCHECK (8)
#define REGERR_NOFILE (9)
#define REGERR_MEMORY (10)
#define REGERR_BUFTOOSMALL (11)
#define REGERR_NAMETOOLONG (12)
#define REGERR_REGVERSION (13)
#define REGERR_DELETED (14)
#define REGERR_BADTYPE (15)
#define REGERR_NOPATH (16)
#define REGERR_BADNAME (17)
#define REGERR_READONLY (18)
#define REGERR_BADUTF8 (19)
/* Total path length */
#define MAXREGPATHLEN (2048)
/* Name on the path (including null terminator) */
#define MAXREGNAMELEN (512)
/* Value of an entry */
#define MAXREGVALUELEN (0x7FFF)
/* Standard keys */
#define ROOTKEY_USERS (0x01)
#define ROOTKEY_COMMON (0x02)
#define ROOTKEY_CURRENT_USER (0x03)
#define ROOTKEY_PRIVATE (0x04)
/* enumeration styles */
#define REGENUM_NORMAL (0x00)
#define REGENUM_CHILDREN REGENUM_NORMAL
#define REGENUM_DESCEND (0x01)
#define REGENUM_DEPTH_FIRST (0x02)
/* entry data types */
#define REGTYPE_ENTRY (0x0010)
#define REGTYPE_ENTRY_STRING_UTF (REGTYPE_ENTRY + 1)
#define REGTYPE_ENTRY_INT32_ARRAY (REGTYPE_ENTRY + 2)
#define REGTYPE_ENTRY_BYTES (REGTYPE_ENTRY + 3)
#define REGTYPE_ENTRY_FILE (REGTYPE_ENTRY + 4)
#define REG_DELETE_LIST_KEY "Netscape/Communicator/SoftwareUpdate/Delete List"
#define REG_REPLACE_LIST_KEY "Netscape/Communicator/SoftwareUpdate/Replace List"
#define REG_UNINSTALL_DIR "Netscape/Communicator/SoftwareUpdate/Uninstall/"
#define UNINSTALL_NAV_STR "_"
#define UNIX_GLOBAL_FLAG "MOZILLA_SHARED_REGISTRY"
/* Platform-dependent declspec for library interface */
#if defined(XP_PC)
#if defined(WIN32)
#if defined (STANDALONE_REGISTRY)
#define VR_INTERFACE(type) __declspec(dllexport) type __cdecl
#else
#define VR_INTERFACE(type) __declspec(dllexport) type __stdcall
#endif
#elif defined(XP_OS2)
#define VR_INTERFACE(type) type _Optlink
#else
#define VR_INTERFACE(type) type _far _pascal _export
#endif
#elif defined XP_MAC
#define VR_INTERFACE(__x) __declspec(export) __x
#else
#define VR_INTERFACE(type) type
#endif
XP_BEGIN_PROTOS
/* ---------------------------------------------------------------------
* Registry API -- General
* ---------------------------------------------------------------------
*/
VR_INTERFACE(REGERR) NR_RegOpen(
char *filename, /* reg. file to open (NULL == standard registry) */
HREG *hReg /* OUT: handle to opened registry */
);
VR_INTERFACE(REGERR) NR_RegClose(
HREG hReg /* handle of open registry to close */
);
VR_INTERFACE(REGERR) NR_RegPack(
HREG hReg, /* handle of open registry to pack */
void *userData,
nr_RegPackCallbackFunc fn
);
VR_INTERFACE(REGERR) NR_RegGetUsername(
char **name /* on return, an alloc'ed copy of the current user name */
);
VR_INTERFACE(REGERR) NR_RegSetUsername(
const char *name /* name of current user */
);
/* ---------------------------------------------------------------------
* Registry API -- Key Management functions
* ---------------------------------------------------------------------
*/
VR_INTERFACE(REGERR) NR_RegAddKey(
HREG hReg, /* handle of open registry */
RKEY key, /* root key */
char *path, /* relative path of subkey to add */
RKEY *newKey /* if not null returns newly created key */
);
VR_INTERFACE(REGERR) NR_RegDeleteKey(
HREG hReg, /* handle of open registry */
RKEY key, /* root key */
char *path /* relative path of subkey to delete */
);
VR_INTERFACE(REGERR) NR_RegGetKey(
HREG hReg, /* handle of open registry */
RKEY key, /* root key */
char *path, /* relative path of subkey to find */
RKEY *result /* returns RKEY of specified sub-key */
);
VR_INTERFACE(REGERR) NR_RegEnumSubkeys(
HREG hReg, /* handle of open registry */
RKEY key, /* containing key */
REGENUM *state, /* enum state, must be NULL to start */
char *buffer, /* buffer for entry names */
uint32 bufsize, /* size of buffer */
uint32 style /* 0: children only; REGENUM_DESCEND: sub-tree */
);
/* ---------------------------------------------------------------------
* Registry API -- Entry Management functions
* ---------------------------------------------------------------------
*/
VR_INTERFACE(REGERR) NR_RegGetEntryInfo(
HREG hReg, /* handle of open registry */
RKEY key, /* containing key */
char *name, /* entry name */
REGINFO *info /* returned entry info */
);
VR_INTERFACE(REGERR) NR_RegGetEntryString(
HREG hReg, /* handle of open registry */
RKEY key, /* containing key */
char *name, /* entry name */
char *buffer, /* buffer to hold value (UTF String) */
uint32 bufsize /* length of buffer */
);
VR_INTERFACE(REGERR) NR_RegGetEntry(
HREG hReg, /* handle of open registry */
RKEY key, /* containing key */
char *name, /* entry name */
void *buffer, /* buffer to hold value */
uint32 *size /* in:length of buffer */
); /* out: data length, >>includes<< null terminator*/
VR_INTERFACE(REGERR) NR_RegSetEntryString(
HREG hReg, /* handle of open registry */
RKEY key, /* containing key */
char *name, /* entry name */
char *buffer /* UTF String value */
);
VR_INTERFACE(REGERR) NR_RegSetEntry(
HREG hReg, /* handle of open registry */
RKEY key, /* containing key */
char *name, /* entry name */
uint16 type, /* type of value data */
void *buffer, /* data buffer */
uint32 size /* data length in bytes; incl. null term for strings */
);
VR_INTERFACE(REGERR) NR_RegDeleteEntry(
HREG hReg, /* handle of open registry */
RKEY key, /* containing key */
char *name /* value name */
);
VR_INTERFACE(REGERR) NR_RegEnumEntries(
HREG hReg, /* handle of open registry */
RKEY key, /* containing key */
REGENUM *state, /* enum state, must be NULL to start */
char *buffer, /* buffer for entry names */
uint32 bufsize, /* size of buffer */
REGINFO *info /* optional; returns info about entry */
);
VR_INTERFACE(void) NR_ShutdownRegistry(void);
VR_INTERFACE(void) NR_StartupRegistry(void);
XP_END_PROTOS
#endif /* _NSREG_H_ */
/* EOF: NSReg.h */

View File

@@ -0,0 +1,82 @@
/* -*- 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.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
* Reserved.
*/
/* VerReg.h
* XP Version Registry functions
*/
#ifndef _VERREG_H_
#define _VERREG_H_
#include "NSReg.h"
typedef struct _version
{
int32 major;
int32 minor;
int32 release;
int32 build;
int32 check;
} VERSION;
/* CreateRegistry flags */
#define CR_NEWREGISTRY 1
XP_BEGIN_PROTOS
/* ---------------------------------------------------------------------
* Version Registry Operations
* ---------------------------------------------------------------------
*/
/* global registry operations */
VR_INTERFACE(REGERR) VR_SetRegDirectory(const char *path);
VR_INTERFACE(REGERR) VR_CreateRegistry(char *installation, char *programPath, char *versionStr);
VR_INTERFACE(REGERR) VR_PackRegistry(void *userData, nr_RegPackCallbackFunc pdCallbackFunction);
VR_INTERFACE(REGERR) VR_Close(void);
/* component-level functions */
VR_INTERFACE(REGERR) VR_Install(char *component_path, char *filepath, char *version, int bDirectory);
VR_INTERFACE(REGERR) VR_Remove(char *component_path);
VR_INTERFACE(REGERR) VR_InRegistry(char *path);
VR_INTERFACE(REGERR) VR_ValidateComponent(char *path);
VR_INTERFACE(REGERR) VR_Enum(char *component_path, REGENUM *state, char *buffer, uint32 buflen);
/* dealing with parts of individual components */
VR_INTERFACE(REGERR) VR_GetVersion(char *component_path, VERSION *result);
VR_INTERFACE(REGERR) VR_GetPath(char *component_path, uint32 sizebuf, char *buf);
VR_INTERFACE(REGERR) VR_SetRefCount(char *component_path, int refcount);
VR_INTERFACE(REGERR) VR_GetRefCount(char *component_path, int *result);
VR_INTERFACE(REGERR) VR_GetDefaultDirectory(char *component_path, uint32 sizebuf, char *buf);
VR_INTERFACE(REGERR) VR_SetDefaultDirectory(char *component_path, char *directory);
/* uninstall functions */
VR_INTERFACE(REGERR) VR_UninstallCreateNode(char *regPackageName, char *userPackageName);
VR_INTERFACE(REGERR) VR_UninstallAddFileToList(char *regPackageName, char *vrName);
VR_INTERFACE(REGERR) VR_UninstallFileExistsInList(char *regPackageName, char *vrName);
VR_INTERFACE(REGERR) VR_UninstallEnumSharedFiles(char *component_path, REGENUM *state, char *buffer, uint32 buflen);
VR_INTERFACE(REGERR) VR_UninstallDeleteFileFromList(char *component_path, char *vrName);
VR_INTERFACE(REGERR) VR_UninstallDeleteSharedFilesKey(char *regPackageName);
VR_INTERFACE(REGERR) VR_UninstallDestroy(char *regPackageName);
VR_INTERFACE(REGERR) VR_EnumUninstall(REGENUM *state, char* userPackageName,
int32 len1, char*regPackageName, int32 len2, Bool bSharedList);
VR_INTERFACE(REGERR) VR_GetUninstallUserName(char *regPackageName, char *outbuf, uint32 buflen);
XP_END_PROTOS
#endif /* _VERREG_H_ */
/* EOF: VerReg.h */

View File

@@ -0,0 +1,34 @@
#!gmake
#
# The contents of this file are subject to the Netscape Public License
# Version 1.0 (the "NPL"); you may not use this file except in
# compliance with the NPL. You may obtain a copy of the NPL at
# http://www.mozilla.org/NPL/
#
# Software distributed under the NPL is distributed on an "AS IS" basis,
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
# for the specific language governing rights and limitations under the
# NPL.
#
# The Initial Developer of this code under the NPL is Netscape
# Communications Corporation. Portions created by Netscape are
# Copyright (C) 1998 Netscape Communications Corporation. All Rights
# Reserved.
IGNORE_MANIFEST=1
#
#//------------------------------------------------------------------------
#//
#// Makefile to install MODULES/LIBREG/INCLUDE header files into the distribution
#// directory.
#//
#//------------------------------------------------------------------------
MODULE=libreg
DEPTH=..\..\..
EXPORTS=VerReg.h NSReg.h
include <$(DEPTH)/config/rules.mak>

View File

@@ -0,0 +1,3 @@
#include "MacPrefix.h"
#define STANDALONE_REGISTRY 1

Binary file not shown.

View File

@@ -0,0 +1,26 @@
globalRegName
NR_ShutdownRegistry
NR_StartupRegistry
NR_RegEnumEntries
NR_RegEnumSubkeys
NR_RegDeleteEntry
NR_RegSetEntry
NR_RegSetEntryString
NR_RegGetEntry
NR_RegGetEntryString
NR_RegGetEntryInfo
NR_RegGetKey
NR_RegDeleteKey
NR_RegAddKey
NR_RegPack
NR_RegClose
NR_RegOpen
NR_RegSetUsername
NR_RegGetUsername
nr_PathFromMacAlias
nr_MacAliasFromPath
vr_findGlobalRegName
#__ptmf_null
#longjmp
#__terminate
#__initialize

View File

@@ -0,0 +1,48 @@
#!gmake
#
# The contents of this file are subject to the Netscape Public License
# Version 1.0 (the "NPL"); you may not use this file except in
# compliance with the NPL. You may obtain a copy of the NPL at
# http://www.mozilla.org/NPL/
#
# Software distributed under the NPL is distributed on an "AS IS" basis,
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
# for the specific language governing rights and limitations under the
# NPL.
#
# The Initial Developer of this code under the NPL is Netscape
# Communications Corporation. Portions created by Netscape are
# Copyright (C) 1998 Netscape Communications Corporation. All Rights
# Reserved.
#//------------------------------------------------------------------------
#//
#// Makefile to build the MODULES\LIBREG tree
#//
#//------------------------------------------------------------------------
#//------------------------------------------------------------------------
#//
#// Specify the depth of the current directory relative to the
#// root of NS
#//
#//------------------------------------------------------------------------
DEPTH=..\..
#//------------------------------------------------------------------------
#//
#// Specify any "command" targets. (ie. DIRS, INSTALL_FILES, ...)
#// (these must come before the common makefiles are included)
#//
#// DIRS - There are subdirectories to process
#//
#//------------------------------------------------------------------------
DIRS=include src standalone
#//------------------------------------------------------------------------
#//
#// Include the common makefile rules
#//
#//------------------------------------------------------------------------
include <$(DEPTH)\config\rules.mak>

View File

@@ -0,0 +1,82 @@
#!gmake
#
# The contents of this file are subject to the Netscape Public License
# Version 1.0 (the "NPL"); you may not use this file except in
# compliance with the NPL. You may obtain a copy of the NPL at
# http://www.mozilla.org/NPL/
#
# Software distributed under the NPL is distributed on an "AS IS" basis,
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
# for the specific language governing rights and limitations under the
# NPL.
#
# The Initial Developer of this code under the NPL is Netscape
# Communications Corporation. Portions created by Netscape are
# Copyright (C) 1998 Netscape Communications Corporation. All Rights
# Reserved.
DEPTH = ../../..
topsrcdir = @top_srcdir@
VPATH = @srcdir@
srcdir = @srcdir@
include $(DEPTH)/config/autoconf.mk
MODULE = libreg
LIBRARY_NAME = reg
REQUIRES = libreg pref js
CSRCS = reg.c VerReg.c vr_stubs.c
BIN_SRCS = VerReg.c reg.c vr_stubs.c
BIN_OBJS = $(addprefix $(OBJDIR)/R_,$(BIN_SRCS:.c=.o))
include $(topsrcdir)/config/rules.mk
# Override gtscc when building vreg on IRIX 5.3.
ifeq ($(OS_ARCH)$(OS_RELEASE),IRIX5)
CC = cc
endif
INCLUDES += -I$(topsrcdir)/include
GARBAGE += $(PROGRAM)
PROGRAM = $(OBJDIR)/vreg$(BIN_SUFFIX)
$(PROGRAM): $(BIN_OBJS)
@$(MAKE_OBJDIR)
ifeq ($(OS_ARCH), OS2)
$(LINK_EXE) -OUT:$@ $(BIN_OBJS) $(LDFLAGS) $(OS_LIBS)
else
$(CCF) -o $@ $(BIN_OBJS) $(LDFLAGS)
endif
$(OBJDIR)/R_VerReg.o: VerReg.c
@$(MAKE_OBJDIR)
ifeq ($(OS_ARCH), OS2)
$(CC) -Fo$@ -c $(CFLAGS) -DSTANDALONE_REGISTRY $<
else
$(CC) -o $@ -c $(CFLAGS) -DSTANDALONE_REGISTRY $<
endif
$(OBJDIR)/R_reg.o: reg.c
@$(MAKE_OBJDIR)
ifeq ($(OS_ARCH), OS2)
$(CC) -Fo$@ -c $(CFLAGS) -DSTANDALONE_REGISTRY $<
else
$(CC) -o $@ -c $(CFLAGS) -DSTANDALONE_REGISTRY $<
endif
$(OBJDIR)/R_vr_stubs.o: vr_stubs.c
@$(MAKE_OBJDIR)
ifeq ($(OS_ARCH), OS2)
$(CC) -Fo$@ -c $(CFLAGS) -DSTANDALONE_REGISTRY $<
else
$(CC) -o $@ -c $(CFLAGS) -DSTANDALONE_REGISTRY $<
endif
$(BIN_OBJS): $(BIN_SRCS)
install:: $(PROGRAM)
$(INSTALL) -m 444 $(PROGRAM) $(DIST)/bin

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,102 @@
#!gmake
#
# The contents of this file are subject to the Netscape Public License
# Version 1.0 (the "NPL"); you may not use this file except in
# compliance with the NPL. You may obtain a copy of the NPL at
# http://www.mozilla.org/NPL/
#
# Software distributed under the NPL is distributed on an "AS IS" basis,
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
# for the specific language governing rights and limitations under the
# NPL.
#
# The Initial Developer of this code under the NPL is Netscape
# Communications Corporation. Portions created by Netscape are
# Copyright (C) 1998 Netscape Communications Corporation. All Rights
# Reserved.
IGNORE_MANIFEST=1
#//------------------------------------------------------------------------
#//
#// Makefile to build
#//
#//------------------------------------------------------------------------
#//------------------------------------------------------------------------
#//
#// Specify the depth of the current directory relative to the
#// root of NS
#//
#//------------------------------------------------------------------------
DEPTH= ..\..\..
!ifndef MAKE_OBJ_TYPE
MAKE_OBJ_TYPE=DLL
!endif
#//------------------------------------------------------------------------
#//
#// Define any Public Make Variables here: (ie. PDFFILE, MAPFILE, ...)
#//
#//------------------------------------------------------------------------
#//------------------------------------------------------------------------
#//
#// Define the files necessary to build the target (ie. OBJS)
#//
#//------------------------------------------------------------------------
OBJS= \
.\$(OBJDIR)\reg.obj \
.\$(OBJDIR)\VerReg.obj \
.\$(OBJDIR)\vr_stubs.obj \
$(NULL)
#//------------------------------------------------------------------------
#//
#// Define any Public Targets here (ie. PROGRAM, LIBRARY, DLL, ...)
#// (these must be defined before the common makefiles are included)
#//
#//------------------------------------------------------------------------
LIBNAME=libreg$(MOZ_BITS)
DLL=$(OBJDIR)\$(LIBNAME).dll
LIBRARY= .\$(OBJDIR)\$(LIBNAME).lib
#//------------------------------------------------------------------------
#//
#// Define any local options for the make tools
#// (ie. LCFLAGS, LLFLAGS, LLIBS, LINCS)
#//
#//------------------------------------------------------------------------
LCFLAGS = $(LCFLAGS)
LLIBS = $(LLIBS) $(LIBNSPR) $(DIST)\lib\libplc21.lib
!if "$(MOZ_BITS)"=="32" && defined(MOZ_DEBUG) && defined(GLOWCODE)
LLIBS=$(LLIBS) $(GLOWDIR)\glowcode.lib
!endif
#//
#// Win16 places ALL public header files in $(PUBLIC)/win16
#//
!if "$(MOZ_BITS)" != "16"
LINCS= $(LINCS) -I$(PUBLIC)/libreg \
$(NULL)
!endif
#//------------------------------------------------------------------------
#//
#// Include the common makefile rules
#//
#//------------------------------------------------------------------------
include <$(DEPTH)/config/rules.mak>
export:: $(DLL)
$(MAKE_INSTALL) $(LIBRARY) $(DIST)\lib
$(MAKE_INSTALL) $(DLL) $(DIST)\bin
clobber::
$(RM) $(DIST)\bin\$(DLL)
$(RM) $(DIST)\lib\$(LIBRARY)

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,175 @@
/* -*- 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.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
* Reserved.
*/
/* reg.h
* XP Registry functions (prototype)
*/
#ifndef _REG_H_
#define _REG_H_
#include "vr_stubs.h"
#ifndef STANDALONE_REGISTRY
#include "prmon.h"
#endif
/* --------------------------------------------------------------------
* Miscellaneous Definitions
* --------------------------------------------------------------------
*/
#define MAGIC_NUMBER 0x76644441L
#define MAJOR_VERSION 1 /* major version for incompatible changes */
#define MINOR_VERSION 2 /* minor ver for new (compatible) features */
#define PATHDEL '/'
#define EQU '='
#define QUOTE '"'
#define HDRRESERVE 128 /* number of bytes reserved for hdr */
#define INTSIZE 4
#define DOUBLESIZE 8
#define PACKBUFFERSIZE 2048
/* Node types */
#define REGTYPE_KEY (1)
#define REGTYPE_DELETED (0x0080)
/* Private standard keys */
#define ROOTKEY (0x20)
#define ROOTKEY_VERSIONS (0x21)
/* strings for standard keys */
#define ROOTKEY_STR "/"
#define ROOTKEY_VERSIONS_STR "Version Registry"
#define ROOTKEY_USERS_STR "Users"
#define ROOTKEY_COMMON_STR "Common"
#define ROOTKEY_PRIVATE_STR "Private Arenas"
#define OLD_VERSIONS_STR "ROOTKEY_VERSIONS"
#define OLD_USERS_STR "ROOTKEY_USERS"
#define OLD_COMMON_STR "ROOTKEY_COMMON"
/* needs to be kept in sync with PE. see ns/cmd/winfe/profile.h */
/* and ns/cmd/macfe/central/profile.cp */
#define ASW_MAGIC_PROFILE_NAME "User1"
/* macros */
#define COPYDESC(dest,src) memcpy((dest),(src),sizeof(REGDESC))
#define VALID_FILEHANDLE(fh) ((fh) != NULL)
#define INVALID_NAME_CHAR(p) ( ((unsigned char)(p) < 0x20) || ((p) == '=') )
#define TYPE_IS_ENTRY(type) ( (type) & REGTYPE_ENTRY )
#define TYPE_IS_KEY(type) ( !((type) & REGTYPE_ENTRY) )
#define VERIFY_HREG(h)\
( ((h) == NULL) ? REGERR_PARAM : \
( (((REGHANDLE*)(h))->magic == MAGIC_NUMBER) ? REGERR_OK : REGERR_BADMAGIC ) )
/* --------------------------------------------------------------------
* Types and Objects
* --------------------------------------------------------------------
*/
#undef REGOFF
typedef int32 REGOFF; /* offset into registry file */
typedef struct _desc
{
REGOFF location; /* this object's offset (for verification) */
REGOFF name; /* name string */
uint16 namelen; /* length of name string (including terminator) */
uint16 type; /* node type (key, or entry style) */
REGOFF left; /* next object at this level (0 if none) */
REGOFF down; /* KEY: first subkey VALUE: 0 */
REGOFF value; /* KEY: first entry object VALUE: value string */
uint32 valuelen; /* KEY: 0 VALUE: length of value data */
uint32 valuebuf; /* KEY: 0 VALUE: length available */
REGOFF parent; /* the node on the immediate level above */
} REGDESC;
/* offsets into structure on disk */
#define DESC_LOCATION 0
#define DESC_NAME 4
#define DESC_NAMELEN 8
#define DESC_TYPE 10
#define DESC_LEFT 12
#define DESC_DOWN 16
#define DESC_VALUE 20
#define DESC_VALUELEN 24
#define DESC_VALUEBUF 16 /* stored in place of "down" for entries */
#define DESC_PARENT 28
#define DESC_SIZE 32 /* size of desc on disk */
typedef struct _hdr
{
uint32 magic; /* must equal MAGIC_NUMBER */
uint16 verMajor; /* major version number */
uint16 verMinor; /* minor version number */
REGOFF avail; /* next available offset */
REGOFF root; /* root object */
} REGHDR;
/* offsets into structure on disk*/
#define HDR_MAGIC 0
#define HDR_VERMAJOR 4
#define HDR_VERMINOR 6
#define HDR_AVAIL 8
#define HDR_ROOT 12
typedef XP_File FILEHANDLE; /* platform-specific file reference */
typedef struct _stdnodes {
REGOFF versions;
REGOFF users;
REGOFF common;
REGOFF current_user;
REGOFF privarea;
} STDNODES;
typedef struct _regfile
{
FILEHANDLE fh;
REGHDR hdr;
int refCount;
int hdrDirty;
int inInit;
int readOnly;
char * filename;
STDNODES rkeys;
struct _regfile *next;
struct _regfile *prev;
#ifndef STANDALONE_REGISTRY
PRMonitor *monitor;
#endif
} REGFILE;
typedef struct _reghandle
{
uint32 magic; /* for validating reg handles */
REGFILE *pReg; /* the real registry file object */
} REGHANDLE;
#endif /* _REG_H_ */
/* EOF: reg.h */

View File

@@ -0,0 +1,554 @@
/* -*- 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.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
* Reserved.
*/
/* this file contains stubs needed to build the registry routines
* into a stand-alone library for use with our installers
*/
#ifdef STANDALONE_REGISTRY
#include <stdio.h>
#include <string.h>
#else
#include "prtypes.h"
#include "plstr.h"
#endif /*STANDALONE_REGISTRY*/
#include "vr_stubs.h"
#ifdef XP_MAC
#include <Folders.h>
#include <Script.h>
#include <stdlib.h>
#include <Errors.h>
#include "MoreFiles.h"
#include "FullPath.h" /* For FSpLocationFromFullPath() */
#endif
extern char* globalRegName;
/* ------------------------------------------------------------------
* OS/2 STUBS
* ------------------------------------------------------------------
*/
#ifdef XP_OS2
#define INCL_DOS
#include <os2.h>
#ifdef STANDALONE_REGISTRY
extern XP_File vr_fileOpen (const char *name, const char * mode)
{
XP_File fh = NULL;
struct stat st;
if ( name != NULL ) {
if ( stat( name, &st ) == 0 )
fh = fopen( name, XP_FILE_UPDATE_BIN );
else
fh = fopen( name, XP_FILE_WRITE_BIN );
}
return fh;
}
#endif /*STANDALONE_REGISTRY*/
extern void vr_findGlobalRegName ()
{
char path[ CCHMAXPATH ];
int pathlen;
XP_File fh = NULL;
struct stat st;
#ifdef XP_OS2_HACK
/*DSR050197 - at this point, I need some front-end call to get the install directory of*/
/*communicator... for now I will let it default to the current directory...*/
#endif
XP_STRCPY(path, ".");
pathlen = strlen(path);
if ( pathlen > 0 ) {
XP_STRCPY( path+pathlen, "\\nsreg.dat" );
globalRegName = XP_STRDUP(path);
}
}
#endif /* XP_OS2 */
/* ------------------------------------------------------------------
* WINDOWS STUBS
* ------------------------------------------------------------------
*/
#ifdef XP_PC
#include "windows.h"
#define PATHLEN 260
#ifdef STANDALONE_REGISTRY
extern XP_File vr_fileOpen (const char *name, const char * mode)
{
XP_File fh = NULL;
struct stat st;
if ( name != NULL ) {
if ( stat( name, &st ) == 0 )
fh = fopen( name, XP_FILE_UPDATE_BIN );
else
fh = fopen( name, XP_FILE_WRITE_BIN );
}
return fh;
}
#endif /*STANDALONE_REGISTRY*/
extern void vr_findGlobalRegName ()
{
char path[ PATHLEN ];
int pathlen;
pathlen = GetWindowsDirectory(path, PATHLEN);
if ( pathlen > 0 ) {
XP_STRCPY( path+pathlen, "\\nsreg.dat" );
globalRegName = XP_STRDUP(path);
}
}
#if !defined(WIN32) && !defined(__BORLANDC__)
int FAR PASCAL _export WEP(int);
int FAR PASCAL LibMain(HANDLE hInst, WORD wDataSeg, WORD wHeapSize, LPSTR lpszCmdLine)
{
if ( wHeapSize > 0 )
UnlockData(0);
return 1;
}
int FAR PASCAL _export WEP(int nParam)
{
return 1;
}
#endif /* not WIN32 */
#endif /* XP_PC */
/* ------------------------------------------------------------------
* MACINTOSH STUBS
* ------------------------------------------------------------------
*/
#ifdef XP_MAC
#include <Files.h>
#include "FullPath.h"
#ifdef STANDALONE_REGISTRY
extern XP_File vr_fileOpen(const char *name, const char * mode)
{
XP_File fh = NULL;
struct stat st;
OSErr anErr;
FSSpec newFSSpec;
#ifdef STANDALONE_REGISTRY
errno = 0; // reset errno (only if we're using stdio)
#endif
anErr = FSpLocationFromFullPath(strlen(name), name, &newFSSpec);
if (anErr == -43)
{
/* if file doesn't exist */
anErr = FSpCreate(&newFSSpec, 'MOSS', 'REGS', smSystemScript);
}
else
{
/* there is not much to do here. if we got noErr, the file exists. If we did not get
noErr or -43, we are pretty hosed.
*/
}
if ( name != NULL ) {
if ( stat( name, &st ) == 0 )
fh = fopen( name, XP_FILE_UPDATE_BIN ); /* If/when we switch to MSL C Lib (gromit uses this), we might have to take out the Macro per bug #62382 */
else
{
/* should never get here! */
fh = fopen( name, XP_FILE_WRITE_BIN );
}
}
#ifdef STANDALONE_REGISTRY
if (anErr != noErr)
errno = anErr;
#endif
return fh;
}
#endif /*STANDALONE_REGISTRY*/
extern void vr_findGlobalRegName()
{
FSSpec regSpec;
OSErr err;
short foundVRefNum;
long foundDirID;
int bCreate = 0;
err = FindFolder(kOnSystemDisk,'pref', false, &foundVRefNum, &foundDirID);
if (!err)
{
err = FSMakeFSSpec(foundVRefNum, foundDirID, "\pNetscape Registry", &regSpec);
if (err == -43) /* if file doesn't exist */
{
err = FSpCreate(&regSpec, 'MOSS', 'REGS', smSystemScript);
bCreate = 1;
}
if (err == noErr)
{
Handle thePath;
short pathLen;
err = FSpGetFullPath(&regSpec, &pathLen, &thePath);
if (err == noErr && thePath)
{
#ifdef STANDALONE_REGISTRY
globalRegName = XP_STRDUP(*(char**)thePath);
#else
/* Since we're now using NSPR, this HAS to be a unix path! */
const char* src;
char* dst;
globalRegName = (char*)XP_ALLOC(pathLen + 2);
src = *(char**)thePath;
dst = globalRegName;
*dst++ = '/';
while (pathLen--)
{
char c = *src++;
*dst++ = (c == ':') ? '/' : c;
}
*dst = '\0';
#endif
}
DisposeHandle(thePath);
}
}
}
/* Moves and renames a file or directory.
Returns 0 on success, -1 on failure (errno contains mac error code).
*/
extern int nr_RenameFile(char *from, char *to)
{
OSErr err = -1;
FSSpec fromSpec;
FSSpec toSpec;
FSSpec destDirSpec;
FSSpec beforeRenameSpec;
#ifdef STANDALONE_REGISTRY
errno = 0; // reset errno (only if we're using stdio)
#endif
if (from && to) {
err = FSpLocationFromFullPath(XP_STRLEN(from), from, &fromSpec);
if (err != noErr) goto exit;
err = FSpLocationFromFullPath(XP_STRLEN(to), to, &toSpec);
if (err != noErr && err != fnfErr) goto exit;
// make an FSSpec for the destination directory
err = FSMakeFSSpec(toSpec.vRefNum, toSpec.parID, nil, &destDirSpec);
if (err != noErr) goto exit; // parent directory must exist
// move it to the directory specified
err = FSpCatMove(&fromSpec, &destDirSpec);
if (err != noErr) goto exit;
// make a new FSSpec for the file or directory in its new location
err = FSMakeFSSpec(toSpec.vRefNum, toSpec.parID, fromSpec.name, &beforeRenameSpec);
if (err != noErr) goto exit;
// rename the file or directory
err = FSpRename(&beforeRenameSpec, toSpec.name);
}
exit:
#ifdef STANDALONE_REGISTRY
if (err != noErr)
errno = err;
#endif
return (err == noErr ? 0 : -1);
}
#if 0
/* Uncomment the following for older Mac build environments
* that don't support these functions
*/
char *strdup(const char *source)
{
char *newAllocation;
size_t stringLength;
stringLength = strlen(source) + 1;
newAllocation = (char *)XP_ALLOC(stringLength);
if (newAllocation == NULL)
return NULL;
BlockMoveData(source, newAllocation, stringLength);
return newAllocation;
}
int strcasecmp(const char *str1, const char *str2)
{
char currentChar1, currentChar2;
while (1) {
currentChar1 = *str1;
currentChar2 = *str2;
if ((currentChar1 >= 'a') && (currentChar1 <= 'z'))
currentChar1 += ('A' - 'a');
if ((currentChar2 >= 'a') && (currentChar2 <= 'z'))
currentChar2 += ('A' - 'a');
if (currentChar1 == '\0')
break;
if (currentChar1 != currentChar2)
return currentChar1 - currentChar2;
str1++;
str2++;
}
return currentChar1 - currentChar2;
}
int strncasecmp(const char *str1, const char *str2, int length)
{
char currentChar1, currentChar2;
while (length > 0) {
currentChar1 = *str1;
currentChar2 = *str2;
if ((currentChar1 >= 'a') && (currentChar1 <= 'z'))
currentChar1 += ('A' - 'a');
if ((currentChar2 >= 'a') && (currentChar2 <= 'z'))
currentChar2 += ('A' - 'a');
if (currentChar1 == '\0')
break;
if (currentChar1 != currentChar2)
return currentChar1 - currentChar2;
str1++;
str2++;
length--;
}
return currentChar1 - currentChar2;
}
#endif /* 0 */
#endif /* XP_MAC */
/* ------------------------------------------------------------------
* UNIX STUBS
* ------------------------------------------------------------------
*/
/*allow OS/2 and Macintosh to use this main to test...*/
#if (defined(STANDALONE_REGISTRY) && defined(XP_MAC)) || defined(XP_UNIX) || defined(XP_OS2)
#include <stdlib.h>
#ifdef XP_OS2
#include <io.h>
#define W_OK 0x02 /*evil hack from the docs...*/
#else
#include <unistd.h>
#endif
#include "NSReg.h"
#include "VerReg.h"
char *TheRegistry = "registry";
char *Flist;
/* WARNING: build hackery */
#if defined(STANDALONE_REGISTRY) && !defined(XP_MAC)
long BUILDNUM =
#include "../../../build/build_number"
;
#endif
REGERR vr_ParseVersion(char *verstr, VERSION *result);
int main(int argc, char *argv[]);
#ifdef XP_UNIX
#define DEF_REG "/.netscape/registry"
#ifdef STANDALONE_REGISTRY
extern XP_File vr_fileOpen (const char *name, const char * mode)
{
XP_File fh = NULL;
struct stat st;
if ( name != NULL ) {
if ( stat( name, &st ) == 0 )
fh = fopen( name, XP_FILE_UPDATE_BIN );
else
fh = fopen( name, XP_FILE_WRITE_BIN );
}
return fh;
}
#endif /*STANDALONE_REGISTRY*/
extern void vr_findGlobalRegName ()
{
#ifndef STANDALONE_REGISTRY
char *def = NULL;
char *home = getenv("HOME");
if (home != NULL) {
def = (char *) XP_ALLOC(XP_STRLEN(home) + XP_STRLEN(DEF_REG)+1);
if (def != NULL) {
XP_STRCPY(def, home);
XP_STRCAT(def, DEF_REG);
}
}
if (def != NULL) {
globalRegName = XP_STRDUP(def);
} else {
globalRegName = TheRegistry;
}
XP_FREEIF(def);
#else
globalRegName = TheRegistry;
#endif /*STANDALONE_REGISTRY*/
}
#endif /*XP_UNIX*/
#if defined(STANDALONE_REGISTRY) && (defined(XP_UNIX) || defined(XP_OS2) || defined(XP_MAC))
int main(int argc, char *argv[])
{
XP_File fh;
char *entry;
char *p;
char *v;
char buff[1024];
char name[MAXREGPATHLEN+1];
char path[MAXREGPATHLEN+1];
char ver[MAXREGPATHLEN+1];
if ( argc >= 3 )
{
TheRegistry = argv[1];
Flist = argv[2];
}
else
{
fprintf(stderr, "Usage: %s RegistryName FileList\n", argv[0]);
fprintf(stderr, " The FileList file contains lines with comma-separated fields:\n");
fprintf(stderr, " <regItemName>,<version>,<full filepath>\n");
exit (1);
}
/* tmp use of buff to get the registry directory, which must be
* the navigator home directory. Preserve the slash to match
* FE_GetDirectoryPath() called during navigator set-up
*/
strcpy(buff, TheRegistry);
p = strrchr( buff, '/' );
if ( p )
{
char pwd[1024];
*(p+1) = '\0';
getcwd(pwd, sizeof(pwd));
chdir(buff); getcwd(buff, sizeof(buff));
chdir(pwd);
}
else
{
getcwd(buff, sizeof(buff));
}
strcat(buff, "/");
NR_StartupRegistry();
VR_SetRegDirectory(buff);
#ifndef XP_MAC
if ( -1 == (access( TheRegistry, W_OK )) ) {
sprintf(ver,"4.50.0.%ld",BUILDNUM);
VR_CreateRegistry("Communicator", buff, ver);
}
#endif
if ( !(fh = fopen( Flist, "r" )) )
{
fprintf(stderr, "%s: Cannot open \"%s\"\n", argv[0], Flist);
exit (1);
}
while ( fgets ( buff, 1024, fh ) )
{
if ( *(entry = &buff[strlen(buff)-1]) == '\n' )
*entry = '\0';
entry = strchr(buff, ',');
strcpy(name, strtok(buff, ","));
strcpy(ver, strtok( NULL, ","));
strcpy(path, strtok( NULL, ","));
v = ver;
while (*v && *v == ' ')
v++;
p = path;
while (*p && *p == ' ')
p++;
VR_Install ( name, p, v, FALSE );
}
fclose( fh );
return 0;
}
#endif /* STANDALONE_REGISTRY && (XP_UNIX || XP_OS2 || XP_MAC) */
#endif /* XP_UNIX || XP_OS2 */

View File

@@ -0,0 +1,253 @@
/* -*- 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.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
* Reserved.
*/
/* vr_stubs.h
*
* XP code stubs for stand-alone registry library
*
*/
#ifndef _VR_STUBS_H_
#define _VR_STUBS_H_
#ifdef STANDALONE_REGISTRY
#include <errno.h>
#include <string.h>
#ifdef XP_MAC
#include "macstdlibextras.h" /* For strcasecmp and strncasecmp */
#endif
#else
#include "prio.h"
#include "prmem.h"
#include "plstr.h"
#endif /* STANDALONE_REGISTRY*/
#ifdef XP_MAC
#include <stat.h>
#else
#if defined(BSDI) && !defined(BSDI_2)
#include <sys/types.h>
#endif
#include <sys/stat.h>
#endif
#ifndef FALSE
#define FALSE 0
#endif
#ifndef TRUE
#define TRUE 1
#endif
#if defined(__cplusplus)
# define XP_CPLUSPLUS
# define XP_IS_CPLUSPLUS 1
#else
# define XP_IS_CPLUSPLUS 0
#endif
#if defined(XP_CPLUSPLUS)
# define XP_BEGIN_PROTOS extern "C" {
# define XP_END_PROTOS }
#else
# define XP_BEGIN_PROTOS
# define XP_END_PROTOS
#endif
#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 XP_FileSeek(file,offset,whence) fseek((file), (offset), (whence))
#define XP_FileRead(dest,count,file) fread((dest), 1, (count), (file))
#define XP_FileWrite(src,count,file) fwrite((src), 1, (count), (file))
#define XP_FileTell(file) ftell(file)
#define XP_FileFlush(file) fflush(file)
#define XP_FileClose(file) fclose(file)
#define XP_ASSERT(x) ((void)0)
#define XP_STRCAT(a,b) strcat((a),(b))
#define XP_ATOI atoi
#define XP_STRCPY(a,b) strcpy((a),(b))
#define XP_STRLEN(x) strlen(x)
#define XP_SPRINTF sprintf
#define XP_FREE(x) free((x))
#define XP_ALLOC(x) malloc((x))
#define XP_FREEIF(x) if ((x)) free((x))
#define XP_STRCMP(x,y) strcmp((x),(y))
#define XP_STRNCMP(x,y,n) strncmp((x),(y),(n))
#define XP_STRDUP(s) strdup((s))
#define XP_MEMCPY(d, s, l) memcpy((d), (s), (l))
#define XP_MEMSET(d, c, l) memset((d), (c), (l))
#ifdef XP_PC
#define XP_STRCASECMP(x,y) stricmp((x),(y))
#define XP_STRNCASECMP(x,y,n) strnicmp((x),(y),(n))
#else
#define XP_STRCASECMP(x,y) strcasecmp((x),(y))
#define XP_STRNCASECMP(x,y,n) strncasecmp((x),(y),(n))
#endif /*XP_PC*/
typedef FILE * XP_File;
#else /* if not standalone, use NSPR */
#define XP_FILE_READ PR_RDONLY, 0700
#define XP_FILE_READ_BIN PR_RDONLY, 0700
#define XP_FILE_WRITE PR_WRONLY, 0700
#define XP_FILE_WRITE_BIN PR_WRONLY, 0700
#define XP_FILE_UPDATE PR_RDWR
#define XP_FILE_TRUNCATE (PR_WRONLY | PR_TRUNCATE), 0700
#define XP_FILE_UPDATE_BIN PR_RDWR, 0700
#define XP_FILE_TRUNCATE_BIN (PR_RDWR | PR_TRUNCATE), 0700
#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
/*
** Note that PR_Seek returns the offset (if successful) and -1 otherwise. So
** to make this code work
** if (XP_FileSeek(fh, offset, SEEK_SET) != 0) { error handling }
** we return 1 if PR_Seek() returns a negative value, and 0 otherwise
*/
#define XP_FileSeek(file,offset,whence) (PR_Seek((file), (offset), (whence)) < 0)
#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_FileFlush(file) PR_Sync(file)
#define XP_FileClose(file) PR_Close(file)
#define XP_ASSERT(x) PR_ASSERT((x))
#define XP_STRCAT(a,b) PL_strcat((a),(b))
#define XP_ATOI PL_atoi
#define XP_STRCPY(a,b) PL_strcpy((a),(b))
#define XP_STRLEN(x) PL_strlen(x)
#define XP_SPRINTF sprintf
#define XP_FREE(x) PR_Free((x))
#define XP_ALLOC(x) PR_Malloc((x))
#define XP_FREEIF(x) PR_FREEIF(x)
#define XP_STRCMP(x,y) PL_strcmp((x),(y))
#define XP_STRNCMP(x,y,n) PL_strncmp((x),(y),(n))
#define XP_STRDUP(s) PL_strdup((s))
#define XP_MEMCPY(d, s, l) memcpy((d), (s), (l))
#define XP_MEMSET(d, c, l) memset((d), (c), (l))
#define XP_STRCASECMP(x,y) PL_strcasecmp((x),(y))
#define XP_STRNCASECMP(x,y,n) PL_strncasecmp((x),(y),(n))
typedef PRFileDesc* XP_File;
#endif /*STANDALONE_REGISTRY*/
#ifdef STANDALONE_REGISTRY /* included from prmon.h otherwise */
#include "prtypes.h"
#if 0
typedef long int32;
typedef unsigned long uint32;
typedef short int16;
typedef unsigned short uint16;
typedef unsigned char uint8;
#ifdef XP_MAC
#include <Types.h>
typedef char BOOL;
typedef char Bool;
typedef char XP_Bool;
#elif defined(XP_PC)
typedef int Bool;
typedef int XP_Bool;
#else
/* XP_UNIX: X11/Xlib.h "define"s Bool to be int. This is really lame
* (that's what typedef is for losers). So.. in lieu of a #undef Bool
* here (Xlib still needs ints for Bool-typed parameters) people have
* been #undef-ing Bool before including this file.
* Can we just #undef Bool here? <mailto:mcafee> (help from djw, converse)
*/
typedef char Bool;
typedef char XP_Bool;
#endif /* XP_MAC */
#endif /* 0 */
#endif /*STANDALONE_REGISTRY*/
#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*/
#ifdef XP_MAC
extern int nr_RenameFile(char *from, char *to);
#else
XP_BEGIN_PROTOS
#define nr_RenameFile(from, to) rename((from), (to))
XP_END_PROTOS
#endif
#ifdef STANDALONE_REGISTRY /* included from prmon.h otherwise */
XP_BEGIN_PROTOS
extern XP_File vr_fileOpen(const char *name, const char * mode);
extern void vr_findGlobalRegName();
#if !defined(XP_PC) && !(defined(__GLIBC__) && __GLIBC__ >= 2)
extern char * strdup(const char * s);
#endif
XP_END_PROTOS
#else
#define vr_fileOpen PR_Open
XP_BEGIN_PROTOS
extern void vr_findGlobalRegName();
XP_END_PROTOS
#endif /* STANDALONE_REGISTRY */
#endif /* _VR_STUBS_H_ */

View File

@@ -0,0 +1,115 @@
#!gmake
#
# The contents of this file are subject to the Netscape Public License
# Version 1.0 (the "NPL"); you may not use this file except in
# compliance with the NPL. You may obtain a copy of the NPL at
# http://www.mozilla.org/NPL/
#
# Software distributed under the NPL is distributed on an "AS IS" basis,
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
# for the specific language governing rights and limitations under the
# NPL.
#
# The Initial Developer of this code under the NPL is Netscape
# Communications Corporation. Portions created by Netscape are
# Copyright (C) 1998 Netscape Communications Corporation. All Rights
# Reserved.
IGNORE_MANIFEST=1
#//------------------------------------------------------------------------
#//
#// Makefile to build
#//
#//------------------------------------------------------------------------
#//------------------------------------------------------------------------
#//
#// Specify the depth of the current directory relative to the
#// root of NS
#//
#//------------------------------------------------------------------------
DEPTH= ..\..\..
!ifndef MAKE_OBJ_TYPE
MAKE_OBJ_TYPE=DLL
!endif
#//------------------------------------------------------------------------
#//
#// Define any Public Make Variables here: (ie. PDFFILE, MAPFILE, ...)
#//
#//------------------------------------------------------------------------
#//------------------------------------------------------------------------
#//
#// Define the files necessary to build the target (ie. OBJS)
#//
#//------------------------------------------------------------------------
OBJS= \
.\$(OBJDIR)\reg.obj \
.\$(OBJDIR)\VerReg.obj \
.\$(OBJDIR)\vr_stubs.obj \
$(NULL)
#//------------------------------------------------------------------------
#//
#// Define any Public Targets here (ie. PROGRAM, LIBRARY, DLL, ...)
#// (these must be defined before the common makefiles are included)
#//
#//------------------------------------------------------------------------
LIBNAME=nsreg
DLL=$(OBJDIR)\$(LIBNAME).dll
#//------------------------------------------------------------------------
#//
#// Define any local options for the make tools
#// (ie. LCFLAGS, LLFLAGS, LLIBS, LINCS)
#//
#//------------------------------------------------------------------------
LCFLAGS = -DSTANDALONE_REGISTRY
LINCS= $(LINCS) -I$(PUBLIC)/libreg \
$(NULL)
#//------------------------------------------------------------------------
#//
#// Include the common makefile rules
#//
#//------------------------------------------------------------------------
include <$(DEPTH)/config/rules.mak>
reg.c::
$(RM) $(DEPTH)\modules\libreg\standalone\reg.h
$(RM) $(DEPTH)\modules\libreg\standalone\reg.c
$(RM) $(DEPTH)\modules\libreg\standalone\vr_stubs.h
$(RM) $(DEPTH)\modules\libreg\standalone\vr_stubs.c
$(RM) $(DEPTH)\modules\libreg\standalone\VerReg.c
copy $(DEPTH)\modules\libreg\src\reg.h $(DEPTH)\modules\libreg\standalone\reg.h
copy $(DEPTH)\modules\libreg\src\reg.c $(DEPTH)\modules\libreg\standalone\reg.c
copy $(DEPTH)\modules\libreg\src\vr_stubs.h $(DEPTH)\modules\libreg\standalone\vr_stubs.h
copy $(DEPTH)\modules\libreg\src\vr_stubs.c $(DEPTH)\modules\libreg\standalone\vr_stubs.c
copy $(DEPTH)\modules\libreg\src\VerReg.c $(DEPTH)\modules\libreg\standalone\VerReg.c
export:: $(DLL)
$(MAKE_INSTALL) $(DLL) $(DIST)\bin
$(RM) $(DEPTH)\modules\libreg\standalone\reg.h
$(RM) $(DEPTH)\modules\libreg\standalone\reg.c
$(RM) $(DEPTH)\modules\libreg\standalone\vr_stubs.h
$(RM) $(DEPTH)\modules\libreg\standalone\vr_stubs.c
$(RM) $(DEPTH)\modules\libreg\standalone\VerReg.c
clobber::
$(RM) $(DIST)\bin\$(DLL)
$(RM) $(DEPTH)\modules\libreg\standalone\reg.h
$(RM) $(DEPTH)\modules\libreg\standalone\reg.c
$(RM) $(DEPTH)\modules\libreg\standalone\vr_stubs.h
$(RM) $(DEPTH)\modules\libreg\standalone\vr_stubs.c
$(RM) $(DEPTH)\modules\libreg\standalone\VerReg.c

View File

@@ -0,0 +1,430 @@
/* -*- 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.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
* Reserved.
*/
// Registry interpreter
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include "VerReg.h"
#include "NSReg.h"
extern char *errstr(REGERR err);
extern int DumpTree(void);
int gVerbose = 1;
int gPretend = 0;
int error(char *func, int err)
{
if (err == REGERR_OK)
{
if (gVerbose)
printf("%s Ok\n", func);
}
else
{
printf("%s returns %s\n", func, errstr(err));
}
return err;
} // error
static char *GetNextWord(char *cmd, char *buf)
{
// copies until ',' or eos, then skips spaces
if (!cmd || !buf)
return 0;
while (*cmd && *cmd != ',')
*buf++ = *cmd++;
*buf = '\0';
if (*cmd == ',')
{
cmd++;
while(*cmd && *cmd == ' ')
cmd++;
}
return cmd;
} // GetNextWord
static int vr_ParseVersion(char *verstr, VERSION *result)
{
result->major = result->minor = result->release = result->build = 0;
result->major = atoi(verstr);
while (*verstr && *verstr != '.')
verstr++;
if (*verstr)
{
verstr++;
result->minor = atoi(verstr);
while (*verstr && *verstr != '.')
verstr++;
if (*verstr)
{
verstr++;
result->release = atoi(verstr);
while (*verstr && *verstr != '.')
verstr++;
if (*verstr)
{
verstr++;
result->build = atoi(verstr);
while (*verstr && *verstr != '.')
verstr++;
}
}
}
return REGERR_OK;
} // ParseVersion
void parse(char *cmd, char *name, VERSION *ver, char *path)
{
// expects 'cmd' points to: "<name>, <ver>, <path>"
char buf[256];
char *p;
cmd = GetNextWord(cmd, buf);
strcpy(name, buf);
p = cmd; // 'cmd' points to version
vr_ParseVersion(cmd, ver);
ver->check = gPretend ? 0xad : 0;
while (*p && *p != ',') // skip to next ','
p++;
if (*p == ',') // skip comma
p++;
while (*p && *p == ' ') // skip white space
p++;
strcpy(path, p);
} // parse
void vVerbose(char *cmd)
{
if (stricmp(cmd, "ON") == 0)
{
gVerbose = 1;
printf("Verbose mode is now ON.\n");
}
else
{
gVerbose = 0;
}
} // vVerbose
void vCreate(char *cmd)
{
// Syntax: Create [new,] 5.0b1
char buf[64];
int flag = 0;
cmd = GetNextWord(cmd, buf);
if (stricmp(buf, "NEW,") == 0)
{
flag = CR_NEWREGISTRY;
}
error("VR_CreateRegistry", VR_CreateRegistry(flag, cmd));
} // vCreate
void vDisplay(char *cmd)
{
DumpTree();
} // vDisplay
void vFind(char *cmd)
{
VERSION ver;
char path[MAXREGPATHLEN];
if (error("VR_GetVersion", VR_GetVersion(cmd, &ver)) == REGERR_OK)
{
if (error("VR_GetPath", VR_GetPath(cmd, sizeof(path), path)) == REGERR_OK)
{
printf("%s found: ver=%d.%d.%d.%d, check=0x%04x, path=%s\n",
cmd, ver.major, ver.minor, ver.release, ver.build, ver.check,
path);
return;
}
}
printf("%s not found.\n", cmd);
return;
} // vFind
void vHelp(char *cmd)
{
puts("Enter a command:");
puts("\tD)isplay - display the current contents of the Registry");
puts("\tI)nstall <name>, <version>, <path> - install a new component");
puts("\tU)pdate <name>, <version>, <path> - update a component");
puts("\tF)ind <name> - returns version and path");
puts("\tV)erify <name> - verify component exists and checks out");
puts("\tC)reate <name> - create a new instance of Navigator (e.g., \"4.0\")");
puts("\tR)emove <name> - deletes a component from the Registry");
puts("\tT)est - perform a simple test on the Registry");
puts("\tver(B)ose ON|off - turn verbose mode on or off");
puts("\tP)retend on|OFF - pretend that test files exist");
puts("\tS)ave - save the Registry to disk");
puts("\tpac(K) registry - squeeze out unused space from the Registry");
puts("\tQ)uit - end the program");
} // vHelp
void vInstall(char *cmd)
{
char name[MAXREGPATHLEN+1];
char path[MAXREGPATHLEN+1];
VERSION ver;
parse(cmd, name, &ver, path);
error("VR_Install", VR_Install(name, path, &ver));
} // vInstall
void vPack(char *cmd)
{
error("VR_PackRegistry", VR_PackRegistry(0));
} // vPack
void vPretend(char *cmd)
{
if (!cmd)
{
gPretend = !!gPretend;
}
else
{
if (stricmp(cmd, "ON") == 0)
gPretend = 1;
else
gPretend = 0;
}
if (gVerbose)
printf("Pretend mode is %s\n", gPretend ? "ON" : "OFF");
} // vPretend
void vRemove(char *cmd)
{
error("VR_Remove", VR_Remove(cmd));
} // vRemove
void vSave(char *cmd)
{
error("VR_Checkpoint", VR_Checkpoint());
} // vSave
void vTest(char *cmd)
{
VERSION ver;
ver.major = 4;
ver.minor = 0;
ver.release = 0;
ver.build = 237;
ver.check = gPretend ? 0xad : 0;
if (error("VR_Install", VR_Install("Navigator/NS.exe",
"c:\\Program Files\\Netscape\\Navigator\\Program\\NETSCAPE.EXE", &ver)))
return;
if (error("VR_Install", VR_Install("Navigator/Help",
"c:\\Program Files\\Netscape\\Navigator\\Program\\NETSCAPE.HLP", &ver)))
return;
if (error("VR_Install", VR_Install("Navigator/NSPR",
"c:\\Program Files\\Netscape\\Navigator\\Program\\NSPR32.DLL", &ver)))
return;
if (error("VR_Install", VR_Install("Navigator/Player",
"c:\\Program Files\\Netscape\\Navigator\\Program\\NSPLAYER.EXE", &ver)))
return;
if (error("VR_Install", VR_Install("Navigator/NSJava",
"c:\\Program Files\\Netscape\\Navigator\\Program\\NSJAVA32.DLL", &ver)))
return;
if (error("VR_Install", VR_Install("Web/Certificate.DB",
"c:\\Program Files\\Netscape\\Navigator\\Program\\CERT.DB", &ver)))
return;
if (error("VR_Install", VR_Install("Web/CertificateNI.DB",
"c:\\Program Files\\Netscape\\Navigator\\Program\\CERTNI.DB", &ver)))
return;
if (error("VR_Install", VR_Install("Web/Keys",
"c:\\Program Files\\Netscape\\Navigator\\Program\\KEY.DB", &ver)))
return;
if (error("VR_Install", VR_Install("MailNews/Postal",
"c:\\Program Files\\Netscape\\Navigator\\System\\POSTAL32.DLL", &ver)))
return;
if (error("VR_Install", VR_Install("MailNews/Folders/Inbox",
"c:\\Program Files\\Netscape\\Navigator\\Mail\\INBOX.SNM", &ver)))
return;
if (error("VR_Install", VR_Install("MailNews/Folders/Sent",
"c:\\Program Files\\Netscape\\Navigator\\Mail\\SENT.SNM", &ver)))
return;
if (error("VR_Install", VR_Install("MailNews/Folders/Trash",
"c:\\Program Files\\Netscape\\Navigator\\Mail\\TRASH.SNM", &ver)))
return;
if (error("VR_Install", VR_Install("Components/NUL",
"c:\\Program Files\\Netscape\\Navigator\\Program\\Plugins\\NPNUL32.DLL", &ver)))
return;
if (error("VR_Install", VR_Install("Components/PointCast",
"c:\\Program Files\\Netscape\\Navigator\\Program\\Plugins\\NPPCN32.DLL", &ver)))
return;
if (error("VR_Install", VR_Install("Components/AWT",
"c:\\Program Files\\Netscape\\Navigator\\Program\\Java\\bin\\AWT3220.DLL", &ver)))
return;
if (error("VR_Install", VR_Install("Components/MM",
"c:\\Program Files\\Netscape\\Navigator\\Program\\Java\\bin\\MM3220.DLL", &ver)))
return;
if (error("VR_Install", VR_Install("Java/Classes.Zip",
"c:\\Program Files\\Netscape\\Navigator\\Program\\Java\\classes\\MOZ2_0.ZIP", &ver)))
return;
if (error("VR_Install", VR_Install("Java/Classes Directory",
"c:\\Program Files\\Netscape\\Navigator\\Program\\Java\\classes\\MOZ2_0", &ver)))
return;
} // vTest
void vUpdate(char *cmd)
{
char name[MAXREGPATHLEN+1];
char path[MAXREGPATHLEN+1];
VERSION ver;
parse(cmd, name, &ver, path);
error("VR_Update", VR_Update(name, path, &ver));
} // vUpdate
void vVerify(char *cmd)
{
error("VR_CheckEntry", VR_CheckEntry(0, cmd));
} // vVerify
void interp(void)
{
char line[256];
char *p;
while(1)
{
putchar('>');
putchar(' ');
flushall();
gets(line);
// p points to next word after verb on command line
p = line;
while (*p && *p!=' ')
p++;
if (!*p)
p = 0;
else
{
while(*p && *p==' ')
p++;
}
switch(toupper(line[0]))
{
case 'B':
vVerbose(p);
break;
case 'C':
vCreate(p);
break;
case 'D':
vDisplay(p);
break;
case 'F':
vFind(p);
break;
case 'H':
default:
vHelp(line);
break;
case 'I':
vInstall(p);
break;
case 'K':
vPack(p);
break;
case 'P':
vPretend(p);
break;
case 'R':
vRemove(p);
break;
case 'S':
vSave(p);
break;
case 'T':
vTest(p);
break;
case 'U':
vUpdate(p);
break;
case 'V':
vVerify(p);
break;
case 'Q':
case 'X':
vSave(0);
return;
} // switch
} // while
assert(0);
return; // shouldn't get here
} // interp
// EOF: interp.c

View File

@@ -0,0 +1,438 @@
/* -*- 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.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
* Reserved.
*/
#include <stdlib.h>
#include <stdio.h>
#include <io.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <string.h>
#include "NSReg.h"
#include "VerReg.h"
extern void interp(void);
#define REGFILE "c:\\temp\\reg.dat"
char *gRegistry;
int main(int argc, char *argv[]);
char *errstr(REGERR err)
{
switch( err )
{
case REGERR_OK:
return "REGERR_OK";
case REGERR_FAIL:
return "REGERR_FAIL";
case REGERR_NOMORE:
return "REGERR_MORE";
case REGERR_NOFIND:
return "REGERR_NOFIND";
case REGERR_BADREAD:
return "REGERR_BADREAD";
case REGERR_BADLOCN:
return "REGERR_BADLOCN";
case REGERR_PARAM:
return "REGERR_PARAM";
case REGERR_BADMAGIC:
return "REGERR_BADMAGIC";
default:
return "<Unknown>";
}
} // errstr
int CreateEmptyRegistry(void)
{
#if 0
int fh;
remove(REGFILE); // ignore errors like file not found
fh = _open(REGFILE, _O_CREAT, _S_IREAD|_S_IWRITE);
if (fh < 0)
return -1;
close(fh);
return 0;
#endif
return VR_CreateRegistry(CR_NEWREGISTRY, "4.0");
} // CreateEmptyRegistry
int BuildTree(void)
{
REGERR err;
err = NR_RegAdd(0,"/Machine/Old");
if (err != REGERR_OK)
{
printf("NR_RegAdd() returned %s.\n", errstr(err));
return err;
}
err = NR_RegAdd(0,"/User");
if (err != REGERR_OK)
{
printf("NR_RegAdd() returned %s.\n", errstr(err));
return err;
}
err = NR_RegAdd(0,"/Machine/4.0/Name1=Val1");
if (err != REGERR_OK)
{
printf("NR_RegAdd() returned %s.\n", errstr(err));
return err;
}
err = NR_RegAdd(0,"/Machine/4.0/Name2=Val2");
if (err != REGERR_OK)
{
printf("NR_RegAdd() returned %s.\n", errstr(err));
return err;
}
err = NR_RegAdd(0,"/Machine/4.0/Name2=Val3");
if (err != REGERR_OK)
{
printf("NR_RegAdd() returned %s.\n", errstr(err));
return err;
}
err = NR_RegAdd(0,"/Machine/4.0/Name3=Val4");
if (err != REGERR_OK)
{
printf("NR_RegAdd() returned %s.\n", errstr(err));
return err;
}
return VR_Checkpoint();
} // BuildTree
int FindKeys(void)
{
RKEY key;
REGERR err;
char buf[80];
if (NR_RegGetKey(0, "", &key) == REGERR_OK)
{
printf("NR_RegGetKey returns ok for an empty path.\n");
return 1;
}
if (NR_RegGetKey(0, "/", &key) != REGERR_OK)
{
printf("NR_RegGetKey couldn't find root.\n");
return 1;
}
if (NR_RegGetKey(0, "/Machine/Old", &key) != REGERR_OK)
{
printf("NR_RegGetKey couldn't find Old\n");
return 1;
}
printf("NR_RegGetKey returns key for Old as: 0x%lx\n", (long) key);
if (NR_RegGetKey(0, "/Machine/4.0", &key) != REGERR_OK)
{
printf("NR_RegGetKey couldn't find 4.0\n");
return 1;
}
printf("NR_RegGetKey returns key for 4.0 as: 0x%lx\n", (long) key);
// ----------------------------------------
if ((err = NR_RegFindValue(0, "/Machine/4.0/Name3", 64, buf)) != REGERR_OK)
{
printf("NR_RegFindValue (no key) returns %s\n", errstr(err));
return 1;
}
printf("NR_RegFindValue (no key) of Name3 = %s\n", buf);
if (NR_RegFindValue(key, "Aliens", 64, buf) == REGERR_OK)
{
printf("NR_RegFindValue finds Aliens.\n");
return 1;
}
if ((err = NR_RegFindValue(key, "Name3", 64, buf)) != REGERR_OK)
{
printf("NR_RegFindValue (w/key) returns %s\n", errstr(err));
return 1;
}
printf("NR_RegFindValue (w/key) of Name3 = %s\n", buf);
return 0;
} // FindTree
int DumpTree(void)
{
char *path;
char *line = "------------------------------------------------------------";
path = malloc(2048);
if (!path)
return REGERR_FAIL;
strcpy(path, "/");
puts(line);
puts(path);
while (NR_RegNext( 0, 512, path ) == REGERR_OK)
{
puts(path);
}
puts(line);
return 0;
} // DumpTree
int ChangeKeys(void)
{
REGERR err;
err = NR_RegUpdate(0,"/Machine/4.0/name3", "Infospect Software, Inc.");
if (err)
{
printf("Couldn't update name3's value to ISI.\n");
return err;
}
err = NR_RegUpdate(0,"/Machine/4.0/name3=Infospect Software, Inc.", "\"Jonathan=Kid1\"");
if (err)
{
printf("Couldn't update name3's value to Jon.\n");
return err;
}
err = NR_RegRename(0,"/Machine/4.0/name3=\"Jonathan=Kid1\"", "First born");
if (err)
{
printf("Couldn't update name3's name to First born.\n");
return err;
}
err = NR_RegUpdate(0,"/Machine/4.0/name2=Val2", "Kelley Ann");
if (err)
{
printf("Couldn't update name2's value to Kelley.\n");
return err;
}
return VR_Checkpoint();
} // ChangeKeys
int DeleteKeys(void)
{
REGERR err;
err = NR_RegDelete(0, "/User");
if (err)
{
printf("NR_RegDelete returned %s.\n", errstr(err));
return err;
}
return VR_Checkpoint();
} // DeleteKeys
int StressTest(void)
{
REGERR err;
RKEY key;
printf("Starting stress...\n");
err = NR_RegGetKey(0, "/Machine/4.0", &key);
if (err)
{
printf("Error getting key for 4.0 = %s\n", errstr(err));
return err;
}
err = NR_RegAdd(key, "A/B/C/D/E/F/G/H/I/J/K/L/M/N/O/P/Q/R/S/T/U/V/W/X/Y/Z/"
"A/B/C/D/E/F/G/H/I/J/K/L/M/N/O/P/Q/R/S/T/U/V/W/X/Y/Z/"
"A/B/C/D/E/F/G/H/I/J/K/L/M/N/O/P/Q/R/S/T/U/V/W/X/Y/Z/" );
if (err)
{
printf("Adding humungous string returned %s\n", errstr(err));
return err;
}
// TODO: Add a value to one of the middle keys, get it back.
printf("Stress done.\n");
return 0;
} // StressTest
int Install(void)
{
int err;
VERSION ver;
ver.major = 4;
ver.minor = 2;
ver.release = 10;
ver.build = 937;
ver.check = 0;
err = VR_Install("Web/Navigator/netscape.exe",
"c:\\Netscape\\NETSCAPE.EXE", &ver);
if (err)
return err;
ver.release = 19;
ver.build = 722;
ver.check = 0;
err = VR_Install("Web/Navigator/nspr.dll",
"c:\\Netscape\\System\\Vtcprac.386", &ver);
if (err)
return err;
return VR_Checkpoint();
}
int GetInfo(void)
{
int err;
char buf[256];
VERSION ver;
err = VR_GetPath("Web/Navigator/nspr.dll", 256, buf);
if (err)
return err;
printf("GetPath(nspr.dll) returns %s\n", buf);
err = VR_GetVersion("Web/Navigator/netscape.exe", &ver);
if (err)
return err;
printf("GetVersion(netscape.exe) returns %d.%d.%d.%d and check=%d\n",
ver.major, ver.minor, ver.release, ver.build, ver.check);
return 0;
}
int main(int argc, char *argv[])
{
printf("Registry Test 10/01/96.\n");
if (argc > 1)
{
gRegistry = argv[1];
}
else
{
gRegistry = REGFILE;
}
VR_RegistryName(gRegistry);
#if 1
if (NR_RegOpen(gRegistry) != REGERR_OK)
VR_CreateRegistry(CR_NEWREGISTRY, "4.0");
interp();
#else
if (CreateEmptyRegistry())
goto abort;
if (Install())
goto done;
if (DumpTree())
goto done;
if (GetInfo())
goto done;
#if defined(TEST_NR)
if ((err = NR_RegOpen(REGFILE)) != REGERR_OK)
{
printf("NR_RegOpen(%s) returned %s...Test aborted.\n", REGFILE, errstr(err));
goto abort;
}
if (BuildTree())
goto done;
if (FindKeys())
goto done;
if (DumpTree())
goto done;
if (ChangeKeys())
goto done;
if (DeleteKeys())
goto done;
if (DumpTree())
goto done;
if (StressTest())
goto done;
if (DumpTree())
goto done;
done:
NR_RegClose();
#else
done:
#endif
abort:
puts("Press Enter to continue...");
getchar();
#endif
return 0;
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,38 +0,0 @@
#
# 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.org code.
#
# The Initial Developer of the Original Code is Netscape
# Communications Corporation. Portions created by Netscape are
# Copyright (C) 1998 Netscape Communications Corporation. All
# Rights Reserved.
#
# Contributor(s):
#
DEPTH = ../..
topsrcdir = @top_srcdir@
srcdir = @srcdir@
VPATH = @srcdir@
include $(DEPTH)/config/autoconf.mk
DIRS = \
public \
memcache \
filecache \
mgr \
build \
$(NULL)
include $(topsrcdir)/config/rules.mk

View File

@@ -1,33 +0,0 @@
#!gmake
#
# 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.org code.
#
# The Initial Developer of the Original Code is Netscape
# Communications Corporation. Portions created by Netscape are
# Copyright (C) 1998 Netscape Communications Corporation. All
# Rights Reserved.
#
# Contributor(s):
DEPTH=..\..
DIRS= \
public \
mgr \
memcache \
filecache \
build \
$(NULL)
include <$(DEPTH)\config\rules.mak>

View File

@@ -1,51 +0,0 @@
#!gmake
#
# 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.org code.
#
# The Initial Developer of the Original Code is Netscape
# Communications Corporation. Portions created by Netscape are
# Copyright (C) 1998 Netscape Communications Corporation. All
# Rights Reserved.
#
DEPTH=..\..\..
MODULE=nkcache
MAKE_OBJ_TYPE=DLL
DLLNAME=nkcache
DLL=.\$(OBJDIR)\$(DLLNAME).dll
CPP_OBJS= \
.\$(OBJDIR)\nsNetDataCacheModule.obj \
$(NULL)
LLIBS= \
$(DIST)\lib\nkcachemgr_s.lib \
$(DIST)\lib\nkfilecache_s.lib \
$(DIST)\lib\nkmemcache_s.lib \
$(DIST)\lib\dbm32.lib \
$(DIST)\lib\xpcom.lib \
$(LIBNSPR)
INCS = $(INCS) \
-I$(DEPTH)\netwerk\cache\memcache \
-I$(DEPTH)\netwerk\cache\filecache \
-I$(DEPTH)\netwerk\cache\mgr \
$(NULL)
include <$(DEPTH)\config\rules.mak>
install:: $(DLL)
$(MAKE_INSTALL) .\$(OBJDIR)\$(DLLNAME).dll $(DIST)\bin\components
$(MAKE_INSTALL) .\$(OBJDIR)\$(DLLNAME).lib $(DIST)\lib

View File

@@ -1,49 +0,0 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
* 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 client code, released
* March 31, 1998.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998-1999 Netscape Communications Corporation. All
* Rights Reserved.
*
*/
#include "nsCOMPtr.h"
#include "nsIModule.h"
#include "nscore.h"
#include "nsIComponentManager.h"
#include "nsIServiceManager.h"
#include "nsIGenericFactory.h"
#include "nsINetDataCache.h"
#include "nsINetDataCacheManager.h"
#include "nsMemCacheCID.h"
#include "nsMemCache.h"
#include "nsNetDiskCache.h"
#include "nsNetDiskCacheCID.h"
#include "nsCacheManager.h"
// Factory method to create a new nsMemCache instance. Used
// by nsNetDataCacheModule
NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(nsMemCache, Init)
NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(nsNetDiskCache, Init)
NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(nsCacheManager, Init)
static nsModuleComponentInfo components[] = {
{ "Memory Cache", NS_MEM_CACHE_FACTORY_CID, NS_NETWORK_MEMORY_CACHE_PROGID, nsMemCacheConstructor },
{ "File Cache", NS_NETDISKCACHE_CID, NS_NETWORK_FILE_CACHE_PROGID, nsNetDiskCacheConstructor },
{ "Cache Manager",NS_CACHE_MANAGER_CID, NS_NETWORK_CACHE_MANAGER_PROGID,nsCacheManagerConstructor }
};
NS_IMPL_NSGETMODULE("Network Data Cache", components)

View File

@@ -1,56 +0,0 @@
#
# The contents of this file are subject to the Mozilla 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/MPL/
#
# 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 Intel Corp.
# Portions created by Intel Corp. are
# Copyright (C) 1999, 1999 Intel Corp. All
# Rights Reserved.
#
# Contributor(s): Yixiong Zou <yixiong.zou@intel.com>
# Carl Wong <carl.wong@intel.com>
#
DEPTH = ../../..
topsrcdir = @top_srcdir@
VPATH = @srcdir@
srcdir = @srcdir@
include $(DEPTH)/config/autoconf.mk
MODULE = nkcache
LIBRARY_NAME = nkfilecache_s
REQUIRES = nspr dbm
EXTRA_DSO_LDOPTS += -L$(DIST)/lib -lmozdbm_s
EXPORTS=nsNetDiskCacheCID.h
CPPSRCS = \
nsDBAccessor.cpp\
nsDBEnumerator.cpp \
nsNetDiskCache.cpp \
nsDiskCacheRecord.cpp \
nsDiskCacheRecordChannel.cpp \
$(NULL)
EXTRA_LIBS = $(NSPR_LIBS)
# we don't want the shared lib, but we want to force the creation of a
# static lib.
override NO_SHARED_LIB=1
override NO_STATIC_LIB=
include $(topsrcdir)/config/rules.mk

View File

@@ -1,351 +0,0 @@
/*
* The contents of this file are subject to the Mozilla 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/MPL/
*
* 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 Intel Corp.
* Portions created by Intel Corp. are
* Copyright (C) 1999, 1999 Intel Corp. All
* Rights Reserved.
*
* Contributor(s): Yixiong Zou <yixiong.zou@intel.com>
* Carl Wong <carl.wong@intel.com>
*/
// FUR - Add overall description comment here
#include "nsDBAccessor.h"
#include "nscore.h"
#include "prtypes.h"
#include "plhash.h"
#include "nsCRT.h"
#include "nsAutoLock.h"
nsDBAccessor::nsDBAccessor() :
mDB(0) ,
mSessionID(0) ,
mSessionCntr(0)
{
NS_INIT_REFCNT();
}
nsDBAccessor::~nsDBAccessor()
{
printf(" ~nsDBAccessor\n") ;
Shutdown() ;
}
//
// Implement nsISupports methods
//
NS_IMPL_ISUPPORTS(nsDBAccessor, NS_GET_IID(nsIDBAccessor))
///////////////////////////////////////////////////////////
// nsIDBAccessor methods
NS_IMETHODIMP
nsDBAccessor::Init(nsIFileSpec* dbfile)
{
// FUR - lock not needed
m_Lock = PR_NewLock() ;
if(!m_Lock)
return NS_ERROR_OUT_OF_MEMORY ;
char* dbname ;
// this should cover all platforms.
dbfile->GetNativePath(&dbname) ;
// FUR - how is page size chosen ? It's worth putting a comment
// in here about the possible usefulness of tuning these parameters
HASHINFO hash_info = {
16*1024 , /* bucket size */
0 , /* fill factor */
0 , /* number of elements */
0 , /* bytes to cache */
0 , /* hash function */
0} ; /* byte order */
// FUR - lock not needed
nsAutoLock lock(m_Lock) ;
mDB = dbopen(dbname,
O_RDWR | O_CREAT ,
0600 ,
DB_HASH ,
& hash_info) ;
// FUR - does dbname have to be free'ed ?
if(!mDB)
return NS_ERROR_FAILURE ;
// set mSessionID
// FUR - Why the +1 ? (No need for key to be NUL-terminated string.)
PRUint32 len = PL_strlen(SessionKey)+1 ;
DBT db_key, db_data ;
db_key.data = NS_CONST_CAST(char*, SessionKey) ;
db_key.size = len ;
int status = (*mDB->get)(mDB, &db_key, &db_data, 0) ;
if(status == -1) {
NS_ERROR("ERROR: failed get session id in database.") ;
return NS_ERROR_FAILURE ;
}
if(status == 0) {
// get the last session id
PRInt16 *old_ID = NS_STATIC_CAST(PRInt16*, db_data.data) ;
if(*old_ID < ini_sessionID) {
NS_ERROR("ERROR: Bad Session ID in database, corrupted db.") ;
return NS_ERROR_FAILURE ;
}
// FUR - need to comment out all printfs, or turn them into PR_LOG statements
printf("found previous session, id = %d\n", *old_ID) ;
mSessionID = *old_ID + 1 ;
}
else if(status == 1) {
// must be a new db
mSessionID = ini_sessionID ;
}
db_data.data = NS_REINTERPRET_CAST(void*, &mSessionID) ;
db_data.size = sizeof(PRInt16) ;
// store the new session id
status = (*mDB->put)(mDB, &db_key, &db_data, 0) ;
if(status == 0) {
(*mDB->sync)(mDB, 0) ;
return NS_OK ;
}
else {
NS_ERROR("reset session ID failure.") ;
return NS_ERROR_FAILURE ;
}
}
NS_IMETHODIMP
nsDBAccessor::Shutdown(void)
{
if(mDB) {
(*mDB->sync)(mDB, 0) ;
(*mDB->close)(mDB) ;
mDB = nsnull ;
}
// FUR - locks not necessary
if(m_Lock)
PR_DestroyLock(m_Lock);
return NS_OK ;
}
NS_IMETHODIMP
nsDBAccessor::Get(PRInt32 aID, void** anEntry, PRUint32 *aLength)
{
if(!anEntry)
return NS_ERROR_NULL_POINTER ;
*anEntry = nsnull ;
*aLength = 0 ;
NS_ASSERTION(mDB, "no database") ;
// Lock the db
nsAutoLock lock(m_Lock) ;
DBT db_key, db_data ;
db_key.data = NS_REINTERPRET_CAST(void*, &aID) ;
db_key.size = sizeof(PRInt32) ;
int status = 0 ;
status = (*mDB->get)(mDB, &db_key, &db_data, 0) ;
if(status == 0) {
*anEntry = db_data.data ;
*aLength = db_data.size ;
return NS_OK ;
}
else if(status == 1)
return NS_OK ;
else
return NS_ERROR_FAILURE ;
}
NS_IMETHODIMP
nsDBAccessor::Put(PRInt32 aID, void* anEntry, PRUint32 aLength)
{
NS_ASSERTION(mDB, "no database") ;
// Lock the db
nsAutoLock lock(m_Lock) ;
DBT db_key, db_data ;
db_key.data = NS_REINTERPRET_CAST(void*, &aID) ;
db_key.size = sizeof(PRInt32) ;
db_data.data = anEntry ;
db_data.size = aLength ;
if(0 == (*mDB->put)(mDB, &db_key, &db_data, 0)) {
// FUR - I would avoid unnecessary sync'ing for performance's
// sake. Maybe you could limit sync to max rate of, say, once
// every few seconds by keeping track of last sync time, using PR_Now().
(*mDB->sync)(mDB, 0) ;
return NS_OK ;
}
else {
// FUR - Try to avoid using NS_ERROR unless error is unrecoverable and serious
NS_ERROR("ERROR: Failed to put anEntry into db.\n") ;
return NS_ERROR_FAILURE ;
}
}
/*
* It's more important to remove the id->metadata entry first since
* key->id mapping is just a reference
*/
NS_IMETHODIMP
nsDBAccessor::Del(PRInt32 aID, void* anEntry, PRUint32 aLength)
{
NS_ASSERTION(mDB, "no database") ;
// FUR - no locks necessary
// Lock the db
nsAutoLock lock(m_Lock) ;
DBT db_key ;
// delete recordID->metadata
db_key.data = NS_REINTERPRET_CAST(void*, &aID) ;
db_key.size = sizeof(PRInt32) ;
PRInt32 status = -1 ;
status = (*mDB->del)(mDB, &db_key, 0) ;
if(-1 == status) {
// FUR - no printf's, use PR_LOG, NS_WARNING, or NS_ASSERTION, as the situation warrants
printf(" delete error\n") ;
return NS_ERROR_FAILURE ;
}
// delete key->recordID
db_key.data = anEntry ;
db_key.size = aLength ;
status = (*mDB->del)(mDB, &db_key, 0) ;
if(-1 == status) {
// FUR - no printf's
printf(" delete error\n") ;
return NS_ERROR_FAILURE ;
}
// FUR - Defer sync ? See above
(*mDB->sync)(mDB, 0) ;
return NS_OK ;
}
NS_IMETHODIMP
nsDBAccessor::GetID(const char* key, PRUint32 length, PRInt32* aID)
{
NS_ASSERTION(mDB, "no database") ;
// Lock the db
nsAutoLock lock(m_Lock) ;
DBT db_key, db_data ;
db_key.data = NS_CONST_CAST(char*, key) ;
db_key.size = length ;
int status = (*mDB->get)(mDB, &db_key, &db_data, 0) ;
if(status == 0) {
// found recordID
*aID = *(NS_REINTERPRET_CAST(PRInt32*, db_data.data)) ;
return NS_OK ;
}
else if(status == 1) {
// create a new one
PRInt32 id = 0 ;
id = mSessionID << 16 | mSessionCntr++ ;
// add new id into mDB
db_data.data = NS_REINTERPRET_CAST(void*, &id) ;
db_data.size = sizeof(PRInt32) ;
status = (*mDB->put)(mDB, &db_key, &db_data, 0) ;
if(status != 0) {
NS_ERROR("updating db failure.") ;
return NS_ERROR_FAILURE ;
}
// FUR - defer sync ?
(*mDB->sync)(mDB, 0) ;
*aID = id ;
return NS_OK ;
}
else {
NS_ERROR("ERROR: keydb failure.") ;
return NS_ERROR_FAILURE ;
}
}
NS_IMETHODIMP
nsDBAccessor::EnumEntry(void** anEntry, PRUint32* aLength, PRBool bReset)
{
if(!anEntry)
return NS_ERROR_NULL_POINTER ;
*anEntry = nsnull ;
*aLength = 0 ;
NS_ASSERTION(mDB, "no database") ;
PRUint32 flag ;
if(bReset)
flag = R_FIRST ;
else
flag = R_NEXT ;
// Lock the db
nsAutoLock lock(m_Lock) ;
DBT db_key, db_data ;
// FUR - +1 unnecessary ?
PRUint32 len = PL_strlen(SessionKey)+1 ;
int status ;
do {
status = (*mDB->seq)(mDB, &db_key, &db_data, flag) ;
flag = R_NEXT ;
if(status == -1)
return NS_ERROR_FAILURE ;
// get next if it's a key->recordID
if(db_key.size > sizeof(PRInt32) && db_data.size == sizeof(PRInt32))
continue ;
// get next if it's a sessionID entry
if(db_key.size == len && db_data.size == sizeof(PRInt16))
continue ;
// recordID is always 32 bits long
if(db_key.size == sizeof(PRInt32))
break ;
} while(!status) ;
if (0 == status) {
*anEntry = db_data.data ;
*aLength = db_data.size ;
}
return NS_OK ;
}

View File

@@ -1,68 +0,0 @@
/*
* The contents of this file are subject to the Mozilla 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/MPL/
*
* 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 Intel Corp.
* Portions created by Intel Corp. are
* Copyright (C) 1999, 1999 Intel Corp. All
* Rights Reserved.
*
* Contributor(s): Yixiong Zou <yixiong.zou@intel.com>
* Carl Wong <carl.wong@intel.com>
*/
// FUR - Add overall description comment here
#ifndef _NSIDBACCESSOR_H_
#define _NSIDBACCESSOR_H_
#include "nsIDBAccessor.h"
#include "mcom_db.h"
// bogus string for the key of session id
// FUR - suggest "SK" instead of "^^"
static const char * const SessionKey = "^^" ;
// initial session id number
static const PRInt16 ini_sessionID = 0xff ;
class nsDBAccessor : public nsIDBAccessor
{
public:
NS_DECL_ISUPPORTS
nsDBAccessor() ;
virtual ~nsDBAccessor() ;
NS_IMETHOD Init(nsIFileSpec* dbfile) ;
NS_IMETHOD Shutdown(void) ;
NS_IMETHOD Put(PRInt32 aID, void* anEntry, PRUint32 aLength) ;
NS_IMETHOD Get(PRInt32 aID, void** anEntry, PRUint32 *aLength) ;
NS_IMETHOD Del(PRInt32 aID, void* anEntry, PRUint32 aLength) ;
NS_IMETHOD GetID(const char* key, PRUint32 length, PRInt32* aID) ;
NS_IMETHOD EnumEntry(void* *anEntry, PRUint32* aLength, PRBool bReset) ;
protected:
private:
DB * mDB ;
PRInt16 mSessionID ;
PRInt16 mSessionCntr ;
PRLock * m_Lock ;
} ;
#endif // _NSIDBACCESSOR_H_

View File

@@ -1,97 +0,0 @@
/*
* The contents of this file are subject to the Mozilla 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/MPL/
*
* 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 Intel Corp.
* Portions created by Intel Corp. are
* Copyright (C) 1999, 1999 Intel Corp. All
* Rights Reserved.
*
* Contributor(s): Yixiong Zou <yixiong.zou@intel.com>
* Carl Wong <carl.wong@intel.com>
*/
// FUR - Add overall description comment here
#include "nsDBEnumerator.h"
#include "nsDiskCacheRecord.h"
nsDBEnumerator::nsDBEnumerator(nsIDBAccessor* aDB, nsNetDiskCache* aCache) :
m_DB(aDB) ,
m_DiskCache(aCache) ,
tempEntry(0) ,
tempEntry_length(0) ,
m_CacheEntry(0) ,
bReset(PR_TRUE)
{
NS_INIT_REFCNT();
}
nsDBEnumerator::~nsDBEnumerator()
{
// printf(" ~nsDBEnumerator()\n") ;
NS_IF_RELEASE(m_CacheEntry) ;
}
//
// Implement nsISupports methods
//
NS_IMPL_ISUPPORTS(nsDBEnumerator, NS_GET_IID(nsIEnumerator))
/////////////////////////////////////////////////////////////////
// nsISimpleEnumerator methods
NS_IMETHODIMP
nsDBEnumerator::HasMoreElements(PRBool *_retval)
{
*_retval = PR_FALSE ;
m_DB->EnumEntry(&tempEntry, &tempEntry_length, bReset) ;
bReset = PR_FALSE ;
if(tempEntry && tempEntry_length != 0)
*_retval = PR_TRUE ;
return NS_OK ;
}
// this routine does not create a new item by itself
// Rather it reuses the item inside the object. So if you need to use the
// item later, you have to
// create a new item specifically, using copy constructor or some other dup
// function. And don't forget to release it after you're done
//
NS_IMETHODIMP
nsDBEnumerator::GetNext(nsISupports **_retval)
{
if(!m_CacheEntry) {
m_CacheEntry = new nsDiskCacheRecord(m_DB, m_DiskCache) ;
if(m_CacheEntry)
NS_ADDREF(m_CacheEntry) ;
else
return NS_ERROR_OUT_OF_MEMORY ;
}
if(!_retval)
return NS_ERROR_NULL_POINTER ;
*_retval = nsnull ;
nsresult rv = m_CacheEntry->RetrieveInfo(tempEntry, tempEntry_length) ;
if(NS_FAILED(rv))
return rv ;
*_retval = NS_STATIC_CAST(nsISupports*, m_CacheEntry) ;
NS_ADDREF(*_retval) ; // all good getter addref
return NS_OK ;
}

View File

@@ -1,61 +0,0 @@
/*
* The contents of this file are subject to the Mozilla 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/MPL/
*
* 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 Intel Corp.
* Portions created by Intel Corp. are
* Copyright (C) 1999, 1999 Intel Corp. All
* Rights Reserved.
*
* Contributor(s): Yixiong Zou <yixiong.zou@intel.com>
* Carl Wong <carl.wong@intel.com>
*/
// FUR - Add overall description comment here
#ifndef _NS_DBENUMERATOR_H_
#define _NS_DBENUMERATOR_H_
#include "nsISimpleEnumerator.h"
#include "nsINetDataCacheRecord.h"
#include "nsIDBAccessor.h"
#include "nsCOMPtr.h"
#include "nsNetDiskCache.h"
#include "nsDiskCacheRecord.h"
class nsCachedDiskData ; /* forward decl */
class nsDBEnumerator : public nsISimpleEnumerator {
public:
NS_DECL_ISUPPORTS
// FUR can use NS_DECL_NSISIMPLEENUMERATOR here
/* boolean HasMoreElements (); */
NS_IMETHOD HasMoreElements(PRBool *_retval) ;
/* nsISupports GetNext (); */
NS_IMETHOD GetNext(nsISupports **_retval) ;
nsDBEnumerator(nsIDBAccessor* aDB, nsNetDiskCache* aCache) ;
virtual ~nsDBEnumerator() ;
// FUR all members should be prefixed by 'm', e.g. mbReset
private:
nsCOMPtr<nsIDBAccessor> m_DB ;
nsCOMPtr<nsNetDiskCache> m_DiskCache ;
void * tempEntry ;
PRUint32 tempEntry_length ;
nsDiskCacheRecord* m_CacheEntry ;
PRBool bReset ;
};
#endif // _NS_DBENUMERATOR_H_

View File

@@ -1,451 +0,0 @@
/*
* The contents of this file are subject to the Mozilla 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/MPL/
*
* 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 Intel Corp.
* Portions created by Intel Corp. are
* Copyright (C) 1999, 1999 Intel Corp. All
* Rights Reserved.
*
* Contributor(s): Yixiong Zou <yixiong.zou@intel.com>
* Carl Wong <carl.wong@intel.com>
*/
#include "nsDiskCacheRecord.h"
#include "nsINetDataDiskCache.h"
#include "nsNetDiskCacheCID.h"
#include "nsDiskCacheRecordChannel.h"
#include "nsFileStream.h"
#include "nsIComponentManager.h"
#include "nsIServiceManager.h"
#include "nsIProtocolHandler.h"
#include "nsIIOService.h"
#include "nsIAllocator.h"
#include "plstr.h"
#include "prprf.h"
#include "prmem.h"
#include "prlog.h"
#include "prtypes.h"
#include "netCore.h"
#include "nsDBAccessor.h"
#if !defined(IS_LITTLE_ENDIAN) && !defined(IS_BIG_ENDIAN)
ERROR! Must have a byte order
#endif
#ifdef IS_LITTLE_ENDIAN
#define COPY_INT32(_a,_b) memcpy(_a, _b, sizeof(int32))
#else
#define COPY_INT32(_a,_b) /* swap */ \
do { \
((char *)(_a))[0] = ((char *)(_b))[3]; \
((char *)(_a))[1] = ((char *)(_b))[2]; \
((char *)(_a))[2] = ((char *)(_b))[1]; \
((char *)(_a))[3] = ((char *)(_b))[0]; \
} while(0)
#endif
nsDiskCacheRecord::nsDiskCacheRecord(nsIDBAccessor* db, nsNetDiskCache* aCache) :
mKey(0) ,
mKeyLength(0) ,
mRecordID(0) ,
mMetaData(0) ,
mMetaDataLength(0) ,
mDB(db) ,
mInfo(0) ,
mInfoSize(0) ,
mNumChannels(0) ,
mDiskCache(aCache)
{
NS_INIT_REFCNT();
}
// mem alloced. so caller should do free() on key.
NS_IMETHODIMP
nsDiskCacheRecord::Init(const char* key, PRUint32 length)
{
NS_NewFileSpec(getter_AddRefs(mFile));
if(!mFile)
return NS_ERROR_OUT_OF_MEMORY ;
// copy key
mKeyLength = length ;
mKey = NS_STATIC_CAST(char*, nsAllocator::Alloc(mKeyLength*sizeof(char))) ;
if(!mKey)
return NS_ERROR_OUT_OF_MEMORY ;
memcpy(mKey, key, length) ;
// get RecordID
// FUR!! Another disk access ? If called from GetCachedData, ID is already known
mDB->GetID(key, length, &mRecordID) ;
// FUR - check for GetID failure
// setup the file name
nsCOMPtr<nsIFileSpec> dbFolder ;
mDiskCache->GetDiskCacheFolder(getter_AddRefs(dbFolder)) ;
nsresult rv = mFile->FromFileSpec(dbFolder) ;
if(NS_FAILED(rv))
return NS_ERROR_FAILURE ;
// dir is a hash result of mRecordID%32, hope it's enough
char filename[9], dirName[3] ;
// FUR!! - should the format string be "%.02x". How does this work !?
PR_snprintf(dirName, 3, "%.2x", (((PRUint32)mRecordID) % 32)) ;
mFile->AppendRelativeUnixPath(dirName) ;
// FUR!! - should the format string be "%.08x". How does this work !?
PR_snprintf(filename, 9, "%.8x", mRecordID) ;
mFile->AppendRelativeUnixPath(filename) ;
return NS_OK ;
}
nsDiskCacheRecord::~nsDiskCacheRecord()
{
// printf(" ~nsDiskCacheRecord()\n") ;
if(mKey)
nsAllocator::Free(mKey) ;
if(mMetaData)
nsAllocator::Free(mMetaData) ;
}
//
// Implement nsISupports methods
//
NS_IMPL_ISUPPORTS(nsDiskCacheRecord, NS_GET_IID(nsINetDataCacheRecord))
///////////////////////////////////////////////////////////////////////
// nsINetDataCacheRecord methods
// yes, mem alloced on *_retval.
NS_IMETHODIMP
nsDiskCacheRecord::GetKey(PRUint32 *length, char** _retval)
{
if(!_retval)
return NS_ERROR_NULL_POINTER ;
*length = mKeyLength ;
*_retval = NS_STATIC_CAST(char*, nsAllocator::Alloc(mKeyLength*sizeof(char))) ;
if(!*_retval)
return NS_ERROR_OUT_OF_MEMORY ;
memcpy(*_retval, mKey, mKeyLength) ;
return NS_OK ;
}
NS_IMETHODIMP
nsDiskCacheRecord::GetRecordID(PRInt32* aRecordID)
{
*aRecordID = mRecordID ;
return NS_OK ;
}
// yes, mem alloced on *_retval.
NS_IMETHODIMP
nsDiskCacheRecord::GetMetaData(PRUint32 *length, char **_retval)
{
if(!_retval)
return NS_ERROR_NULL_POINTER ;
// always null the return value first.
*_retval = nsnull ;
*length = mMetaDataLength ;
if(mMetaDataLength) {
*_retval = NS_STATIC_CAST(char*, nsAllocator::Alloc(mMetaDataLength*sizeof(char))) ;
if(!*_retval)
return NS_ERROR_OUT_OF_MEMORY ;
memcpy(*_retval, mMetaData, mMetaDataLength) ;
}
return NS_OK ;
}
NS_IMETHODIMP
nsDiskCacheRecord::SetMetaData(PRUint32 length, const char* data)
{
// set the mMetaData
mMetaDataLength = length ;
if(mMetaData)
nsAllocator::Free(mMetaData) ;
mMetaData = NS_STATIC_CAST(char*, nsAllocator::Alloc(mMetaDataLength*sizeof(char))) ;
if(!mMetaData) {
return NS_ERROR_OUT_OF_MEMORY ;
}
memcpy(mMetaData, data, length) ;
// Generate mInfo
nsresult rv = GenInfo() ;
if(NS_FAILED(rv))
return rv ;
// write through into mDB
rv = mDB->Put(mRecordID, mInfo, mInfoSize) ;
// FUR - mInfo leaking ?
return rv ;
}
NS_IMETHODIMP
nsDiskCacheRecord::GetStoredContentLength(PRUint32 *aStoredContentLength)
{
return mFile->GetFileSize(aStoredContentLength) ;
}
// untill nsIFileSpec::Truncate() is in, we have to do all this ugly stuff
NS_IMETHODIMP
nsDiskCacheRecord::SetStoredContentLength(PRUint32 aStoredContentLength)
{
PRUint32 len = 0 ;
nsresult rv = mFile->GetFileSize(&len) ;
if(NS_FAILED(rv))
return rv ;
if(len < aStoredContentLength)
{
NS_ERROR("Error: can not set filesize to something bigger than itself.\n") ;
return NS_ERROR_FAILURE ;
}
else
return mFile->Truncate(aStoredContentLength) ;
}
NS_IMETHODIMP
nsDiskCacheRecord::Delete(void)
{
if(mNumChannels)
return NS_ERROR_NOT_AVAILABLE ;
PRUint32 len ;
mFile->GetFileSize(&len) ;
nsFileSpec cache_file ;
nsresult rv = mFile->GetFileSpec(&cache_file) ;
if(NS_FAILED(rv))
return NS_ERROR_FAILURE ;
cache_file.Delete(PR_TRUE) ;
// updata the storage size
mDiskCache->m_StorageInUse -= len ;
rv = mDB->Del(mRecordID, mKey, mKeyLength) ;
if(NS_FAILED(rv))
return NS_ERROR_FAILURE ;
else
return NS_OK ;
}
NS_IMETHODIMP
nsDiskCacheRecord::GetFilename(nsIFileSpec * *aFilename)
{
if(!aFilename)
return NS_ERROR_NULL_POINTER ;
*aFilename = mFile ;
NS_ADDREF(*aFilename) ;
return NS_OK ;
}
NS_IMETHODIMP
nsDiskCacheRecord::NewChannel(nsILoadGroup *loadGroup, nsIChannel **_retval)
{
nsDiskCacheRecordChannel* channel = new nsDiskCacheRecordChannel(this, loadGroup) ;
if(!channel)
return NS_ERROR_OUT_OF_MEMORY ;
nsresult rv = channel->Init() ;
if(NS_FAILED(rv))
return rv ;
NS_ADDREF(channel) ;
*_retval = NS_STATIC_CAST(nsIChannel*, channel) ;
return NS_OK ;
}
//////////////////////////////////////////////////////////////////////////
// nsDiskCacheRecord methods
// file name is represented by a url string. I hope this would be more
// generic
nsresult
nsDiskCacheRecord::GenInfo()
{
if(mInfo)
nsAllocator::Free(mInfo) ;
char* file_url=nsnull ;
PRUint32 name_len ;
mFile->GetURLString(&file_url) ;
name_len = PL_strlen(file_url)+1 ;
mInfoSize = sizeof(PRUint32) ; // checksum for mInfoSize
mInfoSize += sizeof(PRInt32) ; // RecordID
mInfoSize += sizeof(PRUint32) ; // key length
mInfoSize += mKeyLength ; // key
mInfoSize += sizeof(PRUint32) ; // metadata length
mInfoSize += mMetaDataLength ; // metadata
mInfoSize += sizeof(PRUint32) ; // filename length
mInfoSize += name_len ; // filename
void* newInfo = nsAllocator::Alloc(mInfoSize*sizeof(char)) ;
if(!newInfo) {
return NS_ERROR_OUT_OF_MEMORY ;
}
// copy the checksum mInfoSize
char* cur_ptr = NS_STATIC_CAST(char*, newInfo) ;
COPY_INT32(cur_ptr, &mInfoSize) ;
cur_ptr += sizeof(PRUint32) ;
// copy RecordID
COPY_INT32(cur_ptr, &mRecordID) ;
cur_ptr += sizeof(PRInt32) ;
// copy key length
COPY_INT32(cur_ptr, &mKeyLength) ;
cur_ptr += sizeof(PRUint32) ;
// copy key
memcpy(cur_ptr, mKey, mKeyLength) ;
cur_ptr += mKeyLength ;
// copy metadata length
COPY_INT32(cur_ptr, &mMetaDataLength) ;
cur_ptr += sizeof(PRUint32) ;
// copy metadata
memcpy(cur_ptr, mMetaData, mMetaDataLength) ;
cur_ptr += mMetaDataLength ;
// copy file name length
COPY_INT32(cur_ptr, &name_len) ;
cur_ptr += sizeof(PRUint32) ;
// copy file name
memcpy(cur_ptr, file_url, name_len) ;
cur_ptr += name_len ;
PR_ASSERT(cur_ptr == NS_STATIC_CAST(char*, newInfo) + mInfoSize);
mInfo = newInfo ;
return NS_OK ;
}
/*
* This Method suppose to get all the info from the db record
* and set them to accroding members. the original values
* will all be overwritten. only minimal error checking is performed.
*/
NS_IMETHODIMP
nsDiskCacheRecord::RetrieveInfo(void* aInfo, PRUint32 aInfoLength)
{
// reset everything
if(mInfo) {
nsAllocator::Free(mInfo) ;
mInfo = nsnull ;
}
if(mKey) {
nsAllocator::Free(mKey) ;
mKey = nsnull ;
}
if(mMetaData) {
nsAllocator::Free(mMetaData) ;
mMetaData = nsnull ;
}
char * cur_ptr = NS_STATIC_CAST(char*, aInfo) ;
char* file_url ;
PRUint32 name_len ;
// set mInfoSize
COPY_INT32(&mInfoSize, cur_ptr) ;
cur_ptr += sizeof(PRUint32) ;
// check this at least
if(mInfoSize != aInfoLength)
return NS_ERROR_FAILURE ;
// set mRecordID
COPY_INT32(&mRecordID, cur_ptr) ;
cur_ptr += sizeof(PRInt32) ;
// set mKeyLength
COPY_INT32(&mKeyLength, cur_ptr) ;
cur_ptr += sizeof(PRUint32) ;
// set mKey
mKey = NS_STATIC_CAST(char*, nsAllocator::Alloc(mKeyLength*sizeof(char))) ;
if(!mKey)
return NS_ERROR_OUT_OF_MEMORY ;
memcpy(mKey, cur_ptr, mKeyLength) ;
cur_ptr += mKeyLength ;
PRInt32 id ;
mDB->GetID(mKey, mKeyLength, &id) ;
NS_ASSERTION(id==mRecordID, "\t ++++++ bad record, somethings wrong\n") ;
// set mMetaDataLength
COPY_INT32(&mMetaDataLength, cur_ptr) ;
cur_ptr += sizeof(PRUint32) ;
// set mMetaData
mMetaData = NS_STATIC_CAST(char*, nsAllocator::Alloc(mMetaDataLength*sizeof(char))) ;
if(!mMetaData)
return NS_ERROR_OUT_OF_MEMORY ;
memcpy(mMetaData, cur_ptr, mMetaDataLength) ;
cur_ptr += mMetaDataLength ;
// get mFile name length
COPY_INT32(&name_len, cur_ptr) ;
cur_ptr += sizeof(PRUint32) ;
// get mFile native name
file_url = NS_STATIC_CAST(char*, nsAllocator::Alloc(name_len*sizeof(char))) ;
if(!file_url)
return NS_ERROR_OUT_OF_MEMORY ;
memcpy(file_url, cur_ptr, name_len) ;
cur_ptr += name_len ;
PR_ASSERT(cur_ptr == NS_STATIC_CAST(char*, aInfo) + mInfoSize);
// create mFile if Init() isn't called
if(!mFile) {
NS_NewFileSpec(getter_AddRefs(mFile));
if(!mFile)
return NS_ERROR_OUT_OF_MEMORY ;
}
// setup mFile
mFile->SetURLString(file_url) ;
return NS_OK ;
}

View File

@@ -1,70 +0,0 @@
/*
* The contents of this file are subject to the Mozilla 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/MPL/
*
* 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 Intel Corp.
* Portions created by Intel Corp. are
* Copyright (C) 1999, 1999 Intel Corp. All
* Rights Reserved.
*
* Contributor(s): Yixiong Zou <yixiong.zou@intel.com>
* Carl Wong <carl.wong@intel.com>
*/
#ifndef _NET_CACHEDDISKDATA_H_
#define _NET_CACHEDDISKDATA_H_
#include "nsINetDataCacheRecord.h"
#include "nsCOMPtr.h"
#include "nsIDBAccessor.h"
#include "prtypes.h"
#include "nsILoadGroup.h"
#include "nsIFileChannel.h"
#include "nsNetDiskCache.h"
class nsDiskCacheRecord : public nsINetDataCacheRecord
{
public:
NS_DECL_ISUPPORTS
NS_DECL_NSINETDATACACHERECORD
protected:
nsDiskCacheRecord(nsIDBAccessor* db, nsNetDiskCache* aCache) ;
virtual ~nsDiskCacheRecord() ;
NS_IMETHOD RetrieveInfo(void* aInfo, PRUint32 aInfoLength) ;
NS_IMETHOD Init(const char* key, PRUint32 length) ;
nsresult GenInfo(void) ;
private:
char* mKey ;
PRUint32 mKeyLength ;
PRInt32 mRecordID ;
char* mMetaData ;
PRUint32 mMetaDataLength ;
nsCOMPtr<nsIFileSpec> mFile ;
nsCOMPtr<nsIDBAccessor> mDB ;
void* mInfo ;
PRUint32 mInfoSize ;
PRUint32 mNumChannels ;
nsCOMPtr<nsNetDiskCache> mDiskCache ;
friend class nsDiskCacheRecordChannel ;
friend class nsDBEnumerator ;
friend class nsNetDiskCache ;
} ;
#endif // _NET_CACHEDDISKDATA_H_

View File

@@ -1,392 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Mozilla 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/MPL/
*
* 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 Intel Corp.
* Portions created by Intel Corp. are
* Copyright (C) 1999, 1999 Intel Corp. All
* Rights Reserved.
*
* Contributor(s): Yixiong Zou <yixiong.zou@intel.com>
* Carl Wong <carl.wong@intel.com>
*/
#include "nsDiskCacheRecordChannel.h"
//#include "nsFileTransport.h"
#include "nsIIOService.h"
#include "nsIServiceManager.h"
#include "nsIOutputStream.h"
static NS_DEFINE_CID(kIOServiceCID, NS_IOSERVICE_CID);
// This is copied from nsMemCacheChannel, We should consolidate these two.
class WriteStreamWrapper : public nsIOutputStream
{
public:
WriteStreamWrapper(nsDiskCacheRecordChannel* aChannel,
nsIOutputStream *aBaseStream) ;
virtual ~WriteStreamWrapper() ;
static nsresult
Create(nsDiskCacheRecordChannel* aChannel, nsIOutputStream *aBaseStream, nsIOutputStream* *aWrapper) ;
NS_DECL_ISUPPORTS
NS_DECL_NSIBASESTREAM
NS_DECL_NSIOUTPUTSTREAM
private:
nsDiskCacheRecordChannel* mChannel;
nsCOMPtr<nsIOutputStream> mBaseStream;
} ;
// implement nsISupports
NS_IMPL_ISUPPORTS(WriteStreamWrapper, NS_GET_IID(nsIOutputStream))
WriteStreamWrapper::WriteStreamWrapper(nsDiskCacheRecordChannel* aChannel,
nsIOutputStream *aBaseStream)
: mChannel(aChannel), mBaseStream(aBaseStream)
{
NS_INIT_REFCNT();
NS_ADDREF(mChannel);
}
WriteStreamWrapper::~WriteStreamWrapper()
{
NS_RELEASE(mChannel);
}
nsresult
WriteStreamWrapper::Create(nsDiskCacheRecordChannel*aChannel, nsIOutputStream *aBaseStream, nsIOutputStream* * aWrapper)
{
WriteStreamWrapper *wrapper = new WriteStreamWrapper(aChannel, aBaseStream);
if (!wrapper) return NS_ERROR_OUT_OF_MEMORY;
NS_ADDREF(wrapper);
*aWrapper = wrapper;
return NS_OK;
}
NS_IMETHODIMP
WriteStreamWrapper::Write(const char *aBuffer, PRUint32 aCount, PRUint32 *aNumWritten)
{
*aNumWritten = 0;
nsresult rv = mBaseStream->Write(aBuffer, aCount, aNumWritten);
mChannel->NotifyStorageInUse(*aNumWritten);
return rv;
}
NS_IMETHODIMP
WriteStreamWrapper::Flush()
{
return mBaseStream->Flush();
}
NS_IMETHODIMP
WriteStreamWrapper::Close()
{
return mBaseStream->Close();
}
nsDiskCacheRecordChannel::nsDiskCacheRecordChannel(nsDiskCacheRecord *aRecord,
nsILoadGroup *aLoadGroup)
: mRecord(aRecord) ,
mLoadGroup(aLoadGroup)
{
NS_INIT_REFCNT() ;
mRecord->mNumChannels++ ;
}
nsDiskCacheRecordChannel::~nsDiskCacheRecordChannel()
{
mRecord->mNumChannels-- ;
}
// FUR!!
//
// I know that I gave conflicting advice on the issue of file
// transport versus file protocol handler, but I thought that the
// last word was that we would use the raw transport, when I wrote:
//
// > I just thought of an argument for the other side of the coin, i.e. the
// > benefit of *not* reusing the file protocol handler: On the Mac, it's
// > expensive to convert from a string URL to an nsFileSpec, because the Mac
// > is brain-dead and scans every directory on the path to the file. It's
// > cheaper to create a nsFileSpec for a cache file by combining a single,
// > static nsFileSpec that corresponds to the cache directory with the
// > relative path to the cache file (using nsFileSpec's operator +). This
// > operation is optimized on the Mac to avoid the scanning operation.
//
// The Mac guys will eat us alive if we do path string to nsFileSpec
// conversions for every cache file we open.
nsresult
nsDiskCacheRecordChannel::Init(void)
{
char* urlStr ;
mRecord->mFile->GetURLString(&urlStr) ;
nsresult rv ;
NS_WITH_SERVICE(nsIIOService, serv, kIOServiceCID, &rv);
if (NS_FAILED(rv)) return rv;
rv = serv->NewChannel("load", // XXX what should this be?
urlStr,
nsnull, // no base uri
mLoadGroup,
nsnull, // no eventsink getter
0,
nsnull, // no original URI
0,
0,
getter_AddRefs(mFileTransport));
return rv ;
}
nsresult
nsDiskCacheRecordChannel::NotifyStorageInUse(PRInt32 aBytesUsed)
{
return mRecord->mDiskCache->m_StorageInUse += aBytesUsed ;
}
// implement nsISupports
NS_IMPL_ISUPPORTS(nsDiskCacheRecordChannel, NS_GET_IID(nsIChannel))
// implement nsIRequest
NS_IMETHODIMP
nsDiskCacheRecordChannel::IsPending(PRBool *aIsPending)
{
*aIsPending = PR_FALSE ;
if(!mFileTransport)
return NS_OK ;
return mFileTransport->IsPending(aIsPending) ;
}
NS_IMETHODIMP
nsDiskCacheRecordChannel::Cancel(void)
{
if(!mFileTransport)
return NS_ERROR_FAILURE ;
return mFileTransport->Cancel() ;
}
NS_IMETHODIMP
nsDiskCacheRecordChannel::Suspend(void)
{
if(!mFileTransport)
return NS_ERROR_FAILURE ;
return mFileTransport->Suspend() ;
}
NS_IMETHODIMP
nsDiskCacheRecordChannel::Resume(void)
{
if(!mFileTransport)
return NS_ERROR_FAILURE ;
return mFileTransport->Resume() ;
}
// implement nsIChannel
NS_IMETHODIMP
nsDiskCacheRecordChannel::GetURI(nsIURI * *aURI)
{
if(!mFileTransport)
return NS_ERROR_FAILURE ;
return mFileTransport->GetURI(aURI) ;
}
NS_IMETHODIMP
nsDiskCacheRecordChannel::OpenInputStream(PRUint32 aStartPosition,
PRInt32 aReadCount,
nsIInputStream* *aResult)
{
if(!mFileTransport)
return NS_ERROR_FAILURE ;
return mFileTransport->OpenInputStream(aStartPosition,
aReadCount,
aResult) ;
}
NS_IMETHODIMP
nsDiskCacheRecordChannel::OpenOutputStream(PRUint32 startPosition,
nsIOutputStream* *aResult)
{
nsresult rv ;
NS_ENSURE_ARG(aResult) ;
nsCOMPtr<nsIOutputStream> outputStream ;
PRUint32 oldLength ;
mRecord->GetStoredContentLength(&oldLength) ;
if(startPosition < oldLength) {
NotifyStorageInUse(startPosition - oldLength) ;
// we should truncate the file at here.
rv = mRecord->SetStoredContentLength(startPosition) ;
if(NS_FAILED(rv)) {
printf(" failed to truncate\n") ;
return rv ;
}
}
rv = mFileTransport->OpenOutputStream(startPosition, getter_AddRefs(outputStream)) ;
if(NS_FAILED(rv)) return rv ;
return WriteStreamWrapper::Create(this, outputStream, aResult) ;
}
NS_IMETHODIMP
nsDiskCacheRecordChannel::AsyncOpen(nsIStreamObserver *observer,
nsISupports *ctxt)
{
if(!mFileTransport)
return NS_ERROR_FAILURE ;
return mFileTransport->AsyncOpen(observer, ctxt) ;
}
NS_IMETHODIMP
nsDiskCacheRecordChannel::AsyncRead(PRUint32 aStartPosition,
PRInt32 aReadCount,
nsISupports *aContext,
nsIStreamListener *aListener)
{
if(!mFileTransport)
return NS_ERROR_FAILURE ;
return mFileTransport->AsyncRead(aStartPosition ,
aReadCount ,
aContext ,
aListener) ;
}
NS_IMETHODIMP
nsDiskCacheRecordChannel::AsyncWrite(nsIInputStream *fromStream,
PRUint32 startPosition,
PRInt32 writeCount,
nsISupports *ctxt,
nsIStreamObserver *observer)
{
/*
if(!mFileTransport)
return NS_ERROR_FAILURE ;
return mFileTransport->AsyncWrite(fromStream,
startPosition,
writeCount,
ctxt,
observer) ;
*/
// I can't do this since the write is not monitored, and I won't be
// able to updata the storage.
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
nsDiskCacheRecordChannel::GetLoadAttributes(nsLoadFlags *aLoadAttributes)
{
if(!mFileTransport)
return NS_ERROR_FAILURE ;
return mFileTransport->GetLoadAttributes(aLoadAttributes) ;
}
NS_IMETHODIMP
nsDiskCacheRecordChannel::SetLoadAttributes(nsLoadFlags aLoadAttributes)
{
if(!mFileTransport)
return NS_ERROR_FAILURE ;
return mFileTransport->SetLoadAttributes(aLoadAttributes) ;
}
NS_IMETHODIMP
nsDiskCacheRecordChannel::GetContentType(char * *aContentType)
{
if(!mFileTransport)
return NS_ERROR_FAILURE ;
return mFileTransport->GetContentType(aContentType) ;
}
NS_IMETHODIMP
nsDiskCacheRecordChannel::GetContentLength(PRInt32 *aContentLength)
{
if(!mFileTransport)
return NS_ERROR_FAILURE ;
return mFileTransport->GetContentLength(aContentLength) ;
}
NS_IMETHODIMP
nsDiskCacheRecordChannel::GetOwner(nsISupports* *aOwner)
{
*aOwner = mOwner.get() ;
NS_IF_ADDREF(*aOwner) ;
return NS_OK ;
}
NS_IMETHODIMP
nsDiskCacheRecordChannel::SetOwner(nsISupports* aOwner)
{
mOwner = aOwner ;
return NS_OK ;
}
NS_IMETHODIMP
nsDiskCacheRecordChannel::GetOriginalURI(nsIURI* *aURI)
{
// FUR - might need to implement this - not sure
return NS_ERROR_NOT_IMPLEMENTED ;
}
NS_IMETHODIMP
nsDiskCacheRecordChannel::GetLoadGroup(nsILoadGroup* *aLoadGroup)
{
// Not required to be implemented, since it is implemented by cache manager
NS_ASSERTION(0, "nsDiskCacheRecordChannel method unexpectedly called");
return NS_OK ;
}
NS_IMETHODIMP
nsDiskCacheRecordChannel::SetLoadGroup(nsILoadGroup* aLoadGroup)
{
// Not required to be implemented, since it is implemented by cache manager
NS_ASSERTION(0, "nsDiskCacheRecordChannel method unexpectedly called");
return NS_OK;
}
NS_IMETHODIMP
nsDiskCacheRecordChannel::GetNotificationCallbacks(nsIInterfaceRequestor* *aNotificationCallbacks)
{
// Not required to be implemented, since it is implemented by cache manager
NS_ASSERTION(0, "nsDiskCacheRecordChannel method unexpectedly called");
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
nsDiskCacheRecordChannel::SetNotificationCallbacks(nsIInterfaceRequestor* aNotificationCallbacks)
{
// Not required to be implemented, since it is implemented by cache manager
NS_ASSERTION(0, "nsDiskCacheRecordChannel method unexpectedly called");
return NS_ERROR_NOT_IMPLEMENTED;
}

View File

@@ -1,65 +0,0 @@
/*
* The contents of this file are subject to the Mozilla 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/MPL/
*
* 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 Intel Corp.
* Portions created by Intel Corp. are
* Copyright (C) 1999, 1999 Intel Corp. All
* Rights Reserved.
*
* Contributor(s): Yixiong Zou <yixiong.zou@intel.com>
* Carl Wong <carl.wong@intel.com>
*/
#ifndef _ns_DiskCacheRecordChannel_h_
#define _ns_DiskCacheRecordChannel_h_
#include "nsIChannel.h"
#include "nsCOMPtr.h"
#include "nsDiskCacheRecord.h"
/*
* This class is plagiarized from nsMemCacheChannel
*/
class nsDiskCacheRecordChannel : public nsIChannel
{
public:
nsDiskCacheRecordChannel(nsDiskCacheRecord *aRecord, nsILoadGroup *aLoadGroup);
virtual ~nsDiskCacheRecordChannel() ;
// Declare nsISupports methods
NS_DECL_ISUPPORTS
// Declare nsIRequest methods
NS_DECL_NSIREQUEST
// Declare nsIChannel methods
NS_DECL_NSICHANNEL
nsresult Init(void) ;
private:
nsresult NotifyStorageInUse(PRInt32 aBytesUsed) ;
nsCOMPtr<nsDiskCacheRecord> mRecord ;
nsCOMPtr<nsILoadGroup> mLoadGroup ;
nsCOMPtr<nsISupports> mOwner ;
nsCOMPtr<nsIChannel> mFileTransport ;
friend class WriteStreamWrapper ;
} ;
#endif // _ns_DiskCacheRecordChannel_h_

View File

@@ -1,60 +0,0 @@
/*
* The contents of this file are subject to the Mozilla 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/MPL/
*
* 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 Intel Corp.
* Portions created by Intel Corp. are
* Copyright (C) 1999, 1999 Intel Corp. All
* Rights Reserved.
*
* Contributor(s): Yixiong Zou <yixiong.zou@intel.com>
* Carl Wong <carl.wong@intel.com>
*/
#ifndef _NS_IDBACCESSOR_H_
#define _NS_IDBACCESSOR_H_
#include "nsISupports.h"
#include "nsIFileSpec.h"
// nsIDBAccessorIID {6AADD4D0-7785-11d3-87FE-000629D01344}
#define NS_IDBACCESSOR_IID \
{ 0x6aadd4d0, 0x7785, 0x11d3, \
{0x87, 0xfe, 0x0, 0x6, 0x29, 0xd0, 0x13, 0x44}}
// nsDBAccessorCID {6AADD4D1-7785-11d3-87FE-000629D01344}
#define NS_DBACCESSOR_CID \
{ 0x6aadd4d1, 0x7785, 0x11d3, \
{ 0x87, 0xfe, 0x0, 0x6, 0x29, 0xd0, 0x13, 0x44 }}
class nsIDBAccessor : public nsISupports
{
public:
NS_DEFINE_STATIC_IID_ACCESSOR(NS_IDBACCESSOR_IID)
NS_IMETHOD Init(nsIFileSpec* DBFile) = 0 ;
NS_IMETHOD Shutdown(void) = 0 ;
NS_IMETHOD Put(PRInt32 aID, void* anEntry, PRUint32 aLength) = 0 ;
NS_IMETHOD Get(PRInt32 aID, void** anEntry, PRUint32 *aLength) = 0 ;
NS_IMETHOD Del(PRInt32 aID, void* anEntry, PRUint32 aLength) = 0 ;
NS_IMETHOD GetID(const char* key, PRUint32 length, PRInt32* aID) = 0 ;
NS_IMETHOD EnumEntry(void* *anEntry, PRUint32* aLength, PRBool bReset) = 0 ;
} ;
#endif // _NS_IDBACCESSOR_H_

View File

@@ -1,691 +0,0 @@
/*
* The contents of this file are subject to the Mozilla 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/MPL/
*
* 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 Intel Corp.
* Portions created by Intel Corp. are
* Copyright (C) 1999, 1999 Intel Corp. All
* Rights Reserved.
*
* Contributor(s): Yixiong Zou <yixiong.zou@intel.com>
* Carl Wong <carl.wong@intel.com>
*/
#include "nsNetDiskCache.h"
#include "nscore.h"
#include "plstr.h"
#include "prprf.h"
#include "prtypes.h"
#include "prio.h"
#include "prsystem.h" // Directory Seperator
#include "plhash.h"
#include "prclist.h"
#include "prmem.h"
#include "nsIComponentManager.h"
#include "nsIServiceManager.h"
#include "nsIPref.h"
#include "mcom_db.h"
#include "nsDBEnumerator.h"
#include "nsDiskCacheRecord.h"
static NS_DEFINE_CID(kPrefCID, NS_PREF_CID) ;
static NS_DEFINE_CID(kDBAccessorCID, NS_DBACCESSOR_CID) ;
static const PRUint32 DISK_CACHE_SIZE_DEFAULT = 5*1024*1024 ; // 5MB
static const char * const DISK_CACHE_PREF = "browser.cache.disk_cache_size";
static const char * const CACHE_DIR_PREF = "browser.cache.directory";
class nsDiskCacheRecord ;
nsNetDiskCache::nsNetDiskCache() :
m_Enabled(PR_TRUE) ,
m_NumEntries(0) ,
m_pNextCache(0) ,
m_pDiskCacheFolder(0) ,
m_StorageInUse(0) ,
m_DB(0) ,
m_BaseDirNum(32)
{
// set it to INF for now
m_MaxEntries = (PRUint32)-1 ;
NS_INIT_REFCNT();
}
nsNetDiskCache::~nsNetDiskCache()
{
printf("~nsNetDiskCache\n") ;
NS_IF_RELEASE(m_DB) ;
// FUR!!
// You shouldn't rely on the value of m_BaseDirNum to diagnose whether or not
// a cache corruption has occurred since it's possible that the app does not
// shut down cleanly and a corrupted cache has still not been cleaned up from
// a previous session. My suggestion is that you pick a different scheme for
// renaming the dirs, e.g. rename them as "trash*" and remove all directories
// with this name pattern on shutdown.
// FUR
// I think that, eventually, we also want a distinguished key in the DB which
// means "clean cache shutdown". You clear this flag when the db is first
// opened and set it just before the db is closed. If the db wasn't shutdown
// cleanly in a prior session, i.e. because the app crashed, on startup you
// scan all the individual files in directories and look for "orphans",
// i.e. cache files which don't have corresponding entries in the db. That's
// also when storage-in-use and number of entries would be recomputed.
//
// We don't necessarily need all this functionality immediately, though.
if(m_BaseDirNum > 32)
RemoveDirs(32) ;
}
NS_IMETHODIMP
nsNetDiskCache::Init(void)
{
nsresult rv ;
// FUR!!
// I really don't think prefs belong here, since that breaks modularity. It
// presupposes that the file cache code is embedded in the browser or some
// other application that uses the prefs, i.e. the code might be used in a
// standalone cache manipulation tool or, someday, in server code. Pref
// reading belongs at a higher level, either in the application itself or
// possibly the I/O manager.
// Also, Init() needs to be lazy, since folder name is not set on startup,
// i.e. need a call to MaybeInit() at the beginning of every public method
NS_WITH_SERVICE(nsIPref, pref, kPrefCID, &rv) ;
if (NS_FAILED(rv))
NS_ERROR("Failed to get globle preference!\n") ;
rv = NS_NewFileSpec(getter_AddRefs(m_pDiskCacheFolder));
if (!m_pDiskCacheFolder) {
NS_ERROR("ERROR: Could not make a file spec.\n") ;
return NS_ERROR_OUT_OF_MEMORY ;
}
char* tempPref = 0 ;
if(pref) {
PRInt32 nTemp = 0 ;
/*
rv = pref->CopyCharPref(CACHE_DIR_PREF, &tempPref) ;
if (NS_SUCCEEDED(rv)) {
printf("cache dir is %s\n", tempPref) ;
m_pDiskCacheFolder->SetUnixStyleFilePath(tempPref) ;
PR_Free(tempPref) ;
} else */
{
m_pDiskCacheFolder->SetUnixStyleFilePath("/tmp") ;
printf("using default folder, /tmp\n") ;
}
}
else {
// temp hack for now. change later for other platform
m_pDiskCacheFolder->SetUnixStyleFilePath("/tmp") ;
}
// FUR - suggest you use nsCOMPtr for m_DB - it will eliminate
// manual addref/release and reduce likelihood of bugs
NS_IF_RELEASE(m_DB) ;
m_DB = new nsDBAccessor() ;
if(!m_DB)
return NS_ERROR_OUT_OF_MEMORY ;
else
NS_ADDREF(m_DB) ;
rv = InitDB() ;
// try once for recovery
if(rv == NS_ERROR_FAILURE) {
rv = DBRecovery() ;
return rv ;
}
rv = UpdateInfo() ;
return rv ;
}
NS_IMETHODIMP
nsNetDiskCache::InitDB(void)
{
// create cache sub directories
nsresult rv ;
nsCOMPtr<nsIFileSpec> cacheSubDir;
rv = NS_NewFileSpec(getter_AddRefs(cacheSubDir));
// FUR - any way to avoid doing this, if it's already been done ?
for (int i=0; i < 32; i++) {
rv = cacheSubDir->FromFileSpec(m_pDiskCacheFolder) ;
if(NS_FAILED(rv))
return rv ;
char dirName[3];
PR_snprintf (dirName, 3, "%0.2x", i);
cacheSubDir->AppendRelativeUnixPath (dirName) ;
CreateDir(cacheSubDir);
}
NS_NewFileSpec(getter_AddRefs(m_DBFile)) ;
// FUR - check for NS_NewFileSpec failure
rv = m_DBFile->FromFileSpec(m_pDiskCacheFolder) ;
if(NS_FAILED(rv))
return rv ;
m_DBFile->AppendRelativeUnixPath("cache.db") ;
rv = m_DB->Init(m_DBFile) ;
return rv ;
}
//////////////////////////////////////////////////////////////////////////
// nsISupports methods
// FUR - Suggest you use NS_IMPL_ISUPPORTS3() macro instead
NS_IMETHODIMP
nsNetDiskCache::QueryInterface(const nsIID& aIID, void** aInstancePtr)
{
NS_ASSERTION(aInstancePtr, "no instance pointer");
if(aIID.Equals(NS_GET_IID(nsINetDataDiskCache)) ||
aIID.Equals(NS_GET_IID(nsINetDataCache)) ||
aIID.Equals(NS_GET_IID(nsISupports))) {
*aInstancePtr = NS_STATIC_CAST(nsINetDataDiskCache*, this);
NS_ADDREF_THIS();
return NS_OK;
}
else
return NS_NOINTERFACE ;
}
NS_IMPL_ADDREF(nsNetDiskCache) ;
NS_IMPL_RELEASE(nsNetDiskCache) ;
///////////////////////////////////////////////////////////////////////////
// nsINetDataCache Method
NS_IMETHODIMP
nsNetDiskCache::GetDescription(PRUnichar* *aDescription)
{
nsAutoString description("Disk Cache") ;
*aDescription = description.ToNewUnicode() ;
if(!*aDescription)
return NS_ERROR_OUT_OF_MEMORY ;
return NS_OK ;
}
/* don't alloc mem for nsICachedNetData.
* RecordID is generated using the same scheme in nsCacheDiskData,
* see GetCachedNetData() for detail.
*/
NS_IMETHODIMP
nsNetDiskCache::Contains(const char* key, PRUint32 length, PRBool *_retval)
{
*_retval = PR_FALSE ;
NS_ASSERTION(m_DB, "no db.") ;
PRInt32 id = 0 ;
m_DB->GetID(key, length, &id) ;
// FUR - Check for GetID failure ?
void* info = 0 ;
PRUint32 info_size = 0 ;
nsresult rv = m_DB->Get(id, &info, &info_size) ;
if(NS_SUCCEEDED(rv) && info)
*_retval = PR_TRUE ;
return NS_OK ;
}
/* regardless if it's cached or not, a copy of nsNetDiskCache would
* always be returned. so release it appropriately.
* if mem alloced, updata m_NumEntries also.
* for now, the new nsCachedNetData is not written into db yet since
* we have nothing to write.
*/
NS_IMETHODIMP
nsNetDiskCache::GetCachedNetData(const char* key, PRUint32 length, nsINetDataCacheRecord **_retval)
{
NS_ASSERTION(m_DB, "no db.") ;
nsresult rv = 0 ;
if (!_retval)
return NS_ERROR_NULL_POINTER ;
*_retval = nsnull ;
PRInt32 id = 0 ;
m_DB->GetID(key, length, &id) ;
// FUR - Check for GetID failure ?
// construct an empty record
nsDiskCacheRecord* newRecord = new nsDiskCacheRecord(m_DB, this) ;
if(!newRecord)
return NS_ERROR_OUT_OF_MEMORY ;
rv = newRecord->Init(key, length) ;
if(NS_FAILED(rv)) {
delete newRecord ;
return rv ;
}
NS_ADDREF(newRecord) ; // addref for _retval
*_retval = (nsINetDataCacheRecord*) newRecord ;
void* info = 0 ;
PRUint32 info_size = 0 ;
rv = m_DB->Get(id, &info, &info_size) ;
if(NS_SUCCEEDED(rv) && info) {
nsresult r1 ;
r1 = newRecord->RetrieveInfo(info, info_size) ;
// FUR!! need to release and return error if RetrieveInfo() fails
if(NS_SUCCEEDED(rv))
return NS_OK ;
else
return r1;
} else if (NS_SUCCEEDED(rv) && !info) {
// this is a new record.
m_NumEntries ++ ;
return NS_OK ;
} else
return rv ;
}
/* get an nsICachedNetData, mem needs to be de-alloced if not found. */
NS_IMETHODIMP
nsNetDiskCache::GetCachedNetDataByID(PRInt32 RecordID, nsINetDataCacheRecord **_retval)
{
NS_ASSERTION(m_DB, "no db.") ;
if (!_retval)
return NS_ERROR_NULL_POINTER ;
*_retval = nsnull ;
nsresult rv ;
void* info = 0 ;
PRUint32 info_size = 0 ;
rv = m_DB->Get(RecordID, &info, &info_size) ;
if(NS_SUCCEEDED(rv) && info) {
// construct an empty record if only found in db
nsDiskCacheRecord* newRecord = new nsDiskCacheRecord(m_DB, this) ;
if(!newRecord)
return NS_ERROR_OUT_OF_MEMORY ;
NS_ADDREF(newRecord) ; // addref for _retval
rv = newRecord->RetrieveInfo(info, info_size) ;
if(NS_SUCCEEDED(rv)) {
*_retval = (nsINetDataCacheRecord*) newRecord ;
return NS_OK ;
}
else {
// bad record, I guess
NS_RELEASE(newRecord) ; // release if bad things happen
return rv ;
}
} else {
NS_ERROR("Error: RecordID not in DB\n") ;
return rv ;
}
}
NS_IMETHODIMP
nsNetDiskCache::GetEnabled(PRBool *aEnabled)
{
*aEnabled = m_Enabled ;
return NS_OK ;
}
NS_IMETHODIMP
nsNetDiskCache::SetEnabled(PRBool aEnabled)
{
m_Enabled = aEnabled ;
return NS_OK ;
}
NS_IMETHODIMP
nsNetDiskCache::GetFlags(PRUint32 *aFlags)
{
*aFlags = FILE_PER_URL_CACHE;
return NS_OK ;
}
NS_IMETHODIMP
nsNetDiskCache::GetNumEntries(PRUint32 *aNumEntries)
{
*aNumEntries = m_NumEntries ;
return NS_OK ;
}
NS_IMETHODIMP
nsNetDiskCache::GetMaxEntries(PRUint32 *aMaxEntries)
{
*aMaxEntries = m_MaxEntries ;
return NS_OK ;
}
NS_IMETHODIMP
nsNetDiskCache::NewCacheEntryIterator(nsISimpleEnumerator **_retval)
{
if(!_retval)
return NS_ERROR_NULL_POINTER ;
*_retval = nsnull ;
nsISimpleEnumerator* enumerator = new nsDBEnumerator(m_DB, this) ;
if(enumerator) {
NS_ADDREF(enumerator) ;
*_retval = enumerator ;
return NS_OK ;
}
else
return NS_ERROR_OUT_OF_MEMORY ;
}
NS_IMETHODIMP
nsNetDiskCache::GetNextCache(nsINetDataCache * *aNextCache)
{
if(!aNextCache)
return NS_ERROR_NULL_POINTER ;
*aNextCache = m_pNextCache ;
return NS_OK ;
}
NS_IMETHODIMP
nsNetDiskCache::SetNextCache(nsINetDataCache *aNextCache)
{
m_pNextCache = aNextCache ;
return NS_OK ;
}
// db size can always be measured at the last minute. Since it's hard
// to know before hand.
NS_IMETHODIMP
nsNetDiskCache::GetStorageInUse(PRUint32 *aStorageInUse)
{
PRUint32 total_size = m_StorageInUse, len = 0 ;
// FUR!!
// GetStorageInUse() can be called hundreds of times per second, i.e. every
// time a buffer of data is written to the cache, so we can't afford to stat
// the db file on every call. I would suggest caching the size of the db and
// invalidating that cached value every time a record is written to the db,
// or even every ten written records.
// add the size of the db.
// m_DBFile->GetFileSize(&len) ;
// total_size += len ;
// we need size in kB
total_size = total_size >> 10 ;
*aStorageInUse = total_size ;
return NS_OK ;
}
/*
* The whole cache dirs can be whiped clean since all the cache
* files are resides in seperate hashed dirs. It's safe to do so.
*/
NS_IMETHODIMP
nsNetDiskCache::RemoveAll(void)
{
nsresult rv = RemoveDirs(0) ;
if(NS_FAILED(rv))
return rv ;
// don't forget the db file itself
m_DB->Shutdown() ;
nsFileSpec dbfile ;
m_DBFile->GetFileSpec(&dbfile) ;
dbfile.Delete(PR_TRUE) ;
// reinitilize
rv = InitDB() ;
if(NS_FAILED(rv))
return rv ;
rv = UpdateInfo() ;
return rv ;
}
//////////////////////////////////////////////////////////////////
// nsINetDataDiskCache methods
NS_IMETHODIMP
nsNetDiskCache::GetDiskCacheFolder(nsIFileSpec * *aDiskCacheFolder)
{
*aDiskCacheFolder = m_pDiskCacheFolder ;
NS_ADDREF(*aDiskCacheFolder) ;
return NS_OK ;
}
NS_IMETHODIMP
nsNetDiskCache::SetDiskCacheFolder(nsIFileSpec * aDiskCacheFolder)
{
char *newfolder, *oldfolder ;
m_pDiskCacheFolder->GetNativePath(&oldfolder) ;
aDiskCacheFolder->GetNativePath(&newfolder) ;
if(PL_strcmp(newfolder, oldfolder) == 0) {
m_pDiskCacheFolder = aDiskCacheFolder ;
// should we do this?
// FUR - no
nsresult rv = RemoveAll() ;
return rv ;
}
else
// FUR
// Need to blow away old cache, build new one
return NS_OK ;
}
//////////////////////////////////////////////////////////////////
// nsNetDiskCache methods
// create a directory (recursively)
NS_IMETHODIMP
nsNetDiskCache::CreateDir(nsIFileSpec* dir_spec)
{
PRBool does_exist ;
nsCOMPtr<nsIFileSpec> p_spec ;
dir_spec->Exists(&does_exist) ;
if(does_exist)
return NS_OK ;
dir_spec->GetParent(getter_AddRefs(p_spec)) ;
// FUR - check return value
p_spec->Exists(&does_exist) ;
if(!does_exist) {
CreateDir(p_spec) ;
dir_spec->CreateDir() ;
// FUR - check return value
}
else {
dir_spec->CreateDir() ;
// FUR - check return value
}
return NS_OK ;
}
// FUR!!
// We can't afford to make a *separate* pass over the whole db on every
// startup, just to figure out m_NumEntries and m_StorageInUse. (This is a
// several second operation on a large db). We'll likely need to store
// distinguished keys in the db that contain these values and update them
// incrementally, except when failure to shut down the db cleanly is detected.
// this will walk through db and update m_NumEntries and m_StorageInUse
NS_IMETHODIMP
nsNetDiskCache::UpdateInfo(void)
{
// count num of entries in db
// NS_ADDREF(this) ; // addref before assign to a nsCOMPtr.
nsISimpleEnumerator* dbEnumerator = new nsDBEnumerator(m_DB, this) ;
if(dbEnumerator)
NS_ADDREF(dbEnumerator) ;
else
return NS_ERROR_FAILURE ;
PRUint32 numEntries = 0, storageInUse = 0, len = 0 ;
PRBool more = PR_FALSE ;
do {
dbEnumerator->HasMoreElements(&more) ;
if(more) {
// update entry number
numEntries++ ;
// update storage in use
nsINetDataCacheRecord* record ;
dbEnumerator->GetNext((nsISupports**)&record) ;
record->GetStoredContentLength(&len) ;
storageInUse += len ;
NS_IF_RELEASE(record) ;
}
} while (more) ;
NS_IF_RELEASE(dbEnumerator) ;
m_NumEntries = numEntries ;
m_StorageInUse = storageInUse ;
printf(" m_NumEntries = %d, size is %d.\n", m_NumEntries, m_StorageInUse) ;
return NS_OK ;
}
// this routine will add m_BaseDirNum to current CacheSubDir names.
// e.g. 00->20, 1f->5f. and update the m_BaseDirNum to another 32.
// the idea is as long as we remember the base number,
// we know how many dirs needs to be removed during shutdown period
// it will be from 0x20 to m_BaseDirNum.
// also, we assume that this operation will not be performed 3 times more
// within a single session. it is part of scavenging routine.
NS_IMETHODIMP
nsNetDiskCache::RenameCacheSubDirs(void)
{
nsCOMPtr<nsIFileSpec> cacheSubDir;
nsresult rv = NS_NewFileSpec(getter_AddRefs(cacheSubDir)) ;
for (int i=0; i < 32; i++) {
rv = cacheSubDir->FromFileSpec(m_pDiskCacheFolder) ;
if(NS_FAILED(rv))
return rv ;
char dirName[3];
PR_snprintf(dirName, 3, "%0.2x", i) ;
cacheSubDir->AppendRelativeUnixPath(dirName) ;
// re-name the directory
PR_snprintf(dirName, 3, "%0.2x", i+m_BaseDirNum) ;
rv = cacheSubDir->Rename(dirName) ;
if(NS_FAILED(rv))
return NS_ERROR_FAILURE ;
}
// update m_BaseDirNum
m_BaseDirNum += 32 ;
return NS_OK ;
}
// this routine will be called everytime we have a db corruption.
NS_IMETHODIMP
nsNetDiskCache::DBRecovery(void)
{
nsresult rv = RenameCacheSubDirs() ;
if(NS_FAILED(rv))
return rv ;
// remove corrupted db file
rv = m_DB->Shutdown() ;
// FUR!!
// You shouldn't return if this fails. Otherwise, it might prevent db deletion
if(NS_FAILED(rv))
return rv ;
nsFileSpec dbfile ;
m_DBFile->GetFileSpec(&dbfile) ;
dbfile.Delete(PR_TRUE) ;
// make sure it's not there any more
PRBool exists = dbfile.Exists() ;
if(exists) {
NS_ERROR("can't remove old db.") ;
return NS_ERROR_FAILURE ;
}
// reinitilize
rv = InitDB() ;
if(NS_FAILED(rv))
return rv ;
rv = UpdateInfo() ;
return rv ;
}
// this routine is used by dtor and RemoveAll() to clean up dirs.
// All directory named from aNum - m_BasedDirNum will be deleted.
NS_IMETHODIMP
nsNetDiskCache::RemoveDirs(PRUint32 aNum)
{
nsCOMPtr<nsIFileSpec> cacheSubDir;
nsresult rv = NS_NewFileSpec(getter_AddRefs(cacheSubDir));
if(NS_FAILED(rv))
return NS_ERROR_FAILURE ;
for (int i=aNum; i < m_BaseDirNum; i++) {
cacheSubDir->FromFileSpec(m_pDiskCacheFolder) ;
char dirName[3];
PR_snprintf (dirName, 3, "%0.2x", i);
cacheSubDir->AppendRelativeUnixPath (dirName) ;
nsFileSpec subdir ;
cacheSubDir->GetFileSpec(&subdir) ;
for(nsDirectoryIterator di(subdir, PR_FALSE); di.Exists(); di++) {
di.Spec().Delete(PR_TRUE) ;
}
subdir.Delete(PR_FALSE) ; // recursive delete
}
return NS_OK ;
}

View File

@@ -1,82 +0,0 @@
/*
* The contents of this file are subject to the Mozilla 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/MPL/
*
* 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 Intel Corp.
* Portions created by Intel Corp. are
* Copyright (C) 1999, 1999 Intel Corp. All
* Rights Reserved.
*
* Contributor(s): Yixiong Zou <yixiong.zou@intel.com>
* Carl Wong <carl.wong@intel.com>
*/
// FUR - Add overall description comment here
#ifndef __gen_nsNetDiskCache_h__
#define __gen_nsNetDiskCache_h__
#include "nsINetDataDiskCache.h"
#include "nsNetDiskCacheCID.h"
#include "nsCOMPtr.h"
#include "nsIPref.h"
#include "nsDBAccessor.h"
class nsIURI; /* forward decl */
class nsICachedNetData; /* forward decl */
class nsISimpleEnumerator; /* forward decl */
class nsIFileSpec; /* forward decl */
/* starting interface: nsNetDiskCache */
class nsNetDiskCache : public nsINetDataDiskCache {
public:
NS_DECL_ISUPPORTS
NS_DECL_NSINETDATACACHE
NS_DECL_NSINETDATADISKCACHE
NS_IMETHOD Init(void) ;
nsNetDiskCache() ;
virtual ~nsNetDiskCache() ;
protected:
NS_IMETHOD InitDB(void) ;
NS_IMETHOD CreateDir(nsIFileSpec* dir_spec) ;
NS_IMETHOD UpdateInfo(void) ;
NS_IMETHOD RenameCacheSubDirs(void) ;
NS_IMETHOD DBRecovery(void) ;
NS_IMETHOD RemoveDirs(PRUint32 aNum) ;
private:
PRBool m_Enabled ;
PRUint32 m_NumEntries ;
nsCOMPtr<nsINetDataCache> m_pNextCache ;
nsCOMPtr<nsIFileSpec> m_pDiskCacheFolder ;
nsCOMPtr<nsIFileSpec> m_DBFile ;
PRUint32 m_MaxEntries ;
PRUint32 m_StorageInUse ;
nsIDBAccessor* m_DB ;
// this is used to indicate a db corruption
PRInt32 m_BaseDirNum ;
friend class nsDiskCacheRecord ;
friend class nsDiskCacheRecordChannel ;
} ;
#endif /* __gen_nsNetDiskCache_h__ */

View File

@@ -1,32 +0,0 @@
/*
* The contents of this file are subject to the Mozilla 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/MPL/
*
* 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 Intel Corp.
* Portions created by Intel Corp. are
* Copyright (C) 1999, 1999 Intel Corp. All
* Rights Reserved.
*
* Contributor(s): Yixiong Zou <yixiong.zou@intel.com>
* Carl Wong <carl.wong@intel.com>
*/
#ifndef _nsNetDiskCacheCID_h_
#define _nsNetDiskCacheCID_h_
#define NS_NETDISKCACHE_CID_STR "ECFEEA00-7201-11d3-87FE-000629D01344"
#define NS_NETDISKCACHE_CID \
{ 0xecfeea00, 0x7201, 0x11d3, \
{ 0x87, 0xfe, 0x0, 0x6, 0x29, 0xd0, 0x13, 0x44 }}
#endif /* _nsNetDiskCacheCID_h_ */

View File

@@ -1,836 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
* Reserved.
*/
#include "nsIStreamListener.h"
#include "nsIStreamObserver.h"
#include "nsIServiceManager.h"
#include "nsIInputStream.h"
#include "nsIOutputStream.h"
#include "nsIEventQueue.h"
#include "nsIEventQueueService.h"
#include "nsIChannel.h"
#include "nsCOMPtr.h"
#include "nsString.h"
#include <stdio.h>
#include <unistd.h>
#include "nsINetDataCache.h"
#include "nsINetDataCacheRecord.h"
//#include "nsMemCacheCID.h"
#include "nsNetDiskCache.h"
#include "nsIPref.h"
#include "prenv.h"
#include "nsIFileStream.h"
// Number of test entries to be placed in the cache
#define NUM_CACHE_ENTRIES 250
// Cache content stream length will have random length between zero and
// MAX_CONTENT_LENGTH bytes
#define MAX_CONTENT_LENGTH 20000
// Length of random-data cache entry key
#define CACHE_KEY_LENGTH 15
// Length of random-data cache entry meta-data
#define CACHE_METADATA_LENGTH 100
//static NS_DEFINE_CID(kMemCacheCID, NS_MEM_CACHE_FACTORY_CID);
static NS_DEFINE_CID(kEventQueueServiceCID, NS_EVENTQUEUESERVICE_CID);
static NS_DEFINE_CID(kDiskCacheCID, NS_NETDISKCACHE_CID) ;
static NS_DEFINE_CID(kPrefCID, NS_PREF_CID);
static NS_DEFINE_IID(kIPrefIID, NS_IPREF_IID);
// Mapping from test case number to RecordID
static PRInt32 recordID[NUM_CACHE_ENTRIES];
static PRInt32
mapRecordIdToTestNum(PRInt32 aRecordID)
{
int i;
for (i = 0; i < NUM_CACHE_ENTRIES; i++) {
if (recordID[i] == aRecordID)
return i;
}
return -1;
}
// A supply of stream data to either store or compare with
class nsITestDataStream {
public:
virtual ~nsITestDataStream() {};
virtual PRUint32 Next() = 0;
virtual void Read(char* aBuf, PRUint32 aCount) = 0;
virtual PRBool Match(char* aBuf, PRUint32 aCount) = 0;
virtual void Skip(PRUint32 aCount) = 0;
};
// A reproducible stream of random data.
class RandomStream : public nsITestDataStream {
public:
RandomStream(PRUint32 aSeed) {
mStartSeed = mState = aSeed;
}
PRUint32 GetStartSeed() {
return mStartSeed;
}
PRUint32 Next() {
mState = 1103515245 * mState + 12345;
return mState;
}
void Read(char* aBuf, PRUint32 aCount) {
PRUint32 i;
for (i = 0; i < aCount; i++) {
*aBuf++ = Next();
}
}
PRBool
Match(char* aBuf, PRUint32 aCount) {
PRUint32 i;
for (i = 0; i < aCount; i++) {
if (*aBuf++ != (char)(Next() & 0xff))
return PR_FALSE;
}
return PR_TRUE;
}
void
Skip(PRUint32 aCount) {
while (aCount--)
Next();
}
protected:
PRUint32 mState;
PRUint32 mStartSeed;
};
// A stream of data that increments on each byte that is read, modulo 256
class CounterStream : public nsITestDataStream {
public:
CounterStream(PRUint32 aSeed) {
mStartSeed = mState = aSeed;
}
PRUint32 GetStartSeed() {
return mStartSeed;
}
PRUint32 Next() {
mState += 1;
mState &= 0xff;
return mState;
}
void Read(char* aBuf, PRUint32 aCount) {
PRUint32 i;
for (i = 0; i < aCount; i++) {
*aBuf++ = Next();
}
}
PRBool
Match(char* aBuf, PRUint32 aCount) {
PRUint32 i;
for (i = 0; i < aCount; i++) {
if (*aBuf++ != (char)Next())
return PR_FALSE;
}
return PR_TRUE;
}
void
Skip(PRUint32 aCount) {
mState += aCount;
mState &= 0xff;
}
protected:
PRUint32 mState;
PRUint32 mStartSeed;
};
static int gNumReaders = 0;
static PRUint32 gTotalBytesRead = 0;
static PRUint32 gTotalDuration = 0;
class nsReader : public nsIStreamListener {
public:
NS_DECL_ISUPPORTS
nsReader()
: mStartTime(0), mBytesRead(0)
{
NS_INIT_REFCNT();
gNumReaders++;
}
virtual ~nsReader() {
delete mTestDataStream;
gNumReaders--;
}
nsresult
Init(nsIChannel *aChannel, nsITestDataStream* aRandomStream, PRUint32 aExpectedStreamLength) {
mChannel = aChannel;
mTestDataStream = aRandomStream;
mExpectedStreamLength = aExpectedStreamLength;
mRefCnt = 1;
return NS_OK;
}
NS_IMETHOD OnStartRequest(nsIChannel* channel,
nsISupports* context) {
mStartTime = PR_IntervalNow();
return NS_OK;
}
NS_IMETHOD OnDataAvailable(nsIChannel* channel,
nsISupports* context,
nsIInputStream *aIStream,
PRUint32 aSourceOffset,
PRUint32 aLength) {
char buf[1025];
while (aLength > 0) {
PRUint32 amt;
PRBool match;
aIStream->Read(buf, sizeof buf, &amt);
if (amt == 0) break;
aLength -= amt;
mBytesRead += amt;
match = mTestDataStream->Match(buf, amt);
NS_ASSERTION(match, "Stored data was corrupted on read");
}
return NS_OK;
}
NS_IMETHOD OnStopRequest(nsIChannel* channel,
nsISupports* context,
nsresult aStatus,
const PRUnichar* aMsg) {
PRIntervalTime endTime;
PRIntervalTime duration;
endTime = PR_IntervalNow();
duration = (endTime - mStartTime);
if (NS_FAILED(aStatus)) printf("channel failed.\n");
// printf("read %d bytes\n", mBytesRead);
NS_ASSERTION(mBytesRead == mExpectedStreamLength,
"Stream in cache is wrong length");
gTotalBytesRead += mBytesRead;
gTotalDuration += duration;
// Release channel
mChannel = 0;
return NS_OK;
}
protected:
PRIntervalTime mStartTime;
PRUint32 mBytesRead;
nsITestDataStream* mTestDataStream;
PRUint32 mExpectedStreamLength;
nsCOMPtr<nsIChannel> mChannel;
};
NS_IMPL_ISUPPORTS2(nsReader, nsIStreamListener, nsIStreamObserver)
static nsIEventQueue* eventQueue;
nsresult
InitQueue() {
nsresult rv;
NS_WITH_SERVICE(nsIEventQueueService, eventQService, kEventQueueServiceCID, &rv);
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't get event queue service");
rv = eventQService->CreateThreadEventQueue();
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't create event queue");
rv = eventQService->GetThreadEventQueue(PR_CurrentThread(), &eventQueue);
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't get event queue for main thread");
return NS_OK;
}
// Process events until all streams are OnStopRequest'ed
nsresult
WaitForEvents() {
while (gNumReaders) {
eventQueue->ProcessPendingEvents();
}
return NS_OK;
}
// Read data for a single cache record and compare against testDataStream
nsresult
TestReadStream(nsINetDataCacheRecord *record, nsITestDataStream *testDataStream,
PRUint32 expectedStreamLength)
{
nsCOMPtr<nsIChannel> channel;
nsresult rv;
PRUint32 actualContentLength;
rv = record->NewChannel(0, getter_AddRefs(channel));
NS_ASSERTION(NS_SUCCEEDED(rv), " ");
rv = record->GetStoredContentLength(&actualContentLength);
NS_ASSERTION(NS_SUCCEEDED(rv), " ");
NS_ASSERTION(actualContentLength == expectedStreamLength,
"nsINetDataCacheRecord::GetContentLength() busted ?");
nsReader *reader = new nsReader;
reader->AddRef();
rv = reader->Init(channel, testDataStream, expectedStreamLength);
NS_ASSERTION(NS_SUCCEEDED(rv), " ");
rv = channel->AsyncRead(0, -1, 0, reader);
NS_ASSERTION(NS_SUCCEEDED(rv), " ");
reader->Release();
return NS_OK;
}
// Check that records can be retrieved using their record-ID, in addition
// to using the opaque key.
nsresult
TestRecordID(nsINetDataCache *cache)
{
nsresult rv;
nsCOMPtr<nsINetDataCacheRecord> record;
RandomStream *randomStream;
PRUint32 metaDataLength;
char cacheKey[CACHE_KEY_LENGTH];
char *metaData;
PRUint32 testNum;
PRBool match;
for (testNum = 0; testNum < NUM_CACHE_ENTRIES; testNum++) {
randomStream = new RandomStream(testNum);
randomStream->Read(cacheKey, sizeof cacheKey);
rv = cache->GetCachedNetDataByID(recordID[testNum], getter_AddRefs(record));
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't obtain record using record ID");
// Match against previously stored meta-data
rv = record->GetMetaData(&metaDataLength, &metaData);
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't get record meta-data");
match = randomStream->Match(metaData, metaDataLength);
NS_ASSERTION(match, "Meta-data corrupted or incorrect");
nsAllocator::Free(metaData);
delete randomStream;
}
return NS_OK;
}
// Check that all cache entries in the database are enumerated and that
// no duplicates appear.
nsresult
TestEnumeration(nsINetDataCache *cache)
{
nsresult rv;
nsCOMPtr<nsINetDataCacheRecord> record;
nsCOMPtr<nsISupports> tempISupports;
nsCOMPtr<nsISimpleEnumerator> iterator;
RandomStream *randomStream;
PRUint32 metaDataLength;
char cacheKey[CACHE_KEY_LENGTH];
char *metaData;
PRUint32 testNum;
PRBool match;
PRInt32 recID;
int numRecords = 0;
// Iterate over all records in the cache
rv = cache->NewCacheEntryIterator(getter_AddRefs(iterator));
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't create new cache entry iterator");
PRBool notDone;
while (1) {
// Done iterating ?
rv = iterator->HasMoreElements(&notDone);
if (NS_FAILED(rv)) return rv;
if (!notDone)
break;
// Get next record in iteration
rv = iterator->GetNext(getter_AddRefs(tempISupports));
NS_ASSERTION(NS_SUCCEEDED(rv), "iterator bustage");
record = do_QueryInterface(tempISupports);
numRecords++;
// Get record ID
rv = record->GetRecordID(&recID);
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't get Record ID");
testNum = mapRecordIdToTestNum(recID);
NS_ASSERTION(testNum != -1, "Corrupted Record ID ?");
// Erase mapping from table, so that duplicate enumerations are detected
recordID[testNum] = -1;
// Make sure stream matches test data
randomStream = new RandomStream(testNum);
randomStream->Read(cacheKey, sizeof cacheKey);
// Match against previously stored meta-data
rv = record->GetMetaData(&metaDataLength, &metaData);
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't get record meta-data");
match = randomStream->Match(metaData, metaDataLength);
NS_ASSERTION(match, "Meta-data corrupted or incorrect");
nsAllocator::Free(metaData);
delete randomStream;
}
NS_ASSERTION(numRecords == NUM_CACHE_ENTRIES, "Iteration bug");
return NS_OK;
}
// Read the test data that was written in FillCache(), checking for
// corruption, truncation.
nsresult
TestRead(nsINetDataCache *cache)
{
nsresult rv;
PRBool inCache;
nsCOMPtr<nsINetDataCacheRecord> record;
RandomStream *randomStream;
PRUint32 metaDataLength;
char cacheKey[CACHE_KEY_LENGTH];
char *metaData, *storedCacheKey;
PRUint32 testNum, storedCacheKeyLength;
PRBool match;
for (testNum = 0; testNum < NUM_CACHE_ENTRIES; testNum++) {
randomStream = new RandomStream(testNum);
randomStream->Read(cacheKey, sizeof cacheKey);
// Ensure that entry is in the cache
rv = cache->Contains(cacheKey, sizeof cacheKey, &inCache);
NS_ASSERTION(NS_SUCCEEDED(rv), " ");
NS_ASSERTION(inCache, "nsINetDataCache::Contains error");
rv = cache->GetCachedNetData(cacheKey, sizeof cacheKey, getter_AddRefs(record));
NS_ASSERTION(NS_SUCCEEDED(rv), " ");
// Match against previously stored meta-data
match = record->GetMetaData(&metaDataLength, &metaData);
NS_ASSERTION(NS_SUCCEEDED(rv), " ");
match = randomStream->Match(metaData, metaDataLength);
NS_ASSERTION(match, "Meta-data corrupted or incorrect");
nsAllocator::Free(metaData);
// Test GetKey() method
rv = record->GetKey(&storedCacheKeyLength, &storedCacheKey);
NS_ASSERTION(NS_SUCCEEDED(rv) &&
(storedCacheKeyLength == sizeof cacheKey) &&
!memcmp(storedCacheKey, &cacheKey[0], sizeof cacheKey),
"nsINetDataCacheRecord::GetKey failed");
nsAllocator::Free(storedCacheKey);
PRUint32 expectedStreamLength = randomStream->Next() & 0xffff;
TestReadStream(record, randomStream, expectedStreamLength);
}
WaitForEvents();
// Compute rate in MB/s
double rate = gTotalBytesRead / PR_IntervalToMilliseconds(gTotalDuration);
rate *= NUM_CACHE_ENTRIES;
rate *= 1000;
rate /= (1024 * 1024);
printf("Read %d bytes at a rate of %5.1f MB per second \n",
gTotalBytesRead, rate);
return NS_OK;
}
// Repeatedly call SetStoredContentLength() on a cache entry and make
// read the stream's data to ensure that it's not corrupted by the effect
nsresult
TestTruncation(nsINetDataCache *cache)
{
nsresult rv;
nsCOMPtr<nsINetDataCacheRecord> record;
RandomStream *randomStream;
char cacheKey[CACHE_KEY_LENGTH];
randomStream = new RandomStream(0);
randomStream->Read(cacheKey, sizeof cacheKey);
rv = cache->GetCachedNetData(cacheKey, sizeof cacheKey, getter_AddRefs(record));
NS_ASSERTION(NS_SUCCEEDED(rv), " ");
randomStream->Skip(CACHE_METADATA_LENGTH);
PRUint32 initialStreamLength = randomStream->Next() & 0xffff;
delete randomStream;
PRUint32 i;
PRUint32 delta = initialStreamLength / 64;
for (i = initialStreamLength; i >= delta; i -= delta) {
PRUint32 expectedStreamLength = i;
// Do the truncation
record->SetStoredContentLength(expectedStreamLength);
randomStream = new RandomStream(0);
randomStream->Skip(CACHE_KEY_LENGTH + CACHE_METADATA_LENGTH + 1);
TestReadStream(record, randomStream, expectedStreamLength);
WaitForEvents();
}
return NS_OK;
}
// Write known data to random offsets in a single cache entry and test
// resulting stream for correctness.
nsresult
TestOffsetWrites(nsINetDataCache *cache)
{
nsresult rv;
nsCOMPtr<nsINetDataCacheRecord> record;
nsCOMPtr<nsIChannel> channel;
nsCOMPtr<nsIOutputStream> outStream;
char buf[512];
char cacheKey[CACHE_KEY_LENGTH];
RandomStream *randomStream;
randomStream = new RandomStream(0);
randomStream->Read(cacheKey, sizeof cacheKey);
rv = cache->GetCachedNetData(cacheKey, sizeof cacheKey, getter_AddRefs(record));
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't access record via opaque cache key");
nsCOMPtr<nsIFileSpec> file ;
record->GetFilename(getter_AddRefs(file)) ;
char* name ;
file->GetUnixStyleFilePath(&name) ;
printf(" file name is %s \n", name) ;
// Write buffer-fulls of data at random offsets into the cache entry.
// Data written is (offset % 0xff)
PRUint32 startingOffset;
PRUint32 streamLength = 0;
PRUint32 len = 0 ;
CounterStream *counterStream;
int i = 0;
for (i = 0; i < 257; i++) {
rv = record->NewChannel(0, getter_AddRefs(channel));
NS_ASSERTION(NS_SUCCEEDED(rv), " ");
startingOffset = streamLength ? streamLength - (randomStream->Next() % sizeof buf): 0;
rv = channel->OpenOutputStream(startingOffset, getter_AddRefs(outStream));
NS_ASSERTION(NS_SUCCEEDED(rv), " ");
truncate(name, startingOffset) ;
counterStream = new CounterStream(startingOffset);
counterStream->Read(buf, sizeof buf);
nsresult status ;
nsCOMPtr<nsIRandomAccessStore> ras = do_QueryInterface(outStream, &status);
if (NS_FAILED(status)) {
// mState = END_WRITE;
return NS_ERROR_FAILURE;
}
PRIntn offset ;
ras->Tell(&offset) ;
// printf(" offset is %d \n", offset) ;
PRUint32 numWritten;
rv = outStream->Write(buf, sizeof buf, &numWritten);
NS_ASSERTION(NS_SUCCEEDED(rv), " ");
NS_ASSERTION(numWritten == sizeof buf, "Write() bug?");
streamLength = startingOffset + sizeof buf;
rv = outStream->Close();
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't close channel");
delete counterStream;
record->GetStoredContentLength(&len) ;
if(len != streamLength)
printf(" offset = %d is wrong, filesize = %d\n", startingOffset, len) ;
}
/*
rv = record->NewChannel(0, getter_AddRefs(channel));
NS_ASSERTION(NS_SUCCEEDED(rv), " ");
startingOffset = 208;
rv = channel->OpenOutputStream(startingOffset, getter_AddRefs(outStream));
NS_ASSERTION(NS_SUCCEEDED(rv), " ");
counterStream = new CounterStream(startingOffset);
counterStream->Read(buf, sizeof buf);
nsresult status ;
nsCOMPtr<nsIRandomAccessStore> ras = do_QueryInterface(outStream, &status);
if (NS_FAILED(status)) {
// mState = END_WRITE;
return NS_ERROR_FAILURE;
}
PRIntn offset = 0 ;
ras->Tell(&offset) ;
printf(" offset is %d \n", offset) ;
PRUint32 numWritten;
rv = outStream->Write(buf, sizeof buf, &numWritten);
NS_ASSERTION(NS_SUCCEEDED(rv), " ");
NS_ASSERTION(numWritten == sizeof buf, "Write() bug?");
streamLength = startingOffset + sizeof buf;
rv = outStream->Close();
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't close channel");
delete counterStream;
record->GetStoredContentLength(&len) ;
if(len != streamLength)
printf(" offset = %d is wrong, filesize = %d\n", startingOffset, len) ;
*/
delete randomStream;
counterStream = new CounterStream(0);
TestReadStream(record, counterStream, streamLength);
WaitForEvents();
return NS_OK;
}
// Create entries in the network data cache, using random data for the
// key, the meta-data and the stored content data.
nsresult
FillCache(nsINetDataCache *cache)
{
nsresult rv;
PRBool inCache;
nsCOMPtr<nsINetDataCacheRecord> record;
nsCOMPtr<nsIChannel> channel;
nsCOMPtr<nsIOutputStream> outStream;
char buf[1000];
PRUint32 metaDataLength;
char cacheKey[CACHE_KEY_LENGTH];
char metaData[CACHE_METADATA_LENGTH];
PRUint32 testNum;
char *data;
RandomStream *randomStream;
PRIntervalTime startTime = PR_IntervalNow();
for (testNum = 0; testNum < NUM_CACHE_ENTRIES; testNum++) {
randomStream = new RandomStream(testNum);
randomStream->Read(cacheKey, sizeof cacheKey);
// No entry should be in cache until we add it
rv = cache->Contains(cacheKey, sizeof cacheKey, &inCache);
NS_ASSERTION(NS_SUCCEEDED(rv), " ");
NS_ASSERTION(!inCache, "nsINetDataCache::Contains error");
rv = cache->GetCachedNetData(cacheKey, sizeof cacheKey, getter_AddRefs(record));
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't access record via opaque cache key");
// Test nsINetDataCacheRecord::GetRecordID()
rv = record->GetRecordID(&recordID[testNum]);
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't get Record ID");
// Test nsINetDataCache::GetNumEntries()
PRUint32 numEntries = (PRUint32)-1;
rv = cache->GetNumEntries(&numEntries);
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't get number of cache entries");
NS_ASSERTION(numEntries == testNum + 1, "GetNumEntries failure");
// Record meta-data should be initially empty
rv = record->GetMetaData(&metaDataLength, &data);
NS_ASSERTION(NS_SUCCEEDED(rv), " ");
if ((metaDataLength != 0) || (data != 0))
return NS_ERROR_FAILURE;
// Store random data as meta-data
randomStream->Read(metaData, sizeof metaData);
record->SetMetaData(sizeof metaData, metaData);
rv = record->NewChannel(0, getter_AddRefs(channel));
NS_ASSERTION(NS_SUCCEEDED(rv), " ");
rv = channel->OpenOutputStream(0, getter_AddRefs(outStream));
NS_ASSERTION(NS_SUCCEEDED(rv), " ");
PRUint32 beforeOccupancy;
rv = cache->GetStorageInUse(&beforeOccupancy);
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't get cache occupancy");
int streamLength = randomStream->Next() & 0xffff;
int remaining = streamLength;
while (remaining) {
PRUint32 numWritten;
int amount = PR_MIN(sizeof buf, remaining);
randomStream->Read(buf, amount);
rv = outStream->Write(buf, amount, &numWritten);
NS_ASSERTION(NS_SUCCEEDED(rv), " ");
NS_ASSERTION(numWritten == (PRUint32)amount, "Write() bug?");
remaining -= amount;
}
outStream->Close();
PRUint32 afterOccupancy;
rv = cache->GetStorageInUse(&afterOccupancy);
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't get cache occupancy");
PRUint32 streamLengthInKB = streamLength >> 10;
NS_ASSERTION((afterOccupancy - beforeOccupancy) >= streamLengthInKB,
"nsINetDataCache::GetStorageInUse() is busted");
// *Now* there should be an entry in the cache
rv = cache->Contains(cacheKey, sizeof cacheKey, &inCache);
NS_ASSERTION(NS_SUCCEEDED(rv), " ");
NS_ASSERTION(inCache, "nsINetDataCache::Contains error");
delete randomStream;
}
PRIntervalTime endTime = PR_IntervalNow();
return NS_OK;
}
nsresult NS_AutoregisterComponents()
{
nsresult rv = nsComponentManager::AutoRegister(nsIComponentManager::NS_Startup,
NULL /* default */);
return rv;
}
PRBool initPref ()
{
nsresult rv;
NS_WITH_SERVICE(nsIPref, prefPtr, kPrefCID, &rv);
if (NS_FAILED(rv))
return false;
nsCOMPtr<nsIFileSpec> fileSpec;
rv = NS_NewFileSpec (getter_AddRefs(fileSpec));
if (NS_FAILED(rv))
return false;
nsCString defaultPrefFile = PR_GetEnv ("MOZILLA_FIVE_HOME");
if (defaultPrefFile.Length())
defaultPrefFile += "/";
else
defaultPrefFile = "./";
defaultPrefFile += "default_prefs.js";
fileSpec->SetUnixStyleFilePath (defaultPrefFile.GetBuffer());
PRBool exists = false;
fileSpec->Exists(&exists);
if (exists)
prefPtr->ReadUserPrefsFrom(fileSpec);
else
return false;
return true;
}
int
main(int argc, char* argv[])
{
initPref() ;
nsresult rv;
nsCOMPtr<nsINetDataCache> cache;
rv = NS_AutoregisterComponents();
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't register XPCOM components");
rv = nsComponentManager::CreateInstance(kDiskCacheCID, nsnull,
NS_GET_IID(nsINetDataCache),
getter_AddRefs(cache));
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't create memory cache factory");
InitQueue();
PRUnichar* description;
rv = cache->GetDescription(&description);
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't get cache description");
nsCAutoString descStr(description);
printf("Testing: %s\n", descStr.GetBuffer());
rv = cache->RemoveAll();
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't clear cache");
PRUint32 startOccupancy;
rv = cache->GetStorageInUse(&startOccupancy);
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't get cache occupancy");
PRUint32 numEntries = (PRUint32)-1;
rv = cache->GetNumEntries(&numEntries);
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't get number of cache entries");
NS_ASSERTION(numEntries == 0, "Couldn't clear cache");
rv = FillCache(cache);
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't fill cache with random test data");
rv = TestRead(cache);
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't read random test data from cache");
rv = TestRecordID(cache);
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't index records using record ID");
rv = TestEnumeration(cache);
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't successfully enumerate records");
rv = TestTruncation(cache);
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't successfully truncate records");
rv = TestOffsetWrites(cache);
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't successfully write to records using non-zero offsets");
rv = cache->RemoveAll();
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't clear cache");
rv = cache->GetNumEntries(&numEntries);
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't get number of cache entries");
NS_ASSERTION(numEntries == 0, "Couldn't clear cache");
PRUint32 endOccupancy;
rv = cache->GetStorageInUse(&endOccupancy);
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't get cache occupancy");
NS_ASSERTION(startOccupancy == endOccupancy, "Cache occupancy not correctly computed ?");
return 0;
}

View File

@@ -1,334 +0,0 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
* 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 client code, released
* March 31, 1998.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998-1999 Netscape Communications Corporation. All
* Rights Reserved.
*
*/
/**
* nsMemCache is the implementation of an in-memory network-data
* cache, used to cache the responses to network retrieval commands.
* Each cache entry may contain both content, e.g. GIF image data, and
* associated metadata, e.g. HTTP headers. Each entry is indexed by
* two different keys: a record id number and an opaque key, which is
* created by the cache manager by combining the URI with a "secondary
* key", e.g. HTTP post data.
*/
#include "nsMemCache.h"
#include "nsMemCacheRecord.h"
#include "nsIGenericFactory.h"
#include "nsString.h"
#include "nsHashtable.h"
#include "nsHashtableEnumerator.h"
#include "nsEnumeratorUtils.h"
PRInt32 nsMemCache::gRecordSerialNumber = 0;
nsMemCache::nsMemCache()
: mNumEntries(0), mOccupancy(0), mEnabled(PR_TRUE),
mHashTable(0)
{
NS_INIT_REFCNT();
}
nsMemCache::~nsMemCache()
{
nsresult rv;
rv = RemoveAll();
NS_ASSERTION(NS_SUCCEEDED(rv) && (mNumEntries == 0),
"Failure to shut down memory cache. "
"Somewhere, someone is holding references to at least one cache record");
delete mHashTable;
}
nsresult
nsMemCache::Init()
{
mHashTable = new nsHashtable(256);
if (!mHashTable)
return NS_ERROR_OUT_OF_MEMORY;
return NS_OK;
}
NS_IMPL_ISUPPORTS(nsMemCache, NS_GET_IID(nsINetDataCache))
NS_IMETHODIMP
nsMemCache::GetDescription(PRUnichar * *aDescription)
{
nsAutoString description("Memory Cache");
*aDescription = description.ToNewUnicode();
if (!*aDescription)
return NS_ERROR_OUT_OF_MEMORY;
return NS_OK;
}
NS_IMETHODIMP
nsMemCache::Contains(const char *aKey, PRUint32 aKeyLength, PRBool *aFound)
{
nsOpaqueKey *opaqueKey = new nsOpaqueKey(aKey, aKeyLength);
if (!opaqueKey)
return NS_ERROR_OUT_OF_MEMORY;
*aFound = mHashTable->Exists(opaqueKey);
delete opaqueKey;
return NS_OK;
}
NS_IMETHODIMP
nsMemCache::GetCachedNetData(const char *aKey, PRUint32 aKeyLength,
nsINetDataCacheRecord* *aRecord)
{
nsresult rv;
nsMemCacheRecord* record = 0;
nsOpaqueKey *opaqueKey2 = 0;
nsOpaqueKey *opaqueKey3 = 0;
nsOpaqueKey *opaqueKey;
opaqueKey = new nsOpaqueKey(aKey, aKeyLength);
if (!opaqueKey)
goto out_of_memory;
record = (nsMemCacheRecord*)mHashTable->Get(opaqueKey);
delete opaqueKey;
// No existing cache database entry was found. Create a new one.
// This requires two mappings in the hash table:
// Record ID ==> record
// Opaque key ==> record
if (!record) {
record = new nsMemCacheRecord;
if (!record)
goto out_of_memory;
rv = record->Init(aKey, aKeyLength, ++gRecordSerialNumber, this);
if (NS_FAILED(rv)) goto out_of_memory;
// Index the record by opaque key
opaqueKey2 = new nsOpaqueKey(record->mKey, record->mKeyLength);
if (!opaqueKey2) goto out_of_memory;
mHashTable->Put(opaqueKey2, record);
// Index the record by it's record ID
char *recordIDbytes = NS_REINTERPRET_CAST(char *, &record->mRecordID);
opaqueKey3 = new nsOpaqueKey(recordIDbytes,
sizeof record->mRecordID);
if (!opaqueKey3) {
// Clean up the first record from the hash table
mHashTable->Remove(opaqueKey);
goto out_of_memory;
}
mHashTable->Put(opaqueKey3, record);
// The hash table holds on to the record
record->AddRef();
delete opaqueKey2;
delete opaqueKey3;
mNumEntries++;
}
record->AddRef();
*aRecord = record;
return NS_OK;
out_of_memory:
delete opaqueKey2;
delete opaqueKey3;
delete record;
return NS_ERROR_OUT_OF_MEMORY;
}
NS_IMETHODIMP
nsMemCache::GetCachedNetDataByID(PRInt32 RecordID,
nsINetDataCacheRecord* *aRecord)
{
nsOpaqueKey opaqueKey(NS_REINTERPRET_CAST(const char *, &RecordID),
sizeof RecordID);
*aRecord = (nsINetDataCacheRecord*)mHashTable->Get(&opaqueKey);
if (*aRecord) {
NS_ADDREF(*aRecord);
return NS_OK;
}
return NS_ERROR_FAILURE;
}
NS_METHOD
nsMemCache::Delete(nsMemCacheRecord* aRecord)
{
nsMemCacheRecord *removedRecord;
char *recordIDbytes = NS_REINTERPRET_CAST(char *, &aRecord->mRecordID);
nsOpaqueKey opaqueRecordIDKey(recordIDbytes,
sizeof aRecord->mRecordID);
removedRecord = (nsMemCacheRecord*)mHashTable->Remove(&opaqueRecordIDKey);
NS_ASSERTION(removedRecord == aRecord, "memory cache database inconsistent");
nsOpaqueKey opaqueKey(aRecord->mKey, aRecord->mKeyLength);
removedRecord = (nsMemCacheRecord*)mHashTable->Remove(&opaqueKey);
NS_ASSERTION(removedRecord == aRecord, "memory cache database inconsistent");
aRecord->Release();
mNumEntries--;
return NS_OK;
}
NS_IMETHODIMP
nsMemCache::GetEnabled(PRBool *aEnabled)
{
NS_ENSURE_ARG(aEnabled);
*aEnabled = mEnabled;
return NS_OK;
}
NS_IMETHODIMP
nsMemCache::SetEnabled(PRBool aEnabled)
{
mEnabled = aEnabled;
return NS_OK;
}
NS_IMETHODIMP
nsMemCache::GetFlags(PRUint32 *aFlags)
{
NS_ENSURE_ARG(aFlags);
*aFlags = MEMORY_CACHE;
return NS_OK;
}
NS_IMETHODIMP
nsMemCache::GetNumEntries(PRUint32 *aNumEntries)
{
NS_ENSURE_ARG(aNumEntries);
*aNumEntries = mNumEntries;
return NS_OK;
}
NS_IMETHODIMP
nsMemCache::GetMaxEntries(PRUint32 *aMaxEntries)
{
NS_ENSURE_ARG(aMaxEntries);
*aMaxEntries = MEM_CACHE_MAX_ENTRIES;
return NS_OK;
}
static NS_METHOD
HashEntryConverter(nsHashKey *aKey, void *aValue,
void *unused, nsISupports **retval)
{
nsMemCacheRecord *record;
nsOpaqueKey *opaqueKey;
record = (nsMemCacheRecord*)aValue;
opaqueKey = (nsOpaqueKey*)aKey;
// Hash table keys that index cache entries by their record ID
// shouldn't be enumerated.
if ((opaqueKey->GetKeyLength() == sizeof(PRInt32))) {
#ifdef DEBUG
PRInt32 recordID;
record->GetRecordID(&recordID);
NS_ASSERTION(*((PRInt32*)opaqueKey->GetKey()) == recordID,
"Key has incorrect key length");
#endif
return NS_ERROR_FAILURE;
}
NS_IF_ADDREF(record);
*retval = NS_STATIC_CAST(nsISupports*, record);
return NS_OK;
}
NS_IMETHODIMP
nsMemCache::NewCacheEntryIterator(nsISimpleEnumerator* *aIterator)
{
nsCOMPtr<nsIEnumerator> iterator;
NS_ENSURE_ARG(aIterator);
NS_NewHashtableEnumerator(mHashTable, HashEntryConverter,
mHashTable, getter_AddRefs(iterator));
return NS_NewAdapterEnumerator(aIterator, iterator);
}
NS_IMETHODIMP
nsMemCache::GetNextCache(nsINetDataCache* *aNextCache)
{
NS_ENSURE_ARG(aNextCache);
*aNextCache = mNextCache;
NS_ADDREF(*aNextCache);
return NS_OK;
}
NS_IMETHODIMP
nsMemCache::SetNextCache(nsINetDataCache* aNextCache)
{
mNextCache = aNextCache;
return NS_OK;
}
NS_IMETHODIMP
nsMemCache::GetStorageInUse(PRUint32 *aStorageInUse)
{
NS_ENSURE_ARG(aStorageInUse);
// Convert from bytes to KB
*aStorageInUse = (mOccupancy >> 10);
return NS_OK;
}
NS_IMETHODIMP
nsMemCache::RemoveAll(void)
{
PRBool failed;
nsCOMPtr<nsISimpleEnumerator> iterator;
nsCOMPtr<nsISupports> recordSupports;
nsCOMPtr<nsINetDataCacheRecord> record;
nsresult rv;
failed = PR_FALSE;
rv = NewCacheEntryIterator(getter_AddRefs(iterator));
if (NS_FAILED(rv))
return rv;
PRBool notDone;
while (1) {
rv = iterator->HasMoreElements(&notDone);
if (NS_FAILED(rv)) return rv;
if (!notDone)
break;
iterator->GetNext(getter_AddRefs(recordSupports));
record = do_QueryInterface(recordSupports);
recordSupports = 0;
PRUint32 bytesUsed;
record->GetStoredContentLength(&bytesUsed);
rv = record->Delete();
if (NS_FAILED(rv)) {
failed = PR_TRUE;
continue;
}
mOccupancy -= bytesUsed;
}
if (failed)
return NS_ERROR_FAILURE;
return NS_OK;
}

View File

@@ -1,83 +0,0 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
* 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 client code, released
* March 31, 1998.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998-1999 Netscape Communications Corporation. All
* Rights Reserved.
*
*/
/**
* nsMemCache is the implementation of an in-memory network-data
* cache, used to cache the responses to network retrieval commands.
* Each cache entry may contain both content, e.g. GIF image data, and
* associated metadata, e.g. HTTP headers. Each entry is indexed by
* two different keys: a record id number and an opaque key, which is
* created by the cache manager by combining the URI with a "secondary
* key", e.g. HTTP post data.
*/
#ifndef _nsMemCache_h_
#define _nsMemCache_h_
#include "nsINetDataCache.h"
// Maximum number of URIs that may be resident in the cache
#define MEM_CACHE_MAX_ENTRIES 1000
#define MEM_CACHE_SEGMENT_SIZE (1 << 12)
#define MEM_CACHE_MAX_ENTRY_SIZE (1 << 20)
class nsHashtable;
class nsMemCacheRecord;
class nsMemCache : public nsINetDataCache
{
public:
nsMemCache();
virtual ~nsMemCache();
nsresult Init();
// nsISupports methods
NS_DECL_ISUPPORTS
// nsINetDataCache methods
NS_DECL_NSINETDATACACHE
// Factory
static NS_METHOD nsMemCacheConstructor(nsISupports *aOuter, REFNSIID aIID,
void **aResult);
protected:
PRUint32 mNumEntries;
PRUint32 mOccupancy; // Memory used, in bytes
PRBool mEnabled; // If false, bypass mem cache
nsINetDataCache* mNextCache;
// Mapping from either opaque key or record ID to nsMemCacheRecord
nsHashtable* mHashTable;
// Used to assign record ID's
static PRInt32 gRecordSerialNumber;
NS_METHOD Delete(nsMemCacheRecord* aRecord);
friend class nsMemCacheRecord;
friend class nsMemCacheChannel;
};
#endif // _nsMemCache_h_

View File

@@ -1,36 +0,0 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
* 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 client code, released
* March 31, 1998.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998-1999 Netscape Communications Corporation. All
* Rights Reserved.
*
*/
// XPCOM Class ID for the network data in-memory cache
#ifndef nsMEMCACHECID_h__
#define nsMEMCACHECID_h__
// {e4710560-7de2-11d3-90cb-0040056a906e}
#define NS_MEM_CACHE_FACTORY_CID \
{ \
0xe4710560, \
0x7de2, \
0x11d3, \
{0x90, 0xcb, 0x00, 0x40, 0x05, 0x6a, 0x90, 0x6e} \
}
#endif // nsMEMCACHECID_h__

View File

@@ -1,464 +0,0 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
* 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 client code, released
* March 31, 1998.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998-1999 Netscape Communications Corporation. All
* Rights Reserved.
*
*/
#include "nsMemCache.h"
#include "nsMemCacheChannel.h"
#include "nsIStreamListener.h"
#include "nsIChannel.h"
#include "nsIStorageStream.h"
#include "nsIOutputStream.h"
#include "nsIServiceManager.h"
#include "nsIEventQueueService.h"
#include "nsNetUtil.h"
#include "nsILoadGroup.h"
static NS_DEFINE_CID(kIOServiceCID, NS_IOSERVICE_CID);
static NS_DEFINE_CID(kEventQueueService, NS_EVENTQUEUESERVICE_CID);
NS_IMPL_ISUPPORTS(nsMemCacheChannel, NS_GET_IID(nsIChannel))
void
nsMemCacheChannel::NotifyStorageInUse(PRInt32 aBytesUsed)
{
mRecord->mCache->mOccupancy += aBytesUsed;
}
/**
* This class acts as an adaptor around a synchronous input stream to add async
* read capabilities. It adds methods for initiating, suspending, resuming and
* cancelling async reads.
*/
class AsyncReadStreamAdaptor : public nsIInputStream {
public:
AsyncReadStreamAdaptor(nsMemCacheChannel* aChannel, nsIInputStream *aSyncStream):
mSyncStream(aSyncStream), mDataAvailCursor(0),
mRemaining(0), mChannel(aChannel), mAvailable(0), mAborted(false), mSuspended(false)
{
NS_INIT_REFCNT();
NS_ADDREF(mChannel);
}
virtual ~AsyncReadStreamAdaptor() {
mChannel->mAsyncReadStream = 0;
NS_RELEASE(mChannel);
}
NS_DECL_ISUPPORTS
nsresult
IsPending(PRBool* aIsPending) {
*aIsPending = (mRemaining != 0) && !mAborted;
return NS_OK;
}
nsresult
Cancel(void) {
mAborted = true;
return mStreamListener->OnStopRequest(mChannel, mContext, NS_BINDING_ABORTED, nsnull);
}
nsresult
Suspend(void) { mSuspended = true; return NS_OK; }
nsresult
Resume(void) {
if (!mSuspended)
return NS_ERROR_FAILURE;
mSuspended = false;
return NextListenerEvent();
}
NS_IMETHOD
Available(PRUint32 *aNumBytes) { return mAvailable; }
NS_IMETHOD
Read(char* aBuf, PRUint32 aCount, PRUint32 *aBytesRead) {
if (mAborted)
return NS_ERROR_ABORT;
*aBytesRead = 0;
aCount = PR_MIN(aCount, mAvailable);
nsresult rv = mSyncStream->Read(aBuf, aCount, aBytesRead);
mAvailable -= *aBytesRead;
if (NS_FAILED(rv) && (rv != NS_BASE_STREAM_WOULD_BLOCK)) {
Fail();
return rv;
}
if (!mSuspended && !mAvailable) {
rv = NextListenerEvent();
if (NS_FAILED(rv)) {
Fail();
return rv;
}
}
return NS_OK;
}
NS_IMETHOD
Close() {
nsresult rv = mSyncStream->Close();
mSyncStream = 0;
mContext = 0;
mStreamListener = 0;
return rv;
}
nsresult
AsyncRead(PRUint32 aStartPosition, PRInt32 aReadCount,
nsISupports* aContext, nsIStreamListener* aListener) {
nsresult rv;
nsIEventQueue *eventQ;
mContext = aContext;
mStreamListener = aListener;
mRemaining = aReadCount;
NS_WITH_SERVICE(nsIIOService, serv, kIOServiceCID, &rv);
if (NS_FAILED(rv)) return rv;
NS_WITH_SERVICE(nsIEventQueueService, eventQService, kEventQueueService, &rv);
if (NS_FAILED(rv)) return rv;
rv = eventQService->GetThreadEventQueue(PR_CurrentThread(), &eventQ);
if (NS_FAILED(rv)) return rv;
rv = NS_NewAsyncStreamListener(aListener, eventQ,
getter_AddRefs(mStreamListener));
NS_RELEASE(eventQ);
if (NS_FAILED(rv)) return rv;
rv = mStreamListener->OnStartRequest(mChannel, aContext);
if (NS_FAILED(rv)) return rv;
return NextListenerEvent();
}
protected:
nsresult
Fail(void) {
mAborted = true;
return mStreamListener->OnStopRequest(mChannel, mContext, NS_BINDING_FAILED, nsnull);
}
nsresult
NextListenerEvent() {
PRUint32 available;
nsresult rv = mSyncStream->Available(&available);
if (NS_FAILED(rv)) return rv;
available -= mAvailable;
available = PR_MIN(available, mRemaining);
if (available) {
PRUint32 size = PR_MIN(available, MEM_CACHE_SEGMENT_SIZE);
rv = mStreamListener->OnDataAvailable(mChannel, mContext, this,
mDataAvailCursor, size);
mDataAvailCursor += size;
mRemaining -= size;
mAvailable += size;
return rv;
} else {
rv = mStreamListener->OnStopRequest(mChannel, mContext, NS_OK, nsnull);
AsyncReadStreamAdaptor* thisAlias = this;
NS_RELEASE(thisAlias);
return rv;
}
}
private:
nsCOMPtr<nsISupports> mContext; // Opaque context passed to AsyncRead()
nsCOMPtr<nsIStreamListener> mStreamListener; // Stream listener that has been proxied
nsCOMPtr<nsIInputStream> mSyncStream; // Underlying synchronous stream that is
// being converted to an async stream
PRUint32 mDataAvailCursor;
PRUint32 mRemaining; // Size of AsyncRead request less bytes for
// consumer OnDataAvailable's that were fired
PRUint32 mAvailable; // Number of bytes for which OnDataAvailable fired
nsMemCacheChannel* mChannel; // Associated memory cache channel, strong link
// but can not use nsCOMPtr
bool mAborted; // Abort() has been called
bool mSuspended; // Suspend() has been called
};
NS_IMPL_ISUPPORTS(AsyncReadStreamAdaptor, NS_GET_IID(nsIInputStream))
// The only purpose of this output stream wrapper is to adjust the cache's
// overall occupancy as new data flows into the cache entry.
class MemCacheWriteStreamWrapper : public nsIOutputStream {
public:
MemCacheWriteStreamWrapper(nsMemCacheChannel* aChannel, nsIOutputStream *aBaseStream):
mBaseStream(aBaseStream), mChannel(aChannel)
{
NS_INIT_REFCNT();
NS_ADDREF(mChannel);
}
virtual ~MemCacheWriteStreamWrapper() { NS_RELEASE(mChannel); };
static nsresult
Create(nsMemCacheChannel* aChannel, nsIOutputStream *aBaseStream, nsIOutputStream* *aWrapper) {
MemCacheWriteStreamWrapper *wrapper =
new MemCacheWriteStreamWrapper(aChannel, aBaseStream);
if (!wrapper) return NS_ERROR_OUT_OF_MEMORY;
NS_ADDREF(wrapper);
*aWrapper = wrapper;
return NS_OK;
}
NS_DECL_ISUPPORTS
NS_IMETHOD
Write(const char *aBuffer, PRUint32 aCount, PRUint32 *aNumWritten) {
*aNumWritten = 0;
nsresult rv = mBaseStream->Write(aBuffer, aCount, aNumWritten);
mChannel->NotifyStorageInUse(*aNumWritten);
return rv;
}
NS_IMETHOD
Flush() { return mBaseStream->Flush(); }
NS_IMETHOD
Close() { return mBaseStream->Close(); }
private:
nsCOMPtr<nsIOutputStream> mBaseStream;
nsMemCacheChannel* mChannel;
};
NS_IMPL_ISUPPORTS(MemCacheWriteStreamWrapper, NS_GET_IID(nsIOutputStream))
nsMemCacheChannel::nsMemCacheChannel(nsMemCacheRecord *aRecord, nsILoadGroup *aLoadGroup)
: mRecord(aRecord)
{
NS_INIT_REFCNT();
mRecord->mNumChannels++;
}
nsMemCacheChannel::~nsMemCacheChannel()
{
mRecord->mNumChannels--;
}
NS_IMETHODIMP
nsMemCacheChannel::IsPending(PRBool* aIsPending)
{
*aIsPending = PR_FALSE;
if (!mAsyncReadStream)
return NS_OK;
return mAsyncReadStream->IsPending(aIsPending);
}
NS_IMETHODIMP
nsMemCacheChannel::Cancel(void)
{
if (!mAsyncReadStream)
return NS_ERROR_FAILURE;
return mAsyncReadStream->Cancel();
}
NS_IMETHODIMP
nsMemCacheChannel::Suspend(void)
{
if (!mAsyncReadStream)
return NS_ERROR_FAILURE;
return mAsyncReadStream->Suspend();
}
NS_IMETHODIMP
nsMemCacheChannel::Resume(void)
{
if (!mAsyncReadStream)
return NS_ERROR_FAILURE;
return mAsyncReadStream->Resume();
}
NS_IMETHODIMP
nsMemCacheChannel::GetOriginalURI(nsIURI * *aURI)
{
// Not required
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
nsMemCacheChannel::GetURI(nsIURI * *aURI)
{
// Not required to be implemented, since it is implemented by cache manager
NS_ASSERTION(0, "nsMemCacheChannel method unexpectedly called");
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
nsMemCacheChannel::OpenInputStream(PRUint32 aStartPosition, PRInt32 aReadCount,
nsIInputStream* *aResult)
{
nsresult rv;
NS_ENSURE_ARG(aResult);
if (mInputStream)
return NS_ERROR_NOT_AVAILABLE;
rv = mRecord->mStorageStream->NewInputStream(aStartPosition, getter_AddRefs(mInputStream));
*aResult = mInputStream;
NS_ADDREF(*aResult);
return rv;
}
NS_IMETHODIMP
nsMemCacheChannel::OpenOutputStream(PRUint32 startPosition, nsIOutputStream* *aResult)
{
nsresult rv;
NS_ENSURE_ARG(aResult);
nsCOMPtr<nsIOutputStream> outputStream;
PRUint32 oldLength;
mRecord->mStorageStream->GetLength(&oldLength);
rv = mRecord->mStorageStream->GetOutputStream(startPosition, getter_AddRefs(outputStream));
if (NS_FAILED(rv)) return rv;
if (startPosition < oldLength)
NotifyStorageInUse(startPosition - oldLength);
return MemCacheWriteStreamWrapper::Create(this, outputStream, aResult);
}
NS_IMETHODIMP
nsMemCacheChannel::AsyncOpen(nsIStreamObserver *observer, nsISupports *ctxt)
{
// Not required
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
nsMemCacheChannel::AsyncRead(PRUint32 aStartPosition, PRInt32 aReadCount,
nsISupports *aContext, nsIStreamListener *aListener)
{
nsCOMPtr<nsIInputStream> inputStream;
nsresult rv = OpenInputStream(aStartPosition, aReadCount, getter_AddRefs(inputStream));
if (NS_FAILED(rv)) return rv;
AsyncReadStreamAdaptor *asyncReadStreamAdaptor;
asyncReadStreamAdaptor = new AsyncReadStreamAdaptor(this, inputStream);
if (!asyncReadStreamAdaptor)
return NS_ERROR_OUT_OF_MEMORY;
NS_ADDREF(asyncReadStreamAdaptor);
mAsyncReadStream = asyncReadStreamAdaptor;
rv = asyncReadStreamAdaptor->AsyncRead(aStartPosition, aReadCount, aContext, aListener);
if (NS_FAILED(rv))
delete asyncReadStreamAdaptor;
return rv;
}
NS_IMETHODIMP
nsMemCacheChannel::AsyncWrite(nsIInputStream *fromStream, PRUint32 startPosition,
PRInt32 writeCount, nsISupports *ctxt,
nsIStreamObserver *observer)
{
// Not required to be implemented
NS_ASSERTION(0, "nsMemCacheChannel method unexpectedly called");
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
nsMemCacheChannel::GetLoadAttributes(nsLoadFlags *aLoadAttributes)
{
// Not required to be implemented, since it is implemented by cache manager
NS_ASSERTION(0, "nsMemCacheChannel method unexpectedly called");
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
nsMemCacheChannel::SetLoadAttributes(nsLoadFlags aLoadAttributes)
{
// Not required to be implemented, since it is implemented by cache manager
NS_ASSERTION(0, "nsMemCacheChannel method unexpectedly called");
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
nsMemCacheChannel::GetContentType(char* *aContentType)
{
// Not required to be implemented, since it is implemented by cache manager
// NS_ASSERTION(0, "nsMemCacheChannel method unexpectedly called");
// FIXME - lying for the purpose of testing
*aContentType = strdup("text/html");
return NS_OK;
}
NS_IMETHODIMP
nsMemCacheChannel::GetContentLength(PRInt32 *aContentLength)
{
// Not required to be implemented, since it is implemented by cache manager
NS_ASSERTION(0, "nsMemCacheChannel method unexpectedly called");
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
nsMemCacheChannel::GetOwner(nsISupports* *aOwner)
{
*aOwner = mOwner.get();
NS_IF_ADDREF(*aOwner);
return NS_OK;
}
NS_IMETHODIMP
nsMemCacheChannel::SetOwner(nsISupports* aOwner)
{
// Not required to be implemented, since it is implemented by cache manager
mOwner = aOwner;
return NS_OK;
}
NS_IMETHODIMP
nsMemCacheChannel::GetLoadGroup(nsILoadGroup* *aLoadGroup)
{
// Not required to be implemented, since it is implemented by cache manager
NS_ASSERTION(0, "nsMemCacheChannel method unexpectedly called");
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
nsMemCacheChannel::SetLoadGroup(nsILoadGroup* aLoadGroup)
{
// Not required to be implemented, since it is implemented by cache manager
NS_ASSERTION(0, "nsMemCacheChannel method unexpectedly called");
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
nsMemCacheChannel::GetNotificationCallbacks(nsIInterfaceRequestor* *aNotificationCallbacks)
{
// Not required to be implemented, since it is implemented by cache manager
NS_ASSERTION(0, "nsMemCacheChannel method unexpectedly called");
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
nsMemCacheChannel::SetNotificationCallbacks(nsIInterfaceRequestor* aNotificationCallbacks)
{
// Not required to be implemented, since it is implemented by cache manager
NS_ASSERTION(0, "nsMemCacheChannel method unexpectedly called");
return NS_ERROR_NOT_IMPLEMENTED;
}

View File

@@ -1,61 +0,0 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
* 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 client code, released
* March 31, 1998.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998-1999 Netscape Communications Corporation. All
* Rights Reserved.
*
*/
#ifndef _nsMemCacheChannel_h_
#define _nsMemCacheChannel_h_
#include "nsMemCacheRecord.h"
#include "nsIChannel.h"
#include "nsIInputStream.h"
#include "nsCOMPtr.h"
class AsyncReadStreamAdaptor;
class nsMemCacheChannel : public nsIChannel
{
public:
// Constructors and Destructor
nsMemCacheChannel(nsMemCacheRecord *aRecord, nsILoadGroup *aLoadGroup);
virtual ~nsMemCacheChannel();
// Declare nsISupports methods
NS_DECL_ISUPPORTS
// Declare nsIRequest methods
NS_DECL_NSIREQUEST
// Declare nsIChannel methods
NS_DECL_NSICHANNEL
protected:
void NotifyStorageInUse(PRInt32 aBytesUsed);
nsCOMPtr<nsMemCacheRecord> mRecord;
nsCOMPtr<nsIInputStream> mInputStream;
nsCOMPtr<nsISupports> mOwner;
AsyncReadStreamAdaptor* mAsyncReadStream; // non-owning pointer
friend class MemCacheWriteStreamWrapper;
friend class AsyncReadStreamAdaptor;
};
#endif // _nsMemCacheChannel_h_

View File

@@ -1,164 +0,0 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
* 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 client code, released
* March 31, 1998.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998-1999 Netscape Communications Corporation. All
* Rights Reserved.
*
*/
#include "nsMemCache.h"
#include "nsMemCacheRecord.h"
#include "nsMemCacheChannel.h"
#include "nsIAllocator.h"
#include "nsStorageStream.h"
static NS_DEFINE_IID(kINetDataCacheRecord, NS_INETDATACACHERECORD_IID);
nsMemCacheRecord::nsMemCacheRecord()
: mKey(0), mKeyLength(0), mMetaData(0), mMetaDataLength(0), mNumChannels(0)
{
NS_INIT_REFCNT();
}
nsMemCacheRecord::~nsMemCacheRecord()
{
if (mMetaData)
delete[] mMetaData;
if (mKey)
delete[] mKey;
}
NS_IMPL_ISUPPORTS(nsMemCacheRecord, NS_GET_IID(nsINetDataCacheRecord))
NS_IMETHODIMP
nsMemCacheRecord::GetKey(PRUint32 *aLength, char **aResult)
{
NS_ENSURE_ARG(aResult);
*aResult = (char *)nsAllocator::Alloc(mKeyLength);
if (!*aResult)
return NS_ERROR_OUT_OF_MEMORY;
memcpy(*aResult, mKey, mKeyLength);
*aLength = mKeyLength;
return NS_OK;
}
nsresult
nsMemCacheRecord::Init(const char *aKey, PRUint32 aKeyLength,
PRUint32 aRecordID, nsMemCache *aCache)
{
nsresult rv;
NS_ASSERTION(!mKey, "Memory cache record key set multiple times");
rv = NS_NewStorageStream(MEM_CACHE_SEGMENT_SIZE, MEM_CACHE_MAX_ENTRY_SIZE,
getter_AddRefs(mStorageStream));
if (NS_FAILED(rv)) return rv;
mKey = new char[aKeyLength];
if (!mKey)
return NS_ERROR_OUT_OF_MEMORY;
memcpy(mKey, aKey, aKeyLength);
mKeyLength = aKeyLength;
mRecordID = aRecordID;
mCache = aCache;
return NS_OK;
}
NS_IMETHODIMP
nsMemCacheRecord::GetRecordID(PRInt32 *aRecordID)
{
NS_ENSURE_ARG(aRecordID);
*aRecordID = mRecordID;
return NS_OK;
}
NS_IMETHODIMP
nsMemCacheRecord::GetMetaData(PRUint32 *aLength, char **aResult)
{
NS_ENSURE_ARG(aResult);
*aResult = 0;
if (mMetaDataLength) {
*aResult = (char*)nsAllocator::Alloc(mMetaDataLength);
if (!*aResult)
return NS_ERROR_OUT_OF_MEMORY;
memcpy(*aResult, mMetaData, mMetaDataLength);
}
*aLength = mMetaDataLength;
return NS_OK;
}
NS_IMETHODIMP
nsMemCacheRecord::SetMetaData(PRUint32 aLength, const char *aData)
{
if (mMetaData)
delete[] mMetaData;
mMetaData = new char[aLength];
if (!mMetaData)
return NS_ERROR_OUT_OF_MEMORY;
memcpy(mMetaData, aData, aLength);
mMetaDataLength = aLength;
return NS_OK;
}
NS_IMETHODIMP
nsMemCacheRecord::GetStoredContentLength(PRUint32 *aStoredContentLength)
{
NS_ENSURE_ARG(aStoredContentLength);
return mStorageStream->GetLength(aStoredContentLength);
}
NS_IMETHODIMP
nsMemCacheRecord::SetStoredContentLength(PRUint32 aStoredContentLength)
{
PRUint32 before, after;
mStorageStream->GetLength(&before);
nsresult rv = mStorageStream->SetLength(aStoredContentLength);
if (NS_FAILED(rv)) return rv;
mStorageStream->GetLength(&after);
mCache->mOccupancy -= (before - after);
return NS_OK;
}
NS_IMETHODIMP
nsMemCacheRecord::Delete(void)
{
if (mNumChannels)
return NS_ERROR_NOT_AVAILABLE;
return mCache->Delete(this);
}
NS_IMETHODIMP
nsMemCacheRecord::GetFilename(nsIFileSpec* *aFilename)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
nsMemCacheRecord::NewChannel(nsILoadGroup *aLoadGroup, nsIChannel* *aResult)
{
NS_ENSURE_ARG(aResult);
nsMemCacheChannel* channel = new nsMemCacheChannel(this, aLoadGroup);
if (!channel)
return NS_ERROR_OUT_OF_MEMORY;
NS_ADDREF(channel);
*aResult = NS_STATIC_CAST(nsIChannel*, channel);
return NS_OK;
}

View File

@@ -1,65 +0,0 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
* 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 client code, released
* March 31, 1998.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998-1999 Netscape Communications Corporation. All
* Rights Reserved.
*
*/
#ifndef _nsMemCacheRecord_h_
#define _nsMemCacheRecord_h_
#include "nsINetDataCacheRecord.h"
#include "nsCOMPtr.h"
class nsMemCache;
class nsIStorageStream;
class nsMemCacheRecord : public nsINetDataCacheRecord
{
public:
// Declare interface methods
NS_DECL_ISUPPORTS
NS_DECL_NSINETDATACACHERECORD
protected:
// Constructors and Destructor
nsMemCacheRecord();
virtual ~nsMemCacheRecord();
nsresult Init(const char *aKey, PRUint32 aKeyLength,
PRUint32 aRecordID, nsMemCache *aCache);
char* mKey; // opaque database key for this record
PRUint32 mKeyLength; // length, in bytes, of mKey
PRInt32 mRecordID; // An alternate key for this record
char* mMetaData; // opaque URI metadata
PRUint32 mMetaDataLength; // length, in bytes, of mMetaData
nsMemCache* mCache; // weak pointer to the cache database
// that this record inhabits
nsCOMPtr<nsIStorageStream> mStorageStream;
PRUint32 mNumChannels; // Count un-Release'ed nsIChannels
friend class nsMemCache;
friend class nsMemCacheChannel;
};
#endif // _nsMemCacheRecord_h_

View File

@@ -1,51 +0,0 @@
#
# 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.org code.
#
# The Initial Developer of the Original Code is Netscape
# Communications Corporation. Portions created by Netscape are
# Copyright (C) 1998 Netscape Communications Corporation. All
# Rights Reserved.
#
# Contributor(s):
#
DEPTH = ../../..
topsrcdir = @top_srcdir@
srcdir = @srcdir@
VPATH = @srcdir@
include $(DEPTH)/config/autoconf.mk
MODULE = nkcache
LIBRARY_NAME = nkcachemgr_s
REQUIRES = nspr
CPPSRCS = \
nsCacheManager.cpp \
nsCachedNetData.cpp \
nsReplacementPolicy.cpp \
nsCacheEntryChannel.cpp \
$(NULL)
LOCAL_INCLUDES = -I$(srcdir)/../public -I$(srcdir)/../include
EXTRA_LIBS = $(NSPR_LIBS)
# we don't want the shared lib, but we want to force the creation of a
# static lib.
override NO_SHARED_LIB=1
override NO_STATIC_LIB=
include $(topsrcdir)/config/rules.mk

View File

@@ -1,45 +0,0 @@
#!gmake
#
# 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.org code.
#
# The Initial Developer of the Original Code is Netscape
# Communications Corporation. Portions created by Netscape are
# Copyright (C) 1998 Netscape Communications Corporation. All
# Rights Reserved.
#
# Contributor(s):
DEPTH=..\..\..
include <$(DEPTH)/config/config.mak>
MODULE = nkcache
LIBRARY_NAME = nkcachemgr_s
CPP_OBJS = \
.\$(OBJDIR)\nsCacheManager.obj \
.\$(OBJDIR)\nsCachedNetData.obj \
.\$(OBJDIR)\nsReplacementPolicy.obj \
.\$(OBJDIR)\nsCacheEntryChannel.obj \
$(NULL)
include <$(DEPTH)\config\rules.mak>
install:: $(LIBRARY)
$(MAKE_INSTALL) $(LIBRARY) $(DIST)\lib
clobber::
rm -rf $(OBJDIR)
rm -f $(DIST)\lib\$(LIBRARY_NAME).lib

View File

@@ -1,260 +0,0 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* 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 client code, released
* March 31, 1998.
*
* 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.
*
* Contributor(s):
* Scott Furman, fur@netscape.com
*/
#include "nsCacheManager.h"
#include "nsCacheEntryChannel.h"
#include "nsIOutputStream.h"
#include "nsIIOService.h"
#include "nsIServiceManager.h"
#include "nsIStreamListener.h"
nsCacheEntryChannel::nsCacheEntryChannel(nsCachedNetData* aCacheEntry, nsIChannel* aChannel,
nsILoadGroup* aLoadGroup):
nsChannelProxy(aChannel), mCacheEntry(aCacheEntry), mLoadGroup(aLoadGroup), mLoadAttributes(0)
{
NS_ASSERTION(aCacheEntry->mChannelCount < 0xFF, "Overflowed channel counter");
mCacheEntry->mChannelCount++;
NS_INIT_REFCNT();
}
nsCacheEntryChannel::~nsCacheEntryChannel()
{
mCacheEntry->mChannelCount--;
}
NS_IMPL_ISUPPORTS3(nsCacheEntryChannel, nsISupports, nsIChannel, nsIRequest)
// A proxy for nsIOutputStream
class CacheOutputStream : public nsIOutputStream {
public:
CacheOutputStream(nsIOutputStream *aOutputStream, nsCachedNetData *aCacheEntry):
mOutputStream(aOutputStream), mCacheEntry(aCacheEntry), mStartTime(PR_Now())
{ NS_INIT_REFCNT(); }
virtual ~CacheOutputStream() {}
NS_DECL_ISUPPORTS
NS_IMETHOD Close() {
mCacheEntry->NoteDownloadTime(mStartTime, PR_Now());
mCacheEntry->ClearFlag(nsCachedNetData::UPDATE_IN_PROGRESS);
return mOutputStream->Close();
}
NS_IMETHOD Flush() { return mOutputStream->Flush(); }
NS_IMETHOD
Write(const char *aBuf, PRUint32 aCount, PRUint32 *aActualBytes) {
nsresult rv;
*aActualBytes = 0;
rv = mOutputStream->Write(aBuf, aCount, aActualBytes);
mCacheEntry->mLogicalLength += *aActualBytes;
if (NS_FAILED(rv)) return rv;
nsCacheManager::LimitCacheSize();
return rv;
}
protected:
nsCOMPtr<nsIOutputStream> mOutputStream;
nsCOMPtr<nsCachedNetData> mCacheEntry;
// Time at which stream was opened
PRTime mStartTime;
};
NS_IMPL_ISUPPORTS(CacheOutputStream, NS_GET_IID(nsIOutputStream))
NS_IMETHODIMP
nsCacheEntryChannel::OpenOutputStream(PRUint32 aStartPosition, nsIOutputStream* *aOutputStream)
{
nsresult rv;
nsCOMPtr<nsIOutputStream> baseOutputStream;
rv = mChannel->OpenOutputStream(aStartPosition, getter_AddRefs(baseOutputStream));
if (NS_FAILED(rv)) return rv;
mCacheEntry->NoteUpdate();
mCacheEntry->NoteAccess();
mCacheEntry->mLogicalLength = aStartPosition;
*aOutputStream = new CacheOutputStream(baseOutputStream, mCacheEntry);
if (!*aOutputStream)
return NS_ERROR_OUT_OF_MEMORY;
NS_ADDREF(*aOutputStream);
return NS_OK;
}
NS_IMETHODIMP
nsCacheEntryChannel::OpenInputStream(PRUint32 aStartPosition, PRInt32 aReadCount,
nsIInputStream* *aInputStream)
{
mCacheEntry->NoteAccess();
return mChannel->OpenInputStream(aStartPosition, aReadCount, aInputStream);
}
class CacheManagerStreamListener: public nsIStreamListener {
public:
CacheManagerStreamListener(nsIStreamListener *aListener,
nsILoadGroup *aLoadGroup, nsIChannel *aChannel):
mListener(aListener), mLoadGroup(aLoadGroup), mChannel(aChannel)
{ NS_INIT_REFCNT(); }
virtual ~CacheManagerStreamListener() {}
private:
NS_DECL_ISUPPORTS
NS_IMETHOD
OnDataAvailable(nsIChannel *channel, nsISupports *aContext,
nsIInputStream *inStr, PRUint32 sourceOffset, PRUint32 count) {
return mListener->OnDataAvailable(mChannel, aContext, inStr, sourceOffset, count);
}
NS_IMETHOD
OnStartRequest(nsIChannel *channel, nsISupports *aContext) {
if (mLoadGroup)
mLoadGroup->AddChannel(mChannel, aContext);
return mListener->OnStartRequest(mChannel, aContext);
}
NS_IMETHOD
OnStopRequest(nsIChannel *channel, nsISupports *aContext,
nsresult status, const PRUnichar *errorMsg) {
nsresult rv;
rv = mListener->OnStopRequest(mChannel, aContext, status, errorMsg);
if (mLoadGroup)
mLoadGroup->RemoveChannel(mChannel, aContext, status, errorMsg);
return rv;
}
private:
nsCOMPtr<nsIStreamListener> mListener;
nsCOMPtr<nsILoadGroup> mLoadGroup;
nsCOMPtr<nsIChannel> mChannel;
};
NS_IMPL_ISUPPORTS2(CacheManagerStreamListener, nsIStreamListener, nsIStreamObserver)
NS_IMETHODIMP
nsCacheEntryChannel::AsyncRead(PRUint32 aStartPosition, PRInt32 aReadCount,
nsISupports *aContext, nsIStreamListener *aListener)
{
nsresult rv;
mCacheEntry->NoteAccess();
nsCOMPtr<nsIStreamListener> headListener;
if (mLoadGroup) {
mLoadGroup->GetDefaultLoadAttributes(&mLoadAttributes);
// Create a load group "proxy" listener...
nsCOMPtr<nsILoadGroupListenerFactory> factory;
rv = mLoadGroup->GetGroupListenerFactory(getter_AddRefs(factory));
if (NS_SUCCEEDED(rv) && factory) {
rv = factory->CreateLoadGroupListener(aListener,
getter_AddRefs(headListener));
if (NS_FAILED(rv)) return rv;
}
} else {
headListener = aListener;
}
CacheManagerStreamListener* cacheManagerStreamListener;
nsIChannel *channelForListener;
channelForListener = mProxyChannel ? mProxyChannel : this;
cacheManagerStreamListener =
new CacheManagerStreamListener(headListener, mLoadGroup, channelForListener);
if (!cacheManagerStreamListener) return NS_ERROR_OUT_OF_MEMORY;
NS_ADDREF(cacheManagerStreamListener);
rv = mChannel->AsyncRead(aStartPosition, aReadCount, aContext,
cacheManagerStreamListener);
NS_RELEASE(cacheManagerStreamListener);
return rv;
}
// No async writes allowed to the cache yet
NS_IMETHODIMP
nsCacheEntryChannel::AsyncWrite(nsIInputStream *aFromStream, PRUint32 aStartPosition,
PRInt32 aWriteCount, nsISupports *aContext,
nsIStreamObserver *aObserver)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
nsCacheEntryChannel::GetLoadGroup(nsILoadGroup* *aLoadGroup)
{
*aLoadGroup = mLoadGroup;
return NS_OK;
}
NS_IMETHODIMP
nsCacheEntryChannel::GetLoadAttributes(nsLoadFlags *aLoadAttributes)
{
*aLoadAttributes = mLoadAttributes;
return NS_OK;
}
NS_IMETHODIMP
nsCacheEntryChannel::SetLoadAttributes(nsLoadFlags aLoadAttributes)
{
mLoadAttributes = aLoadAttributes;
return NS_OK;
}
static NS_DEFINE_CID(kIOServiceCID, NS_IOSERVICE_CID);
NS_IMETHODIMP
nsCacheEntryChannel::GetURI(nsIURI * *aURI)
{
char* spec;
nsresult rv;
rv = mCacheEntry->GetUriSpec(&spec);
if (NS_FAILED(rv)) return rv;
NS_WITH_SERVICE(nsIIOService, serv, kIOServiceCID, &rv);
if (NS_FAILED(rv)) return rv;
rv = serv->NewURI(spec, 0, aURI);
nsAllocator::Free(spec);
return rv;
}
NS_IMETHODIMP
nsCacheEntryChannel::GetOriginalURI(nsIURI * *aURI)
{
// FIXME - should return original URI passed into NewChannel() ?
return NS_ERROR_NOT_IMPLEMENTED;
}

View File

@@ -1,82 +0,0 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* 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 client code, released
* March 31, 1998.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998-1999 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
* Scott Furman, fur@netscape.com
*/
#ifndef _nsCacheEntryChannel_h_
#define _nsCacheEntryChannel_h_
#include "nsCOMPtr.h"
#include "nsIChannel.h"
#include "nsCachedNetData.h"
#include "nsILoadGroup.h"
class nsIStreamListener;
// A proxy for an nsIChannel, useful when only a few nsIChannel
// methods must be overridden
class nsChannelProxy : public nsIChannel {
public:
NS_FORWARD_NSICHANNEL(mChannel->)
NS_FORWARD_NSIREQUEST(mChannel->)
protected:
nsChannelProxy(nsIChannel* aChannel):mChannel(aChannel) {};
virtual ~nsChannelProxy() {};
nsCOMPtr<nsIChannel> mChannel;
};
// Override several nsIChannel methods so that they interact with the cache manager
class nsCacheEntryChannel : public nsChannelProxy {
public:
NS_DECL_ISUPPORTS
NS_IMETHOD OpenOutputStream(PRUint32 aStartPosition, nsIOutputStream* *aOutputStream);
NS_IMETHOD OpenInputStream(PRUint32 aStartPosition, PRInt32 aReadCount,
nsIInputStream* *aInputStream);
NS_IMETHOD AsyncRead(PRUint32 aStartPosition, PRInt32 aReadCount,
nsISupports *aContext, nsIStreamListener *aListener);
NS_IMETHOD AsyncWrite(nsIInputStream *aFromStream, PRUint32 aStartPosition,
PRInt32 aWriteCount, nsISupports *aContext,
nsIStreamObserver *aObserver);
NS_IMETHOD GetLoadAttributes(nsLoadFlags *aLoadAttributes);
NS_IMETHOD SetLoadAttributes(nsLoadFlags aLoadAttributes);
NS_IMETHOD GetLoadGroup(nsILoadGroup* *aLoadGroup);
NS_IMETHOD GetURI(nsIURI * *aURI);
NS_IMETHOD GetOriginalURI(nsIURI * *aURI);
protected:
nsCacheEntryChannel(nsCachedNetData* aCacheEntry, nsIChannel* aChannel, nsILoadGroup* aLoadGroup);
virtual ~nsCacheEntryChannel();
friend class nsCachedNetData;
private:
nsCOMPtr<nsCachedNetData> mCacheEntry;
nsCOMPtr<nsILoadGroup> mLoadGroup;
nsCOMPtr<nsIChannel> mProxyChannel;
nsLoadFlags mLoadAttributes;
};
#endif // _nsCacheEntryChannel_h_

View File

@@ -1,496 +0,0 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* 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 client code, released
* March 31, 1998.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998-1999 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
* Scott Furman, fur@netscape.com
*/
#include "nsINetDataCache.h"
#include "nsCacheManager.h"
#include "nsCachedNetData.h"
#include "nsReplacementPolicy.h"
#include "nsString.h"
#include "nsIURI.h"
#include "nsHashtable.h"
#include "nsIComponentManager.h"
#include "nsINetDataDiskCache.h"
// Limit the number of entries in the cache to conserve memory space
// in the nsReplacementPolicy code
#define MAX_MEM_CACHE_ENTRIES 800
#define MAX_DISK_CACHE_ENTRIES 3200
// Cache capacities in MB, overridable via APIs
#define DEFAULT_MEMORY_CACHE_CAPACITY 2000
#define DEFAULT_DISK_CACHE_CAPACITY 10000
#define CACHE_HIGH_WATER_MARK(capacity) ((PRUint32)(0.98 * (capacity)))
#define CACHE_LOW_WATER_MARK(capacity) ((PRUint32)(0.97 * (capacity)))
nsCacheManager* gCacheManager = 0;
NS_IMPL_ISUPPORTS(nsCacheManager, NS_GET_IID(nsINetDataCacheManager))
nsCacheManager::nsCacheManager()
: mActiveCacheRecords(0),
mDiskCacheCapacity(DEFAULT_DISK_CACHE_CAPACITY),
mMemCacheCapacity(DEFAULT_MEMORY_CACHE_CAPACITY)
{
NS_ASSERTION(!gCacheManager, "Multiple cache managers created");
gCacheManager = this;
NS_INIT_REFCNT();
}
nsCacheManager::~nsCacheManager()
{
gCacheManager = 0;
delete mActiveCacheRecords;
delete mMemSpaceManager;
delete mDiskSpaceManager;
}
nsresult
nsCacheManager::Init()
{
nsresult rv;
mActiveCacheRecords = new nsHashtable(64);
if (!mActiveCacheRecords)
return NS_ERROR_OUT_OF_MEMORY;
// Instantiate the memory cache component
rv = nsComponentManager::CreateInstance(NS_NETWORK_MEMORY_CACHE_PROGID,
nsnull,
NS_GET_IID(nsINetDataCache),
getter_AddRefs(mMemCache));
if (NS_FAILED(rv))
return rv;
rv = nsComponentManager::CreateInstance(NS_NETWORK_FLAT_CACHE_PROGID,
nsnull,
NS_GET_IID(nsINetDataCache),
getter_AddRefs(mFlatCache));
if (NS_FAILED(rv)) {
// For now, we don't require a flat cache module to be present
if (rv != NS_ERROR_FACTORY_NOT_REGISTERED)
return rv;
}
#ifdef FILE_CACHE_IS_READY
// Instantiate the file cache component
rv = nsComponentManager::CreateInstance(NS_NETWORK_FILE_CACHE_PROGID,
nsnull,
NS_GET_IID(nsINetDataCache),
getter_AddRefs(mFileCache));
if (NS_FAILED(rv)) {
NS_WARNING("No disk cache present");
}
#endif
// Set up linked list of caches in search order
mCacheSearchChain = mMemCache;
if (mFlatCache) {
mMemCache->SetNextCache(mFlatCache);
mFlatCache->SetNextCache(mFileCache);
} else {
mMemCache->SetNextCache(mFileCache);
}
// TODO - Load any extension caches here
// Initialize replacement policy for memory cache module
mMemSpaceManager = new nsReplacementPolicy;
if (!mMemSpaceManager)
return NS_ERROR_OUT_OF_MEMORY;
rv = mMemSpaceManager->Init(MAX_MEM_CACHE_ENTRIES);
if (NS_FAILED(rv)) return rv;
rv = mMemSpaceManager->AddCache(mMemCache);
// Initialize replacement policy for disk cache modules (file
// cache and flat cache)
mDiskSpaceManager = new nsReplacementPolicy;
if (!mDiskSpaceManager)
return NS_ERROR_OUT_OF_MEMORY;
rv = mDiskSpaceManager->Init(MAX_DISK_CACHE_ENTRIES);
if (NS_FAILED(rv)) return rv;
if (mFileCache) {
rv = mDiskSpaceManager->AddCache(mFileCache);
if (NS_FAILED(rv)) return rv;
}
if (mFlatCache) {
rv = mDiskSpaceManager->AddCache(mFlatCache);
if (NS_FAILED(rv)) return rv;
}
return NS_OK;
}
NS_IMETHODIMP
nsCacheManager::GetCachedNetData(const char *aUriSpec, const char *aSecondaryKey,
PRUint32 aSecondaryKeyLength,
PRUint32 aFlags, nsICachedNetData* *aResult)
{
nsCachedNetData *cachedData;
nsresult rv;
nsINetDataCache *cache;
nsReplacementPolicy *spaceManager;
if (aFlags & CACHE_AS_FILE) {
cache = mFileCache;
spaceManager = mDiskSpaceManager;
// Ensure that cache is initialized
if (mDiskCacheCapacity == (PRUint32)-1)
return NS_ERROR_NOT_AVAILABLE;
} else if ((aFlags & BYPASS_PERSISTENT_CACHE) || !mDiskCacheCapacity) {
cache = mMemCache;
spaceManager = mMemSpaceManager;
} else {
cache = mFlatCache ? mFlatCache : mFileCache;
spaceManager = mDiskSpaceManager;
}
// Construct the cache key by appending the secondary key to the URI spec
nsCAutoString cacheKey(aUriSpec);
// Insert NUL at end of URI spec
cacheKey += '\0';
if (aSecondaryKey)
cacheKey.Append(aSecondaryKey, aSecondaryKeyLength);
nsStringKey key(cacheKey);
cachedData = (nsCachedNetData*)mActiveCacheRecords->Get(&key);
// There is no existing instance of nsCachedNetData for this URL.
// Make one from the corresponding record in the cache module.
if (cachedData) {
NS_ASSERTION(cache == cachedData->mCache,
"Cannot yet handle simultaneously active requests for the "
"same URL using different caches");
NS_ADDREF(cachedData);
} else {
rv = spaceManager->GetCachedNetData(cacheKey.GetBuffer(), cacheKey.Length(),
cache, &cachedData);
if (NS_FAILED(rv)) return rv;
mActiveCacheRecords->Put(&key, cachedData);
}
*aResult = cachedData;
return NS_OK;
}
// Remove this cache entry from the list of active ones
nsresult
nsCacheManager::NoteDormant(nsCachedNetData* aEntry)
{
nsresult rv;
PRUint32 keyLength;
char* key;
nsCOMPtr<nsINetDataCacheRecord> record;
nsCachedNetData* deletedEntry;
rv = aEntry->GetRecord(getter_AddRefs(record));
if (NS_FAILED(rv)) return rv;
rv = record->GetKey(&keyLength, &key);
if (NS_FAILED(rv)) return rv;
nsStringKey hashTableKey(nsCString(key, keyLength));
deletedEntry = (nsCachedNetData*)gCacheManager->mActiveCacheRecords->Remove(&hashTableKey);
NS_ASSERTION(deletedEntry == aEntry, "Hash table inconsistency");
return NS_OK;
}
NS_IMETHODIMP
nsCacheManager::Contains(const char *aUriSpec, const char *aSecondaryKey,
PRUint32 aSecondaryKeyLength,
PRUint32 aFlags, PRBool *aResult)
{
nsINetDataCache *cache;
nsReplacementPolicy *spaceManager;
nsCachedNetData *cachedData;
if (aFlags & CACHE_AS_FILE) {
cache = mFileCache;
spaceManager = mDiskSpaceManager;
} else if ((aFlags & BYPASS_PERSISTENT_CACHE) ||
(!mFileCache && !mFlatCache) || !mDiskCacheCapacity) {
cache = mMemCache;
spaceManager = mMemSpaceManager;
} else {
cache = mFlatCache ? mFlatCache : mFileCache;
spaceManager = mDiskSpaceManager;
}
// Construct the cache key by appending the secondary key to the URI spec
nsCAutoString cacheKey(aUriSpec);
// Insert NUL between URI spec and secondary key
cacheKey += '\0';
cacheKey.Append(aSecondaryKey, aSecondaryKeyLength);
// Locate the record using (URI + secondary key)
nsStringKey key(cacheKey);
cachedData = (nsCachedNetData*)mActiveCacheRecords->Get(&key);
if (cachedData && (cache == cachedData->mCache)) {
*aResult = PR_TRUE;
return NS_OK;
} else {
// No active cache entry, see if there is a dormant one
return cache->Contains(cacheKey.GetBuffer(), cacheKey.Length(), aResult);
}
}
NS_IMETHODIMP
nsCacheManager::GetNumEntries(PRUint32 *aNumEntries)
{
nsresult rv;
nsCOMPtr<nsISimpleEnumerator> iterator;
nsCOMPtr<nsISupports> cacheSupports;
nsCOMPtr<nsINetDataCache> cache;
PRUint32 totalEntries = 0;
rv = NewCacheModuleIterator(getter_AddRefs(iterator));
if (NS_FAILED(rv)) return rv;
while (1) {
PRBool notDone;
rv = iterator->HasMoreElements(&notDone);
if (NS_FAILED(rv)) return rv;
if (!notDone)
break;
iterator->GetNext(getter_AddRefs(cacheSupports));
cache = do_QueryInterface(cacheSupports);
PRUint32 numEntries;
rv = cache->GetNumEntries(&numEntries);
if (NS_FAILED(rv)) return rv;
totalEntries += numEntries;
}
*aNumEntries = totalEntries;
return NS_OK;
}
NS_IMETHODIMP
nsCacheManager::NewCacheEntryIterator(nsISimpleEnumerator* *aResult)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
class CacheEnumerator : public nsISimpleEnumerator
{
public:
CacheEnumerator(nsINetDataCache* aFirstCache):mCache(aFirstCache)
{ NS_INIT_REFCNT(); }
virtual ~CacheEnumerator() {};
NS_DECL_ISUPPORTS
NS_IMETHODIMP
HasMoreElements(PRBool* aMoreElements) {
*aMoreElements = (mCache != 0);
return NS_OK;
}
NS_IMETHODIMP
GetNext(nsISupports* *aSupports) {
*aSupports = mCache;
if (!mCache)
return NS_ERROR_FAILURE;
NS_ADDREF(*aSupports);
nsCOMPtr<nsINetDataCache> nextCache;
nsresult rv = mCache->GetNextCache(getter_AddRefs(nextCache));
mCache = nextCache;
return rv;
}
private:
nsCOMPtr<nsINetDataCache> mCache;
};
NS_IMPL_ISUPPORTS(CacheEnumerator, NS_GET_IID(nsISimpleEnumerator))
NS_IMETHODIMP
nsCacheManager::NewCacheModuleIterator(nsISimpleEnumerator* *aResult)
{
*aResult = new CacheEnumerator(mCacheSearchChain);
if (!*aResult)
return NS_ERROR_OUT_OF_MEMORY;
NS_ADDREF(*aResult);
return NS_OK;
}
NS_IMETHODIMP
nsCacheManager::RemoveAll(void)
{
nsresult rv, result;
nsCOMPtr<nsISimpleEnumerator> iterator;
nsCOMPtr<nsINetDataCache> cache;
nsCOMPtr<nsISupports> iSupports;
result = NS_OK;
rv = NewCacheModuleIterator(getter_AddRefs(iterator));
if (NS_FAILED(rv)) return rv;
while (1) {
PRBool notDone;
rv = iterator->HasMoreElements(&notDone);
if (NS_FAILED(rv)) return rv;
if (!notDone)
break;
iterator->GetNext(getter_AddRefs(iSupports));
cache = do_QueryInterface(iSupports);
PRUint32 cacheFlags;
rv = cache->GetFlags(&cacheFlags);
if (NS_FAILED(rv)) return rv;
if ((cacheFlags & nsINetDataCache::READ_ONLY) == 0) {
rv = cache->RemoveAll();
if (NS_FAILED(rv))
result = rv;
}
}
return result;
}
nsresult
nsCacheManager::LimitMemCacheSize()
{
nsresult rv;
nsReplacementPolicy* spaceManager;
NS_ASSERTION(gCacheManager, "No cache manager");
spaceManager = gCacheManager->mMemSpaceManager;
PRUint32 occupancy;
rv = spaceManager->GetStorageInUse(&occupancy);
if (NS_FAILED(rv)) return rv;
PRUint32 memCacheCapacity = gCacheManager->mMemCacheCapacity;
if (occupancy > CACHE_HIGH_WATER_MARK(memCacheCapacity))
return spaceManager->Evict(CACHE_LOW_WATER_MARK(memCacheCapacity));
return NS_OK;
}
nsresult
nsCacheManager::LimitDiskCacheSize()
{
nsresult rv;
nsReplacementPolicy* spaceManager;
NS_ASSERTION(gCacheManager, "No cache manager");
spaceManager = gCacheManager->mDiskSpaceManager;
PRUint32 occupancy;
rv = spaceManager->GetStorageInUse(&occupancy);
if (NS_FAILED(rv)) return rv;
PRUint32 diskCacheCapacity = gCacheManager->mDiskCacheCapacity;
if (occupancy > CACHE_HIGH_WATER_MARK(diskCacheCapacity))
return spaceManager->Evict(CACHE_LOW_WATER_MARK(diskCacheCapacity));
return NS_OK;
}
nsresult
nsCacheManager::LimitCacheSize()
{
nsresult rv;
rv = LimitDiskCacheSize();
if (NS_FAILED(rv)) return rv;
rv = LimitMemCacheSize();
if (NS_FAILED(rv)) return rv;
return NS_OK;
}
NS_IMETHODIMP
nsCacheManager::SetMemCacheCapacity(PRUint32 aCapacity)
{
mMemCacheCapacity = aCapacity;
LimitCacheSize();
return NS_OK;
}
NS_IMETHODIMP
nsCacheManager::GetMemCacheCapacity(PRUint32* aCapacity)
{
NS_ENSURE_ARG_POINTER(aCapacity);
*aCapacity = mMemCacheCapacity;
return NS_OK;
}
NS_IMETHODIMP
nsCacheManager::SetDiskCacheCapacity(PRUint32 aCapacity)
{
mDiskCacheCapacity = aCapacity;
LimitCacheSize();
return NS_OK;
}
NS_IMETHODIMP
nsCacheManager::GetDiskCacheCapacity(PRUint32* aCapacity)
{
NS_ENSURE_ARG_POINTER(aCapacity);
*aCapacity = mDiskCacheCapacity;
return NS_OK;
}
NS_IMETHODIMP
nsCacheManager::SetDiskCacheFolder(nsIFileSpec* aFolder)
{
NS_ENSURE_ARG(aFolder);
if (!mFileCache)
return NS_ERROR_NOT_AVAILABLE;
nsCOMPtr<nsINetDataDiskCache> fileCache;
fileCache = do_QueryInterface(mFileCache);
return fileCache->SetDiskCacheFolder(aFolder);
}
NS_IMETHODIMP
nsCacheManager::GetDiskCacheFolder(nsIFileSpec* *aFolder)
{
NS_ENSURE_ARG(aFolder);
if (!mFileCache)
return NS_ERROR_NOT_AVAILABLE;
nsCOMPtr<nsINetDataDiskCache> fileCache;
fileCache = do_QueryInterface(mFileCache);
return fileCache->GetDiskCacheFolder(aFolder);
}

View File

@@ -1,99 +0,0 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* 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 client code, released
* March 31, 1998.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998-1999 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
* Scott Furman, fur@netscape.com
*/
#ifndef _nsCacheManager_h_
#define _nsCacheManager_h_
// 2030f0b0-9567-11d3-90d3-0040056a906e
#define NS_CACHE_MANAGER_CID \
{ \
0x2030f0b0, \
0x9567, \
0x11d3, \
{0x90, 0xd3, 0x00, 0x40, 0x05, 0x6a, 0x90, 0x6e} \
}
#include "nsINetDataCacheManager.h"
#include "nsCOMPtr.h"
class nsHashtable;
class nsReplacementPolicy;
class nsCachedNetData;
class nsCacheManager : public nsINetDataCacheManager {
public:
nsCacheManager();
virtual ~nsCacheManager();
NS_METHOD Init();
// nsISupports methods
NS_DECL_ISUPPORTS
// nsINetDataCacheManager methods
NS_DECL_NSINETDATACACHEMANAGER
private:
// Mapping from cache key to nsCachedNetData, but only for those cache
// entries with external references, i.e. those referred to outside the
// cache manager
nsHashtable* mActiveCacheRecords;
// Memory cache
nsCOMPtr<nsINetDataCache> mMemCache;
// Flat-file database cache; All content aggregated into single disk file
nsCOMPtr<nsINetDataCache> mFlatCache;
// stream-as-file cache
nsCOMPtr<nsINetDataCache> mFileCache;
// Unified replacement policy for flat-cache and file-cache
nsReplacementPolicy* mDiskSpaceManager;
// Replacement policy for memory cache
nsReplacementPolicy* mMemSpaceManager;
// List of caches in search order
nsINetDataCache* mCacheSearchChain;
// Combined file/flat cache capacity, in KB
PRUint32 mDiskCacheCapacity;
// Memory cache capacity, in KB
PRUint32 mMemCacheCapacity;
protected:
static nsresult NoteDormant(nsCachedNetData* aEntry);
static nsresult LimitCacheSize();
static nsresult LimitMemCacheSize();
static nsresult LimitDiskCacheSize();
friend class nsCachedNetData;
friend class CacheOutputStream;
};
#endif // _nsCacheManager_h_

File diff suppressed because it is too large Load Diff

View File

@@ -1,242 +0,0 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* 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 client code, released
* March 31, 1998.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998-1999 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
* Scott Furman, fur@netscape.com
*/
#ifndef _nsCachedNetData_h_
#define _nsCachedNetData_h_
#include "nsICachedNetData.h"
#include "nsCOMPtr.h"
#include "nsINetDataCacheRecord.h"
class nsINetDataCache;
class nsIStreamAsFileObserver;
class nsIStreamAsFile;
class nsIArena;
class StreamAsFileObserverClosure;
class CacheMetaData;
// Number of recent access times recorded
#define MAX_K 3
/**
* FIXME - add comment. There are a lot of these data structures resident in
* memory, so be careful about adding members unnecessarily.
*/
class nsCachedNetData : public nsICachedNetData {
public:
NS_DECL_ISUPPORTS
// nsICachedNetData methods
NS_DECL_NSICACHEDNETDATA
NS_METHOD Init(nsINetDataCacheRecord *aRecord, nsINetDataCache *aCache);
protected:
// Bits for mFlags, below
typedef enum {
DIRTY = 1 << 0, // Cache entry data needs to be flushed to database
// ==== Flags that can be set by the protocol handler ====
ALLOW_PARTIAL = 1 << 1, // Protocol handler supports partial fetching
UPDATE_IN_PROGRESS = 1 << 2, // Protocol handler now modifying cache data
// ==== Cache-entry state flags. At most one of these flags can be set ====
TRUNCATED_CONTENT = 1 << 4, // Entry contains valid content, but it has
// been truncated by cache manager
// A previously-used cache entry, which has been purged of all cached
// content and protocol-private data. This cache entry can be refilled
// with new content or it may be retained in this vestigial state
// because the usage statistics it contains will be used by the
// replacement policy if the same URI is ever cached again.
VESTIGIAL = 1 << 5,
// ==== Memory usage status bits. At most one of these flags can be set ====
RECYCLED = 1 << 8, // Previously associated database record has
// been deleted; This cache entry is available
// for recycling.
DORMANT = 1 << 9, // No references to this cache entry, except by
// the cache manager itself
// ==== Setter bits ====
LAST_MODIFIED_KNOWN = 1 <<12, // Protocol handler called SetLastModifiedTime()
EXPIRATION_KNOWN = 1 <<13, // Protocol handler called SetExpirationTime()
STALE_TIME_KNOWN = 1 <<14, // Protocol handler called SetStaleTime()
// ==== Useful flag combinations ====
// Cache entry not eligible for eviction
UNEVICTABLE = VESTIGIAL | RECYCLED | UPDATE_IN_PROGRESS,
// State flags that are in-memory only, i.e. not persistent
TRANSIENT_FLAGS = DIRTY | RECYCLED | DORMANT
} Flag;
PRBool GetFlag(Flag aFlag) { return (mFlags & aFlag) != 0; }
nsresult GetFlag(PRBool *aResult, Flag aFlag) { *aResult = GetFlag(aFlag); return NS_OK; }
// Set a boolean flag for the cache entry
nsresult SetFlag(PRBool aValue, Flag aFlag);
nsresult SetFlag(Flag aFlag) { return SetFlag(PR_TRUE, aFlag); }
nsresult ClearFlag(Flag aFlag) { return SetFlag(PR_FALSE, aFlag); }
void ComputeProfit(PRUint32 aCurrentTime);
static int Compare(const void *a, const void *b, void *unused);
void NoteAccess();
void NoteUpdate();
// Get underlying raw cache database record.
nsresult GetRecord(nsINetDataCacheRecord* *aRecord);
nsresult GetRecordID(PRInt32 *aRecordID);
nsresult Evict(PRUint32 aTruncatedContentLength);
nsresult GetFileSpec(nsIFileSpec* *aFileSpec);
void NoteDownloadTime(PRTime start, PRTime end);
// placement new for arena-allocation
void *operator new (size_t aSize, nsIArena *aArena);
friend class nsReplacementPolicy;
friend class nsCacheManager;
friend class StreamAsFile;
friend class nsCacheEntryChannel;
friend class CacheOutputStream;
friend class InterceptStreamListener;
private:
nsCachedNetData() {};
virtual ~nsCachedNetData() {};
// Initialize internal fields of this nsCachedNetData instance from the
// underlying raw cache database record.
nsresult Deserialize(bool aDeserializeFlags);
// Notify stream-as-file observers about change in cache entry status
nsresult Notify(PRUint32 aMessage, nsresult aError);
// Add/Remove stream-as-file observers
nsresult AddObserver(nsIStreamAsFile *aStreamAsFile, nsIStreamAsFileObserver* aObserver);
nsresult RemoveObserver(nsIStreamAsFileObserver* aObserver);
// Mark cache entry to indicate a write out to the cache database is required
void SetDirty() { mFlags |= DIRTY; }
nsresult Resurrect(nsINetDataCacheRecord *aRecord);
nsresult CommitFlags();
CacheMetaData* FindTaggedMetaData(const char* aTag, PRBool aCreate);
private:
// List of nsIStreamAsFileObserver's that will receive notification events
// when the cache manager or a client desires to delete/truncate a cache
// entry file.
StreamAsFileObserverClosure* mObservers;
// Protocol-specific meta-data, opaque to the cache manager
CacheMetaData *mMetaData;
// Next in chain for a single bucket in the replacement policy hash table
// that maps from record ID to nsCachedNetData
nsCachedNetData* mNext;
// See flag bits, above
// NOTE: 16 bit member is combined with members below for
// struct packing efficiency. Do not change order of members!
PRUint16 mFlags;
protected:
// Number of nsCacheEntryChannels referring to this record
PRUint8 mChannelCount;
// Below members are statistics kept per cache-entry, used to decide how
// profitable it will be to evict a record from the cache relative to other
// existing records. Note: times are measured in *seconds* since the
// 1/1/70 epoch, same as a unix time_t.
// Number of accesses for this cache record
// NOTE: 8 bit member is combined with members above for
// struct packing efficiency. Do not change order of members!
PRUint8 mNumAccesses;
// A reference to the underlying, raw cache database record, either as a
// pointer to an in-memory object or as a database record identifier
union {
nsINetDataCacheRecord* mRecord;
// Database record ID of associated cache record. See
// nsINetDataCache::GetRecordByID().
PRInt32 mRecordID;
};
// Weak link to parent cache
nsINetDataCache* mCache;
// Length of stored content, which may be less than storage consumed if
// compression is used
PRUint32 mLogicalLength;
// Most recent cache entry access times, used to compute access frequency
PRUint32 mAccessTime[MAX_K];
// We use modification time of the original document for replacement policy
// computations, i.e. to compute a document's age, but if we don't know it,
// we use the time that the document was last written to the cache.
union {
// Document modification time, if known.
PRUint32 mLastModifiedTime;
// Time of last cache update for this doc
PRUint32 mLastUpdateTime;
};
union {
// Time until which document is fresh, i.e. does not have to be validated
// with server and, therefore, data in cache is guaranteed usable
PRUint32 mExpirationTime;
// Heuristic time at which cached document is likely to be out-of-date
// with respect to canonical copy on server. Used for cache replacement
// policy, not for validation.
PRUint32 mStaleTime;
};
// Download time per byte, measure roughly in units of KB/s
float mDownloadRate;
// Heuristic estimate of cache entry future benefits, based on above values
float mProfit;
};
#endif // _nsCachedNetData_h_

View File

@@ -1,658 +0,0 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
* 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 client code, released
* March 31, 1998.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998-1999 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
* Scott Furman, fur@netscape.com
*/
#include "nsReplacementPolicy.h"
#include "nsCachedNetData.h"
#include "nsQuickSort.h"
#include "nsIAllocator.h"
#include "nsIEnumerator.h"
#include "prtime.h"
#include "prbit.h"
#include "nsCOMPtr.h"
#include <math.h>
// Constant used to estimate frequency of access to a document based on size
#define CACHE_CONST_B 1.35
// A cache whose space is managed by this replacement policy
class nsReplacementPolicy::CacheInfo {
public:
CacheInfo(nsINetDataCache* aCache):mCache(aCache),mNext(0) {}
nsINetDataCache* mCache;
CacheInfo* mNext;
};
nsReplacementPolicy::nsReplacementPolicy()
: mRankedEntries(0), mCaches(0), mRecordsRemovedSinceLastRanking(0),
mNumEntries(0), mCapacityRankedEntriesArray(0), mLastRankTime(0) {}
nsReplacementPolicy::~nsReplacementPolicy()
{
if (mRankedEntries)
nsAllocator::Free(mRankedEntries);
if (mMapRecordIdToEntry)
nsAllocator::Free(mMapRecordIdToEntry);
}
nsresult
nsReplacementPolicy::Init(PRUint32 aMaxCacheEntries)
{
nsresult rv;
rv = NS_NewHeapArena(getter_AddRefs(mArena), sizeof(nsCachedNetData) * 32);
if (NS_FAILED(rv)) return rv;
mMaxEntries = aMaxCacheEntries;
mHashArrayLength = PR_CeilingLog2(aMaxCacheEntries) >> 3;
size_t numBytes = mHashArrayLength * sizeof(*mMapRecordIdToEntry);
mMapRecordIdToEntry = (nsCachedNetData**)nsAllocator::Alloc(numBytes);
if (!mMapRecordIdToEntry)
return NS_ERROR_OUT_OF_MEMORY;
nsCRT::zero(mMapRecordIdToEntry, numBytes);
return NS_OK;
}
nsresult
nsReplacementPolicy::AddCache(nsINetDataCache *aCache)
{
CacheInfo *cacheInfo = new CacheInfo(aCache);
if (!cacheInfo)
return NS_ERROR_OUT_OF_MEMORY;
cacheInfo->mNext = mCaches;
mCaches = cacheInfo;
return NS_OK;
}
PRUint32
nsReplacementPolicy::HashRecordID(PRInt32 aRecordID)
{
return ((aRecordID >> 16) ^ aRecordID) & (mHashArrayLength - 1);
}
nsCachedNetData*
nsReplacementPolicy::FindCacheEntryByRecordID(PRInt32 aRecordID, nsINetDataCache *aCache)
{
nsresult rv;
nsCachedNetData* cacheEntry;
PRUint32 bucket = HashRecordID(aRecordID);
cacheEntry = mMapRecordIdToEntry[bucket];
for (;cacheEntry; cacheEntry = cacheEntry->mNext) {
PRInt32 recordID;
rv = cacheEntry->GetRecordID(&recordID);
if (NS_FAILED(rv))
continue;
if ((recordID == aRecordID) && (cacheEntry->mCache == aCache))
return cacheEntry;
}
return 0;
}
// Add a cache entry to the hash table that maps record ID to entries
void
nsReplacementPolicy::AddCacheEntry(nsCachedNetData* aCacheEntry, PRInt32 aRecordID)
{
nsCachedNetData** cacheEntryp;
PRUint32 bucket = HashRecordID(aRecordID);
cacheEntryp = &mMapRecordIdToEntry[bucket];
while (*cacheEntryp)
cacheEntryp = &(*cacheEntryp)->mNext;
*cacheEntryp = aCacheEntry;
aCacheEntry->mNext = 0;
}
// Delete a cache entry from the hash table that maps record ID to entries
nsresult
nsReplacementPolicy::DeleteCacheEntry(nsCachedNetData* aCacheEntry)
{
nsresult rv;
PRInt32 recordID;
rv = aCacheEntry->GetRecordID(&recordID);
if (NS_FAILED(rv)) return rv;
PRUint32 bucket = HashRecordID(recordID);
nsCachedNetData** cacheEntryp;
cacheEntryp = &mMapRecordIdToEntry[bucket];
while (*cacheEntryp) {
if (*cacheEntryp == aCacheEntry) {
*cacheEntryp = aCacheEntry->mNext;
return NS_OK;
}
cacheEntryp = &(*cacheEntryp)->mNext;
}
NS_ASSERTION(0, "hash table inconsistency");
return NS_ERROR_FAILURE;
}
nsresult
nsReplacementPolicy::AddAllRecordsInCache(nsINetDataCache *aCache)
{
nsresult rv;
nsCOMPtr<nsISimpleEnumerator> iterator;
nsCOMPtr<nsISupports> iSupports;
nsCOMPtr<nsINetDataCacheRecord> record;
rv = aCache->NewCacheEntryIterator(getter_AddRefs(iterator));
if (!NS_SUCCEEDED(rv)) return rv;
while (1) {
PRBool notDone;
rv = iterator->HasMoreElements(&notDone);
if (NS_FAILED(rv)) return rv;
if (!notDone)
break;
rv = iterator->GetNext(getter_AddRefs(iSupports));
if (!NS_SUCCEEDED(rv)) return rv;
record = do_QueryInterface(iSupports);
rv = AssociateCacheEntryWithRecord(record, aCache, 0);
if (!NS_SUCCEEDED(rv)) return rv;
}
return NS_OK;
}
// Get current time and convert to seconds since the epoch
static PRUint32
now32()
{
double nowFP;
PRInt64 now64 = PR_Now();
LL_L2D(nowFP, now64);
PRUint32 now = (PRUint32)(nowFP * 1e-6);
return now;
}
void
nsCachedNetData::NoteDownloadTime(PRTime start, PRTime end)
{
double startFP, endFP, rate, duration;
LL_L2D(startFP, start);
LL_L2D(endFP, end);
duration = endFP - startFP;
// Sanity-check
if (!duration)
return;
// Compute download rate in kB/s
rate = mLogicalLength / (duration * (1e-6 /1024.0));
// Exponentially smooth download rate
const double alpha = 0.5;
mDownloadRate = (float)(mDownloadRate * alpha + rate * (1.0 - alpha));
}
// 1 hour
#define MIN_HALFLIFE (60 * 60)
// 1 week
#define TYPICAL_HALFLIFE (7 * 24 * 60 * 60)
/**
* Estimate the profit that would be lost if the given cache entry was evicted
* from the cache. Profit is defined as the future expected download delay per
* byte of cached content. The profit computation is made based on projected
* frequency of access, prior download performance and a heuristic staleness
* criteria. The technique used is a variation of that described in the
* following paper:
*
* "A Case for Delay-Conscious Caching of Web Documents"
* http://www.bell-labs.com/user/rvingral/www97.html
*
* Briefly, expected profit is:
*
* (projected frequency of access) * (download time per byte) * (probability freshness)
*/
void
nsCachedNetData::ComputeProfit(PRUint32 aNow)
{
PRUint32 K, now;
if (aNow)
now = aNow;
else
now = now32();
K = PR_MIN(MAX_K, mNumAccesses);
if (!K) {
mProfit = 0;
return;
}
// Compute time, in seconds, since k'th most recent access
double timeSinceKthAccess = now - mAccessTime[K - 1];
if (timeSinceKthAccess <= 0.0) // Sanity check
timeSinceKthAccess = 1.0;
// Estimate frequency of future document access based on past
// access frequency
double frequencyAccess = K / timeSinceKthAccess;
// If we don't have much historical data on access frequency
// use a heuristic based on document size as an estimate
if (mLogicalLength) {
if (K == 1) {
frequencyAccess /= pow(mLogicalLength, CACHE_CONST_B);
} else if (K == 2) {
frequencyAccess /= pow(mLogicalLength, CACHE_CONST_B / 2);
}
}
// Estimate likelihood that data in cache is fresh, i.e.
// that it corresponds to the document on the server
double probabilityFreshness;
PRInt32 halfLife, age, docTime;
bool potentiallyStale;
docTime = GetFlag(LAST_MODIFIED_KNOWN) ? mLastModifiedTime : mLastUpdateTime;
age = now - docTime;
probabilityFreshness = 1.0; // Optimistic
if (GetFlag(EXPIRATION_KNOWN)) {
potentiallyStale = now > mExpirationTime;
halfLife = mExpirationTime - mLastModifiedTime;
} else if (GetFlag(STALE_TIME_KNOWN)) {
potentiallyStale = true;
halfLife = mStaleTime - docTime;
} else {
potentiallyStale = true;
halfLife = TYPICAL_HALFLIFE;
}
if (potentiallyStale) {
if (halfLife < MIN_HALFLIFE)
halfLife = MIN_HALFLIFE;
probabilityFreshness = pow(0.5, (double)age / (double)halfLife);
}
mProfit = (float)(frequencyAccess * probabilityFreshness * mDownloadRate);
}
// Number of entries to grow mRankedEntries array when it's full
#define STATS_GROWTH_INCREMENT 256
// Sorting predicate for NS_Quicksort
int
nsCachedNetData::Compare(const void *a, const void *b, void *unused)
{
nsCachedNetData* entryA = (nsCachedNetData*)a;
nsCachedNetData* entryB = (nsCachedNetData*)b;
// Percolate deleted or empty entries to the end of the mRankedEntries
// array, so that they can be recycled.
if (!entryA || entryA->GetFlag(RECYCLED)) {
if (!entryB || entryB->GetFlag(RECYCLED))
return 0;
else
return +1;
}
if (!entryB || entryB->GetFlag(RECYCLED))
return -1;
// Evicted entries (those with no content data) and active entries (those
// currently being updated) are collected towards the end of the sorted
// array just prior to the deleted cache entries, since evicted entries
// can't be re-evicted.
if (entryA->GetFlag(UPDATE_IN_PROGRESS)) {
if (entryB->GetFlag(UPDATE_IN_PROGRESS))
return 0;
else
return +1;
}
if (entryB->GetFlag(UPDATE_IN_PROGRESS))
return -1;
PRUint16 Ka = PR_MIN(MAX_K, entryA->mNumAccesses);
PRUint16 Kb = PR_MIN(MAX_K, entryB->mNumAccesses);
// Order cache entries by the number of times they've been accessed
if (Ka < Kb)
return -1;
if (Ka > Kb)
return +1;
/*
* Among records that have been accessed an equal number of times, order
* them by profit.
*/
if (entryA->mProfit > entryB->mProfit)
return +1;
if (entryA->mProfit < entryB->mProfit)
return -1;
return 0;
}
/**
* Rank cache entries in terms of their elegibility for eviction.
*/
nsresult
nsReplacementPolicy::RankRecords()
{
PRUint32 i, now;
// Add all cache records if this is the first ranking
if (!mLastRankTime) {
nsresult rv;
CacheInfo *cacheInfo;
cacheInfo = mCaches;
while (cacheInfo) {
rv = AddAllRecordsInCache(cacheInfo->mCache);
if (NS_FAILED(rv)) return rv;
cacheInfo = cacheInfo->mNext;
}
}
// Get current time and convert to seconds since the epoch
now = now32();
// Recompute profit for every known cache record, except deleted ones
for (i = 0; i < mNumEntries; i++) {
nsCachedNetData* entry = mRankedEntries[i];
if (entry && !entry->GetFlag(nsCachedNetData::RECYCLED))
entry->ComputeProfit(now);
}
NS_QuickSort(mRankedEntries, mNumEntries, sizeof *mRankedEntries,
nsCachedNetData::Compare, 0);
mNumEntries -= mRecordsRemovedSinceLastRanking;
mRecordsRemovedSinceLastRanking = 0;
mLastRankTime = now;
return NS_OK;
}
// A heuristic policy to avoid the cost of re-ranking cache records by
// profitability every single time space must be made available in the cache.
void
nsReplacementPolicy::MaybeRerankRecords()
{
// Rank at most once per minute
PRUint32 now = now32();
if ((now - mLastRankTime) >= 60)
RankRecords();
}
void
nsReplacementPolicy::CompactRankedEntriesArray()
{
if (mRecordsRemovedSinceLastRanking || !mLastRankTime)
RankRecords();
}
nsresult
nsReplacementPolicy::CheckForTooManyCacheEntries()
{
if (mCapacityRankedEntriesArray == mMaxEntries) {
return DeleteOneEntry(0);
} else {
nsresult rv;
CacheInfo *cacheInfo;
cacheInfo = mCaches;
while (cacheInfo) {
PRUint32 numEntries, maxEntries;
rv = cacheInfo->mCache->GetNumEntries(&numEntries);
if (NS_FAILED(rv)) return rv;
rv = cacheInfo->mCache->GetMaxEntries(&maxEntries);
if (NS_FAILED(rv)) return rv;
if (numEntries == maxEntries)
return DeleteOneEntry(cacheInfo->mCache);
cacheInfo = cacheInfo->mNext;
}
}
return NS_OK;
}
/**
* Create a new association between a low-level cache database record and a
* cache entry. Add the entry to the set of entries eligible for eviction from
* the cache. This would typically be done when the cache entry is created.
*/
nsresult
nsReplacementPolicy::AssociateCacheEntryWithRecord(nsINetDataCacheRecord *aRecord,
nsINetDataCache* aCache,
nsCachedNetData** aResult)
{
nsCachedNetData* cacheEntry;
nsresult rv;
// First, see if the record is already known to the replacement policy
PRInt32 recordID;
rv = aRecord->GetRecordID(&recordID);
if (NS_FAILED(rv)) return rv;
cacheEntry = FindCacheEntryByRecordID(recordID, aCache);
if (cacheEntry) {
if (aResult) {
if (cacheEntry->GetFlag(nsCachedNetData::DORMANT))
cacheEntry->Resurrect(aRecord);
NS_ADDREF(cacheEntry);
*aResult = cacheEntry;
}
return NS_OK;
}
// Compact the array of cache entry statistics, so that free entries appear
// at the end, for possible reuse.
if (mNumEntries && (mNumEntries == mCapacityRankedEntriesArray))
CompactRankedEntriesArray();
// If compaction doesn't yield available entries in the
// mRankedEntries array, then extend the array.
if (mNumEntries == mCapacityRankedEntriesArray) {
PRUint32 newCapacity;
rv = CheckForTooManyCacheEntries();
if (NS_FAILED(rv)) return rv;
newCapacity = mCapacityRankedEntriesArray + STATS_GROWTH_INCREMENT;
if (newCapacity > mMaxEntries)
newCapacity = mMaxEntries;
nsCachedNetData** newRankedEntriesArray;
PRUint32 numBytes = sizeof(nsCachedNetData*) * newCapacity;
newRankedEntriesArray =
(nsCachedNetData**)nsAllocator::Realloc(mRankedEntries, numBytes);
if (!newRankedEntriesArray)
return NS_ERROR_OUT_OF_MEMORY;
mRankedEntries = newRankedEntriesArray;
mCapacityRankedEntriesArray = newCapacity;
PRUint32 i;
for (i = mNumEntries; i < newCapacity; i++)
mRankedEntries[i] = 0;
}
// Recycle the record after the last in-use record in the array
nsCachedNetData *entry = mRankedEntries[mNumEntries];
NS_ASSERTION(!entry || !entry->GetFlag(nsCachedNetData::RECYCLED),
"Only deleted cache entries should appear at end of array");
if (!entry) {
entry = new(mArena) nsCachedNetData;
if (!entry)
return NS_ERROR_OUT_OF_MEMORY;
mRankedEntries[mNumEntries] = entry;
} else {
// Clear out recycled data structure
nsCRT::zero(entry, sizeof(*entry));
}
entry->Init(aRecord, aCache);
AddCacheEntry(entry, recordID);
// Add one reference to the cache entry from the cache manager
NS_ADDREF(entry);
if (aResult) {
// And one reference from our caller
NS_ADDREF(entry);
*aResult = entry;
}
mNumEntries++;
return NS_OK;
}
nsresult
nsReplacementPolicy::GetCachedNetData(const char* cacheKey, PRUint32 cacheKeyLength,
nsINetDataCache* aCache,
nsCachedNetData** aResult)
{
nsresult rv;
nsCOMPtr<nsINetDataCacheRecord> record;
rv = aCache->GetCachedNetData(cacheKey, cacheKeyLength,
getter_AddRefs(record));
if (NS_FAILED(rv)) return rv;
return AssociateCacheEntryWithRecord(record, aCache, aResult);
}
/**
* Delete the least desirable record from the cache database. This is used
* when the addition of another record would exceed either the cache manager or
* the cache's maximum permitted number of records.
*/
nsresult
nsReplacementPolicy::DeleteOneEntry(nsINetDataCache *aCache)
{
PRUint32 i;
nsresult rv;
nsCachedNetData *entry;
i = 0;
while (1) {
MaybeRerankRecords();
for (; i < mNumEntries; i++) {
entry = mRankedEntries[i];
if (!entry || entry->GetFlag(nsCachedNetData::RECYCLED))
continue;
if (!aCache || (entry->mCache == aCache))
break;
}
// Report error if no record found to delete
if (i == mNumEntries)
return NS_ERROR_FAILURE;
rv = entry->Delete();
if (NS_SUCCEEDED(rv)) {
rv = DeleteCacheEntry(entry);
return rv;
}
}
}
nsresult
nsReplacementPolicy::GetStorageInUse(PRUint32* aStorageInUse)
{
nsresult rv;
CacheInfo *cacheInfo;
*aStorageInUse = 0;
cacheInfo = mCaches;
while (cacheInfo) {
PRUint32 cacheStorage;
rv = cacheInfo->mCache->GetStorageInUse(&cacheStorage);
if (NS_FAILED(rv)) return rv;
*aStorageInUse += cacheStorage;
cacheInfo = cacheInfo->mNext;
}
return NS_OK;
}
/**
* Delete the least desirable records from the cache until the occupancy of the
* cache has been reduced by the given number of KB. This is used when the
* addition of more cache data would exceed the cache's capacity.
*/
nsresult
nsReplacementPolicy::Evict(PRUint32 aTargetOccupancy)
{
PRUint32 i;
nsCachedNetData *entry;
nsresult rv;
PRUint32 occupancy;
PRInt32 truncatedLength;
nsCOMPtr<nsINetDataCacheRecord> record;
MaybeRerankRecords();
for (i = 0; i < mNumEntries; i++) {
rv = GetStorageInUse(&occupancy);
if (!NS_SUCCEEDED(rv)) return rv;
if (occupancy <= aTargetOccupancy)
return NS_OK;
entry = mRankedEntries[i];
// Skip deleted/empty cache entries and ones that have already been evicted
if (!entry || entry->GetFlag(nsCachedNetData::UNEVICTABLE))
continue;
if (entry->GetFlag(nsCachedNetData::ALLOW_PARTIAL)) {
rv = entry->GetRecord(getter_AddRefs(record));
if (NS_FAILED(rv))
continue;
PRUint32 contentLength;
rv = record->GetStoredContentLength(&contentLength);
if (NS_FAILED(rv))
continue;
// Additional cache storage required, in KB
PRUint32 storageToReclaim = (occupancy - aTargetOccupancy) << 10;
truncatedLength = (PRInt32)(contentLength - storageToReclaim);
if (truncatedLength < 0)
truncatedLength = 0;
} else {
truncatedLength = 0;
}
rv = entry->Evict(truncatedLength);
}
return NS_ERROR_FAILURE;
}

View File

@@ -1,136 +0,0 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* 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 client code, released
* March 31, 1998.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998-1999 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
* Scott Furman, fur@netscape.com
*/
/**
* This class manages one or more caches that share a storage resource, e.g. a
* file cache and a flat-database cache might each occupy space on the disk and
* they would share a single instance of nsReplacementPolicy. The replacement
* policy heuristically chooses which cache entries to evict when storage is
* required to accommodate incoming cache data.
*/
#ifndef _nsReplacementPolicy_h_
#define _nsReplacementPolicy_h_
#include "nscore.h"
#include "nsISupportsUtils.h"
#include "nsINetDataCache.h"
#include "nsICachedNetData.h"
#include "nsIArena.h"
#include "nsCOMPtr.h"
#include "nsHashtable.h"
class nsCachedNetData;
struct PL_HashTable;
/**
* This private class is responsible for implementing the network data cache's
* replacement policy, i.e. it decides which cache data should be evicted to
* make room for new incoming data.
*/
class nsReplacementPolicy {
public:
nsReplacementPolicy();
~nsReplacementPolicy();
protected:
nsresult Init(PRUint32 aMaxCacheEntries);
nsresult AddCache(nsINetDataCache *aCache);
nsresult GetCachedNetData(const char* cacheKey, PRUint32 cacheKeyLength,
nsINetDataCache* aCache,
nsCachedNetData** aResult);
nsresult GetStorageInUse(PRUint32* aNumKBytes);
friend class nsCacheManager;
private:
nsresult RankRecords();
void MaybeRerankRecords();
void CompactRankedEntriesArray();
nsresult DeleteOneEntry(nsINetDataCache* aCache);
nsresult Evict(PRUint32 aTargetOccupancy);
nsCachedNetData* FindCacheEntryByRecordID(PRInt32 aRecordID, nsINetDataCache *aCache);
void AddCacheEntry(nsCachedNetData* aCacheEntry, PRInt32 aRecordID);
nsresult DeleteCacheEntry(nsCachedNetData* aCacheEntry);
PRUint32 HashRecordID(PRInt32 aRecordID);
nsresult AssociateCacheEntryWithRecord(nsINetDataCacheRecord *aRecord,
nsINetDataCache* aCache,
nsCachedNetData** aResult);
nsresult AddAllRecordsInCache(nsINetDataCache *aCache);
nsresult CheckForTooManyCacheEntries();
class CacheInfo;
private:
// Growable array of pointers to individual cache entries; It is sorted by
// profitability, such that low-numbered array indices refer to cache
// entries that are the least profitable to retain. New cache entries are
// added to the end of the array. Deleted cache entries are specially
// marked and percolate to the end of the array for recycling whenever
// mRankedEntries is sorted. Evicted cache entries (those with no
// associated content data) are retained for the purpose of improving the
// replacement policy efficacy, and are percolated towards the end of the
// array, just prior to the deleted cache entries.
//
// The array is not in sorted order 100% of the time; For efficiency
// reasons, sorting is only done when heuristically deemed necessary.
nsCachedNetData** mRankedEntries;
// Hash table buckets to map Record ID to cache entry. We use this instead
// of a PL_HashTable to reduce storage requirements
nsCachedNetData** mMapRecordIdToEntry;
// Length of mMapRecordIdToEntry array
PRUint32 mHashArrayLength;
// Linked list of caches that share this replacement policy
CacheInfo* mCaches;
// Allocation area for cache entry (nsCachedNetData) instances
nsCOMPtr<nsIArena> mArena;
// Bookkeeping
PRUint32 mRecordsRemovedSinceLastRanking;
// Maximum permitted length of mRankedEntries array
PRUint32 mMaxEntries;
// Number of occupied slots in mRankedEntries array
PRUint32 mNumEntries;
// Capacity of mRankedEntries array
PRUint32 mCapacityRankedEntriesArray;
// Time at which cache entries were last ranked by profitability
PRUint32 mLastRankTime;
};
#endif // _nsReplacementPolicy_h_

View File

@@ -1,39 +0,0 @@
#
# 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.org code.
#
# The Initial Developer of the Original Code is Netscape
# Communications Corporation. Portions created by Netscape are
# Copyright (C) 1998 Netscape Communications Corporation. All
# Rights Reserved.
#
# Contributor(s):
#
DEPTH = ../../..
topsrcdir = @top_srcdir@
srcdir = @srcdir@
VPATH = @srcdir@
include $(DEPTH)/config/autoconf.mk
EXPORTS = \
nsICacheManager.h \
nsICacheObject.h \
nsICachePref.h \
nsICacheModule.h \
$(NULL)
EXPORTS := $(addprefix $(srcdir)/, $(EXPORTS))
include $(topsrcdir)/config/rules.mk

View File

@@ -1,41 +0,0 @@
#!gmake
#
# 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.org code.
#
# The Initial Developer of the Original Code is Netscape
# Communications Corporation. Portions created by Netscape are
# Copyright (C) 1998 Netscape Communications Corporation. All
# Rights Reserved.
#
# Contributor(s):
MODULE = nkcache
DEPTH = ..\..\..
include <$(DEPTH)/config/config.mak>
EXPORTS = \
$(NULL)
XPIDLSRCS = \
.\nsICachedNetData.idl \
.\nsINetDataCacheManager.idl \
.\nsINetDataCache.idl \
.\nsINetDataCacheRecord.idl \
.\nsINetDataDiskCache.idl \
.\nsIStreamAsFile.idl \
$(NULL)
include <$(DEPTH)/config/rules.mak>

View File

@@ -1,229 +0,0 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* 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.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
#include "nsrootidl.idl"
#include "nsISupports.idl"
interface nsIFileSpec;
interface nsIURI;
interface nsIObserver;
interface nsIChannel;
interface nsINetDataCache;
interface nsINetDataCacheRecord;
interface nsILoadGroup;
interface nsIStreamListener;
/**
* The nsICachedNetData interface represents a single entry in a database that
* caches data retrieved from the network. This interface is implemented by the
* cache manager on top of the low-level nsINetDataCacheRecord and
* nsINetDataCache interfaces that are implemented by the database.
*
* Each cache record may contain both content and metadata. The content may
* be, for example, GIF image data or HTML, and it is accessed through
* nsIChannel's streaming API. The opaque metadata, which may contain HTTP
* headers among other things, is stored as a byte array. Each entry in the
* cache is indexed by two different keys: a record id number and a key created
* by combining the URI with a "secondary key", e.g. HTTP post data.
*
* @See nsINetDataCacheRecord
* @See nsINetDataCache
* @See nsINetDataDiskCache
* @See nsINetDataCacheManager
*/
[scriptable, uuid(6aeb2a40-6d43-11d3-90c8-000064657374)]
interface nsICachedNetData : nsISupports
{
/**
* String form of the URI provided as an argument to the call to
* nsINetDataCacheManager::GetCachedNetData() that created this record.
*/
readonly attribute string uriSpec;
/**
* Getter for the opaque secondary database key provided as an argument to
* the call to nsINetDataCacheManager::GetCachedNetData() that created this
* record.
*/
void getSecondaryKey(out unsigned long length,
[retval, size_is(length)] out string secondaryKey);
/**
* This flag may be set by a protocol handler to indicate that it supports
* partial fetching of data. In that case, the cache manager is permitted
* to truncate the entry's content to accommodate incoming data for other
* cache entries rather than deleting it wholesale.
*/
attribute boolean allowPartial;
/**
* This flag indicates that the write stream supplying content data for the
* cache did not complete normally and, therefore, the content may be
* truncated.
*/
readonly attribute boolean partialFlag;
/**
* This flag can be set and cleared by a protocol handler as a form of
* self-notification, so as to avoid race conditions in which a protocol
* handler issues two identical network requests to fill the same cache
* entry. The cache manager itself largely ignores this flag.
*/
attribute boolean updateInProgress;
/**
* inUse is set if any existing channels are associated with this cache
* entry or if the updateInProgess flag is set. This can be used to
* prevent writing to a cache entry by a protocol handler if it's being
* read or written elsewhere.
*/
readonly attribute boolean inUse;
/**
* Date/time that the document was last stored on the origin server, as
* supplied by the protocol handler. This value is used as input to the
* cache replacement policy, i.e. it is not used for validation. If the
* protocol can't supply a last-modified time, this attribute should remain
* unset. When unset, the value of this attribute is zero.
*
* FIXME: Should use nsIDateTime interface, once it's created
* instead of PRTime, for improved scriptability ?
*/
attribute PRTime lastModifiedTime;
/**
* Supplied by the protocol handler, the expirationTime attribute specifies
* the time until which the document is guaranteed fresh, i.e. the document
* does not have to be validated with the server and, therefore, any data
* in cache is definitely usable. The value of this attribute serves as a
* hint to the cache replacement policy. Only one of either staleTime or
* expirationTime may be set for a single cache record. When unset, the
* value of this attribute is zero.
*/
attribute PRTime expirationTime;
/**
* Date/time supplied by the protocol handler, at which point the content
* is *likely* to be stale, i.e. the data in the cache may be out-of-date
* with respect to the data on the server. This heuristic date does not
* necessarily correspond to the HTTP Expires header, as it does not
* determine when cached network data must be validated with the origin
* server, but only serves as a hint to the cache replacement policy. Only
* one of either staleTime or expirationTime may be set for a single cache
* record. When unset, the value of this attribute is zero.
*/
attribute PRTime staleTime;
/**
* Date/time of last access of the data in this cache record, as determined
* by the cache manager.
*/
readonly attribute PRTime lastAccessTime;
/**
* Number of times this record has been accessed since it was first stored.
*/
readonly attribute PRUint16 numberAccesses;
/**
* Accessor methods for opaque meta-data which can be read and updated
* independently of the content data.
*
* The aTag argument can be used to accommodate multiple clients of the
* cache API, each of which wants to store its own private meta-data into
* the cache. For example, there could be a "headers" tag that the HTTP
* protocol handler uses to store http response headers and a "image size"
* tag used to store the image dimensions of a GIF file. The aData
* argument refers to an opaque blob of arbitrary bytes.
*
* IMPORTANT: If aData does not contain byte-oriented data, i.e. it's not a
* string, the contents of aData must be byte-swapped by the,
* caller, so as to make the cache files endian-independent.
*/
void getAnnotation(in string aTag,
out PRUint32 aLength, [size_is(aLength), retval] out string aData);
void setAnnotation(in string aTag,
in PRUint32 aLength, [size_is(aLength)] in string aData);
/**
* As a getter, return the number of content bytes stored in the cache,
* i.e. via the nsIChannel streaming APIs. This may be less than the
* complete content length if a partial cache fill occurred. The cached
* content can be truncated by setting the value of this attribute. The
* value of the attribute represents a logical, not a physical, length. If
* compression has been used, the content may consume less storage than
* indicated by this attribute.
*
* When this attribute is set to zero the associated cache disk file, if
* any, should be deleted.
*/
attribute PRUint32 storedContentLength;
/**
* Notify any observers associated with this cache entry of the deletion
* request. If all observers drop their reference to the cache entry,
* proceed to delete the underlying cache database record and associated
* content storage.
*/
void delete();
/**
* Flush any changes in this entry's data to the cache database. This
* method will automatically be called when the last reference to the cache
* is dropped, but it can also be called explicitly for a synchronous
* effect.
*/
void commit();
/**
* Parent container cache for this entry.
*/
readonly attribute nsINetDataCache cache;
/**
* Create a channel for reading or writing a stream of content into the
* entry. It is expected that many of the nsIChannel methods return
* NS_NOT_IMPLEMENTED, including:
*
* + GetURI()
* + GetContentType()
* + GetContentLength()
*
* Though nsIChannel provides for both async and synchronous I/O APIs, both
* may not be implemented. Only AsyncRead() and OpenOutputStream() is
* required. The aProxyChannel argument allows another channel to be
* specified as the proffered argument to nsIStreamListener methods rather
* than the cache's own channel.
*/
nsIChannel newChannel(in nsILoadGroup aLoadGroup,
in nsIChannel aProxyChannel);
/**
* This method can be used by a caching protocol handler to store data in
* the cache by forking an asynchronous read stream so that it is
* simultaneously sent to a requester and written into the cache. This
* method implicitly sets the updateInProgress flag, if it has not already
* been set.
*/
nsIStreamListener interceptAsyncRead(in nsIStreamListener aOriginalListener,
in PRUint32 aStartOffset);
};

View File

@@ -1,143 +0,0 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* 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.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
#include "nsISupports.idl"
interface nsIURI;
interface nsINetDataCacheRecord;
interface nsISimpleEnumerator;
interface nsIFileSpec;
/**
* The nsINetDataCache defines the low-level API for a network-data
* cache, used to cache the responses to network retrieval commands.
* This interface, along with nsINetDataCacheRecord, is implemented by
* the memory cache, the file cache and, optionally, by some extension
* caches. This interface is essentially a pseudo-private API for the
* cache manager. Other clients should never use this interface.
*
* Each cache entry may contain both content, e.g. GIF image data, and
* associated metadata, e.g. HTTP headers. Each entry is indexed by two
* different keys: a record id number and a key created by combining the URI
* with a "secondary key", e.g. HTTP post data.
*
* The nsINetDataCache interface is agnostic as to where the data is
* stored and whether the storage is volatile or persistent. The
* memory cache, any disk caches and any extension caches must all
* implement this interface.
*
*/
[scriptable, uuid(ccfc58c0-6dde-11d3-90c8-000064657374)]
interface nsINetDataCache : nsISupports
{
/**
* Human-readable description of the cache module, e.g. "Disk Cache"
*/
readonly attribute wstring description;
/**
* Returns true if cached data is available for the given opaque key,
* even if only partial data is stored.
*/
boolean contains([size_is(length)] in string key, in PRUint32 length);
/**
* Fetch the cache entry record for the given opaque key. If one does not
* exist, create a new, empty record.
*/
nsINetDataCacheRecord getCachedNetData([size_is(length)] in string key,
in PRUint32 length);
/**
* Fetch the cache entry record for the given URI using the record ID as a key.
*/
nsINetDataCacheRecord getCachedNetDataByID(in PRInt32 RecordID);
/**
* False indicates that this cache is entirely bypassed.
*/
attribute boolean enabled;
/**
* Constants for flags attribute, below
*/
// Used for extension caches, e.g. a CD-ROM cache
const long READ_ONLY = 1 << 0;
// One of these bits must be set
const long MEMORY_CACHE = 1 << 1;
const long FLAT_FILE_CACHE = 1 << 2;
const long FILE_PER_URL_CACHE = 1 << 3;
/**
* See constants defined above.
*/
readonly attribute PRUint32 flags;
/**
* Total number of URI entries stored in the cache.
*/
readonly attribute PRUint32 numEntries;
/**
* Maximum number of URI entries that may be stored in the cache.
*/
readonly attribute PRUint32 maxEntries;
/**
* Enumerate the URI entries stored in the cache.
*/
nsISimpleEnumerator newCacheEntryIterator();
/**
* Contains a reference to the next cache in search order. For the memory
* cache, this attribute always references the disk cache. For the disk
* cache, it contains a reference to the first extension cache.
*/
attribute nsINetDataCache nextCache;
/**
* An estimate of the amount of storage occupied by the cache, in kB.
* Actual use may be slightly higher than reported due to cache overhead
* and heap fragmentation (in the memory cache) or block quantization (in
* the disk cache).
*/
readonly attribute PRUint32 storageInUse;
/**
* Remove all entries from a writable cache. This could be used, for
* example, after a guest ends a browser session. This is equivalent to
* setting the cache's Capacity to zero, except that all cache entries,
* even those in active use, will be deleted. Also, any global cache
* database files will be deleted.
*/
void removeAll();
};
%{ C++
// ProgID prefix for Components that implement this interface
#define NS_NETWORK_CACHE_PROGID "component://netscape/network/cache"
#define NS_NETWORK_MEMORY_CACHE_PROGID NS_NETWORK_CACHE_PROGID "?name=memory-cache"
#define NS_NETWORK_FLAT_CACHE_PROGID NS_NETWORK_CACHE_PROGID "?name=flat-cache"
#define NS_NETWORK_FILE_CACHE_PROGID NS_NETWORK_CACHE_PROGID "?name=file-cache"
%}

View File

@@ -1,163 +0,0 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* 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.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
#include "nsISupports.idl"
interface nsISimpleEnumerator;
interface nsICachedNetData;
interface nsINetDataCache;
interface nsINetDataDiskCache;
interface nsIURI;
interface nsIFileSpec;
/**
* The network-response cache manager is partly responsible for the caching of
* content and associated metadata that has been retrieved via the network.
* (The remaining responsibility for caching lies with individual network
* protocol handlers.)
*
* The cache manager supervises the actions of individual cache components,
* such as the memory cache, the disk cache and any extension caches, e.g. a
* read-only CD-ROM cache.
*
* @See nsINetDataCache
* @See nsICachedNetData
*/
[scriptable, uuid(71c8ab00-6d5c-11d3-90c8-000064657374)]
interface nsINetDataCacheManager : nsISupports
{
/**
* Flag for the GetCachedNetData() method: If set, the memory cache is
* neither searched nor will any data be stored into it. This might be
* appropriate, for example, with images, because they have their own
* cache for storing *decoded* images.
*/
const unsigned long BYPASS_MEMORY_CACHE = 1 << 0;
/**
* Flag for the GetCachedNetData() method: If set, the disk cache
* is neither searched nor will any be data stored into it.
* However, read-only extension caches may be searched. This
* might be used to avoid leaving persistent records of secure
* data.
*/
const unsigned long BYPASS_PERSISTENT_CACHE = 1 << 1;
/**
* Flag for the GetCachedNetData() method: If set, any stream
* content is stored in the cache as a single disk file. Content
* will not be cached in the memory cache nor is it cached in a
* flat-file cache database. This is used to implement the jar
* protocol handler and to provide the stream-as-file semantics
* required by the classic bowser plugin API.
*/
const unsigned long CACHE_AS_FILE = 1 << 2;
/**
* Fetch the cache entry record for the given URI. If one does not exist,
* create a new, empty record. The normal search order for caches is:
* + Memory cache
* + Disk cache
* + File cache (stream-as-file cache)
* + All extension caches
*
* When writing, data is typically stored in both the memory cache and the
* disk cache. Both the search order and this write policy can be modified by
* setting one or more of the flag argument bits, as defined above.
*
* The optionally-NULL secondaryKey argument can be used, e.g. for form
* post data or for HTTP headers in the case of HTTP.
*/
nsICachedNetData getCachedNetData(in string uri,
[size_is(secondaryKeyLength)] in string secondaryKey,
in PRUint32 secondaryKeyLength,
in PRUint32 flags);
/**
* Returns true if cached content is available for the given URI, even if
* only partial data is stored. The flags argument behaves the same as for
* the GetCachedNetData() method, above.
*/
boolean contains(in string uri,
[size_is(secondaryKeyLength)] in string secondaryKey,
in PRUint32 secondaryKeyLength,
in PRUint32 flags);
/**
* Total number of unexpired URI entries stored in all caches. This number
* does not take into account duplicate URIs, e.g. because the memory cache
* and the disk cache might each contain an entry for the same URI.
*/
readonly attribute PRUint32 numEntries;
/**
* Enumerate the unexpired URI entries stored in all caches. Some URIs may
* be enumerated more than once, e.g. because the the memory cache and the
* disk cache might each contain an entry for the same URI.
*/
nsISimpleEnumerator newCacheEntryIterator();
/*
* Enumerate all the loaded nsINetDataCache-implementing cache modules.
* The first module enumerated will be the memory cache, the second will be
* the disk cache, then the file cache, followed by all the extension
* caches, in search order.
*/
nsISimpleEnumerator newCacheModuleIterator();
/**
* Remove all entries from all writable caches. This could be used, for
* example, after a guest ends a browser session. This is equivalent to
* setting the DiskCacheCapacity to zero, except that all cache entries,
* even those in active use, will be deleted. Also, any global cache
* database files will be deleted.
*/
void RemoveAll();
/**
* The disk cache is made up of the file cache (for stream-as-file
* requests) and a (possibly independent) persistent cache that handles all
* other cache requests. This attribute sets/gets the combined capacity of
* these caches, measured in KBytes. Setting the capacity lower than the
* current amount of space currently in use may cause cache entries to be
* evicted from the cache to accomodate the requested capacity.
*/
attribute PRUint32 diskCacheCapacity;
/**
* This attribute sets/gets the capacity of the memory cache, measured in
* KBytes. Setting the capacity lower than the current amount of space
* currently in use may cause cache entries to be evicted from the cache to
* accomodate the requested capacity.
*/
attribute PRUint32 memCacheCapacity;
/**
* This attribute must be set before attempting to store into the disk cache.
*/
attribute nsIFileSpec diskCacheFolder;
};
%{ C++
// ProgID prefix for Components that implement this interface
#define NS_NETWORK_CACHE_MANAGER_PROGID NS_NETWORK_CACHE_PROGID "?name=manager"
%}

View File

@@ -1,125 +0,0 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* 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.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
#include "nsISupports.idl"
#include "nsrootidl.idl"
interface nsIFileSpec;
interface nsIChannel;
interface nsINetDataCache;
/**
* The nsINetDataCacheRecord represents a single entry in a database that
* caches data retrieved from the network. On top of this low-level interface
* to the raw record data, the cache manager implements a higher-level record
* interface, nsICachedNetData. Each instance of nsINetDataCacheRecord is
* (internally) associated with a parent database, an instance of the
* nsINetDataCache interface. This interface is essentially a pseudo-private
* API for the cache manager. Other clients should never use this interface.
*
* Each cache record may contain both content and metadata. The content may
* be, for example, GIF image data or HTML, and it is accessed through
* nsIChannel's streaming API. The opaque metadata, which may contain HTTP
* headers among other things, is accessed as a contiguous byte array. Each
* entry in the cache is indexed by two different keys: a unique record id
* number, generated by the cache, and an opaque string. The latter contains
* the URI and other secondary key information, e.g. HTTP form post key/value
* pairs.
*
* The nsINetDataCacheRecord interface is agnostic as to where the data is
* stored and whether the storage is volatile or persistent. The memory cache,
* the disk cache, a flat-file cache and any read-only extension caches must
* all implement this interface.
*
* @See nsICachedNetData
* @See nsINetDataCache
* @See nsINetDataDiskCache
* @See nsINetDataCacheManager
*/
interface nsILoadGroup;
[scriptable, uuid(fdcdd6a0-7461-11d3-90ca-0040056a906e)]
interface nsINetDataCacheRecord : nsISupports
{
/**
* As far as the nsINetDataCacheRecord implementation is concerned, the
* cache entry database key is an opaque blob, but it's intended to contain
* both the URI and any secondary keys, such as HTTP post data.
*/
void getKey(out unsigned long length, [size_is(length), retval] out string key);
/**
* A persistent record number assigned by the cache which must be unique
* among all entries stored within the same cache. The record ID serves as
* an alternate key to the cache record. Providing that they satisfy the
* afforementioned uniqueness requirement, record IDs can be assigned any
* value by the database except that they may never be zero.
*/
readonly attribute PRInt32 recordID;
/**
* Opaque data which can be updated for each cache entry independently of
* the content data. This data is a combination of protocol-independent
* data provided by the cache manager and protocol-specific meta-data,
* e.g. HTTP headers.
*/
void getMetaData(out PRUint32 length, [size_is(length), retval] out string metaData);
void setMetaData(in PRUint32 length, [size_is(length)] in string data);
/**
* Number of content bytes stored in the cache, i.e. via the nsIChannel
* streaming APIs. This may be less than the complete content length if a
* partial cache fill occurred. Additionally, the cached content can be
* truncated by reducing the value of this attribute. When this attribute
* is set to zero the associated cache disk file, if any, should be
* deleted.
*/
attribute PRUint32 storedContentLength;
/**
* Delete this cache entry and its associated content.
*/
void delete();
/**
* Create a channel for reading or writing a stream of content into the
* entry. However, many of the nsIChannel methods may return
* NS_NOT_IMPLEMENTED, including:
*
* + GetURI()
* + GetContentType()
* + GetContentLength()
*/
nsIChannel newChannel(in nsILoadGroup loadGroup);
/**
* If a cache is implemented such that it stores each URI's content in an
* individual disk file, this method will identify the file corresponding
* to this record. This may be used to implement the "stream-as-file"
* semantics required by some plugins and by the 'jar:' protocol handler.
* However, not all cache implementations are *required* to store the data
* from each URI in an individual file, so it is acceptable for an
* implementation of this method to signal NS_NOT_IMPLEMENTED.
*/
readonly attribute nsIFileSpec filename;
};

View File

@@ -1,42 +0,0 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* 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.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
#include "nsINetDataCache.idl"
interface nsIFileSpec;
/**
/**
* A network-data disk cache is used to persistently cache the responses to
* network retrieval commands. Each cache entry may contain both content,
* e.g. GIF image data, and associated metadata, e.g. HTTP headers.
*/
[scriptable, uuid(6408e390-6f13-11d3-90c8-000064657374)]
interface nsINetDataDiskCache : nsINetDataCache
{
/**
* This attribute must be set before calling any other methods of this
* interface.
*/
attribute nsIFileSpec diskCacheFolder;
};

View File

@@ -1,106 +0,0 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* 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 client code, released
* March 31, 1998.
*
* 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.
*
* Contributor(s):
* Scott Furman, fur@netscape.com
*/
#include "nsrootidl.idl"
#include "nsISupports.idl"
interface nsIFileSpec;
interface nsIStreamAsFileObserver;
/**
* In addition to enhancing effective network response time via caching, the
* cache manager serves a second purpose by providing the stream-as-file
* service required by traditional browser plugins and the jar: protocol
* handler. The interface below provides a means for a client to determine the
* filename associated with a stream and to detect modification/deletion of
* that file.
*/
[scriptable, uuid(0eedbbf0-92d9-11d3-90d3-0040056a906e)]
interface nsIStreamAsFile : nsISupports
{
/**
* Filename containing stream-as-file
*/
readonly attribute nsIFileSpec fileSpec;
/**
* Add an observer for this cache record. When the cache wants to delete
* or truncate a record, so as to make space for another cache entry's
* content data, it will call <code>aObserver</code>'s Observe() method,
* passing the nsIStreamAsFile instance as the <code>aSubject</code>
* argument and an appropriate message. If the observer does not wish to
* inhibit deletion/truncation, it should Release() any references it has to the
* cache record.
*
* @See nsIStreamAsFileObserver
*/
void addObserver(in nsIStreamAsFileObserver aObserver);
/**
* Delete an observer that was added by the AddObserver() method.
*/
void removeObserver(in nsIStreamAsFileObserver aObserver);
};
/**
* This interface can be implemented by a client to receive notifications of
* either modification or deletion of a file created by the cache manager using
* the stream-as-file semantics.
*/
[scriptable, uuid(a26e27c0-92da-11d3-90d3-0040056a906e)]
interface nsIStreamAsFileObserver : nsISupports
{
/**
* Flag bits for argument to Observe() method.
*/
const long NOTIFY_AVAILABLE = 1 << 0; // Stream-as-file now available for reading
const long NOTIFY_ERROR = 1 << 1; // Error while loading stream / creating file
const long REQUEST_DELETION = 1 << 2; // Cache manager wishes to delete/truncate file
const long INVALIDATE = 1 << 3; // File is out-of-date
// Convenience value
const long MAKE_UNAVAILABLE = REQUEST_DELETION | INVALIDATE;
/**
* Receive either a notification or a request concerning a file that has
* been opened using stream-as-file. The aMessage and aError arguments
* have varying values depending on the nature of the notification.
* aMessage is set to NOTIFY_AVAILABLE when a complete stream has been read
* and stored on disk in a file. At that point, and no sooner, may the
* filename attribute of the associated nsIStreamAsFile be accessed via the
* associated nsIStreamAsFile interface. If the aMessage argument is
* NOTIFY_ERROR, the aError argument contains the relevant error code. If
* the aMessage argument is either REQUEST_DELETION or REQUEST_TRUNCATION,
* the callee should immediately Release() all references to the
* nsIStreamAsFile (and any references to its associated nsICachedNetData
* instances), unless it wishes to inhibit the requested file modification.
* If the aMessage argument is INVALIDATE, the cache manager is replacing
* the file with a more recent version. If a client wants to continue
* using the (now out-of-date) file, it must delete it when it has finished,
* as the cache manager will effectively relinquished ownership of the
* file.
*/
void ObserveStreamAsFile(in nsIStreamAsFile aStreamAsFile,
in PRUint32 aMessage,
in nsresult aError);
};

View File

@@ -1,4 +1,4 @@
#
#!gmake
# The contents of this file are subject to the Netscape Public License
# Version 1.0 (the "NPL"); you may not use this file except in
# compliance with the NPL. You may obtain a copy of the NPL at
@@ -13,38 +13,18 @@
# Communications Corporation. Portions created by Netscape are
# Copyright (C) 1998 Netscape Communications Corporation. All Rights
# Reserved.
#
DEPTH = ../../../..
DEPTH = ..
topsrcdir = @top_srcdir@
srcdir = @srcdir@
VPATH = @srcdir@
srcdir = @srcdir@
include $(DEPTH)/config/autoconf.mk
REQUIRES = libreg xpcom
DIRS = public src
CPPSRCS = \
diskcache.cpp \
$(NULL)
SIMPLE_PROGRAMS = $(CPPSRCS:.cpp=)
ifdef NO_LD_ARCHIVE_FLAGS
LOST_SYM_LIBS = -lxpcomds_s -lxptinfo -lmozreg_s
ifdef ENABLE_TESTS
DIRS += tests
endif
LIBS = \
-lmozjs \
-lxpcom \
-lmozdbm_s \
$(MOZ_NECKO_UTIL_LIBS) \
$(LOST_SYM_LIBS) \
$(NSPR_LIBS) \
$(NULL)
include $(topsrcdir)/config/rules.mk
LOCAL_INCLUDES = -I$(srcdir)/..
DEFINES += -DUSE_NSREG -DCACHE

6027
mozilla/xpcom/base/IIDS.h Normal file

File diff suppressed because it is too large Load Diff

170
mozilla/xpcom/base/nsAgg.h Normal file
View File

@@ -0,0 +1,170 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
* Reserved.
*/
#ifndef nsAgg_h___
#define nsAgg_h___
#include "nsISupports.h"
/**
* Outer objects can implement nsIOuter if they choose, allowing them to
* get notification if their inner objects (children) are effectively freed.
* This allows them to reset any state associated with the inner object and
* potentially unload it.
*/
class nsIOuter : public nsISupports {
public:
/**
* This method is called whenever an inner object's refcount is about to
* become zero and the inner object should be released by the outer. This
* allows the outer to clean up any state associated with the inner and
* potentially unload the inner object. This method should call
* inner->Release().
*/
NS_IMETHOD
ReleaseInner(nsISupports* inner) = 0;
};
#define NS_IOUTER_IID \
{ /* ea0bf9f0-3d67-11d2-8163-006008119d7a */ \
0xea0bf9f0, \
0x3d67, \
0x11d2, \
{0x81, 0x63, 0x00, 0x60, 0x08, 0x11, 0x9d, 0x7a} \
}
////////////////////////////////////////////////////////////////////////////////
// Put this in your class's declaration:
#define NS_DECL_AGGREGATED \
NS_DECL_ISUPPORTS \
\
protected: \
\
/* You must implement this operation instead of the nsISupports */ \
/* methods if you inherit from nsAggregated. */ \
NS_IMETHOD \
AggregatedQueryInterface(const nsIID& aIID, void** aInstancePtr); \
\
class Internal : public nsISupports { \
public: \
\
Internal() {} \
\
NS_IMETHOD QueryInterface(const nsIID& aIID, \
void** aInstancePtr); \
NS_IMETHOD_(nsrefcnt) AddRef(void); \
NS_IMETHOD_(nsrefcnt) Release(void); \
\
}; \
\
friend class Internal; \
\
nsISupports* fOuter; \
Internal fAggregated; \
\
nsISupports* GetInner(void) { return &fAggregated; } \
\
public: \
// Put this in your class's constructor:
#define NS_INIT_AGGREGATED(outer) \
PR_BEGIN_MACRO \
NS_INIT_REFCNT(); \
fOuter = outer; \
PR_END_MACRO
// Put this in your class's implementation file:
#define NS_IMPL_AGGREGATED(_class) \
NS_IMETHODIMP \
_class::QueryInterface(const nsIID& aIID, void** aInstancePtr) \
{ \
/* try our own interfaces first before delegating to outer */ \
nsresult rslt = AggregatedQueryInterface(aIID, aInstancePtr); \
if (rslt != NS_OK && fOuter) \
return fOuter->QueryInterface(aIID, aInstancePtr); \
else \
return rslt; \
} \
\
NS_IMETHODIMP_(nsrefcnt) \
_class::AddRef(void) \
{ \
++mRefCnt; /* keep track of our refcount as well as outer's */ \
if (fOuter) \
return NS_ADDREF(fOuter); \
else \
return mRefCnt; \
} \
\
NS_IMETHODIMP_(nsrefcnt) \
_class::Release(void) \
{ \
if (fOuter) { \
nsISupports* outer = fOuter; /* in case we release ourself */ \
nsIOuter* outerIntf; \
static NS_DEFINE_IID(kIOuterIID, NS_IOUTER_IID); \
if (mRefCnt == 1 && \
outer->QueryInterface(kIOuterIID, \
(void**)&outerIntf) == NS_OK) { \
outerIntf->ReleaseInner(GetInner()); \
outerIntf->Release(); \
} \
else \
--mRefCnt; /* keep track of our refcount as well as outer's */ \
return outer->Release(); \
} \
else { \
if (--mRefCnt == 0) { \
delete this; \
return 0; \
} \
return mRefCnt; \
} \
} \
\
NS_IMETHODIMP \
_class::Internal::QueryInterface(const nsIID& aIID, void** aInstancePtr) \
{ \
_class* agg = (_class*)((char*)(this) - offsetof(_class, fAggregated)); \
return agg->AggregatedQueryInterface(aIID, aInstancePtr); \
} \
\
NS_IMETHODIMP_(nsrefcnt) \
_class::Internal::AddRef(void) \
{ \
_class* agg = (_class*)((char*)(this) - offsetof(_class, fAggregated)); \
return ++agg->mRefCnt; \
} \
\
NS_IMETHODIMP_(nsrefcnt) \
_class::Internal::Release(void) \
{ \
_class* agg = (_class*)((char*)(this) - offsetof(_class, fAggregated)); \
if (--agg->mRefCnt == 0) { \
delete agg; \
return 0; \
} \
return agg->mRefCnt; \
} \
#endif /* nsAgg_h___ */

View File

@@ -0,0 +1,129 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
* Reserved.
*/
////////////////////////////////////////////////////////////////////////////////
// Implementation of nsIAllocator using NSPR
////////////////////////////////////////////////////////////////////////////////
#include "nsAllocator.h"
static NS_DEFINE_IID(kISupportsIID, NS_ISUPPORTS_IID);
static NS_DEFINE_IID(kIAllocatorIID, NS_IALLOCATOR_IID);
nsAllocator::nsAllocator(nsISupports* outer)
{
NS_INIT_AGGREGATED(outer);
}
nsAllocator::~nsAllocator(void)
{
}
NS_IMPL_AGGREGATED(nsAllocator);
NS_METHOD
nsAllocator::AggregatedQueryInterface(const nsIID& aIID, void** aInstancePtr)
{
if (NULL == aInstancePtr) {
return NS_ERROR_NULL_POINTER;
}
if (aIID.Equals(kIAllocatorIID) ||
aIID.Equals(kISupportsIID)) {
*aInstancePtr = (void*) this;
AddRef();
return NS_OK;
}
return NS_NOINTERFACE;
}
NS_METHOD
nsAllocator::Create(nsISupports* outer, const nsIID& aIID, void* *aInstancePtr)
{
if (outer && !aIID.Equals(kISupportsIID))
return NS_NOINTERFACE; // XXX right error?
nsAllocator* mm = new nsAllocator(outer);
if (mm == NULL)
return NS_ERROR_OUT_OF_MEMORY;
mm->AddRef();
if (aIID.Equals(kISupportsIID))
*aInstancePtr = mm->GetInner();
else
*aInstancePtr = mm;
return NS_OK;
}
////////////////////////////////////////////////////////////////////////////////
NS_METHOD_(void*)
nsAllocator::Alloc(PRUint32 size)
{
return PR_Malloc(size);
}
NS_METHOD_(void*)
nsAllocator::Realloc(void* ptr, PRUint32 size)
{
return PR_Realloc(ptr, size);
}
NS_METHOD
nsAllocator::Free(void* ptr)
{
PR_Free(ptr);
return NS_OK;
}
NS_METHOD
nsAllocator::HeapMinimize(void)
{
#ifdef XP_MAC
// This used to live in the memory allocators no Mac, but does no more
// Needs to be hooked up in the new world.
// CallCacheFlushers(0x7fffffff);
#endif
return NS_OK;
}
////////////////////////////////////////////////////////////////////////////////
nsAllocatorFactory::nsAllocatorFactory(void)
{
}
nsAllocatorFactory::~nsAllocatorFactory(void)
{
}
static NS_DEFINE_IID(kIFactoryIID, NS_IFACTORY_IID);
NS_IMPL_ISUPPORTS(nsAllocatorFactory, kIFactoryIID);
NS_METHOD
nsAllocatorFactory::CreateInstance(nsISupports *aOuter,
REFNSIID aIID,
void **aResult)
{
return nsAllocator::Create(aOuter, aIID, aResult);
}
NS_METHOD
nsAllocatorFactory::LockFactory(PRBool aLock)
{
return NS_OK; // XXX what?
}
////////////////////////////////////////////////////////////////////////////////

View File

@@ -0,0 +1,93 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
* Reserved.
*/
////////////////////////////////////////////////////////////////////////////////
// Implementation of nsIAllocator using NSPR
////////////////////////////////////////////////////////////////////////////////
#ifndef nsAllocator_h__
#define nsAllocator_h__
#include "nsIAllocator.h"
#include "prmem.h"
#include "nsAgg.h"
class nsAllocator : public nsIAllocator {
public:
/**
* Allocates a block of memory of a particular size.
*
* @param size - the size of the block to allocate
* @result the block of memory
*/
NS_IMETHOD_(void*) Alloc(PRUint32 size);
/**
* Reallocates a block of memory to a new size.
*
* @param ptr - the block of memory to reallocate
* @param size - the new size
* @result the rellocated block of memory
*/
NS_IMETHOD_(void*) Realloc(void* ptr, PRUint32 size);
/**
* Frees a block of memory.
*
* @param ptr - the block of memory to free
*/
NS_IMETHOD Free(void* ptr);
/**
* Attempts to shrink the heap.
*/
NS_IMETHOD HeapMinimize(void);
////////////////////////////////////////////////////////////////////////////
nsAllocator(nsISupports* outer);
virtual ~nsAllocator(void);
NS_DECL_AGGREGATED
static NS_METHOD
Create(nsISupports* outer, const nsIID& aIID, void* *aInstancePtr);
};
////////////////////////////////////////////////////////////////////////////////
#include "nsIFactory.h"
class nsAllocatorFactory : nsIFactory {
public:
NS_IMETHOD CreateInstance(nsISupports *aOuter,
REFNSIID aIID,
void **aResult);
NS_IMETHOD LockFactory(PRBool aLock);
nsAllocatorFactory(void);
~nsAllocatorFactory(void);
NS_DECL_ISUPPORTS
};
////////////////////////////////////////////////////////////////////////////////
#endif // nsAllocator_h__

View File

@@ -0,0 +1,54 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
* Reserved.
*/
#include "nsCOMPtr.h"
void
nsCOMPtr_base::assign_with_AddRef( nsISupports* rawPtr )
{
if ( rawPtr )
NSCAP_ADDREF(rawPtr);
if ( mRawPtr )
NSCAP_RELEASE(mRawPtr);
mRawPtr = rawPtr;
}
void
nsCOMPtr_base::assign_with_QueryInterface( nsISupports* rawPtr, const nsIID& iid, nsresult* result )
{
nsresult status = NS_OK;
if ( !rawPtr || !NS_SUCCEEDED( status = rawPtr->QueryInterface(iid, NSCAP_REINTERPRET_CAST(void**, &rawPtr)) ) )
rawPtr = 0;
if ( mRawPtr )
NSCAP_RELEASE(mRawPtr);
mRawPtr = rawPtr;
if ( result )
*result = status;
}
void**
nsCOMPtr_base::begin_assignment()
{
if ( mRawPtr )
NSCAP_RELEASE(mRawPtr);
mRawPtr = 0;
return NSCAP_REINTERPRET_CAST(void**, &mRawPtr);
}

View File

@@ -0,0 +1,668 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
* Reserved.
*/
#ifndef nsCOMPtr_h___
#define nsCOMPtr_h___
// Wrapping includes can speed up compiles (see "Large Scale C++ Software Design")
#ifndef nsDebug_h___
#include "nsDebug.h"
// for |NS_PRECONDITION|
#endif
#ifndef nsISupports_h___
#include "nsISupports.h"
// for |nsresult|, |NS_ADDREF|, et al
#endif
/*
TO DO...
+ make alternative function for |getter_AddRefs| (or something)
+ make constructor for |nsQueryInterface| explicit (suddenly construct/assign from raw pointer becomes illegal)
+ Improve internal documentation
+ mention *&
+ alternatives for comparison
+ do_QueryInterface
*/
/* USER MANUAL
See also:
<http://www.meer.net/ScottCollins/doc/nsCOMPtr.html>, or
<http://www.mozilla.org/projects/xpcom/nsCOMPtr.html>
What is |nsCOMPtr|?
|nsCOMPtr| is a `smart-pointer'. It is a template class that acts, syntactically,
just like an ordinary pointer in C or C++, i.e., you can apply |*| or |->| to it to
`get to' what it points at. |nsCOMPtr| is smart in that, unlike a raw COM
interface pointer, |nsCOMPtr| manages |AddRef|, |Release|, and |QueryInterface|
_for_ you.
For instance, here is a typical snippet of code (at its most compact) where you assign
a COM interface pointer into a member variable:
NS_IF_RELEASE(mFoop); // If I have one already, I must release it before over-writing it.
if ( mFooP = aPtr ) // Now it's safe to assign it in, and, if it's not NULL
mFooP->AddRef(); // I must |AddRef| it, since I'll be holding on to it.
If our member variable |mFooP| were a |nsCOMPtr|, however, the snippet above
would look like this:
mFoop = aPtr; // Note: automatically |Release|s the old and |AddRef|s the new
|nsCOMPtr| helps you write code that is leak-proof, exception safe, and significantly
less verbose than you would with raw COM interface pointers. With |nsCOMPtr|, you
may never have to call |AddRef|, |Release|, or |QueryInterface| by hand.
You still have to understand COM. You still have to know which functions return
interface pointers that have already been |AddRef|ed and which don't. You still
have to ensure your program logic doesn't produce circularly referencing garbage.
|nsCOMPtr| is not a panacea. It is, however, helpful, easy to use, well-tested,
and polite. It doesn't require that a function author cooperate with you, nor does
your use force others to use it.
Where should I use |nsCOMPtr|?
...
Where _shouldn't_ I use |nsCOMPtr|?
In public interfaces... [[others]]
How does a |nsCOMPtr| differ from a raw pointer?
A |nsCOMPtr| differs, syntactically, from a raw COM interface pointer in three
ways:
+ It's declared differently, e.g.,
// instead of saying // you say
IFoo* fooP; nsCOMPtr<IFoo> fooP;
+ You can't call |AddRef| or |Release| through it,
fooP->AddRef(); // OK fooP->AddRef(); // Error: no permission
fooP->Release(); // OK fooP->Release(); // Error: no permission
+ You can't just apply an |&| to it to pass it to the typical `getter' function
AcquireFoo(&fooP); AcquireFoo( getter_AddRefs(fooP) );
GetFoo(&fooP); GetFoo( getter_doesnt_AddRef(fooP) );
How do I use |nsCOMPtr|?
Typically, you can use a |nsCOMPtr| exactly as you would a standard COM
interface pointer:
IFoo* fooP; nsCOMPtr<IFoo> fooP;
// ... // ...
fooP->SomeFunction(x, y, z); fooP->SomeFunction(x, y, z);
AnotherFunction(fooP); AnotherFunction(fooP);
if ( fooP ) if ( fooP )
// ... // ...
if ( fooP == barP ) if ( fooP == barP )
// ... // ...
There are some differences, though. In particular, you can't call |AddRef| or |Release|
through a |nsCOMPtr| directly, nor would you need to. |AddRef| is called for you
whenever you assign a COM interface pointer _into_ a |nsCOMPtr|. |Release| is
called on the old value, and also when the |nsCOMPtr| goes out of scope. Trying
to call |AddRef| or |Release| yourself will generate a compile-time error.
fooP->AddRef(); // fooP->AddRef(); // ERROR: no permission
fooP->Release(); // fooP->Release(); // ERROR: no permission
The final difference is that a bare |nsCOMPtr| (or rather a pointer to it) can't
be supplied as an argument to a function that `fills in' a COM interface pointer.
Rather it must be wrapped with a utility call that says whether the function calls
|AddRef| before returning, e.g.,
...->QueryInterface(riid, &fooP) ...->QueryInterface(riid, getter_AddRefs(fooP))
LookupFoo(&fooP); LookupFoo( getter_doesnt_AddRef(fooP) );
Don't worry. It's a compile-time error if you forget to wrap it.
Compare the raw-pointer way...
IFoo* foo = 0;
nsresult status = CreateIFoo(&foo);
if ( NS_SUCCEEDED(status) )
{
IBar* bar = 0;
if ( NS_SUCCEEDED(status = foo->QueryInterface(riid, &bar)) )
{
IFooBar* foobar = 0;
if ( NS_SUCCEEDED(status = CreateIFooBar(foo, bar, &foobar)) )
{
foobar->DoTheReallyHardThing();
foobar->Release();
}
bar->Release();
}
foo->Release();
}
To the smart-pointer way...
nsCOMPtr<IFoo> fooP;
nsresult status = CreateIFoo( getter_AddRefs(fooP) );
if ( NS_SUCCEEDED(status) )
if ( nsCOMPtr<IBar> barP( fooP ) )
{
nsCOMPtr<IFooBar> fooBarP;
if ( NS_SUCCEEDED(status = CreateIFooBar(fooP, barP, getter_AddRefs(fooBarP))) )
fooBarP->DoTheReallyHardThing();
}
Is there an easy way to convert my current code?
...
What do I have to beware of?
VC++ < 6.0 _can't_ handle the following situation
class nsIFoo; // forward declare some class
// ...
nsCOMPtr<nsIFoo> bar; // ERROR: incomplete type nsIFoo, etc.
Instead, you must make sure that you actually defined the underlying interface class, e.g.,
#include "nsIFoo.h" // fully defines |class nsIFoo|
// ...
nsCOMPtr<nsIFoo> bar; // no problem
Why is this? It's because VC++ tries to instantiate every member of the template
as soon as it sees the template declarations. Bad compiler. No cookie!
[[Thanks to mjudge, waterson, and pinkerton on this one.]]
Why does |getter_AddRefs| have such a funny name? I.e., why doesn't it follow our
naming conventions?
|getter_AddRefs| and |getter_doesnt_AddRef| use underscores for the same
reason our special macros do, quoting from our coding conventions "...to make them
stick out like a sore thumb". Note also that since |AddRef| is one word,
|getter_AddRefs| and |getter_doesnt_AddRef| couldn't have the right spacing if only inter-
caps were used.
*/
/*
WARNING:
This file defines several macros for internal use only. These macros begin with the
prefix |NSCAP_|. Do not use these macros in your own code. They are for internal use
only for cross-platform compatibility, and are subject to change without notice.
*/
/*
Set up some |#define|s to turn off a couple of troublesome C++ features.
Interestingly, none of the compilers barf on template stuff.
Ideally, we would want declarations like these in a configuration file
that everybody would get. Deciding exactly how to do that should
be part of the process of moving from experimental to production.
Update: ramiro is working on getting these into the configuration system.
*/
#if defined(__GNUG__) && (__GNUC_MINOR__ <= 90) && !defined(SOLARIS)
#define NSCAP_NO_MEMBER_USING_DECLARATIONS
#if (defined(LINUX) || defined(__bsdi__)) && (__GNUC_MINOR__ <= 7)
#define NSCAP_NEED_UNUSED_VIRTUAL_IMPLEMENTATIONS
#endif
#endif
#if defined(SOLARIS) && !defined(__GNUG__)
#define NSCAP_NO_BOOL
#define NSCAP_NO_EXPLICIT
#define NSCAP_NO_NEW_CASTS
#define NSCAP_NO_MEMBER_USING_DECLARATIONS
#endif
#if defined(_MSC_VER) && (_MSC_VER<1100)
#define NSCAP_NO_EXPLICIT
#define NSCAP_NO_BOOL
#endif
#if defined(IRIX)
#define NSCAP_NO_MEMBER_USING_DECLARATIONS
#define NSCAP_NO_EXPLICIT
#define NSCAP_NO_NEW_CASTS
#define NSCAP_NO_BOOL
#endif
#ifdef NSCAP_NO_EXPLICIT
#define explicit
#endif
#ifndef NSCAP_NO_NEW_CASTS
#define NSCAP_REINTERPRET_CAST(T,x) reinterpret_cast<T>(x)
#else
#define NSCAP_REINTERPRET_CAST(T,x) ((T)(x))
#endif
#ifndef NSCAP_NO_BOOL
typedef bool NSCAP_BOOL;
#else
typedef PRBool NSCAP_BOOL;
#endif
#ifdef NSCAP_FEATURE_DEBUG_MACROS
#define NSCAP_ADDREF(ptr) NS_ADDREF(ptr)
#define NSCAP_RELEASE(ptr) NS_RELEASE(ptr)
#else
#define NSCAP_ADDREF(ptr) (ptr)->AddRef()
#define NSCAP_RELEASE(ptr) (ptr)->Release()
#endif
/*
WARNING:
VC++4.2 is very picky. To compile under VC++4.2, the classes must be defined
in an order that satisfies:
nsDerivedSafe < nsCOMPtr
nsDontAddRef < nsCOMPtr
nsCOMPtr < nsGetterAddRefs
The other compilers probably won't complain, so please don't reorder these
classes, on pain of breaking 4.2 compatibility.
*/
template <class T>
class nsDerivedSafe : public T
/*
No client should ever see or have to type the name of this class. It is the
artifact that makes it a compile-time error to call |AddRef| and |Release|
on a |nsCOMPtr|.
See |nsCOMPtr::operator->|, |nsCOMPtr::operator*|, et al.
*/
{
private:
#ifndef NSCAP_NO_MEMBER_USING_DECLARATIONS
using T::AddRef;
using T::Release;
#else
nsrefcnt AddRef();
nsrefcnt Release();
#endif
void operator delete( void* ); // NOT TO BE IMPLEMENTED
// declaring |operator delete| private makes calling delete on an interface pointer a compile error
nsDerivedSafe& operator=( const nsDerivedSafe& ); // NOT TO BE IMPLEMENTED
// you may not call |operator=()| through a dereferenced |nsCOMPtr|, because you'd get the wrong one
};
#if defined(NSCAP_NO_MEMBER_USING_DECLARATIONS) && defined(NSCAP_NEED_UNUSED_VIRTUAL_IMPLEMENTATIONS)
template <class T>
nsrefcnt
nsDerivedSafe<T>::AddRef()
{
return 0;
}
template <class T>
nsrefcnt
nsDerivedSafe<T>::Release()
{
return 0;
}
#endif
template <class T>
struct nsDontQueryInterface
/*
...
*/
{
explicit
nsDontQueryInterface( T* aRawPtr )
: mRawPtr(aRawPtr)
{
// nothing else to do here
}
T* mRawPtr;
};
template <class T>
inline
nsDontQueryInterface<T>
dont_QueryInterface( T* aRawPtr )
{
return nsDontQueryInterface<T>(aRawPtr);
}
struct nsQueryInterface
{
// explicit
nsQueryInterface( nsISupports* aRawPtr, nsresult* error = 0 )
: mRawPtr(aRawPtr),
mErrorPtr(error)
{
// nothing else to do here
}
nsISupports* mRawPtr;
nsresult* mErrorPtr;
};
inline
nsQueryInterface
do_QueryInterface( nsISupports* aRawPtr, nsresult* error = 0 )
{
return nsQueryInterface(aRawPtr, error);
}
template <class T>
struct nsDontAddRef
/*
...cooperates with |nsCOMPtr| to allow you to assign in a pointer _without_
|AddRef|ing it. You would rarely use this directly, but rather through the
machinery of |getter_AddRefs| in the argument list to functions that |AddRef|
their results before returning them to the caller.
See also |getter_AddRefs()| and |class nsGetterAddRefs|.
*/
{
explicit
nsDontAddRef( T* aRawPtr )
: mRawPtr(aRawPtr)
{
// nothing else to do here
}
T* mRawPtr;
};
template <class T>
inline
nsDontAddRef<T>
dont_AddRef( T* aRawPtr )
/*
...makes typing easier, because it deduces the template type, e.g.,
you write |dont_AddRef(fooP)| instead of |nsDontAddRef<IFoo>(fooP)|.
Like the class it is shorthand for, you would rarely use this directly,
but rather through |getter_AddRefs|.
*/
{
return nsDontAddRef<T>(aRawPtr);
}
class nsCOMPtr_base
{
public:
nsCOMPtr_base( nsISupports* rawPtr = 0 )
: mRawPtr(rawPtr)
{
// nothing else to do here
}
~nsCOMPtr_base()
{
if ( mRawPtr )
NSCAP_RELEASE(mRawPtr);
}
NS_EXPORT void assign_with_AddRef( nsISupports* );
NS_EXPORT void assign_with_QueryInterface( nsISupports*, const nsIID&, nsresult* );
NS_EXPORT void** begin_assignment();
protected:
nsISupports* mRawPtr;
};
template <class T>
class nsCOMPtr : private nsCOMPtr_base
/*
...
*/
{
public:
typedef T element_type;
nsCOMPtr()
// : nsCOMPtr_base(0)
{
// nothing else to do here
}
nsCOMPtr( const nsQueryInterface& aSmartPtr )
// : nsCOMPtr_base(0)
{
assign_with_QueryInterface(aSmartPtr.mRawPtr, T::IID(), aSmartPtr.mErrorPtr);
}
nsCOMPtr( const nsDontAddRef<T>& aSmartPtr )
: nsCOMPtr_base(aSmartPtr.mRawPtr)
{
// nothing else to do here
}
nsCOMPtr( const nsDontQueryInterface<T>& aSmartPtr )
: nsCOMPtr_base(aSmartPtr.mRawPtr)
{
if ( mRawPtr )
NSCAP_ADDREF(mRawPtr);
}
nsCOMPtr( const nsCOMPtr<T>& aSmartPtr )
: nsCOMPtr_base(aSmartPtr.mRawPtr)
{
if ( mRawPtr )
NSCAP_ADDREF(mRawPtr);
}
nsCOMPtr<T>&
operator=( const nsQueryInterface& rhs )
{
assign_with_QueryInterface(rhs.mRawPtr, T::IID(), rhs.mErrorPtr);
return *this;
}
nsCOMPtr<T>&
operator=( const nsDontAddRef<T>& rhs )
{
if ( mRawPtr )
NSCAP_RELEASE(mRawPtr);
mRawPtr = rhs.mRawPtr;
return *this;
}
nsCOMPtr<T>&
operator=( const nsDontQueryInterface<T>& rhs )
{
assign_with_AddRef(rhs.mRawPtr);
return *this;
}
nsCOMPtr<T>&
operator=( const nsCOMPtr& rhs )
{
assign_with_AddRef(rhs.mRawPtr);
return *this;
}
nsDerivedSafe<T>*
get() const
// returns a |nsDerivedSafe<T>*| to deny clients the use of |AddRef| and |Release|
{
return NSCAP_REINTERPRET_CAST(nsDerivedSafe<T>*, mRawPtr);
}
nsDerivedSafe<T>*
operator->() const
// returns a |nsDerivedSafe<T>*| to deny clients the use of |AddRef| and |Release|
{
NS_PRECONDITION(mRawPtr != 0, "You can't dereference a NULL nsCOMPtr with operator->().");
return get();
}
nsDerivedSafe<T>&
operator*() const
// returns a |nsDerivedSafe<T>*| to deny clients the use of |AddRef| and |Release|
{
NS_PRECONDITION(mRawPtr != 0, "You can't dereference a NULL nsCOMPtr with operator*().");
return *get();
}
operator nsDerivedSafe<T>*() const
{
return get();
}
#if 0
private:
friend class nsGetterAddRefs<T>;
/*
In a perfect world, the following member function, |StartAssignment|, would be private.
It is and should be only accessed by the closely related class |nsGetterAddRefs<T>|.
Unfortunately, some compilers---most notably VC++5.0---fail to grok the
friend declaration above or in any alternate acceptable form. So, physically
it will be public (until our compilers get smarter); but it is not to be
considered part of the logical public interface.
*/
#endif
T**
StartAssignment()
{
return NSCAP_REINTERPRET_CAST(T**, begin_assignment());
}
};
template <class T>
class nsGetterAddRefs
/*
...
This class is designed to be used for anonymous temporary objects in the
argument list of calls that return COM interface pointers, e.g.,
nsCOMPtr<IFoo> fooP;
...->QueryInterface(iid, nsGetterAddRefs<IFoo>(fooP))
...->QueryInterface(iid, getter_AddRefs(fooP))
When initialized with a |nsCOMPtr|, as in the example above, it returns
a |void**| (or |T**| if needed) that the outer call (|QueryInterface| in this
case) can fill in. When this temporary object goes out of scope, just after
the call returns, its destructor assigned the resulting interface pointer, i.e.,
|QueryInterface|s result, into the |nsCOMPtr| it was initialized with.
See also |nsGetterDoesntAddRef|.
*/
{
public:
explicit
nsGetterAddRefs( nsCOMPtr<T>& aSmartPtr )
: mTargetSmartPtr(aSmartPtr)
{
// nothing else to do
}
operator void**()
{
// NS_PRECONDITION(mTargetSmartPtr != 0, "getter_AddRefs into no destination");
return NSCAP_REINTERPRET_CAST(void**, mTargetSmartPtr.StartAssignment());
}
T*&
operator*()
{
// NS_PRECONDITION(mTargetSmartPtr != 0, "getter_AddRefs into no destination");
return *(mTargetSmartPtr.StartAssignment());
}
operator T**()
{
// NS_PRECONDITION(mTargetSmartPtr != 0, "getter_AddRefs into no destination");
return mTargetSmartPtr.StartAssignment();
}
private:
nsCOMPtr<T>& mTargetSmartPtr;
};
template <class T>
inline
nsGetterAddRefs<T>
getter_AddRefs( nsCOMPtr<T>& aSmartPtr )
/*
Used around a |nsCOMPtr| when
...makes the class |nsGetterAddRefs<T>| invisible.
*/
{
return nsGetterAddRefs<T>(aSmartPtr);
}
#endif // !defined(nsCOMPtr_h___)

218
mozilla/xpcom/base/nsCom.h Normal file
View File

@@ -0,0 +1,218 @@
/* -*- 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.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
* Reserved.
*/
#ifndef nsCom_h__
#define nsCom_h__
/*
* API Import/Export macros
*/
#ifdef _IMPL_NS_COM
#ifdef XP_PC
#define NS_COM _declspec(dllexport)
#else /* !XP_PC */
#define NS_COM
#endif /* !XP_PC */
#else /* !_IMPL_NS_COM */
#ifdef XP_PC
#define NS_COM _declspec(dllimport)
#else /* !XP_PC */
#define NS_COM
#endif /* !XP_PC */
#endif /* !_IMPL_NS_COM */
/*
* DLL Export macro
*/
#if defined(XP_PC)
#define NS_EXPORT _declspec(dllexport)
#define NS_EXPORT_(type) _declspec(dllexport) type __stdcall
#define NS_IMETHOD_(type) virtual type __stdcall
#define NS_IMETHOD virtual nsresult __stdcall
#define NS_IMETHODIMP_(type) type __stdcall
#define NS_IMETHODIMP nsresult __stdcall
#define NS_METHOD_(type) type __stdcall
#define NS_METHOD nsresult __stdcall
#elif defined(XP_MAC)
#define NS_EXPORT __declspec(export)
#define NS_EXPORT_(type) __declspec(export) type
#define NS_IMETHOD_(type) virtual type
#define NS_IMETHOD virtual nsresult
#define NS_IMETHODIMP_(type) type
#define NS_IMETHODIMP nsresult
#define NS_METHOD_(type) type
#define NS_METHOD nsresult
#else /* !XP_PC && !XP_MAC */
#define NS_EXPORT
#define NS_EXPORT_(type) type
#define NS_IMETHOD_(type) virtual type
#define NS_IMETHOD virtual nsresult
#define NS_IMETHODIMP_(type) type
#define NS_IMETHODIMP nsresult
#define NS_METHOD_(type) type
#define NS_METHOD nsresult
#endif /* !XP_PC */
/* use these functions to associate get/set methods with a
C++ member variable
*/
#define NS_METHOD_GETTER(_method, _type, _member) \
_method(_type* aResult) \
{\
if (!aResult) return NS_ERROR_NULL_POINTER; \
*aResult = _member; \
return NS_OK; \
}
#define NS_METHOD_SETTER(_method, _type, _member) \
_method(_type aResult) \
{ \
_member = aResult; \
return NS_OK; \
}
/*
* special for strings to get/set char* strings
* using PL_strdup and PR_FREEIF
*/
#define NS_METHOD_GETTER_STR(_method,_member) \
_method(char* *aString)\
{\
if (!aString) return NS_ERROR_NULL_POINTER; \
*aString = PL_strdup(_member); \
return NS_OK; \
}
#define NS_METHOD_SETTER_STR(_method, _member) \
_method(char *aString)\
{\
PR_FREEIF(_member);\
if (aString) _member = PL_strdup(aString); \
else _member = nsnull;\
return NS_OK; \
}
/* Getter/Setter macros.
Usage:
NS_IMPL_[CLASS_]GETTER[_<type>](method, [type,] member);
NS_IMPL_[CLASS_]SETTER[_<type>](method, [type,] member);
NS_IMPL_[CLASS_]GETSET[_<type>]([class, ]postfix, [type,] member);
where:
CLASS_ - implementation is inside a class definition
(otherwise the class name is needed)
Do NOT use in publicly exported header files, because
the implementation may be included many times over.
Instead, use the non-CLASS_ version.
_<type> - For more complex (STR, IFACE) data types
(otherwise the simple data type is needed)
method - name of the method, such as GetWidth or SetColor
type - simple data type if required
member - class member variable such as m_width or mColor
class - the class name, such as Window or MyObject
postfix - Method part after Get/Set such as "Width" for "GetWidth"
Example:
class Window {
public:
NS_IMPL_CLASS_GETSET(Width, int, m_width);
NS_IMPL_CLASS_GETTER_STR(GetColor, m_color);
NS_IMETHOD SetColor(char *color);
private:
int m_width; // read/write
char *m_color; // readonly
};
// defined outside of class
NS_IMPL_SETTER_STR(Window::GetColor, m_color);
Questions/Comments to alecf@netscape.com
*/
/*
* Getter/Setter implementation within a class definition
*/
/* simple data types */
#define NS_IMPL_CLASS_GETTER(_method, _type, _member) \
NS_IMETHOD NS_METHOD_GETTER(_method, _type, _member)
#define NS_IMPL_CLASS_SETTER(_method, _type, _member) \
NS_IMETHOD NS_METHOD_SETTER(_method, _type, _member)
#define NS_IMPL_CLASS_GETSET(_postfix, _type, _member) \
NS_IMPL_CLASS_GETTER(Get##_postfix, _type, _member) \
NS_IMPL_CLASS_SETTER(Set##_postfix, _type, _member)
/* strings */
#define NS_IMPL_CLASS_GETTER_STR(_method, _member) \
NS_IMETHOD NS_METHOD_GETTER_STR(_method, _member)
#define NS_IMPL_CLASS_SETTER_STR(_method, _member) \
NS_IMETHOD NS_METHOD_SETTER_STR(_method, _member)
#define NS_IMPL_CLASS_GETSET_STR(_postfix, _member) \
NS_IMPL_CLASS_GETTER_STR(Get##_postfix, _member) \
NS_IMPL_CLASS_SETTER_STR(Set##_postfix, _member)
/* Getter/Setter implementation outside of a class definition */
/* simple data types */
#define NS_IMPL_GETTER(_method, _type, _member) \
NS_IMETHODIMP NS_METHOD_GETTER(_method, _type, _member)
#define NS_IMPL_SETTER(_method, _type, _member) \
NS_IMETHODIMP NS_METHOD_SETTER(_method, _type, _member)
#define NS_IMPL_GETSET(_class, _postfix, _type, _member) \
NS_IMPL_GETTER(_class::Get##_postfix, _type, _member) \
NS_IMPL_SETTER(_class::Set##_postfix, _type, _member)
/* strings */
#define NS_IMPL_GETTER_STR(_method, _member) \
NS_IMETHODIMP NS_METHOD_GETTER_STR(_method, _member)
#define NS_IMPL_SETTER_STR(_method, _member) \
NS_IMETHODIMP NS_METHOD_SETTER_STR(_method, _member)
#define NS_IMPL_GETSET_STR(_class, _postfix, _member) \
NS_IMPL_GETTER_STR(_class::Get##_postfix, _member) \
NS_IMPL_SETTER_STR(_class::Set##_postfix, _member)
#endif

View File

@@ -0,0 +1,169 @@
/* -*- 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.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
* Reserved.
*/
#include "nsDebug.h"
#include "prlog.h"
#if defined(_WIN32)
#include <windows.h>
#elif defined(XP_MAC)
#define TEMP_MAC_HACK
//------------------------
#ifdef TEMP_MAC_HACK
#include <MacTypes.h>
#include <Processes.h>
// TEMPORARY UNTIL WE HAVE MACINTOSH ENVIRONMENT VARIABLES THAT CAN TURN ON
// LOGGING ON MACINTOSH
// At this moment, NSPR's logging is a no-op on Macintosh.
#include <stdarg.h>
#include <stdio.h>
#undef PR_LOG
#define PR_LOG(module,level,args) dprintf args
static void dprintf(const char *format, ...)
{
va_list ap;
Str255 buffer;
va_start(ap, format);
buffer[0] = vsnprintf((char *)buffer + 1, sizeof(buffer) - 1, format, ap);
va_end(ap);
DebugStr(buffer);
}
#endif // TEMP_MAC_HACK
//------------------------
#endif
/**
* Implementation of the nsDebug methods. Note that this code is
* always compiled in, in case some other module that uses it is
* compiled with debugging even if this library is not.
*/
static PRLogModuleInfo* gDebugLog;
static void InitLog(void)
{
if (0 == gDebugLog) {
gDebugLog = PR_NewLogModule("nsDebug");
gDebugLog->level = PR_LOG_DEBUG;
}
}
NS_COM void nsDebug::Abort(const char* aFile, PRIntn aLine)
{
InitLog();
PR_LOG(gDebugLog, PR_LOG_ERROR,
("Abort: at file %s, line %d", aFile, aLine));
PR_LogFlush();
#if defined(_WIN32)
long* __p = (long*) 0x7;
*__p = 0x7;
#elif defined(XP_MAC)
ExitToShell();
#elif defined(XP_UNIX)
::abort();
#endif
}
NS_COM void nsDebug::Break(const char* aFile, PRIntn aLine)
{
#ifndef TEMP_MAC_HACK
InitLog();
PR_LOG(gDebugLog, PR_LOG_ERROR,
("Break: at file %s, line %d", aFile, aLine));
PR_LogFlush();
//XXX this works on win32 only for now. For all the other platforms call Abort
#if defined(_WIN32)
::DebugBreak();
#else
Abort(aFile, aLine);
#endif
#endif // TEMP_MAC_HACK
}
NS_COM void nsDebug::PreCondition(const char* aStr, const char* aExpr,
const char* aFile, PRIntn aLine)
{
InitLog();
PR_LOG(gDebugLog, PR_LOG_ERROR,
("PreCondition: \"%s\" (%s) at file %s, line %d", aStr, aExpr,
aFile, aLine));
Break(aFile, aLine);
}
NS_COM void nsDebug::PostCondition(const char* aStr, const char* aExpr,
const char* aFile, PRIntn aLine)
{
InitLog();
PR_LOG(gDebugLog, PR_LOG_ERROR,
("PostCondition: \"%s\" (%s) at file %s, line %d", aStr, aExpr,
aFile, aLine));
Break(aFile, aLine);
}
NS_COM void nsDebug::Assertion(const char* aStr, const char* aExpr,
const char* aFile, PRIntn aLine)
{
InitLog();
PR_LOG(gDebugLog, PR_LOG_ERROR,
("Assertion: \"%s\" (%s) at file %s, line %d", aStr, aExpr,
aFile, aLine));
Break(aFile, aLine);
}
NS_COM void nsDebug::NotYetImplemented(const char* aMessage,
const char* aFile, PRIntn aLine)
{
InitLog();
PR_LOG(gDebugLog, PR_LOG_ERROR,
("NotYetImplemented: \"%s\" at file %s, line %d", aMessage,
aFile, aLine));
Break(aFile, aLine);
}
NS_COM void nsDebug::NotReached(const char* aMessage,
const char* aFile, PRIntn aLine)
{
InitLog();
PR_LOG(gDebugLog, PR_LOG_ERROR,
("NotReached: \"%s\" at file %s, line %d", aMessage, aFile, aLine));
Break(aFile, aLine);
}
NS_COM void nsDebug::Error(const char* aMessage,
const char* aFile, PRIntn aLine)
{
InitLog();
PR_LOG(gDebugLog, PR_LOG_ERROR,
("Error: \"%s\" at file %s, line %d", aMessage, aFile, aLine));
Break(aFile, aLine);
}
NS_COM void nsDebug::Warning(const char* aMessage,
const char* aFile, PRIntn aLine)
{
InitLog();
PR_LOG(gDebugLog, PR_LOG_ERROR,
("Warning: \"%s\" at file %s, line %d", aMessage, aFile, aLine));
}

View File

@@ -0,0 +1,179 @@
/* -*- 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.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
* Reserved.
*/
#ifndef nsDebug_h___
#define nsDebug_h___
#include "nsCom.h"
#include "prtypes.h"
#ifdef DEBUG
#define NS_DEBUG
#endif
/**
* Namespace for debugging methods. Note that your code must use the
* macros defined later in this file so that the debug code can be
* conditionally compiled out.
*/
class nsDebug {
public:
// XXX add in log controls here
// XXX probably want printf type arguments
/**
* Abort the executing program. This works on all architectures.
*/
static NS_COM void Abort(const char* aFile, PRIntn aLine);
/**
* Break the executing program into the debugger.
*/
static NS_COM void Break(const char* aFile, PRIntn aLine);
/**
* Log a pre-condition message to the debug log
*/
static NS_COM void PreCondition(const char* aStr, const char* aExpr,
const char* aFile, PRIntn aLine);
/**
* Log a post-condition message to the debug log
*/
static NS_COM void PostCondition(const char* aStr, const char* aExpr,
const char* aFile, PRIntn aLine);
/**
* Log an assertion message to the debug log
*/
static NS_COM void Assertion(const char* aStr, const char* aExpr,
const char* aFile, PRIntn aLine);
/**
* Log a not-yet-implemented message to the debug log
*/
static NS_COM void NotYetImplemented(const char* aMessage,
const char* aFile, PRIntn aLine);
/**
* Log a not-reached message to the debug log
*/
static NS_COM void NotReached(const char* aMessage,
const char* aFile, PRIntn aLine);
/**
* Log an error message to the debug log. This call returns.
*/
static NS_COM void Error(const char* aMessage,
const char* aFile, PRIntn aLine);
/**
* Log a warning message to the debug log.
*/
static NS_COM void Warning(const char* aMessage,
const char* aFile, PRIntn aLine);
};
#ifdef NS_DEBUG
/**
* Test a precondition for truth. If the expression is not true then
* trigger a program failure.
*/
#define NS_PRECONDITION(expr,str) \
if (!(expr)) \
nsDebug::PreCondition(str, #expr, __FILE__, __LINE__)
/**
* Test an assertion for truth. If the expression is not true then
* trigger a program failure.
*/
#define NS_ASSERTION(expr,str) \
if (!(expr)) \
nsDebug::Assertion(str, #expr, __FILE__, __LINE__)
/**
* Test an assertion for truth. If the expression is not true then
* trigger a program failure. The expression will still be
* executed in release mode.
*/
#define NS_VERIFY(expr,str) \
if (!(expr)) \
nsDebug::Assertion(str, #expr, __FILE__, __LINE__)
/**
* Test a post-condition for truth. If the expression is not true then
* trigger a program failure.
*/
#define NS_POSTCONDITION(expr,str) \
if (!(expr)) \
nsDebug::PostCondition(str, #expr, __FILE__, __LINE__)
/**
* This macros triggers a program failure if executed. It indicates that
* an attempt was made to execute some unimplimented functionality.
*/
#define NS_NOTYETIMPLEMENTED(str) \
nsDebug::NotYetImplemented(str, __FILE__, __LINE__)
/**
* This macros triggers a program failure if executed. It indicates that
* an attempt was made to execute some unimplimented functionality.
*/
#define NS_NOTREACHED(str) \
nsDebug::NotReached(str, __FILE__, __LINE__)
/**
* Log an error message.
*/
#define NS_ERROR(str) \
nsDebug::Error(str, __FILE__, __LINE__)
/**
* Log a warning message.
*/
#define NS_WARNING(str) \
nsDebug::Warning(str, __FILE__, __LINE__)
/**
* Trigger an abort
*/
#define NS_ABORT() \
nsDebug::Abort(__FILE__, __LINE__)
/**
* Cause a break
*/
#define NS_BREAK() \
nsDebug::Break(__FILE__, __LINE__)
#else /* NS_DEBUG */
#define NS_PRECONDITION(expr,str) {}
#define NS_ASSERTION(expr,str) {}
#define NS_VERIFY(expr,str) expr
#define NS_POSTCONDITION(expr,str) {}
#define NS_NOTYETIMPLEMENTED(str) {}
#define NS_NOTREACHED(str) {}
#define NS_ERROR(str) {}
#define NS_WARNING(str) {}
#define NS_ABORT() {}
#define NS_BREAK() {}
#endif /* ! NS_DEBUG */
#endif /* nsDebug_h___ */

View File

@@ -0,0 +1,186 @@
/* -*- 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.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
* Reserved.
*/
#ifndef nsError_h
#define nsError_h
#ifndef prtypes_h___
#include "prtypes.h"
#endif
/**
* Generic result data type
*/
typedef PRUint32 nsresult;
/*
* To add error code to your module, you need to do the following:
*
* 1) Add a module offset code. Add yours to the bottom of the list
* right below this comment, adding 1.
*
* 2) In your module, define a header file which uses one of the
* NE_ERROR_GENERATExxxxxx macros. Some examples below:
*
* #define NS_ERROR_MYMODULE_MYERROR1 NS_ERROR_GENERATE(NS_ERROR_SEVERITY_ERROR,NS_ERROR_MODULE_MYMODULE,1)
* #define NS_ERROR_MYMODULE_MYERROR2 NS_ERROR_GENERATE_SUCCESS(NS_ERROR_MODULE_MYMODULE,2)
* #define NS_ERROR_MYMODULE_MYERROR3 NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_MYMODULE,3)
*
*/
/**
* @name Standard Module Offset Code. Each Module should identify a unique number
* and then all errors associated with that module become offsets from the
* base associated with that module id. There are 16 bits of code bits for
* each module.
*/
#define NS_ERROR_MODULE_XPCOM 1
#define NS_ERROR_MODULE_BASE 2
#define NS_ERROR_MODULE_GFX 3
#define NS_ERROR_MODULE_WIDGET 4
#define NS_ERROR_MODULE_CALENDAR 5
#define NS_ERROR_MODULE_NETWORK 6
#define NS_ERROR_MODULE_PLUGINS 7
#define NS_ERROR_MODULE_LAYOUT 8
#define NS_ERROR_MODULE_HTMLPARSER 9
#define NS_ERROR_MODULE_RDF 10
#define NS_ERROR_MODULE_UCONV 11
#define NS_ERROR_MODULE_REG 12
#define NS_ERROR_MODULE_FILES 13
#define NS_ERROR_MODULE_MAILNEWS 16
/**
* @name Standard Error Handling Macros
*/
#define NS_FAILED(_nsresult) ((_nsresult) & 0x80000000)
#define NS_SUCCEEDED(_nsresult) (!((_nsresult) & 0x80000000))
/**
* @name Severity Code. This flag identifies the level of warning
*/
#define NS_ERROR_SEVERITY_SUCCESS 0
#define NS_ERROR_SEVERITY_ERROR 1
/**
* @name Mozilla Code. This flag separates consumers of mozilla code
* from the native platform
*/
#define NS_ERROR_MODULE_BASE_OFFSET 0x45
/**
* @name Standard Error Generating Macros
*/
#define NS_ERROR_GENERATE(sev,module,code) \
((nsresult) (((PRUint32)(sev)<<31) | ((PRUint32)(module+NS_ERROR_MODULE_BASE_OFFSET)<<16) | ((PRUint32)(code))) )
#define NS_ERROR_GENERATE_SUCCESS(module,code) \
((nsresult) (((PRUint32)(NS_ERROR_SEVERITY_SUCCESS)<<31) | ((PRUint32)(module+NS_ERROR_MODULE_BASE_OFFSET)<<16) | ((PRUint32)(code))) )
#define NS_ERROR_GENERATE_FAILURE(module,code) \
((nsresult) (((PRUint32)(NS_ERROR_SEVERITY_ERROR)<<31) | ((PRUint32)(module+NS_ERROR_MODULE_BASE_OFFSET)<<16) | ((PRUint32)(code))) )
/**
* @name Standard Macros for retrieving error bits
*/
#if PR_BYTES_PER_INT == 4
#define NS_IS_ERROR(err) (((nsresult)(err))<0)
#else
#define NS_IS_ERROR(err) (((((PRUint32)(err)) >> 31) & 0x1) == NS_ERROR_SEVERITY_ERROR)
#endif
#define NS_ERROR_GET_CODE(err) ((err) & 0xffff)
#define NS_ERROR_GET_MODULE(err) (((((err) >> 16) - NS_ERROR_MODULE_BASE_OFFSET) & 0x1fff))
#define NS_ERROR_GET_SEVERITY(err) (((err) >> 31) & 0x1)
/**
* @name Standard return values
*/
/*@{*/
/* Standard "it worked" return value */
#define NS_OK 0
/* The backwards COM false */
#define NS_COMFALSE 1
#define NS_ERROR_BASE ((nsresult) 0xC1F30000)
/* Returned when an instance is not initialized */
#define NS_ERROR_NOT_INITIALIZED (NS_ERROR_BASE + 1)
/* Returned when an instance is already initialized */
#define NS_ERROR_ALREADY_INITIALIZED (NS_ERROR_BASE + 2)
/* Returned by a not implemented function */
#define NS_ERROR_NOT_IMPLEMENTED ((nsresult) 0x80004001L)
/* Returned when a given interface is not supported. */
#define NS_NOINTERFACE ((nsresult) 0x80004002L)
#define NS_ERROR_NO_INTERFACE NS_NOINTERFACE
#define NS_ERROR_INVALID_POINTER ((nsresult) 0x80004003L)
#define NS_ERROR_NULL_POINTER NS_ERROR_INVALID_POINTER
/* Returned when a function aborts */
#define NS_ERROR_ABORT ((nsresult) 0x80004004L)
/* Returned when a function fails */
#define NS_ERROR_FAILURE ((nsresult) 0x80004005L)
/* Returned when an unexpected error occurs */
#define NS_ERROR_UNEXPECTED ((nsresult) 0x8000ffffL)
/* Returned when a memory allocation failes */
#define NS_ERROR_OUT_OF_MEMORY ((nsresult) 0x8007000eL)
/* Returned when an illegal value is passed */
#define NS_ERROR_ILLEGAL_VALUE ((nsresult) 0x80070057L)
#define NS_ERROR_INVALID_ARG NS_ERROR_ILLEGAL_VALUE
/* Returned when a class doesn't allow aggregation */
#define NS_ERROR_NO_AGGREGATION ((nsresult) 0x80040110L)
/* Returned when a class doesn't allow aggregation */
#define NS_ERROR_NOT_AVAILABLE ((nsresult) 0x80040111L)
/* Returned when a class is not registered */
#define NS_ERROR_FACTORY_NOT_REGISTERED ((nsresult) 0x80040154L)
/* Returned when a dynamically loaded factory couldn't be found */
#define NS_ERROR_FACTORY_NOT_LOADED ((nsresult) 0x800401f8L)
/* Returned when a factory doesn't support signatures */
#define NS_ERROR_FACTORY_NO_SIGNATURE_SUPPORT \
(NS_ERROR_BASE + 0x101)
/* Returned when a factory already is registered */
#define NS_ERROR_FACTORY_EXISTS (NS_ERROR_BASE + 0x100)
/*@}*/
#endif

View File

@@ -0,0 +1,82 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
* Reserved.
*/
#ifndef nsIAllocator_h___
#define nsIAllocator_h___
#include "nsISupports.h"
/**
* Unlike IMalloc, this interface returns nsresults and doesn't
* implement the problematic GetSize and DidAlloc routines.
*/
class nsIAllocator : public nsISupports {
public:
/**
* Allocates a block of memory of a particular size.
*
* @param size - the size of the block to allocate
* @result the block of memory
*/
NS_IMETHOD_(void*) Alloc(PRUint32 size) = 0;
/**
* Reallocates a block of memory to a new size.
*
* @param ptr - the block of memory to reallocate
* @param size - the new size
* @result the rellocated block of memory
*/
NS_IMETHOD_(void*) Realloc(void* ptr, PRUint32 size) = 0;
/**
* Frees a block of memory.
*
* @param ptr - the block of memory to free
*/
NS_IMETHOD Free(void* ptr) = 0;
/**
* Attempts to shrink the heap.
*/
NS_IMETHOD HeapMinimize(void) = 0;
};
#define NS_IALLOCATOR_IID \
{ /* 56def700-b1b9-11d2-8177-006008119d7a */ \
0x56def700, \
0xb1b9, \
0x11d2, \
{0x81, 0x77, 0x00, 0x60, 0x08, 0x11, 0x9d, 0x7a} \
}
// To get the global memory manager service:
#define NS_ALLOCATOR_CID \
{ /* aafe6770-b1bb-11d2-8177-006008119d7a */ \
0xaafe6770, \
0xb1bb, \
0x11d2, \
{0x81, 0x77, 0x00, 0x60, 0x08, 0x11, 0x9d, 0x7a} \
}
////////////////////////////////////////////////////////////////////////////////
#endif /* nsIAllocator_h___ */

View File

@@ -0,0 +1,73 @@
/* -*- 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.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
* Reserved.
*/
#include "nsID.h"
#include "prprf.h"
static const char gIDFormat[] =
"{%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}";
static const char gIDFormat2[] =
"%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x";
/*
* Turns a {xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx} string into
* an nsID
*/
NS_COM PRBool nsID::Parse(char *aIDStr)
{
PRInt32 count = 0;
PRInt32 n1, n2, n3[8];
PRInt32 n0;
if (NULL != aIDStr) {
count = PR_sscanf(aIDStr,
(aIDStr[0] == '{') ? gIDFormat : gIDFormat2,
&n0, &n1, &n2,
&n3[0],&n3[1],&n3[2],&n3[3],
&n3[4],&n3[5],&n3[6],&n3[7]);
m0 = (PRInt32) n0;
m1 = (PRInt16) n1;
m2 = (PRInt16) n2;
for (int i = 0; i < 8; i++) {
m3[i] = (PRInt8) n3[i];
}
}
return (PRBool) (count == 11);
}
/*
* Returns an allocated string in {xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx}
* format. Caller should delete [] the string.
*/
NS_COM char *nsID::ToString() const
{
char *res = new char[39];
if (res != NULL) {
PR_snprintf(res, 39, gIDFormat,
m0, (PRUint32) m1, (PRUint32) m2,
(PRUint32) m3[0], (PRUint32) m3[1], (PRUint32) m3[2],
(PRUint32) m3[3], (PRUint32) m3[4], (PRUint32) m3[5],
(PRUint32) m3[6], (PRUint32) m3[7]);
}
return res;
}

89
mozilla/xpcom/base/nsID.h Normal file
View File

@@ -0,0 +1,89 @@
/* -*- 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.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
* Reserved.
*/
#ifndef nsID_h__
#define nsID_h__
#include "prtypes.h"
#include "string.h"
#include "nsCom.h"
/**
* A "unique identifier". This is modeled after OSF DCE UUIDs.
*/
struct nsID {
/**
* @name Indentifier values
*/
//@{
PRUint32 m0;
PRUint16 m1;
PRUint16 m2;
PRUint8 m3[8];
//@}
/**
* @name Methods
*/
//@{
/**
* Equivalency method. Compares this nsID with another.
* @return <b>PR_TRUE</b> if they are the same, <b>PR_FALSE</b> if not.
*/
inline PRBool Equals(const nsID& other) const {
return (PRBool)
((((PRUint32*) &m0)[0] == ((PRUint32*) &other.m0)[0]) &&
(((PRUint32*) &m0)[1] == ((PRUint32*) &other.m0)[1]) &&
(((PRUint32*) &m0)[2] == ((PRUint32*) &other.m0)[2]) &&
(((PRUint32*) &m0)[3] == ((PRUint32*) &other.m0)[3]));
}
/**
* nsID Parsing method. Turns a {xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx}
* string into an nsID
*/
NS_COM PRBool Parse(char *aIDStr);
/**
* nsID string encoder. Returns an allocated string in
* {xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx} format. Caller should free string.
*/
NS_COM char* ToString() const;
//@}
};
/**
* Declare an ID. If NS_IMPL_IDS is set, a variable <i>_name</i> is declared
* with the given values, otherwise <i>_name</i> is declared as an
* <tt>extern</tt> variable.
*/
#ifdef NS_IMPL_IDS
#define NS_DECLARE_ID(_name,m0,m1,m2,m30,m31,m32,m33,m34,m35,m36,m37) \
extern "C" const nsID _name = {m0,m1,m2,{m30,m31,m32,m33,m34,m35,m36,m37}}
#else
#define NS_DECLARE_ID(_name,m0,m1,m2,m30,m31,m32,m33,m34,m35,m36,m37) \
extern "C" const nsID _name
#endif
#endif

142
mozilla/xpcom/base/nsIPtr.h Normal file
View File

@@ -0,0 +1,142 @@
/* -*- 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.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
* Reserved.
*/
#ifndef nsIPtr_h___
#define nsIPtr_h___
#include "nsISupports.h"
/*
* nsIPtr is an "auto-release pointer" class for nsISupports based interfaces
*
* It's intent is to be a "set and forget" pointer to help with managing
* active references to nsISupports bases objects.
*
* The pointer object ensures that the underlying pointer is always
* released whenever the value is changed or when the object leaves scope.
*
* Proper care needs to be taken when assigning pointers to a nsIPtr.
* When asigning from a C pointer (nsISupports*), the pointer presumes
* an active reference and subsumes it. When assigning from another nsIPtr,
* a new reference is established.
*
* There are 3 ways to assign a value to a nsIPtr.
* 1) Direct construction or assignment from a C pointer.
* 2) Direct construction or assignment form another nsIPtr.
* 3) Usage of an "out parameter" method.
* a) AssignRef() releases the underlying pointer and returns a reference to it.
* Useful for pointer reference out paramaters.
* b) AssignPtr() releases the underlying pointer and returns a pointer to it.
* c) Query() releases the underlying pointer and returns a (void**) pointer to it.
* Useful for calls to QueryInterface()
* 4) The SetAddRef() method. This is equivalent to an assignment followed by an AddRef().
*
* examples:
*
* class It {
* void NS_NewFoo(nsIFoo** aFoo);
* nsIFoo* GetFoo(void);
* void GetBar(nsIBar*& aBar);
* };
*
* nsIFooPtr foo = it->GetFoo();
* nsIBarPtr bar;
*
* it->NS_NewFoo(foo.AssignPtr());
* it->GetBar(bar.AssignRef());
* it->QueryInterface(kIFooIID, foo.Query());
* bar.SetAddRef(new Bar());
*
* Advantages:
* Set and forget. Once a pointer is assigned to a nsIPtr, it is impossible
* to forget to release it.
* Always pre-initialized. You can't forget to initialize the pointer.
*
* Disadvantages:
* Usage of this class doesn't eliminate the need to think about ref counts
* and assign values properly, AddRef'ing as needed.
* The nsIPtr doesn't typecast exactly like a C pointer. In order to achieve
* typecasting, it may be necessary to first cast to a C pointer of the
* underlying type.
*
*/
#define NS_DEF_PTR(cls) \
class cls##Ptr { \
public: \
cls##Ptr(void) : mPtr(0) {} \
cls##Ptr(const cls##Ptr& aCopy) : mPtr(aCopy.mPtr) \
{ NS_IF_ADDREF(mPtr); } \
cls##Ptr(cls* aInterface) : mPtr(aInterface) {} \
~cls##Ptr(void) { NS_IF_RELEASE(mPtr); } \
cls##Ptr& operator=(const cls##Ptr& aCopy) \
{ if(mPtr == aCopy.mPtr) return *this; \
NS_IF_ADDREF(aCopy.mPtr); \
NS_IF_RELEASE(mPtr); \
mPtr = aCopy.mPtr; return *this; } \
cls##Ptr& operator=(cls* aInterface) \
{ if(mPtr == aInterface) return *this; \
NS_IF_RELEASE(mPtr); mPtr = aInterface; \
return *this; } \
cls##Ptr& operator=(PRInt32 aInt) \
{ NS_IF_RELEASE(mPtr); \
return *this; } \
void SetAddRef(cls* aInterface) \
{ if(aInterface == mPtr) return; \
NS_IF_ADDREF(aInterface); \
NS_IF_RELEASE(mPtr); mPtr = aInterface; } \
cls* AddRef(void) { NS_ADDREF(mPtr); return mPtr; } \
cls* IfAddRef(void) \
{ NS_IF_ADDREF(mPtr); return mPtr; } \
cls*& AssignRef(void) \
{ NS_IF_RELEASE(mPtr); return mPtr; } \
cls** AssignPtr(void) \
{ NS_IF_RELEASE(mPtr); return &mPtr; } \
void** Query(void) \
{ NS_IF_RELEASE(mPtr); return (void**)&mPtr; } \
PRBool IsNull() const \
{ return PRBool(0 == mPtr); } \
PRBool IsNotNull() const \
{ return PRBool(0 != mPtr); } \
PRBool operator==(const cls##Ptr& aCopy) const \
{ return PRBool(mPtr == aCopy.mPtr); } \
PRBool operator==(cls* aInterface) const \
{ return PRBool(mPtr == aInterface); } \
PRBool operator!=(const cls##Ptr& aCopy) const \
{ return PRBool(mPtr != aCopy.mPtr); } \
PRBool operator!=(cls* aInterface) const \
{ return PRBool(mPtr != aInterface); } \
cls* operator->(void) { return mPtr; } \
cls& operator*(void) { return *mPtr; } \
operator cls*(void) { return mPtr; } \
const cls* operator->(void) const { return mPtr; } \
const cls& operator*(void) const { return *mPtr; } \
operator const cls* (void) const { return mPtr; } \
private: \
void* operator new(size_t size) { return 0; } \
void operator delete(void* aPtr) {} \
cls* mPtr; \
public: \
friend inline PRBool operator==(const cls* aInterface, const cls##Ptr& aPtr) \
{ return PRBool(aInterface == aPtr.mPtr); } \
friend inline PRBool operator!=(const cls* aInterface, const cls##Ptr& aPtr) \
{ return PRBool(aInterface != aPtr.mPtr); } \
}
#endif // nsIPtr_h___

View File

@@ -0,0 +1,314 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (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 client code.
*
* The Initial Developer of the Original Code is Netscape Communications
* Corporation. Portions created by Netscape are Copyright (C) 1998
* Netscape Communications Corporation. All Rights Reserved.
*/
#include "nsISupports.h"
#include "prprf.h"
#include "prlog.h"
#if defined(_WIN32)
#include <windows.h>
#endif
static PRLogModuleInfo* gTraceRefcntLog;
#if defined(NS_MT_SUPPORTED)
#include "prlock.h"
static PRLock* gTraceLock;
#define LOCK_TRACELOG() PR_Lock(gTraceLock)
#define UNLOCK_TRACELOG() PR_Unlock(gTraceLock)
#else /* ! NT_MT_SUPPORTED */
#define LOCK_TRACELOG()
#define UNLOCK_TRACELOG()
#endif /* ! NS_MT_SUPPORTED */
static void InitTraceLog(void)
{
if (0 == gTraceRefcntLog) {
gTraceRefcntLog = PR_NewLogModule("xpcomrefcnt");
#if defined(NS_MT_SUPPORTED)
gTraceLock = PR_NewLock();
#endif /* NS_MT_SUPPORTED */
}
}
#if defined(_WIN32)
#include "imagehlp.h"
#include <stdio.h>
#if 0
static BOOL __stdcall
EnumSymbolsCB(LPSTR aSymbolName,
ULONG aSymbolAddress,
ULONG aSymbolSize,
PVOID aUserContext)
{
int* countp = (int*) aUserContext;
int count = *countp;
if (count < 3) {
printf(" %p[%4d]: %s\n", aSymbolAddress, aSymbolSize, aSymbolName);
count++;
*countp = count++;
}
return TRUE;
}
static BOOL __stdcall
EnumModulesCB(LPSTR aModuleName,
ULONG aBaseOfDll,
PVOID aUserContext)
{
HANDLE myProcess = ::GetCurrentProcess();
printf("module=%s dll=%x\n", aModuleName, aBaseOfDll);
// int count = 0;
// SymEnumerateSymbols(myProcess, aBaseOfDll, EnumSymbolsCB, (void*) &count);
return TRUE;
}
#endif
/**
* Walk the stack, translating PC's found into strings and recording the
* chain in aBuffer. For this to work properly, the dll's must be rebased
* so that the address in the file agrees with the address in memory.
* Otherwise StackWalk will return FALSE when it hits a frame in a dll's
* whose in memory address doesn't match it's in-file address.
*
* Fortunately, there is a handy dandy routine in IMAGEHLP.DLL that does
* the rebasing and accordingly I've made a tool to use it to rebase the
* DLL's in one fell swoop (see xpcom/tools/windows/rebasedlls.cpp).
*/
void
nsTraceRefcnt::WalkTheStack(char* aBuffer, int aBufLen)
{
CONTEXT context;
STACKFRAME frame;
char* cp = aBuffer;
aBuffer[0] = '\0';
aBufLen--; // leave room for nul
HANDLE myProcess = ::GetCurrentProcess();
HANDLE myThread = ::GetCurrentThread();
// Get the context information for this thread. That way we will
// know where our sp, fp, pc, etc. are and can fill in the
// STACKFRAME with the initial values.
context.ContextFlags = CONTEXT_FULL;
GetThreadContext(myThread, &context);
if (!SymInitialize(myProcess, ".;..\\lib", TRUE)) {
return;
}
#if 0
SymEnumerateModules(myProcess, EnumModulesCB, NULL);
#endif
// Setup initial stack frame to walk from
memset(&frame, 0, sizeof(frame));
frame.AddrPC.Mode = AddrModeFlat;
frame.AddrPC.Offset = context.Eip;
frame.AddrReturn.Mode = AddrModeFlat;
frame.AddrReturn.Offset = context.Ebp;
frame.AddrFrame.Mode = AddrModeFlat;
frame.AddrFrame.Offset = context.Ebp;
frame.AddrStack.Mode = AddrModeFlat;
frame.AddrStack.Offset = context.Esp;
frame.Params[0] = context.Eax;
frame.Params[1] = context.Ecx;
frame.Params[2] = context.Edx;
frame.Params[3] = context.Ebx;
// Now walk the stack and map the pc's to symbol names that we stuff
// append to *cp.
int skip = 2;
int syms = 0;
while (aBufLen > 0) {
char symbolBuffer[sizeof(IMAGEHLP_SYMBOL) + 512];
PIMAGEHLP_SYMBOL pSymbol = (PIMAGEHLP_SYMBOL) symbolBuffer;
pSymbol->SizeOfStruct = sizeof(symbolBuffer);
pSymbol->MaxNameLength = 512;
DWORD oldAddress = frame.AddrPC.Offset;
BOOL b = ::StackWalk(IMAGE_FILE_MACHINE_I386, myProcess, myThread,
&frame, &context, NULL,
SymFunctionTableAccess,
SymGetModuleBase,
NULL);
if (!b || (0 == frame.AddrPC.Offset)) {
if (syms <= 1) {
skip = 7;
}
break;
}
if (--skip >= 0) {
continue;
}
DWORD disp;
if (SymGetSymFromAddr(myProcess, frame.AddrPC.Offset, &disp, pSymbol)) {
int nameLen = strlen(pSymbol->Name);
if (nameLen + 2 > aBufLen) {
break;
}
memcpy(cp, pSymbol->Name, nameLen);
cp += nameLen;
*cp++ = ' ';
aBufLen -= nameLen + 1;
syms++;
}
else {
if (11 > aBufLen) {
break;
}
char tmp[30];
PR_snprintf(tmp, sizeof(tmp), "0x%08x ", frame.AddrPC.Offset);
memcpy(cp, tmp, 11);
cp += 11;
aBufLen -= 11;
syms++;
}
}
*cp = 0;
}
#else /* _WIN32 */
void
nsTraceRefcnt::WalkTheStack(char* aBuffer, int aBufLen)
{
aBuffer[0] = '\0';
}
#endif /* _WIN32 */
NS_COM void
nsTraceRefcnt::LoadLibrarySymbols(const char* aLibraryName,
void* aLibrayHandle)
{
#ifdef MOZ_TRACE_XPCOM_REFCNT
#if defined(_WIN32)
InitTraceLog();
if (PR_LOG_TEST(gTraceRefcntLog,PR_LOG_DEBUG)) {
HANDLE myProcess = ::GetCurrentProcess();
if (!SymInitialize(myProcess, ".;..\\lib", TRUE)) {
return;
}
BOOL b = ::SymLoadModule(myProcess,
NULL,
(char*)aLibraryName,
(char*)aLibraryName,
0,
0);
// DWORD lastError = 0;
// if (!b) lastError = ::GetLastError();
// printf("loading symbols for library %s => %s [%d]\n", aLibraryName,
// b ? "true" : "false", lastError);
}
#endif
#endif
}
NS_COM unsigned long
nsTraceRefcnt::AddRef(void* aPtr,
unsigned long aNewRefcnt,
const char* aFile,
PRIntn aLine)
{
#ifdef MOZ_TRACE_XPCOM_REFCNT
InitTraceLog();
LOCK_TRACELOG();
if (PR_LOG_TEST(gTraceRefcntLog,PR_LOG_DEBUG)) {
char sb[1000];
WalkTheStack(sb, sizeof(sb));
PR_LOG(gTraceRefcntLog, PR_LOG_DEBUG,
("AddRef: %p: %d=>%d [%s] in %s (line %d)",
aPtr, aNewRefcnt-1, aNewRefcnt, sb, aFile, aLine));
}
UNLOCK_TRACELOG();
#endif
return aNewRefcnt;
}
NS_COM unsigned long
nsTraceRefcnt::Release(void* aPtr,
unsigned long aNewRefcnt,
const char* aFile,
PRIntn aLine)
{
#ifdef MOZ_TRACE_XPCOM_REFCNT
InitTraceLog();
LOCK_TRACELOG();
if (PR_LOG_TEST(gTraceRefcntLog,PR_LOG_DEBUG)) {
char sb[1000];
WalkTheStack(sb, sizeof(sb));
PR_LOG(gTraceRefcntLog, PR_LOG_DEBUG,
("Release: %p: %d=>%d [%s] in %s (line %d)",
aPtr, aNewRefcnt+1, aNewRefcnt, sb, aFile, aLine));
}
UNLOCK_TRACELOG();
#endif
return aNewRefcnt;
}
NS_COM void
nsTraceRefcnt::Create(void* aPtr,
const char* aType,
const char* aFile,
PRIntn aLine)
{
#ifdef MOZ_TRACE_XPCOM_REFCNT
InitTraceLog();
LOCK_TRACELOG();
if (PR_LOG_TEST(gTraceRefcntLog,PR_LOG_DEBUG)) {
char sb[1000];
WalkTheStack(sb, sizeof(sb));
PR_LOG(gTraceRefcntLog, PR_LOG_DEBUG,
("Create: %p[%s]: [%s] in %s (line %d)",
aPtr, aType, sb, aFile, aLine));
}
UNLOCK_TRACELOG();
#endif
}
NS_COM void
nsTraceRefcnt::Destroy(void* aPtr,
const char* aFile,
PRIntn aLine)
{
#ifdef MOZ_TRACE_XPCOM_REFCNT
InitTraceLog();
LOCK_TRACELOG();
if (PR_LOG_TEST(gTraceRefcntLog,PR_LOG_DEBUG)) {
char sb[1000];
WalkTheStack(sb, sizeof(sb));
PR_LOG(gTraceRefcntLog, PR_LOG_DEBUG,
("Destroy: %p: [%s] in %s (line %d)",
aPtr, sb, aFile, aLine));
}
UNLOCK_TRACELOG();
#endif
}

View File

@@ -0,0 +1,61 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (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 client code.
*
* The Initial Developer of the Original Code is Netscape Communications
* Corporation. Portions created by Netscape are Copyright (C) 1998
* Netscape Communications Corporation. All Rights Reserved.
*/
#ifndef nsTraceRefcnt_h___
#define nsTraceRefcnt_h___
#include "nsCom.h"
/**
* This class is used to support tracing (and logging using nspr) of
* addref and release calls. Note that only calls that use the
* NS_ADDREF and related macros in nsISupports can be traced.
*
* The name of the nspr log module is "xpcomrefcnt" (case matters).
*
* This code only performs tracing built with debugging AND when
* built with -DMOZ_TRACE_XPCOM_REFCNT (because it's expensive!).
*/
class nsTraceRefcnt {
public:
static NS_COM unsigned long AddRef(void* aPtr,
unsigned long aNewRefcnt,
const char* aFile,
int aLine);
static NS_COM unsigned long Release(void* aPtr,
unsigned long aNewRefcnt,
const char* aFile,
int aLine);
static NS_COM void Create(void* aPtr,
const char* aType,
const char* aFile,
int aLine);
static NS_COM void Destroy(void* aPtr,
const char* aFile,
int aLine);
static NS_COM void LoadLibrarySymbols(const char* aLibraryName,
void* aLibrayHandle);
static NS_COM void WalkTheStack(char* aBuffer, int aBufLen);
};
#endif /* nsTraceRefcnt_h___ */

View File

@@ -0,0 +1,314 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (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 client code.
*
* The Initial Developer of the Original Code is Netscape Communications
* Corporation. Portions created by Netscape are Copyright (C) 1998
* Netscape Communications Corporation. All Rights Reserved.
*/
#include "nsISupports.h"
#include "prprf.h"
#include "prlog.h"
#if defined(_WIN32)
#include <windows.h>
#endif
static PRLogModuleInfo* gTraceRefcntLog;
#if defined(NS_MT_SUPPORTED)
#include "prlock.h"
static PRLock* gTraceLock;
#define LOCK_TRACELOG() PR_Lock(gTraceLock)
#define UNLOCK_TRACELOG() PR_Unlock(gTraceLock)
#else /* ! NT_MT_SUPPORTED */
#define LOCK_TRACELOG()
#define UNLOCK_TRACELOG()
#endif /* ! NS_MT_SUPPORTED */
static void InitTraceLog(void)
{
if (0 == gTraceRefcntLog) {
gTraceRefcntLog = PR_NewLogModule("xpcomrefcnt");
#if defined(NS_MT_SUPPORTED)
gTraceLock = PR_NewLock();
#endif /* NS_MT_SUPPORTED */
}
}
#if defined(_WIN32)
#include "imagehlp.h"
#include <stdio.h>
#if 0
static BOOL __stdcall
EnumSymbolsCB(LPSTR aSymbolName,
ULONG aSymbolAddress,
ULONG aSymbolSize,
PVOID aUserContext)
{
int* countp = (int*) aUserContext;
int count = *countp;
if (count < 3) {
printf(" %p[%4d]: %s\n", aSymbolAddress, aSymbolSize, aSymbolName);
count++;
*countp = count++;
}
return TRUE;
}
static BOOL __stdcall
EnumModulesCB(LPSTR aModuleName,
ULONG aBaseOfDll,
PVOID aUserContext)
{
HANDLE myProcess = ::GetCurrentProcess();
printf("module=%s dll=%x\n", aModuleName, aBaseOfDll);
// int count = 0;
// SymEnumerateSymbols(myProcess, aBaseOfDll, EnumSymbolsCB, (void*) &count);
return TRUE;
}
#endif
/**
* Walk the stack, translating PC's found into strings and recording the
* chain in aBuffer. For this to work properly, the dll's must be rebased
* so that the address in the file agrees with the address in memory.
* Otherwise StackWalk will return FALSE when it hits a frame in a dll's
* whose in memory address doesn't match it's in-file address.
*
* Fortunately, there is a handy dandy routine in IMAGEHLP.DLL that does
* the rebasing and accordingly I've made a tool to use it to rebase the
* DLL's in one fell swoop (see xpcom/tools/windows/rebasedlls.cpp).
*/
void
nsTraceRefcnt::WalkTheStack(char* aBuffer, int aBufLen)
{
CONTEXT context;
STACKFRAME frame;
char* cp = aBuffer;
aBuffer[0] = '\0';
aBufLen--; // leave room for nul
HANDLE myProcess = ::GetCurrentProcess();
HANDLE myThread = ::GetCurrentThread();
// Get the context information for this thread. That way we will
// know where our sp, fp, pc, etc. are and can fill in the
// STACKFRAME with the initial values.
context.ContextFlags = CONTEXT_FULL;
GetThreadContext(myThread, &context);
if (!SymInitialize(myProcess, ".;..\\lib", TRUE)) {
return;
}
#if 0
SymEnumerateModules(myProcess, EnumModulesCB, NULL);
#endif
// Setup initial stack frame to walk from
memset(&frame, 0, sizeof(frame));
frame.AddrPC.Mode = AddrModeFlat;
frame.AddrPC.Offset = context.Eip;
frame.AddrReturn.Mode = AddrModeFlat;
frame.AddrReturn.Offset = context.Ebp;
frame.AddrFrame.Mode = AddrModeFlat;
frame.AddrFrame.Offset = context.Ebp;
frame.AddrStack.Mode = AddrModeFlat;
frame.AddrStack.Offset = context.Esp;
frame.Params[0] = context.Eax;
frame.Params[1] = context.Ecx;
frame.Params[2] = context.Edx;
frame.Params[3] = context.Ebx;
// Now walk the stack and map the pc's to symbol names that we stuff
// append to *cp.
int skip = 2;
int syms = 0;
while (aBufLen > 0) {
char symbolBuffer[sizeof(IMAGEHLP_SYMBOL) + 512];
PIMAGEHLP_SYMBOL pSymbol = (PIMAGEHLP_SYMBOL) symbolBuffer;
pSymbol->SizeOfStruct = sizeof(symbolBuffer);
pSymbol->MaxNameLength = 512;
DWORD oldAddress = frame.AddrPC.Offset;
BOOL b = ::StackWalk(IMAGE_FILE_MACHINE_I386, myProcess, myThread,
&frame, &context, NULL,
SymFunctionTableAccess,
SymGetModuleBase,
NULL);
if (!b || (0 == frame.AddrPC.Offset)) {
if (syms <= 1) {
skip = 7;
}
break;
}
if (--skip >= 0) {
continue;
}
DWORD disp;
if (SymGetSymFromAddr(myProcess, frame.AddrPC.Offset, &disp, pSymbol)) {
int nameLen = strlen(pSymbol->Name);
if (nameLen + 2 > aBufLen) {
break;
}
memcpy(cp, pSymbol->Name, nameLen);
cp += nameLen;
*cp++ = ' ';
aBufLen -= nameLen + 1;
syms++;
}
else {
if (11 > aBufLen) {
break;
}
char tmp[30];
PR_snprintf(tmp, sizeof(tmp), "0x%08x ", frame.AddrPC.Offset);
memcpy(cp, tmp, 11);
cp += 11;
aBufLen -= 11;
syms++;
}
}
*cp = 0;
}
#else /* _WIN32 */
void
nsTraceRefcnt::WalkTheStack(char* aBuffer, int aBufLen)
{
aBuffer[0] = '\0';
}
#endif /* _WIN32 */
NS_COM void
nsTraceRefcnt::LoadLibrarySymbols(const char* aLibraryName,
void* aLibrayHandle)
{
#ifdef MOZ_TRACE_XPCOM_REFCNT
#if defined(_WIN32)
InitTraceLog();
if (PR_LOG_TEST(gTraceRefcntLog,PR_LOG_DEBUG)) {
HANDLE myProcess = ::GetCurrentProcess();
if (!SymInitialize(myProcess, ".;..\\lib", TRUE)) {
return;
}
BOOL b = ::SymLoadModule(myProcess,
NULL,
(char*)aLibraryName,
(char*)aLibraryName,
0,
0);
// DWORD lastError = 0;
// if (!b) lastError = ::GetLastError();
// printf("loading symbols for library %s => %s [%d]\n", aLibraryName,
// b ? "true" : "false", lastError);
}
#endif
#endif
}
NS_COM unsigned long
nsTraceRefcnt::AddRef(void* aPtr,
unsigned long aNewRefcnt,
const char* aFile,
PRIntn aLine)
{
#ifdef MOZ_TRACE_XPCOM_REFCNT
InitTraceLog();
LOCK_TRACELOG();
if (PR_LOG_TEST(gTraceRefcntLog,PR_LOG_DEBUG)) {
char sb[1000];
WalkTheStack(sb, sizeof(sb));
PR_LOG(gTraceRefcntLog, PR_LOG_DEBUG,
("AddRef: %p: %d=>%d [%s] in %s (line %d)",
aPtr, aNewRefcnt-1, aNewRefcnt, sb, aFile, aLine));
}
UNLOCK_TRACELOG();
#endif
return aNewRefcnt;
}
NS_COM unsigned long
nsTraceRefcnt::Release(void* aPtr,
unsigned long aNewRefcnt,
const char* aFile,
PRIntn aLine)
{
#ifdef MOZ_TRACE_XPCOM_REFCNT
InitTraceLog();
LOCK_TRACELOG();
if (PR_LOG_TEST(gTraceRefcntLog,PR_LOG_DEBUG)) {
char sb[1000];
WalkTheStack(sb, sizeof(sb));
PR_LOG(gTraceRefcntLog, PR_LOG_DEBUG,
("Release: %p: %d=>%d [%s] in %s (line %d)",
aPtr, aNewRefcnt+1, aNewRefcnt, sb, aFile, aLine));
}
UNLOCK_TRACELOG();
#endif
return aNewRefcnt;
}
NS_COM void
nsTraceRefcnt::Create(void* aPtr,
const char* aType,
const char* aFile,
PRIntn aLine)
{
#ifdef MOZ_TRACE_XPCOM_REFCNT
InitTraceLog();
LOCK_TRACELOG();
if (PR_LOG_TEST(gTraceRefcntLog,PR_LOG_DEBUG)) {
char sb[1000];
WalkTheStack(sb, sizeof(sb));
PR_LOG(gTraceRefcntLog, PR_LOG_DEBUG,
("Create: %p[%s]: [%s] in %s (line %d)",
aPtr, aType, sb, aFile, aLine));
}
UNLOCK_TRACELOG();
#endif
}
NS_COM void
nsTraceRefcnt::Destroy(void* aPtr,
const char* aFile,
PRIntn aLine)
{
#ifdef MOZ_TRACE_XPCOM_REFCNT
InitTraceLog();
LOCK_TRACELOG();
if (PR_LOG_TEST(gTraceRefcntLog,PR_LOG_DEBUG)) {
char sb[1000];
WalkTheStack(sb, sizeof(sb));
PR_LOG(gTraceRefcntLog, PR_LOG_DEBUG,
("Destroy: %p: [%s] in %s (line %d)",
aPtr, sb, aFile, aLine));
}
UNLOCK_TRACELOG();
#endif
}

View File

@@ -0,0 +1,61 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (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 client code.
*
* The Initial Developer of the Original Code is Netscape Communications
* Corporation. Portions created by Netscape are Copyright (C) 1998
* Netscape Communications Corporation. All Rights Reserved.
*/
#ifndef nsTraceRefcnt_h___
#define nsTraceRefcnt_h___
#include "nsCom.h"
/**
* This class is used to support tracing (and logging using nspr) of
* addref and release calls. Note that only calls that use the
* NS_ADDREF and related macros in nsISupports can be traced.
*
* The name of the nspr log module is "xpcomrefcnt" (case matters).
*
* This code only performs tracing built with debugging AND when
* built with -DMOZ_TRACE_XPCOM_REFCNT (because it's expensive!).
*/
class nsTraceRefcnt {
public:
static NS_COM unsigned long AddRef(void* aPtr,
unsigned long aNewRefcnt,
const char* aFile,
int aLine);
static NS_COM unsigned long Release(void* aPtr,
unsigned long aNewRefcnt,
const char* aFile,
int aLine);
static NS_COM void Create(void* aPtr,
const char* aType,
const char* aFile,
int aLine);
static NS_COM void Destroy(void* aPtr,
const char* aFile,
int aLine);
static NS_COM void LoadLibrarySymbols(const char* aLibraryName,
void* aLibrayHandle);
static NS_COM void WalkTheStack(char* aBuffer, int aBufLen);
};
#endif /* nsTraceRefcnt_h___ */

View File

@@ -0,0 +1,168 @@
/* -*- 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.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
* Reserved.
*/
#ifndef __mozIClassRegistry_h
#define __mozIClassRegistry_h
#include "nsRepository.h"
/*---------------------------- mozIClassRegistry -------------------------------
| This interface provides access to a mapping from mnemonic interface names |
| to shared libraries where implementations of those interfaces can be located.|
| |
| This interface is designed to provide two things: |
| 1. A means of less static binding between clients and the code that |
| implements the XPCOM interfaces those clients use. This accomplished |
| by the mapping from interface names to nsCID (and the shared libraries |
| that implement those classes). |
| 2. A means of dynamically changing the mapping from interface name to |
| implementation. The canonical example of this is to switch to a |
| "native" widget set versus an "XP" (implemented using gfx) set. |
| |
| The first goal is achieved by storing (in a "Netscape Registry" file, see |
| nsReg.h) information that maps interface/class "names" to information about |
| where to load implementations of those interfaces. That information |
| includes the interface ID, class ID (of the implementation class), and the |
| name of the shared library that contains the implementation. |
| |
| The class registry object will register those classes with the "repository" |
| (see nsRepository.h) the first time a request is made to create an |
| instance. Subsequent requests will simply be forwarded to the repository |
| after the appropriate interface and class IDs are determined. |
| |
| The second goal is accomplished by permitting the mnemonic interface |
| "names" to be "overloaded", that is, mapped to distinct implementations |
| by separate class registry objects. Further, class registries can be |
| cascaded: they can be chained together so that when a name is not |
| recognized by one registry, it can pass the request to the next registry in |
| the chain. Users can control resolution by making the request of a |
| registry further up/down the chain. |
| |
| For example, consider the case of "native" vs. "gfx" widgets. This might |
| be structured by a class registry arrangment like this: |
| |
| nativeWidgetRegistry baseWidgetRegistry |
| +----------+ +----------+ |
| | ----+---------------->| | |
| +----------+ +----------+ |
| |toolbar| -+-----+ |toolbar| -+-----+ |
| +----------+ | +----------+ | |
| |button | -+-----+ |button | -+-----+ |
| +----------+ | +----------+ | |
| V V |
| +-----------------+ +-----------------+ |
| | native.dll | | base.dll | |
| +-----------------+ +-----------------+ |
| |
| If a specialized implementation of widgets is present (e.g., native.dll) |
| then a corresponding class registry object is created and added to the |
| head of the registry chain. Object creation requests (normal ones) are |
| resolved to the native implementation. If such a library is not present, |
| then the resolution is to the base implementation. If objects of the |
| base implementation are required, then creation requests can be directed |
| directly to the baseWidgetRegistry object, rather than the head of the |
| registry chain. |
| |
| It is intended that there be a single instance of this interface, accessed |
| via the Service Manager (see nsServiceManager.h). |
------------------------------------------------------------------------------*/
struct mozIClassRegistry : public ISupports {
/*------------------------------ CreateInstance ----------------------------
| Create an instance of the requested class/interface. The interface |
| ID is required to specify how the result will be treated. The class |
| named by aName must support this interface. The result is placed in |
| ncomment aResult (NULL if the request fails). "start" specifies the |
| registry at which the search for an implementation of the named |
| interface should start. It defaults to 0 (indicating to start at the |
| head of the registry chain). |
--------------------------------------------------------------------------*/
NS_IMETHOD CreateInstance( const char *anInterfaceName,
const nsIID &aIID,
void* *aResult,
const char *start = 0 ) = 0;
/*--------------------------- CreateEnumerator -----------------------------
| Creates an nsIEnumerator interface object that can be used to examine |
| the contents of the registry. "pattern" specifies either "*" or the |
| name of a specific interface that you want to query. "result" will |
| be set to point to a new object (which will be freed on the last call |
| to its Release() member). See nsIEnumerator.h for details on how to |
| use the returned interface pointer. |
--------------------------------------------------------------------------*/
NS_IMETHOD CreateEnumerator( const char *pattern,
nsIEnumerator* *result ) = 0;
}; // mozIClassRegistry
/*-------------------------- mozIClassRegistryEntry ----------------------------
| Objects of this class represent the individual elements that comprise a |
| mozIClassRegistry interface. You obtain such objects by applying the |
| CreateEnumerator member function to the class registry and then applying |
| the CurrentItem member function to the resulting nsIEnumerator interface. |
| |
| Each entry can be queried for the following information: |
| o sub-registry name |
| o interface name |
| o Class ID |
| o IIDs implemented |
| |
| The information obtained from the entry (specifically, the const char* |
| strings) remains valid for the life of the entry (i.e., until you |
| Release() it). |
| |
| Here is an example of code that uses this interface to dump the contents |
| of a mozIClassRegistry: |
| |
| mozIClassRegistry *reg = nsServiceManager::GetService( kIDRegistry ); |
| nsIEnumerator *enum; |
| reg->CreateEnumerator( "*", &enum ); |
| for ( enum->First(); !enum->IsDone(); enum->Next(); ) { |
| mozIClassRegistryEntry *entry; |
| enum->CurrentItem( &entry ); |
| const char *subreg; |
| const char *name; |
| nsCID cid; |
| int numIIDs; |
| entry->GetSubRegistryName( &subreg ); |
| entry->GetInterfaceName( &name ); |
| entry->GetClassID( &cid ); |
| entry->GetNumIIDs( &numIIDs ); |
| cout << subreg << "/" << name << " = " << cid.ToString() << endl; |
| for ( int i = 0; i < numIIDs; i++ ) { |
| nsIID iid; |
| entry->GetInterfaceID( i, &iid ); |
| cout << "/tIID[" << i << "] = " << iid.ToString() << endl; |
| } |
| entry->Release(); |
| } |
| enum->Release(); |
------------------------------------------------------------------------------*/
struct mozIClassRegistryEntry : public nsISupports {
NS_IMETHOD GetSubRegistryName( const char **result ) = 0;
NS_IMETHOD GetInterfaceName( const char **result ) = 0;
NS_IMETHOD GetClassID( nsCID *result ) = 0;
NS_IMETHOD GetNumIIDs( int *result ) = 0;
NS_IMETHOD GetInterfaceID( int n, nsIID *result ) = 0;
}; // mozIClassRegistryEntry
// {5D41A440-8E37-11d2-8059-00600811A9C3}
#define MOZ_ICLASSREGISTRY_IID { 0x5d41a440, 0x8e37, 0x11d2, { 0x80, 0x59, 0x0, 0x60, 0x8, 0x11, 0xa9, 0xc3 } }
// {D1B54831-AC07-11d2-805E-00600811A9C3}
#define MOZ_ICLASSREGISTRYENTRY_IID { 0xd1b54831, 0xac07, 0x11d2, { 0x80, 0x5e, 0x0, 0x60, 0x8, 0x11, 0xa9, 0xc3 } }
#endif

View File

@@ -0,0 +1,326 @@
/* -*- 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.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
* Reserved.
*/
#ifndef __mozIRegistry_h
#define __mozIRegistry_h
#include "nsISupports.h"
class nsIEnumerator;
/*------------------------------- mozIRegistry ---------------------------------
| This interface provides access to a tree of arbitrary values. |
| |
| Each node of the tree contains either a value or a subtree or both. |
| |
| The value at any of these leaf nodes can be any of these "primitive" types: |
| o string (null terminated UTF string) |
| o array of 32-bit integers |
| o arbitrary array of bytes |
| o file identifier |
| Of course, since you can store an arbitrary array of bytes, you can put |
| any data you like into a registry (although you have the burden of |
| encoding/decoding your data in that case). |
| |
| Each branch of the tree is labelled with a string "key." The entire path |
| from a given point of the tree to another point further down can be |
| presented as a single string composed of each branch's label, concatenated |
| to the next, with an intervening forward slash ('/'). The term "key" |
| refers to both specific tree branch labels and to such concatenated paths. |
| |
| The branches from a given node must have unique labels. Distinct nodes can |
| have branches with the same label. |
| |
| For example, here's a small registry tree: |
| | |
| /\ |
| / \ |
| / \ |
| / \ |
| "Classes" "Users" |
| / \ |
| / \ |
| / ["joe"] |
| / / \ |
| | / \ |
| /\ / \ |
| / \ "joe" "bob" |
| / \ / \ |
| / \ |
| "{xxxx-xx-1}" "{xxxx-xx-2}" ["c:/joe"] ["d:/Robert"] |
| | | |
| /\ /\ |
| / \ / \ |
| / \ / \ |
| "Library" "Version" "Library" "Version" |
| / \ / \ |
| ["foo.dll"] 2 ["bar.dll"] 1 |
| |
| In this example, there are 2 keys under the root: "Classes" and "Users". |
| The first denotes a subtree only (which has two subtrees, ...). The second |
| denotes both a value ["joe"] and two subtrees labelled "joe" and "bob". |
| The value at the node "/Users" is ["joe"], at "/Users/bob" is ["d:/Robert"]. |
| The value at "/Classes/{xxxx-xx-1}/Version" is 2. |
| |
| The registry interface provides functions that let you navigate the tree |
| and manipulate it's contents. |
| |
| Please note that the registry itself does not impose any structure or |
| meaning on the contents of the tree. For example, the registry doesn't |
| control whether the value at the key "/Users" is the label for the subtree |
| with information about the last active user. That meaning is applied by |
| the code that stores these values and uses them for that purpose. |
| |
| [Any resemblence between this example and actual contents of any actual |
| registry is purely coincidental.] |
------------------------------------------------------------------------------*/
struct mozIRegistry : public nsISupports {
/*------------------------------ Constants ---------------------------------
| The following enumerated types and values are used by the registry |
| interface. |
--------------------------------------------------------------------------*/
typedef enum {
String = 1,
Int32,
Bytes,
File
} DataType;
/*-------------------------------- Types -----------------------------------
| The following data types are used by this interface. All are basically |
| opaque types. You obtain objects of these types via certain member |
| function calls and re-use them later (without having to know what they |
| contain). |
| |
| Key - Placeholder to represent a particular node in a registry |
| tree. There are 3 enumerated values that correspond to |
| specific nodes: |
| Common - Where most stuff goes. |
| Users - Special subtree to hold info about |
| "users"; if you don't know what goes |
| here, don't mess with it. |
| CurrentUser - Subtree under Users corresponding to |
| whatever user is designed the "current" |
| one; see note above. |
| You can specify any of these enumerated values as "keys" |
| on any member function that takes a mozRegistry::Key. |
| ValueInfo - Structure describing a registry value. |
--------------------------------------------------------------------------*/
typedef uint32 Key;
enum { Users = 1, Common = 2, CurrentUser = 3 };
struct ValueInfo {
DataType type;
uint32 length;
};
/*--------------------------- Opening/Closing ------------------------------
| These functions open the specified registry file (Open() with a non-null |
| argument) or the default "standard" registry file (Open() with a null |
| argument or OpenDefault()). |
| |
| Once opened, you can access the registry contents via the read/write |
| or query functions. |
| |
| The registry file will be closed automatically when the registry object |
| is destroyed. You can close the file prior to that by using the |
| Close() function. |
--------------------------------------------------------------------------*/
NS_IMETHOD Open( const char *regFile = 0 ) = 0;
NS_IMETHOD OpenDefault() = 0;
NS_IMETHOD Close() = 0;
/*----------------------- Reading/Writing Values ---------------------------
| These functions read/write the registry values at a given node. |
| |
| All functions require you to specify where in the registry key to |
| get/set the value. The location is specified using two components: |
| o A "base key" indicating where to start from; this is a value of type |
| mozIRegistry::Key. You use either one of the special "root" key |
| values or a subkey obtained via some other member function call. |
| o A "relative path," expressed as a sequence of subtree names |
| separated by forward slashes. This path describes how to get from |
| the base key to the node at which you want to store the data. This |
| component can be a null pointer which means the value goes directly |
| at the node denoted by the base key. |
| |
| When you request a value of a given type, the data stored at the |
| specified node must be of the type requested. If not, an error results. |
| |
| GetString - Obtains a newly allocated copy of a string type value. The |
| caller is obligated to free the returned string using |
| PR_Free. |
| SetString - Stores the argument string at the specified node. |
| GetInt - Obtains an int32 value at the specified node. The result |
| is returned into an int32 location you specify. |
| SetInt - Stores a given int32 value at a node. |
| GetBytes - Obtains a byte array value; this returns both an allocated |
| array of bytes and a length (necessary because there may be |
| embedded null bytes in the array). You must free the |
| resulting array using PR_Free. |
| SetBytes - Stores a given array of bytes; you specify the bytes via a |
| pointer and a length. |
| GetIntArray - Obtains the array of int32 values stored at a given node. |
| The result is composed of two values: a pointer to an |
| array of integer values (which must be freed using |
| PR_Free) and the number of elements in that array. |
| SetIntArray - Stores a set of int32 values at a given node. You must |
| provide a pointer to the array and the number of entries. |
--------------------------------------------------------------------------*/
NS_IMETHOD GetString( Key baseKey, const char *path, char **result ) = 0;
NS_IMETHOD SetString( Key baseKey, const char *path, const char *value ) = 0;
NS_IMETHOD GetInt( Key baseKey, const char *path, int32 *result ) = 0;
NS_IMETHOD SetInt( Key baseKey, const char *path, int32 value ) = 0;
NS_IMETHOD GetBytes( Key baseKey, const char *path, void **result, uint32 *len ) = 0;
NS_IMETHOD SetBytes( Key baseKey, const char *path, void *value, uint32 len ) = 0;
NS_IMETHOD GetIntArray( Key baseKey, const char *path, int32 **result, uint32 *len ) = 0;
NS_IMETHOD SetIntArray( Key baseKey, const char *path, const int32 *value, uint32 len ) = 0;
/*------------------------------ Navigation --------------------------------
| These functions let you navigate through the registry tree, querying |
| its contents. |
| |
| As above, all these functions requires a starting tree location ("base |
| key") specified as a mozIRegistry::Key. Some also require a path |
| name to locate the registry node location relative to this base key. |
| |
| AddSubtree - Adds a new registry subtree at the specified |
| location. Returns the resulting key in |
| the location specified by the third argument |
| (unless that pointer is 0). |
| RemoveNode - Removes the specified registry subtree or |
| value at the specified location. |
| GetSubtree - Returns a mozIRegistry::Key that can be used |
| to refer to the specified registry location. |
| EnumerateSubtrees - Returns a nsIEnumerator object that you can |
| use to enumerate all the subtrees descending |
| from a specified location. You must free the |
| enumerator via Release() when you're done with |
| it. |
| EnumerateAllSubtrees - Like EnumerateSubtrees, but will recursively |
| enumerate lower-level subtrees, too. |
| GetValueInfo - Returns a uint32 value that designates the type |
| of data stored at this location in the registry; |
| the possible values are defined by the enumerated |
| type mozIRegistry::DataType. |
| GetValueLength - Returns a uint32 value that indicates the length |
| of this registry value; the length is the number |
| of characters (for Strings), the number of bytes |
| (for Bytes), or the number of int32 values (for |
| Int32). |
| EnumerateValues - Returns a nsIEnumerator that you can use to |
| enumerate all the value nodes descending from |
| a specified location. |
--------------------------------------------------------------------------*/
NS_IMETHOD AddSubtree( Key baseKey, const char *path, Key *result ) = 0;
NS_IMETHOD RemoveSubtree( Key baseKey, const char *path ) = 0;
NS_IMETHOD GetSubtree( Key baseKey, const char *path, Key *result ) = 0;
NS_IMETHOD EnumerateSubtrees( Key baseKey, nsIEnumerator **result ) = 0;
NS_IMETHOD EnumerateAllSubtrees( Key baseKey, nsIEnumerator **result ) = 0;
NS_IMETHOD GetValueType( Key baseKey, const char *path, uint32 *result ) = 0;
NS_IMETHOD GetValueLength( Key baseKey, const char *path, uint32 *result ) = 0;
NS_IMETHOD EnumerateValues( Key baseKey, nsIEnumerator **result ) = 0;
/*------------------------------ User Name ---------------------------------
| These functions manipulate the current "user name." This value controls |
| the behavior of certain registry functions (namely, ?). |
| |
| GetCurrentUserName allocates a copy of the current user name (which the |
| caller should free using PR_Free). |
--------------------------------------------------------------------------*/
NS_IMETHOD GetCurrentUserName( char **result ) = 0;
NS_IMETHOD SetCurrentUserName( const char *name ) = 0;
/*------------------------------ Utilities ---------------------------------
| Various utility functions: |
| |
| Pack() is used to compress the contents of an open registry file. |
--------------------------------------------------------------------------*/
NS_IMETHOD Pack() = 0;
}; // mozIRegistry
/*----------------------------- mozIRegistryNode -------------------------------
| This interface is implemented by all the objects obtained from the |
| nsIEnumerators that mozIRegistry provides when you call either of the |
| subtree enumeration functions EnumerateSubtrees or EnumerateAllSubtrees. |
| |
| You can call this function to get the name of this subtree. This is the |
| relative path from the base key from which you got this interface. |
| |
| GetName - Returns the path name of this node; this is the relative path |
| from the base key from which this subtree was obtained. The |
| function allocates a copy of the name; the caller must free it |
| using PR_Free. |
------------------------------------------------------------------------------*/
struct mozIRegistryNode : public nsISupports {
NS_IMETHOD GetName( char **result ) = 0;
}; // mozIRegistryNode
/*----------------------------- mozIRegistryValue ------------------------------
| This interface is implemented by the objects obtained from the |
| nsIEnumerators that mozIRegistry provides when you call the |
| EnumerateValues function. An object supporting this interface is |
| returned when you call the CurrentItem() function on that enumerator. |
| |
| You use the member functions of this interface to obtain information |
| about each registry value. |
| |
| GetName - Returns the path name of this node; this is the relative |
| path\ from the base key from which this value was obtained. |
| The function allocates a copy of the name; the caller must |
| subsequently free it via PR_Free. |
| GetValueType - Returns (into a location provided by the caller) the type |
| of the value; the types are defined by the enumerated |
| type mozIRegistry::DataType. |
| GetValueLength - Returns a uint32 value that indicates the length |
| of this registry value; the length is the number |
| of characters (for Strings), the number of bytes |
| (for Bytes), or the number of int32 values (for |
| Int32). |
------------------------------------------------------------------------------*/
struct mozIRegistryValue : public nsISupports {
NS_IMETHOD GetName( char **result ) = 0;
NS_IMETHOD GetValueType( uint32 *result ) = 0;
NS_IMETHOD GetValueLength( uint32 *result ) = 0;
}; // mozIRegistryEntry
/*------------------------------- Error Codes ----------------------------------
------------------------------------------------------------------------------*/
#define NS_ERROR_REG_BADTYPE NS_ERROR_GENERATE_FAILURE( NS_ERROR_MODULE_REG, 1 )
#define NS_ERROR_REG_NO_MORE NS_ERROR_GENERATE_SUCCESS( NS_ERROR_MODULE_REG, 2 )
#define NS_ERROR_REG_NOT_FOUND NS_ERROR_GENERATE_FAILURE( NS_ERROR_MODULE_REG, 3 )
#define NS_ERROR_REG_NOFILE NS_ERROR_GENERATE_FAILURE( NS_ERROR_MODULE_REG, 4 )
#define NS_ERROR_REG_BUFFER_TOO_SMALL NS_ERROR_GENERATE_FAILURE( NS_ERROR_MODULE_REG, 5 )
#define NS_ERROR_REG_NAME_TOO_LONG NS_ERROR_GENERATE_FAILURE( NS_ERROR_MODULE_REG, 6 )
#define NS_ERROR_REG_NO_PATH NS_ERROR_GENERATE_FAILURE( NS_ERROR_MODULE_REG, 7 )
#define NS_ERROR_REG_READ_ONLY NS_ERROR_GENERATE_FAILURE( NS_ERROR_MODULE_REG, 8 )
#define NS_ERROR_REG_BAD_UTF8 NS_ERROR_GENERATE_FAILURE( NS_ERROR_MODULE_REG, 9 )
// {5D41A440-8E37-11d2-8059-00600811A9C3}
#define MOZ_IREGISTRY_IID { 0x5d41a440, 0x8e37, 0x11d2, { 0x80, 0x59, 0x0, 0x60, 0x8, 0x11, 0xa9, 0xc3 } }
// {D1B54831-AC07-11d2-805E-00600811A9C3}
#define MOZ_IREGISTRYNODE_IID { 0xd1b54831, 0xac07, 0x11d2, { 0x80, 0x5e, 0x0, 0x60, 0x8, 0x11, 0xa9, 0xc3 } }
// {5316C380-B2F8-11d2-A374-0080C6F80E4B}
#define MOZ_IREGISTRYVALUE_IID { 0x5316c380, 0xb2f8, 0x11d2, { 0xa3, 0x74, 0x0, 0x80, 0xc6, 0xf8, 0xe, 0x4b } }
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,80 @@
/* -*- 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.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
* Reserved.
*/
#ifndef __nsIFactory_h
#define __nsIFactory_h
#include "prtypes.h"
#include "nsISupports.h"
/*
* Datatypes and helper macros
*/
typedef nsID nsCID;
// Define an CID
#define NS_DEFINE_CID(_name, _cidspec) \
const nsCID _name = _cidspec
#define REFNSCID const nsCID&
/*
* nsIFactory interface
*/
// {00000001-0000-0000-c000-000000000046}
#define NS_IFACTORY_IID \
{ 0x00000001, 0x0000, 0x0000, \
{ 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46 } }
class nsIFactory: public nsISupports {
public:
static const nsIID& IID() { static nsIID iid = NS_IFACTORY_IID; return iid; }
NS_IMETHOD CreateInstance(nsISupports *aOuter,
REFNSIID aIID,
void **aResult) = 0;
NS_IMETHOD LockFactory(PRBool aLock) = 0;
};
#if 0
/* Excluding IFactory2 until there is proof of its use - dp */
/**
* nsIFactory2 allows passing in a signature token when creating an
* instance. This allows instance recycling.
*/
// {19997C41-A343-11d1-B665-00805F8A2676}
#define NS_IFACTORY2_IID \
{ 0x19997c41, 0xa343, 0x11d1, \
{ 0xb6, 0x65, 0x0, 0x80, 0x5f, 0x8a, 0x26, 0x76 } }
class nsIFactory2: public nsIFactory {
public:
static const nsIID& IID() { static nsIID iid = NS_IFACTORY2_IID; return iid; }
NS_IMETHOD CreateInstance2(nsISupports *aOuter,
REFNSIID aIID,
void *aSignature,
void **aResult) = 0;
};
#endif /* 0 */
#endif

View File

@@ -0,0 +1,326 @@
/* -*- 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.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
* Reserved.
*/
#ifndef __nsIRegistry_h
#define __nsIRegistry_h
#include "nsISupports.h"
class nsIEnumerator;
/*-------------------------------- nsIRegistry ---------------------------------
| This interface provides access to a tree of arbitrary values. |
| |
| Each node of the tree contains either a value or a subtree or both. |
| |
| The value at any of these leaf nodes can be any of these "primitive" types: |
| o string (null terminated UTF string) |
| o array of 32-bit integers |
| o arbitrary array of bytes |
| o file identifier |
| Of course, since you can store an arbitrary array of bytes, you can put |
| any data you like into a registry (although you have the burden of |
| encoding/decoding your data in that case). |
| |
| Each branch of the tree is labelled with a string "key." The entire path |
| from a given point of the tree to another point further down can be |
| presented as a single string composed of each branch's label, concatenated |
| to the next, with an intervening forward slash ('/'). The term "key" |
| refers to both specific tree branch labels and to such concatenated paths. |
| |
| The branches from a given node must have unique labels. Distinct nodes can |
| have branches with the same label. |
| |
| For example, here's a small registry tree: |
| | |
| /\ |
| / \ |
| / \ |
| / \ |
| "Classes" "Users" |
| / \ |
| / \ |
| / ["joe"] |
| / / \ |
| | / \ |
| /\ / \ |
| / \ "joe" "bob" |
| / \ / \ |
| / \ |
| "{xxxx-xx-1}" "{xxxx-xx-2}" ["c:/joe"] ["d:/Robert"] |
| | | |
| /\ /\ |
| / \ / \ |
| / \ / \ |
| "Library" "Version" "Library" "Version" |
| / \ / \ |
| ["foo.dll"] 2 ["bar.dll"] 1 |
| |
| In this example, there are 2 keys under the root: "Classes" and "Users". |
| The first denotes a subtree only (which has two subtrees, ...). The second |
| denotes both a value ["joe"] and two subtrees labelled "joe" and "bob". |
| The value at the node "/Users" is ["joe"], at "/Users/bob" is ["d:/Robert"]. |
| The value at "/Classes/{xxxx-xx-1}/Version" is 2. |
| |
| The registry interface provides functions that let you navigate the tree |
| and manipulate it's contents. |
| |
| Please note that the registry itself does not impose any structure or |
| meaning on the contents of the tree. For example, the registry doesn't |
| control whether the value at the key "/Users" is the label for the subtree |
| with information about the last active user. That meaning is applied by |
| the code that stores these values and uses them for that purpose. |
| |
| [Any resemblence between this example and actual contents of any actual |
| registry is purely coincidental.] |
------------------------------------------------------------------------------*/
struct nsIRegistry : public nsISupports {
/*------------------------------ Constants ---------------------------------
| The following enumerated types and values are used by the registry |
| interface. |
--------------------------------------------------------------------------*/
typedef enum {
String = 1,
Int32,
Bytes,
File
} DataType;
/*-------------------------------- Types -----------------------------------
| The following data types are used by this interface. All are basically |
| opaque types. You obtain objects of these types via certain member |
| function calls and re-use them later (without having to know what they |
| contain). |
| |
| Key - Placeholder to represent a particular node in a registry |
| tree. There are 3 enumerated values that correspond to |
| specific nodes: |
| Common - Where most stuff goes. |
| Users - Special subtree to hold info about |
| "users"; if you don't know what goes |
| here, don't mess with it. |
| CurrentUser - Subtree under Users corresponding to |
| whatever user is designed the "current" |
| one; see note above. |
| You can specify any of these enumerated values as "keys" |
| on any member function that takes a nsRegistry::Key. |
| ValueInfo - Structure describing a registry value. |
--------------------------------------------------------------------------*/
typedef uint32 Key;
enum { Users = 1, Common = 2, CurrentUser = 3 };
struct ValueInfo {
DataType type;
uint32 length;
};
/*--------------------------- Opening/Closing ------------------------------
| These functions open the specified registry file (Open() with a non-null |
| argument) or the default "standard" registry file (Open() with a null |
| argument or OpenDefault()). |
| |
| Once opened, you can access the registry contents via the read/write |
| or query functions. |
| |
| The registry file will be closed automatically when the registry object |
| is destroyed. You can close the file prior to that by using the |
| Close() function. |
--------------------------------------------------------------------------*/
NS_IMETHOD Open( const char *regFile = 0 ) = 0;
NS_IMETHOD OpenDefault() = 0;
NS_IMETHOD Close() = 0;
/*----------------------- Reading/Writing Values ---------------------------
| These functions read/write the registry values at a given node. |
| |
| All functions require you to specify where in the registry key to |
| get/set the value. The location is specified using two components: |
| o A "base key" indicating where to start from; this is a value of type |
| nsIRegistry::Key. You use either one of the special "root" key |
| values or a subkey obtained via some other member function call. |
| o A "relative path," expressed as a sequence of subtree names |
| separated by forward slashes. This path describes how to get from |
| the base key to the node at which you want to store the data. This |
| component can be a null pointer which means the value goes directly |
| at the node denoted by the base key. |
| |
| When you request a value of a given type, the data stored at the |
| specified node must be of the type requested. If not, an error results. |
| |
| GetString - Obtains a newly allocated copy of a string type value. The |
| caller is obligated to free the returned string using |
| PR_Free. |
| SetString - Stores the argument string at the specified node. |
| GetInt - Obtains an int32 value at the specified node. The result |
| is returned into an int32 location you specify. |
| SetInt - Stores a given int32 value at a node. |
| GetBytes - Obtains a byte array value; this returns both an allocated |
| array of bytes and a length (necessary because there may be |
| embedded null bytes in the array). You must free the |
| resulting array using PR_Free. |
| SetBytes - Stores a given array of bytes; you specify the bytes via a |
| pointer and a length. |
| GetIntArray - Obtains the array of int32 values stored at a given node. |
| The result is composed of two values: a pointer to an |
| array of integer values (which must be freed using |
| PR_Free) and the number of elements in that array. |
| SetIntArray - Stores a set of int32 values at a given node. You must |
| provide a pointer to the array and the number of entries. |
--------------------------------------------------------------------------*/
NS_IMETHOD GetString( Key baseKey, const char *path, char **result ) = 0;
NS_IMETHOD SetString( Key baseKey, const char *path, const char *value ) = 0;
NS_IMETHOD GetInt( Key baseKey, const char *path, int32 *result ) = 0;
NS_IMETHOD SetInt( Key baseKey, const char *path, int32 value ) = 0;
NS_IMETHOD GetBytes( Key baseKey, const char *path, void **result, uint32 *len ) = 0;
NS_IMETHOD SetBytes( Key baseKey, const char *path, void *value, uint32 len ) = 0;
NS_IMETHOD GetIntArray( Key baseKey, const char *path, int32 **result, uint32 *len ) = 0;
NS_IMETHOD SetIntArray( Key baseKey, const char *path, const int32 *value, uint32 len ) = 0;
/*------------------------------ Navigation --------------------------------
| These functions let you navigate through the registry tree, querying |
| its contents. |
| |
| As above, all these functions requires a starting tree location ("base |
| key") specified as a nsIRegistry::Key. Some also require a path |
| name to locate the registry node location relative to this base key. |
| |
| AddSubtree - Adds a new registry subtree at the specified |
| location. Returns the resulting key in |
| the location specified by the third argument |
| (unless that pointer is 0). |
| RemoveNode - Removes the specified registry subtree or |
| value at the specified location. |
| GetSubtree - Returns a nsIRegistry::Key that can be used |
| to refer to the specified registry location. |
| EnumerateSubtrees - Returns a nsIEnumerator object that you can |
| use to enumerate all the subtrees descending |
| from a specified location. You must free the |
| enumerator via Release() when you're done with |
| it. |
| EnumerateAllSubtrees - Like EnumerateSubtrees, but will recursively |
| enumerate lower-level subtrees, too. |
| GetValueInfo - Returns a uint32 value that designates the type |
| of data stored at this location in the registry; |
| the possible values are defined by the enumerated |
| type nsIRegistry::DataType. |
| GetValueLength - Returns a uint32 value that indicates the length |
| of this registry value; the length is the number |
| of characters (for Strings), the number of bytes |
| (for Bytes), or the number of int32 values (for |
| Int32). |
| EnumerateValues - Returns a nsIEnumerator that you can use to |
| enumerate all the value nodes descending from |
| a specified location. |
--------------------------------------------------------------------------*/
NS_IMETHOD AddSubtree( Key baseKey, const char *path, Key *result ) = 0;
NS_IMETHOD RemoveSubtree( Key baseKey, const char *path ) = 0;
NS_IMETHOD GetSubtree( Key baseKey, const char *path, Key *result ) = 0;
NS_IMETHOD EnumerateSubtrees( Key baseKey, nsIEnumerator **result ) = 0;
NS_IMETHOD EnumerateAllSubtrees( Key baseKey, nsIEnumerator **result ) = 0;
NS_IMETHOD GetValueType( Key baseKey, const char *path, uint32 *result ) = 0;
NS_IMETHOD GetValueLength( Key baseKey, const char *path, uint32 *result ) = 0;
NS_IMETHOD EnumerateValues( Key baseKey, nsIEnumerator **result ) = 0;
/*------------------------------ User Name ---------------------------------
| These functions manipulate the current "user name." This value controls |
| the behavior of certain registry functions (namely, ?). |
| |
| GetCurrentUserName allocates a copy of the current user name (which the |
| caller should free using PR_Free). |
--------------------------------------------------------------------------*/
NS_IMETHOD GetCurrentUserName( char **result ) = 0;
NS_IMETHOD SetCurrentUserName( const char *name ) = 0;
/*------------------------------ Utilities ---------------------------------
| Various utility functions: |
| |
| Pack() is used to compress the contents of an open registry file. |
--------------------------------------------------------------------------*/
NS_IMETHOD Pack() = 0;
}; // nsIRegistry
/*------------------------------ nsIRegistryNode -------------------------------
| This interface is implemented by all the objects obtained from the |
| nsIEnumerators that nsIRegistry provides when you call either of the |
| subtree enumeration functions EnumerateSubtrees or EnumerateAllSubtrees. |
| |
| You can call this function to get the name of this subtree. This is the |
| relative path from the base key from which you got this interface. |
| |
| GetName - Returns the path name of this node; this is the relative path |
| from the base key from which this subtree was obtained. The |
| function allocates a copy of the name; the caller must free it |
| using PR_Free. |
------------------------------------------------------------------------------*/
struct nsIRegistryNode : public nsISupports {
NS_IMETHOD GetName( char **result ) = 0;
}; // nsIRegistryNode
/*------------------------------ nsIRegistryValue ------------------------------
| This interface is implemented by the objects obtained from the |
| nsIEnumerators that nsIRegistry provides when you call the |
| EnumerateValues function. An object supporting this interface is |
| returned when you call the CurrentItem() function on that enumerator. |
| |
| You use the member functions of this interface to obtain information |
| about each registry value. |
| |
| GetName - Returns the path name of this node; this is the relative |
| path\ from the base key from which this value was obtained. |
| The function allocates a copy of the name; the caller must |
| subsequently free it via PR_Free. |
| GetValueType - Returns (into a location provided by the caller) the type |
| of the value; the types are defined by the enumerated |
| type nsIRegistry::DataType. |
| GetValueLength - Returns a uint32 value that indicates the length |
| of this registry value; the length is the number |
| of characters (for Strings), the number of bytes |
| (for Bytes), or the number of int32 values (for |
| Int32). |
------------------------------------------------------------------------------*/
struct nsIRegistryValue : public nsISupports {
NS_IMETHOD GetName( char **result ) = 0;
NS_IMETHOD GetValueType( uint32 *result ) = 0;
NS_IMETHOD GetValueLength( uint32 *result ) = 0;
}; // nsIRegistryEntry
/*------------------------------- Error Codes ----------------------------------
------------------------------------------------------------------------------*/
#define NS_ERROR_REG_BADTYPE NS_ERROR_GENERATE_FAILURE( NS_ERROR_MODULE_REG, 1 )
#define NS_ERROR_REG_NO_MORE NS_ERROR_GENERATE_SUCCESS( NS_ERROR_MODULE_REG, 2 )
#define NS_ERROR_REG_NOT_FOUND NS_ERROR_GENERATE_FAILURE( NS_ERROR_MODULE_REG, 3 )
#define NS_ERROR_REG_NOFILE NS_ERROR_GENERATE_FAILURE( NS_ERROR_MODULE_REG, 4 )
#define NS_ERROR_REG_BUFFER_TOO_SMALL NS_ERROR_GENERATE_FAILURE( NS_ERROR_MODULE_REG, 5 )
#define NS_ERROR_REG_NAME_TOO_LONG NS_ERROR_GENERATE_FAILURE( NS_ERROR_MODULE_REG, 6 )
#define NS_ERROR_REG_NO_PATH NS_ERROR_GENERATE_FAILURE( NS_ERROR_MODULE_REG, 7 )
#define NS_ERROR_REG_READ_ONLY NS_ERROR_GENERATE_FAILURE( NS_ERROR_MODULE_REG, 8 )
#define NS_ERROR_REG_BAD_UTF8 NS_ERROR_GENERATE_FAILURE( NS_ERROR_MODULE_REG, 9 )
// {5D41A440-8E37-11d2-8059-00600811A9C3}
#define NS_IREGISTRY_IID { 0x5d41a440, 0x8e37, 0x11d2, { 0x80, 0x59, 0x0, 0x60, 0x8, 0x11, 0xa9, 0xc3 } }
// {D1B54831-AC07-11d2-805E-00600811A9C3}
#define NS_IREGISTRYNODE_IID { 0xd1b54831, 0xac07, 0x11d2, { 0x80, 0x5e, 0x0, 0x60, 0x8, 0x11, 0xa9, 0xc3 } }
// {5316C380-B2F8-11d2-A374-0080C6F80E4B}
#define NS_IREGISTRYVALUE_IID { 0x5316c380, 0xb2f8, 0x11d2, { 0xa3, 0x74, 0x0, 0x80, 0xc6, 0xf8, 0xe, 0x4b } }
#endif

View File

@@ -0,0 +1,148 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
* Reserved.
*/
#ifndef nsIServiceManager_h___
#define nsIServiceManager_h___
#include "nsRepository.h"
class nsIShutdownListener;
/**
* The nsIServiceManager manager interface provides a means to obtain
* global services in an application. The service manager depends on the
* repository to find and instantiate factories to obtain services.
*
* Users of the service manager must first obtain a pointer to the global
* service manager by calling NS_GetGlobalServiceManager. After that,
* they can request specific services by calling GetService. When they are
* finished with a service the release it by calling ReleaseService (instead
* of releasing the service object directly):
*
* nsICacheManager* cm;
* nsServiceManager::GetService(kCacheManagerCID, kICacheManagerIID, (nsISupports**)&cm);
*
* ... use cm, and then sometime later ...
*
* nsServiceManager::ReleaseService(kCacheManagerCID, cm);
*
* A user of a service may keep references to particular services indefinitely
* and only must call ReleaseService when it shuts down. However if the user
* wishes to voluntarily cooperate with the shutdown of the service it is
* using, it may supply an nsIShutdownListener to provide for asynchronous
* release of the services it is using. The shutdown listener's OnShutdown
* method will be called for a service that is being shut down, and it is
* its responsiblity to release references obtained from that service if at
* all possible.
*
* The process of shutting down a particular service is initiated by calling
* the service manager's ShutdownService method. This will iterate through
* all the registered shutdown listeners for the service being shut down, and
* then will attempt to unload the library associated with the service if
* possible. The status result of ShutdownService indicates whether the
* service was successfully shut down, failed, or was not in service.
*
* XXX QUESTIONS:
* - Should a "service" be more than nsISupports? Should it be a factory
* and/or have Startup(), Shutdown(), etc.
* - If the asynchronous OnShutdown operation gets called, does the user
* of a service still need to call ReleaseService? (Or should they _not_
* call it?)
*/
class nsIServiceManager : public nsISupports {
public:
NS_IMETHOD
GetService(const nsCID& aClass, const nsIID& aIID,
nsISupports* *result,
nsIShutdownListener* shutdownListener = NULL) = 0;
NS_IMETHOD
ReleaseService(const nsCID& aClass, nsISupports* service,
nsIShutdownListener* shutdownListener = NULL) = 0;
/**
* Requests a service to be shut down, possibly unloading its DLL.
*
* @returns NS_OK - if shutdown was successful and service was unloaded,
* @returns NS_ERROR_SERVICE_NOT_FOUND - if shutdown failed because
* the service was not currently loaded
* @returns NS_ERROR_SERVICE_IN_USE - if shutdown failed because some
* user of the service wouldn't voluntarily release it by using
* a shutdown listener.
*/
NS_IMETHOD
ShutdownService(const nsCID& aClass) = 0;
};
#define NS_ISERVICEMANAGER_IID \
{ /* cf0df3b0-3401-11d2-8163-006008119d7a */ \
0xcf0df3b0, \
0x3401, \
0x11d2, \
{0x81, 0x63, 0x00, 0x60, 0x08, 0x11, 0x9d, 0x7a} \
}
#define NS_ERROR_SERVICE_NOT_FOUND NS_ERROR_GENERATE_SUCCESS(NS_ERROR_MODULE_XPCOM, 22)
#define NS_ERROR_SERVICE_IN_USE NS_ERROR_GENERATE_SUCCESS(NS_ERROR_MODULE_XPCOM, 23)
////////////////////////////////////////////////////////////////////////////////
class nsIShutdownListener : public nsISupports {
public:
NS_IMETHOD
OnShutdown(const nsCID& aClass, nsISupports* service) = 0;
};
#define NS_ISHUTDOWNLISTENER_IID \
{ /* 56decae0-3406-11d2-8163-006008119d7a */ \
0x56decae0, \
0x3406, \
0x11d2, \
{0x81, 0x63, 0x00, 0x60, 0x08, 0x11, 0x9d, 0x7a} \
}
////////////////////////////////////////////////////////////////////////////////
// Interface to Global Services
class NS_COM nsServiceManager {
public:
static nsresult GetService(const nsCID& aClass, const nsIID& aIID,
nsISupports* *result,
nsIShutdownListener* shutdownListener = NULL);
static nsresult ReleaseService(const nsCID& aClass, nsISupports* service,
nsIShutdownListener* shutdownListener = NULL);
static nsresult ShutdownService(const nsCID& aClass);
// Since the global Service Manager is truly global, there's no need to
// release it.
static nsresult GetGlobalServiceManager(nsIServiceManager* *result);
protected:
static nsIServiceManager* globalServiceManager;
};
////////////////////////////////////////////////////////////////////////////////
#endif /* nsIServiceManager_h___ */

View File

@@ -0,0 +1,31 @@
/* -*- 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.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
* Reserved.
*/
#ifndef __nsIServerProvider_h
#define __nsIServerProvider_h
#include "nsISupports.h"
typedef nsID nsSID;
#define NSSIDREF const nsSID&
class nsIServiceProvider: public nsISupports {
public:
NS_IMETHOD QueryService(NSSIDREF aSID, NSIIDREF sIID, (void **) pService);
};
#endif /* __nsIServerProvider_h */

View File

@@ -0,0 +1,118 @@
/* -*- 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.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
* Reserved.
*/
#ifdef XP_MAC
#ifdef MOZ_NGLAYOUT
#error "nsMacRepository.h became obsolete when the shared lib conversion was completed."
// The Mac NGLayout is not based on shared libraries yet.
// All the DLLs are built as static libraries and we present them as
// shared libraries by redefining PR_LoadLibrary(), PR_UnloadLibrary()
// and PR_FindSymbol() below.
//
// If you add or remove shared libraries on other platforms, you must
// - Add the library name to the defines below.
// - Rename the "NSGetFactory" and "NSCanUnload" procs for the Mac:
// just append the library name to the function name.
// - Add the library and its procs to the static list below.
typedef struct MacLibrary
{
char * name;
nsFactoryProc factoryProc;
nsCanUnloadProc unloadProc;
} MacLibrary;
// library names
#define WIDGET_DLL "WIDGET_DLL"
#define GFXWIN_DLL "GFXWIN_DLL"
#define VIEW_DLL "VIEW_DLL"
#define WEB_DLL "WEB_DLL"
#define PLUGIN_DLL "PLUGIN_DLL"
#define PREF_DLL "PREF_DLL"
#define PARSER_DLL "PARSER_DLL"
#define DOM_DLL "DOM_DLL"
#define LAYOUT_DLL "LAYOUT_DLL"
#define NETLIB_DLL "NETLIB_DLL"
#define EDITOR_DLL "EDITOR_DLL"
#ifdef IMPL_MAC_REPOSITORY
extern "C" nsresult NSGetFactory_WIDGET_DLL(const nsCID &, nsISupports* , nsIFactory ** );
extern "C" nsresult NSGetFactory_GFXWIN_DLL(const nsCID &, nsISupports*, nsIFactory ** );
extern "C" nsresult NSGetFactory_VIEW_DLL(const nsCID &, nsISupports*, nsIFactory **);
extern "C" nsresult NSGetFactory_WEB_DLL(const nsCID &, nsISupports*, nsIFactory **);
//extern "C" nsresult NSGetFactory_PLUGIN_DLL(const nsCID &, nsISupports*, nsIFactory **);
extern "C" nsresult NSGetFactory_PREF_DLL(const nsCID &, nsISupports*, nsIFactory **);
extern "C" nsresult NSGetFactory_PARSER_DLL(const nsCID &, nsISupports*, nsIFactory **);
extern "C" nsresult NSGetFactory_DOM_DLL(const nsCID &, nsISupports*, nsIFactory **);
extern "C" nsresult NSGetFactory_LAYOUT_DLL(const nsCID &, nsISupports*, nsIFactory **);
extern "C" nsresult NSGetFactory_NETLIB_DLL(const nsCID &, nsISupports*, nsIFactory **);
extern "C" nsresult NSGetFactory_EDITOR_DLL(const nsCID &, nsISupports*, nsIFactory **);
extern "C" PRBool NSCanUnload_PREF_DLL(void);
// library list
static MacLibrary libraries[] = {
#if 0
WIDGET_DLL, NSGetFactory_WIDGET_DLL, NULL,
GFXWIN_DLL, NSGetFactory_GFXWIN_DLL, NULL,
VIEW_DLL, NSGetFactory_VIEW_DLL, NULL,
WEB_DLL, NSGetFactory_WEB_DLL, NULL,
//PLUGIN_DLL, NSGetFactory_PLUGIN_DLL, NULL,
PREF_DLL, NSGetFactory_PREF_DLL, NSCanUnload_PREF_DLL,
PARSER_DLL, NSGetFactory_PARSER_DLL, NULL,
DOM_DLL, NSGetFactory_DOM_DLL, NULL,
LAYOUT_DLL, NSGetFactory_LAYOUT_DLL, NULL,
NETLIB_DLL, NSGetFactory_NETLIB_DLL, NULL,
//EDITOR_DLL, NSGetFactory_EDITOR_DLL, NULL, // FIX ME
#endif
NULL
};
static void* FindMacSymbol(char* libName, const char *symbolName)
{
MacLibrary * macLib;
for (macLib = libraries; ; macLib ++)
{
if (macLib->name == NULL)
return NULL;
if (PL_strcmp(macLib->name, libName) == 0)
break;
}
if (PL_strcmp(symbolName, "NSGetFactory") == 0) {
return macLib->factoryProc;
}
else if (PL_strcmp(symbolName, "NSCanUnload") == 0) {
return macLib->unloadProc;
}
return NULL;
}
#define PR_LoadLibrary(libName) (PRLibrary *)libName
#define PR_UnloadLibrary(lib) lib = NULL
#define PR_FindSymbol(lib, symbolName) FindMacSymbol((char*)lib, symbolName)
#endif // IMPL_MAC_REPOSITORY
#endif // MOZ_NGLAYOUT
#endif // XP_MAC

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,213 @@
/* -*- 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.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
* Reserved.
*/
#ifndef __nsRespository_h
#define __nsRespository_h
#include "prtypes.h"
#include "prlog.h"
#include "prmon.h"
#include "nsCom.h"
#include "nsID.h"
#include "nsError.h"
#include "nsISupports.h"
#include "nsIFactory.h"
#include "nsHashtable.h"
/*
* Prototypes for dynamic library export functions
*/
class nsIServiceManager;
//***********************************************************
//
// NSGetFactory should take nsISupports instead of nsIServiceManager
// as the second param. This is done on purpose!! Please don't change
// it.
// sudu / stanley
//
//***********************************************************
extern "C" NS_EXPORT nsresult NSGetFactory(const nsCID &aClass,
nsISupports* serviceMgr,
nsIFactory **aFactory);
extern "C" NS_EXPORT PRBool NSCanUnload();
extern "C" NS_EXPORT nsresult NSRegisterSelf(const char *fullpath);
extern "C" NS_EXPORT nsresult NSUnregisterSelf(const char *fullpath);
/* Quick Registration
*
* For quick registration, dlls can define
* NSQuickRegisterClassData g_NSQuickRegisterData[];
* and export the symbol "g_NSQuickRegisterData"
*
* Quick registration is tried only if the symbol "NSRegisterSelf"
* is not found. If it is found but fails registration, quick registration
* will not kick in.
*
* The array is terminated by having a NULL last element. Specifically, the
* array will be assumed to end when
* (g_NSQuickRegisterData[i].classIdStr == NULL)
*
*/
#define NS_QUICKREGISTER_DATA_SYMBOL "g_NSQuickRegisterData"
typedef struct NSQuickRegisterClassData {
const char *CIDString; // {98765-8776-8958758759-958785}
const char *className; // "Layout Engine"
const char *progID; // "Gecko.LayoutEngine.1"
} NSQuickRegisterClassData;
typedef NSQuickRegisterClassData* NSQuickRegisterData;
/* Autoregistration will try only files with these extensions.
* All extensions are case insensitive.
".dll", // Windows
".dso", // Unix
".so", // Unix
".sl", // Unix: HP
"_dll", // Mac
".dlm", // new for all platforms
*/
/*
* Dynamic library export function types
*/
typedef nsresult (*nsFactoryProc)(const nsCID &aCLass,
nsISupports* serviceMgr,
nsIFactory **aFactory);
typedef PRBool (*nsCanUnloadProc)(void);
typedef nsresult (*nsRegisterProc)(const char *path);
typedef nsresult (*nsUnregisterProc)(const char *path);
/*
* Support types
*/
class FactoryEntry;
class nsDllStore;
class nsDll;
enum NSRegistrationInstant
{
NS_Startup = 0,
NS_Script = 1,
NS_Timer = 2
};
/* Error codes generated by the repository methods */
#define NS_XPCOM_ERRORCODE_IS_DIR 1
/* The separator for each path part in the pathlist for autoregistration */
#define NS_PATH_SEPARATOR ';'
/*
* nsRepository class
*/
class NS_COM nsRepository {
private:
#define NS_MAX_FILENAME_LEN 1024
static nsHashtable *factories;
static PRMonitor *monitor;
static nsresult checkInitialized(void);
static nsresult loadFactory(FactoryEntry *aEntry, nsIFactory **aFactory);
static nsresult SelfRegisterDll(nsDll *dll);
static nsresult SelfUnregisterDll(nsDll *dll);
public:
static nsDllStore *dllStore;
static nsresult Initialize(void);
// Finds a factory for a specific class ID
static nsresult FindFactory(const nsCID &aClass,
nsIFactory **aFactory);
// Finds a class ID for a specific Program ID
static nsresult ProgIDToCLSID(const char *aProgID,
nsCID *aClass);
// Creates a class instance for a specific class ID
static nsresult CreateInstance(const nsCID &aClass,
nsISupports *aDelegate,
const nsIID &aIID,
void **aResult);
// Creates a class instance for a specific class ID
/*
static nsresult CreateInstance2(const nsCID &aClass,
nsISupports *aDelegate,
const nsIID &aIID,
void *aSignature,
void **aResult);
*/
// Manually registry a factory for a class
static nsresult RegisterFactory(const nsCID &aClass,
nsIFactory *aFactory,
PRBool aReplace);
// Manually registry a dynamically loaded factory for a class
static nsresult RegisterFactory(const nsCID &aClass,
const char *aLibrary,
PRBool aReplace,
PRBool aPersist);
// Manually register a dynamically loaded component.
static nsresult RegisterComponent(const nsCID &aClass,
const char *aClassName,
const char *aProgID,
const char *aLibrary,
PRBool aReplace,
PRBool aPersist);
// Manually unregister a factory for a class
static nsresult UnregisterFactory(const nsCID &aClass,
nsIFactory *aFactory);
// Manually unregister a dynamically loaded factory for a class
static nsresult UnregisterFactory(const nsCID &aClass,
const char *aLibrary);
// Manually unregister a dynamically loaded component
static nsresult UnregisterComponent(const nsCID &aClass,
const char *aLibrary);
// Unload dynamically loaded factories that are not in use
static nsresult FreeLibraries(void);
// DLL registration support
static nsresult AutoRegister(NSRegistrationInstant when,
const char* pathlist);
// Pathlist is a semicolon separated list of pathnames
static nsresult AddToDefaultPathList(const char *pathlist);
static nsresult SyncComponentsInPathList(const char *pathlist);
static nsresult SyncComponentsInDir(const char *path);
static nsresult SyncComponentsInFile(const char *fullname);
};
#endif

View File

@@ -0,0 +1,350 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
* Reserved.
*/
#include "nsIServiceManager.h"
#include "nsVector.h"
#include "prcmon.h"
#include "prthread.h" /* XXX: only used for the NSPR initialization hack (rick) */
class nsServiceEntry {
public:
nsServiceEntry(const nsCID& cid, nsISupports* service);
~nsServiceEntry();
nsresult AddListener(nsIShutdownListener* listener);
nsresult RemoveListener(nsIShutdownListener* listener);
nsresult NotifyListeners(void);
const nsCID& mClassID;
nsISupports* mService;
nsVector* mListeners; // nsVector<nsIShutdownListener>
PRBool mShuttingDown;
};
nsServiceEntry::nsServiceEntry(const nsCID& cid, nsISupports* service)
: mClassID(cid), mService(service), mListeners(NULL), mShuttingDown(PR_FALSE)
{
}
nsServiceEntry::~nsServiceEntry()
{
if (mListeners) {
NS_ASSERTION(mListeners->GetSize() == 0, "listeners not removed or notified");
#if 0
PRUint32 size = mListeners->GetSize();
for (PRUint32 i = 0; i < size; i++) {
nsIShutdownListener* listener = (nsIShutdownListener*)(*mListeners)[i];
listener->Release();
}
#endif
delete mListeners;
}
}
nsresult
nsServiceEntry::AddListener(nsIShutdownListener* listener)
{
if (listener == NULL)
return NS_OK;
if (mListeners == NULL) {
mListeners = new nsVector();
if (mListeners == NULL)
return NS_ERROR_OUT_OF_MEMORY;
}
PRInt32 err = mListeners->Add(listener);
listener->AddRef();
return err == -1 ? NS_ERROR_FAILURE : NS_OK;
}
nsresult
nsServiceEntry::RemoveListener(nsIShutdownListener* listener)
{
if (listener == NULL)
return NS_OK;
NS_ASSERTION(mListeners, "no listeners added yet");
PRUint32 size = mListeners->GetSize();
for (PRUint32 i = 0; i < size; i++) {
if ((*mListeners)[i] == listener) {
mListeners->Remove(i);
listener->Release();
return NS_OK;
}
}
NS_ASSERTION(0, "unregistered shutdown listener");
return NS_ERROR_FAILURE;
}
nsresult
nsServiceEntry::NotifyListeners(void)
{
if (mListeners) {
PRUint32 size = mListeners->GetSize();
for (PRUint32 i = 0; i < size; i++) {
nsIShutdownListener* listener = (nsIShutdownListener*)(*mListeners)[0];
nsresult err = listener->OnShutdown(mClassID, mService);
if (err) return err;
listener->Release();
mListeners->Remove(0);
}
NS_ASSERTION(mListeners->GetSize() == 0, "failed to notify all listeners");
delete mListeners;
mListeners = NULL;
}
return NS_OK;
}
////////////////////////////////////////////////////////////////////////////////
class nsServiceManagerImpl : public nsIServiceManager {
public:
NS_IMETHOD
GetService(const nsCID& aClass, const nsIID& aIID,
nsISupports* *result,
nsIShutdownListener* shutdownListener = NULL);
NS_IMETHOD
ReleaseService(const nsCID& aClass, nsISupports* service,
nsIShutdownListener* shutdownListener = NULL);
NS_IMETHOD
ShutdownService(const nsCID& aClass);
nsServiceManagerImpl(void);
NS_DECL_ISUPPORTS
protected:
virtual ~nsServiceManagerImpl(void);
nsHashtable* mServices; // nsHashtable<nsServiceEntry>
};
nsServiceManagerImpl::nsServiceManagerImpl(void)
{
NS_INIT_REFCNT();
mServices = new nsHashtable();
NS_ASSERTION(mServices, "out of memory already?");
}
static PRBool
DeleteEntry(nsHashKey *aKey, void *aData, void* closure)
{
nsServiceEntry* entry = (nsServiceEntry*)aData;
entry->mService->Release();
delete entry;
return PR_TRUE;
}
nsServiceManagerImpl::~nsServiceManagerImpl(void)
{
mServices->Enumerate(DeleteEntry);
delete mServices;
}
static NS_DEFINE_IID(kIServiceManagerIID, NS_ISERVICEMANAGER_IID);
static NS_DEFINE_IID(kISupportsIID, NS_ISUPPORTS_IID);
NS_IMPL_ADDREF(nsServiceManagerImpl);
NS_IMPL_RELEASE(nsServiceManagerImpl);
nsresult
nsServiceManagerImpl::QueryInterface(const nsIID& aIID, void* *aInstancePtr)
{
if (NULL == aInstancePtr) {
return NS_ERROR_NULL_POINTER;
}
*aInstancePtr = NULL;
if (aIID.Equals(kIServiceManagerIID) ||
aIID.Equals(kISupportsIID)) {
*aInstancePtr = (void*) this;
AddRef();
return NS_OK;
}
return NS_NOINTERFACE;
}
nsresult
nsServiceManagerImpl::GetService(const nsCID& aClass, const nsIID& aIID,
nsISupports* *result,
nsIShutdownListener* shutdownListener)
{
nsresult err = NS_OK;
/* XXX: This is a hack to force NSPR initialization.. This should be
* removed once PR_CEnterMonitor(...) initializes NSPR... (rick)
*/
(void)PR_GetCurrentThread();
PR_CEnterMonitor(this);
nsIDKey key(aClass);
nsServiceEntry* entry = (nsServiceEntry*)mServices->Get(&key);
if (entry) {
nsISupports* service;
err = entry->mService->QueryInterface(aIID, (void**)&service);
if (err == NS_OK) {
err = entry->AddListener(shutdownListener);
if (err == NS_OK) {
*result = service;
// If someone else requested the service to be shut down,
// and we just asked to get it again before it could be
// released, then cancel their shutdown request:
if (entry->mShuttingDown) {
entry->mShuttingDown = PR_FALSE;
service->AddRef(); // Released in ShutdownService
}
}
}
}
else {
nsISupports* service;
err = nsRepository::CreateInstance(aClass, NULL, aIID, (void**)&service);
if (err == NS_OK) {
entry = new nsServiceEntry(aClass, service);
if (entry == NULL) {
service->Release();
err = NS_ERROR_OUT_OF_MEMORY;
}
else {
err = entry->AddListener(shutdownListener);
if (err == NS_OK) {
mServices->Put(&key, entry);
*result = service;
service->AddRef(); // Released in ShutdownService
}
else {
service->Release();
delete entry;
}
}
}
}
PR_CExitMonitor(this);
return err;
}
nsresult
nsServiceManagerImpl::ReleaseService(const nsCID& aClass, nsISupports* service,
nsIShutdownListener* shutdownListener)
{
nsresult err = NS_OK;
PR_CEnterMonitor(this);
nsIDKey key(aClass);
nsServiceEntry* entry = (nsServiceEntry*)mServices->Get(&key);
NS_ASSERTION(entry, "service not found");
NS_ASSERTION(entry->mService == service, "service looked failed");
if (entry) {
err = entry->RemoveListener(shutdownListener);
nsrefcnt cnt = service->Release();
if (err == NS_OK && cnt == 0) {
mServices->Remove(&key);
delete entry;
err = nsRepository::FreeLibraries();
}
}
PR_CExitMonitor(this);
return err;
}
nsresult
nsServiceManagerImpl::ShutdownService(const nsCID& aClass)
{
nsresult err = NS_OK;
PR_CEnterMonitor(this);
nsIDKey key(aClass);
nsServiceEntry* entry = (nsServiceEntry*)mServices->Get(&key);
if (entry == NULL) {
err = NS_ERROR_SERVICE_NOT_FOUND;
}
else {
err = entry->NotifyListeners(); // break the cycles
entry->mShuttingDown = PR_TRUE;
nsrefcnt cnt = entry->mService->Release(); // AddRef in GetService
if (err == NS_OK && cnt == 0) {
mServices->Remove(&key);
delete entry;
err = nsRepository::FreeLibraries();
}
else
err = NS_ERROR_SERVICE_IN_USE;
}
PR_CExitMonitor(this);
return err;
}
////////////////////////////////////////////////////////////////////////////////
// Global service manager interface (see nsIServiceManager.h)
nsIServiceManager* nsServiceManager::globalServiceManager = NULL;
nsresult
nsServiceManager::GetGlobalServiceManager(nsIServiceManager* *result)
{
if (globalServiceManager == NULL) {
globalServiceManager = new nsServiceManagerImpl();
if (globalServiceManager == NULL)
return NS_ERROR_OUT_OF_MEMORY;
globalServiceManager->AddRef();
}
*result = globalServiceManager;
return NS_OK;
}
nsresult
nsServiceManager::GetService(const nsCID& aClass, const nsIID& aIID,
nsISupports* *result,
nsIShutdownListener* shutdownListener)
{
nsIServiceManager* mgr;
nsresult rslt = GetGlobalServiceManager(&mgr);
if (rslt != NS_OK) return rslt;
return mgr->GetService(aClass, aIID, result, shutdownListener);
}
nsresult
nsServiceManager::ReleaseService(const nsCID& aClass, nsISupports* service,
nsIShutdownListener* shutdownListener)
{
nsIServiceManager* mgr;
nsresult rslt = GetGlobalServiceManager(&mgr);
if (rslt != NS_OK) return rslt;
return mgr->ReleaseService(aClass, service, shutdownListener);
}
nsresult
nsServiceManager::ShutdownService(const nsCID& aClass)
{
nsIServiceManager* mgr;
nsresult rslt = GetGlobalServiceManager(&mgr);
if (rslt != NS_OK) return rslt;
return mgr->ShutdownService(aClass);
}
////////////////////////////////////////////////////////////////////////////////

View File

@@ -0,0 +1,153 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (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 client code.
*
* The Initial Developer of the Original Code is Netscape Communications
* Corporation. Portions created by Netscape are Copyright (C) 1998
* Netscape Communications Corporation. All Rights Reserved.
*/
#ifndef nsXPComFactory_h__
#define nsXPComFactory_h__
#include "nsIFactory.h"
/*
* This file contains a templatized implementation of a simple XPCOM factory.
*
* To implement a factory for a given component, just provide a function
* like the one below which can be called by your DLL's NSGetFactory(...)
* entry point...
*
* nsresult NS_New_SomeComponent_Factory(nsIFactory** aResult)
* {
* nsresult rv = NS_OK;
* nsIFactory* inst = new nsFactory<SomeComponent>();
* if (NULL == inst) {
* rv = NS_ERROR_OUT_OF_MEMORY;
* } else {
* NS_ADDREF(inst);
* }
* *aResult = inst;
* return rv;
* }
*
* NOTE:
* ----
* The factories created by this template are not thread-safe and do not
* support aggregation.
*
*/
template <class T> class nsFactory : public nsIFactory
{
public:
nsFactory() { NS_INIT_REFCNT(); }
//
// nsISupports interface...
//
// These implementations were copied from the NS_IMPL_ISUPPORTS macro
// in nsISupports.h
//
NS_IMETHOD_(nsrefcnt) AddRef (void)
{
return ++mRefCnt;
}
NS_IMETHOD_(nsrefcnt) Release(void)
{
NS_PRECONDITION(0 != mRefCnt, "dup release");
if (--mRefCnt == 0) {
NS_DELETEXPCOM(this);
return 0;
}
return mRefCnt;
}
NS_IMETHOD QueryInterface(REFNSIID aIID, void** aInstancePtr)
{
if (NULL == aInstancePtr) {
return NS_ERROR_NULL_POINTER;
}
*aInstancePtr = NULL;
static NS_DEFINE_IID(kIFactoryIID, NS_IFACTORY_IID);
static NS_DEFINE_IID(kISupportsIID, NS_ISUPPORTS_IID);
if (aIID.Equals(kIFactoryIID)) {
*aInstancePtr = (void*) this;
NS_ADDREF_THIS();
return NS_OK;
}
if (aIID.Equals(kISupportsIID)) {
*aInstancePtr = (void*) ((nsISupports*)this);
NS_ADDREF_THIS();
return NS_OK;
}
return NS_NOINTERFACE;
}
//
// nsIFactory interface...
//
NS_IMETHOD CreateInstance(nsISupports *aOuter,
const nsIID &aIID,
void **aResult)
{
nsresult rv;
T* inst;
// Parameter validation...
if (NULL == aResult) {
rv = NS_ERROR_NULL_POINTER;
goto done;
}
// Do not support aggregatable components...
*aResult = NULL;
if (NULL != aOuter) {
rv = NS_ERROR_NO_AGGREGATION;
goto done;
}
// Create a new instance of the component...
NS_NEWXPCOM(inst, T);
if (NULL == inst) {
rv = NS_ERROR_OUT_OF_MEMORY;
goto done;
}
// If the QI fails, the component will be destroyed...
NS_ADDREF(inst);
rv = inst->QueryInterface(aIID, aResult);
NS_RELEASE(inst);
done:
return rv;
}
NS_IMETHOD LockFactory(PRBool aLock)
{
// Not implemented in simplest case.
return NS_OK;
}
protected:
virtual ~nsFactory()
{
NS_ASSERTION(mRefCnt == 0, "non-zero refcnt at destruction");
}
// Reference count variable used by nsISupports...
nsrefcnt mRefCnt;
};
#endif /* nsXPComFactory_h__ */

View File

@@ -0,0 +1,184 @@
/* -*- 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.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
* Reserved.
*/
/* nsDll
*
* Abstraction of a Dll. Stores modifiedTime and size for easy detection of
* change in dll.
*
* dp Suresh <dp@netscape.com>
*/
#include "xcDll.h"
#include "plstr.h" // strdup and strfree
nsDll::nsDll(const char *libFullPath) : m_fullpath(NULL), m_instance(NULL),
m_status(DLL_OK)
{
m_lastModTime = LL_ZERO;
m_size = 0;
if (libFullPath == NULL)
{
m_status = DLL_INVALID_PARAM;
return;
}
m_fullpath = PL_strdup(libFullPath);
if (m_fullpath == NULL)
{
// No more memory
m_status = DLL_NO_MEM;
return;
}
PRFileInfo statinfo;
if (PR_GetFileInfo(m_fullpath, &statinfo) != PR_SUCCESS)
{
// The stat things works only if people pass in the full pathname.
// Even if our stat fails, we could be able to load it because of
// LD_LIBRARY_PATH and other such paths where dlls are searched for
// XXX we need a way of marking this occurance.
// XXX m_status = DLL_STAT_ERROR;
}
else
{
m_size = statinfo.size;
m_lastModTime = statinfo.modifyTime;
if (statinfo.type != PR_FILE_FILE)
{
// Not a file. Cant work with it.
m_status = DLL_NOT_FILE;
return;
}
}
m_status = DLL_OK;
}
nsDll::nsDll(const char *libFullPath, PRTime lastModTime, PRUint32 fileSize)
: m_fullpath(NULL), m_instance(NULL), m_status(DLL_OK)
{
m_lastModTime = lastModTime;
m_size = fileSize;
if (libFullPath == NULL)
{
m_status = DLL_INVALID_PARAM;
return;
}
m_fullpath = PL_strdup(libFullPath);
if (m_fullpath == NULL)
{
// No more memory
m_status = DLL_NO_MEM;
return;
}
m_status = DLL_OK;
}
nsDll::~nsDll(void)
{
if (m_instance != NULL)
Unload();
if (m_fullpath != NULL) PL_strfree(m_fullpath);
m_fullpath = NULL;
}
PRBool nsDll::Load(void)
{
// Of course, this is all buggy, because it uses paths instead of nsFileSpec.
// Also, instead of writing yet another converter for path separators, for
// pete's sake use the converters in nsFileSpec.h. Thank you.
#ifdef XP_MAC
char *macFileName = NULL;
int loop;
#endif
if (m_status != DLL_OK)
{
return (PR_FALSE);
}
if (m_instance != NULL)
{
// Already loaded
return (PR_TRUE);
}
#ifdef XP_MAC
// err = ConvertUnixPathToMacPath(m_fullpath, &macFileName);
if ((macFileName = PL_strdup(m_fullpath)) != NULL)
{
if (macFileName[0] == '/')
{
for (loop=0; loop<PL_strlen(macFileName); loop++)
{
if (macFileName[loop] == '/') macFileName[loop] = ':';
}
m_instance = PR_LoadLibrary(&macFileName[1]); // skip over initial slash
}
else
{
m_instance = PR_LoadLibrary(macFileName);
}
}
#else
#ifdef XP_UNIX
// On linux we seem to load multiple copies of the same dll but with different path
// like libraptorhtml.so and ./libraptorhtml.so
// Until this get fixed right, for now for ./libraptorhtml.so remove the "./"
if (m_fullpath[0] == '.' && m_fullpath[1] == '/')
m_instance = PR_LoadLibrary( &(m_fullpath[2]) );
else
#endif /* XP_UNIX */
{
// This is the only right way of doing this...
m_instance = PR_LoadLibrary(m_fullpath);
}
#endif /* XP_MAC */
return ((m_instance == NULL) ? PR_FALSE : PR_TRUE);
}
PRBool nsDll::Unload(void)
{
if (m_status != DLL_OK || m_instance == NULL)
return (PR_FALSE);
PRStatus ret = PR_UnloadLibrary(m_instance);
if (ret == PR_SUCCESS)
{
m_instance = NULL;
return (PR_TRUE);
}
else
return (PR_FALSE);
}
void * nsDll::FindSymbol(const char *symbol)
{
if (symbol == NULL)
return (NULL);
// If not already loaded, load it now.
if (Load() != PR_TRUE)
return (NULL);
return (PR_FindSymbol(m_instance, symbol));
}

View File

@@ -0,0 +1,71 @@
/* -*- 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.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
* Reserved.
*/
/* Dll
*
* Programmatic representation of a dll. Stores modifiedTime and size for
* easy detection of change in dll.
*
* dp Suresh <dp@netscape.com>
*/
#include "prio.h"
#include "prlink.h"
typedef enum nsDllStatus
{
DLL_OK = 0,
DLL_NO_MEM = 1,
DLL_STAT_ERROR = 2,
DLL_NOT_FILE = 3,
DLL_INVALID_PARAM = 4
} nsDllStatus;
class nsDll
{
private:
char *m_fullpath; // system format full filename of dll
PRTime m_lastModTime; // last modified time
PRUint32 m_size; // size of the dynamic library
PRLibrary *m_instance; // Load instance
nsDllStatus m_status; // holds current status
public:
nsDll(const char *libFullPath);
nsDll(const char *libFullPath, PRTime lastModTime, PRUint32 fileSize);
~nsDll(void);
// Status checking on operations completed
nsDllStatus GetStatus(void) { return (m_status); }
// Dll Loading
PRBool Load(void);
PRBool Unload(void);
PRBool IsLoaded(void)
{
return ((m_instance != 0) ? PR_TRUE : PR_FALSE);
}
void *FindSymbol(const char *symbol);
const char *GetFullPath(void) { return (m_fullpath); }
PRTime GetLastModifiedTime(void) { return(m_lastModTime); }
PRUint32 GetSize(void) { return(m_size); }
PRLibrary *GetInstance(void) { return (m_instance); }
};

View File

@@ -0,0 +1,87 @@
/* -*- 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.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
* Reserved.
*/
/* nsDllStore
*
* Stores dll and their accociated info in a hash keyed on the system format
* full dll path name e.g C:\Program Files\Netscape\Program\raptor.dll
*
* NOTE: dll names are considered to be case sensitive.
*/
#include "xcDllStore.h"
static PR_CALLBACK PRIntn _deleteDllInfo(PLHashEntry *he, PRIntn i, void *arg)
{
delete (nsDll *)he->value;
return (HT_ENUMERATE_NEXT);
}
nsDllStore::nsDllStore(void) : m_dllHashTable(NULL)
{
PRUint32 initSize = 128;
m_dllHashTable = PL_NewHashTable(initSize, PL_HashString,
PL_CompareStrings, PL_CompareValues, NULL, NULL);
}
nsDllStore::~nsDllStore(void)
{
if (m_dllHashTable)
{
// Delete each of the nsDll stored before deleting the Hash Table
PL_HashTableEnumerateEntries(m_dllHashTable, _deleteDllInfo, NULL);
PL_HashTableDestroy(m_dllHashTable);
}
m_dllHashTable = NULL;
}
nsDll* nsDllStore::Get(const char *dll)
{
nsDll *dllInfo = NULL;
if (m_dllHashTable)
{
dllInfo = (nsDll *)PL_HashTableLookup(m_dllHashTable, dll);
}
return (dllInfo);
}
nsDll* nsDllStore::Remove(const char *dll)
{
if (m_dllHashTable == NULL)
{
return (NULL);
}
nsDll *dllInfo = Get(dll);
PL_HashTableRemove(m_dllHashTable, dll);
return (dllInfo);
}
PRBool nsDllStore::Put(const char *dll, nsDll *dllInfo)
{
if (m_dllHashTable == NULL)
return(PR_FALSE);
PLHashEntry *entry =
PL_HashTableAdd(m_dllHashTable, (void *)dll, (void *)dllInfo);
return ((entry != NULL) ? PR_TRUE : PR_FALSE);
}

View File

@@ -0,0 +1,49 @@
/* -*- 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.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
* Reserved.
*/
/* nsDllStore
*
* Stores dll and their accociated info in a hash keyed on the system format
* full dll path name e.g C:\Program Files\Netscape\Program\raptor.dll
*
* NOTE: dll names are considered to be case sensitive.
*/
#include "plhash.h"
#include "xcDll.h"
class nsDllStore
{
private:
PLHashTable *m_dllHashTable;
public:
// Constructor
nsDllStore(void);
~nsDllStore(void);
// Caller is not expected to delete nsDll returned
// The nsDll returned in NOT removed from the hash
nsDll* Get(const char *filename);
PRBool Put(const char *filename, nsDll *dllInfo);
// The nsDll returned is removed from the hash
// Caller is expected to delete the returned nsDll
nsDll* Remove(const char *filename);
};

Some files were not shown because too many files have changed in this diff Show More