Bug 511761 - Only use compatibility.ini (not .autoreg, or stat()s) to invalidate fastloads and other caches (r=bsmedberg)

This commit is contained in:
bhsieh@mozilla.com 2009-10-14 09:40:45 -07:00
Родитель a6bcf9f738
Коммит 2a87a15f5a
8 изменённых файлов: 102 добавлений и 125 удалений

Просмотреть файл

@ -298,9 +298,6 @@ libs::
endif
endif
libs::
touch $(DIST)/bin/.autoreg
libs:: $(srcdir)/profile/prefs.js
$(INSTALL) $(IFLAGS1) $^ $(DIST)/bin/defaults/profile

Просмотреть файл

@ -88,7 +88,6 @@ const FILE_EXTENSIONS = "extensions.rdf";
const FILE_EXTENSION_MANIFEST = "extensions.ini";
const FILE_EXTENSIONS_STARTUP_CACHE = "extensions.cache";
const FILE_EXTENSIONS_LOG = "extensions.log";
const FILE_AUTOREG = ".autoreg";
const FILE_INSTALL_MANIFEST = "install.rdf";
const FILE_CHROME_MANIFEST = "chrome.manifest";
@ -3599,16 +3598,13 @@ ExtensionManager.prototype = {
*/
set _extensionListChanged(val) {
// When an extension has an operation perform on it (e.g. install, upgrade,
// disable, etc.) we are responsible for creating the .autoreg file and
// nsAppRunner is responsible for removing it on restart. At some point it
// may make sense to be able to cancel a registration but for now we only
// create the file.
try {
var autoregFile = getFile(KEY_PROFILEDIR, [FILE_AUTOREG]);
if (val && !autoregFile.exists())
autoregFile.create(Ci.nsILocalFile.NORMAL_FILE_TYPE, PERMS_FILE);
}
catch (e) {
// disable, etc.) we are responsible for writing this information to
// compatibility.ini, and nsAppRunner is responsible for checking this on
// restart. At some point it may make sense to be able to cancel a
// registration but for now we only create the file.
if (val) {
let XRE = Cc["@mozilla.org/xre/app-info;1"].getService(Ci.nsIXULRuntime);
XRE.invalidateCachesOnRestart();
}
return val;
},

Просмотреть файл

@ -238,6 +238,8 @@ protected:
extern void InstallUnixSignalHandlers(const char *ProgramName);
#endif
#define FILE_COMPATIBILITY_INFO NS_LITERAL_CSTRING("compatibility.ini")
int gArgc;
char **gArgv;
@ -712,6 +714,48 @@ nsXULAppInfo::GetWidgetToolkit(nsACString& aResult)
return NS_OK;
}
NS_IMETHODIMP
nsXULAppInfo::InvalidateCachesOnRestart()
{
nsCOMPtr<nsIFile> file;
nsresult rv = NS_GetSpecialDirectory(NS_APP_PROFILE_DIR_STARTUP,
getter_AddRefs(file));
if (NS_FAILED(rv))
return rv;
if (!file)
return NS_ERROR_NOT_AVAILABLE;
file->AppendNative(FILE_COMPATIBILITY_INFO);
nsCOMPtr<nsILocalFile> localFile(do_QueryInterface(file));
nsINIParser parser;
rv = parser.Init(localFile);
if (NS_FAILED(rv)) {
// This fails if compatibility.ini is not there, so we'll
// flush the caches on the next restart anyways.
return NS_OK;
}
nsCAutoString buf;
rv = parser.GetString("Compatibility", "InvalidateCaches", buf);
if (NS_FAILED(rv)) {
PRFileDesc *fd = nsnull;
localFile->OpenNSPRFileDesc(PR_RDWR | PR_APPEND, 0600, &fd);
if (!fd) {
NS_ERROR("could not create output stream");
return NS_ERROR_NOT_AVAILABLE;
}
static const char kInvalidationHeader[] = NS_LINEBREAK "InvalidateCaches=1" NS_LINEBREAK;
rv = PR_Write(fd, kInvalidationHeader, sizeof(kInvalidationHeader) - 1);
PR_Close(fd);
if (NS_FAILED(rv))
return rv;
}
return NS_OK;
}
#ifdef XP_WIN
// Matches the enum in WinNT.h for the Vista SDK but renamed so that we can
// safely build with the Vista SDK and without it.
@ -2147,13 +2191,19 @@ SelectProfile(nsIProfileLock* *aResult, nsINativeAppSupport* aNative,
return ShowProfileManager(profileSvc, aNative);
}
#define FILE_COMPATIBILITY_INFO NS_LITERAL_CSTRING("compatibility.ini")
/**
* Checks the compatibility.ini file to see if we have updated our application
* or otherwise invalidated our caches. If the application has been updated,
* we return PR_FALSE; otherwise, we return PR_TRUE. We also write the status
* of the caches (valid/invalid) into the return param aCachesOK. The aCachesOK
* is always invalid if the application has been updated.
*/
static PRBool
CheckCompatibility(nsIFile* aProfileDir, const nsCString& aVersion,
const nsCString& aOSABI, nsIFile* aXULRunnerDir,
nsIFile* aAppDir)
nsIFile* aAppDir, PRBool* aCachesOK)
{
*aCachesOK = false;
nsCOMPtr<nsIFile> file;
aProfileDir->Clone(getter_AddRefs(file));
if (!file)
@ -2205,6 +2255,10 @@ CheckCompatibility(nsIFile* aProfileDir, const nsCString& aVersion,
return PR_FALSE;
}
rv = parser.GetString("Compatibility", "InvalidateCaches", buf);
// If we see this flag, caches are invalid.
*aCachesOK = (NS_FAILED(rv) || !buf.EqualsLiteral("1"));
return PR_TRUE;
}
@ -2271,19 +2325,6 @@ WriteVersion(nsIFile* aProfileDir, const nsCString& aVersion,
PR_Close(fd);
}
static PRBool ComponentsListChanged(nsIFile* aProfileDir)
{
nsCOMPtr<nsIFile> file;
aProfileDir->Clone(getter_AddRefs(file));
if (!file)
return PR_TRUE;
file->AppendNative(NS_LITERAL_CSTRING(".autoreg"));
PRBool exists = PR_FALSE;
file->Exists(&exists);
return exists;
}
static void RemoveComponentRegistries(nsIFile* aProfileDir, nsIFile* aLocalProfileDir,
PRBool aRemoveEMFiles)
{
@ -2312,6 +2353,9 @@ static void RemoveComponentRegistries(nsIFile* aProfileDir, nsIFile* aLocalProfi
file->AppendNative(NS_LITERAL_CSTRING("XUL" PLATFORM_FASL_SUFFIX));
file->Remove(PR_FALSE);
file->SetNativeLeafName(NS_LITERAL_CSTRING("XPC" PLATFORM_FASL_SUFFIX));
file->Remove(PR_FALSE);
}
// To support application initiated restart via nsIAppStartup.quit, we
@ -3172,9 +3216,12 @@ XRE_main(int argc, char* argv[], const nsXREAppData* aAppData)
// Check for version compatibility with the last version of the app this
// profile was started with. The format of the version stamp is defined
// by the BuildVersion function.
PRBool versionOK = CheckCompatibility(profD, version, osABI,
// Also check to see if something has happened to invalidate our
// fastload caches, like an extension upgrade or installation.
PRBool cachesOK;
PRBool versionOK = CheckCompatibility(profD, version, osABI,
dirProvider.GetGREDir(),
gAppData->directory);
gAppData->directory, &cachesOK);
// Every time a profile is loaded by a build with a different version,
// it updates the compatibility.ini file saying what version last wrote
@ -3189,11 +3236,15 @@ XRE_main(int argc, char* argv[], const nsXREAppData* aAppData)
dirProvider.GetGREDir(), gAppData->directory);
}
else if (versionOK) {
if (ComponentsListChanged(profD)) {
if (!cachesOK) {
// Remove compreg.dat and xpti.dat, forcing component re-registration.
// The new list of additional components directories is derived from
// information in "extensions.ini".
RemoveComponentRegistries(profD, profLD, PR_FALSE);
// Rewrite compatibility.ini to remove the flag
WriteVersion(profD, version, osABI,
dirProvider.GetGREDir(), gAppData->directory);
}
// Nothing need be done for the normal startup case.
}

Просмотреть файл

@ -285,85 +285,6 @@ RegisterGenericFactory(nsIComponentRegistrar* registrar,
return rv;
}
// In order to support the installer, we need
// to be told out of band if we should cause
// an autoregister. If the file ".autoreg" exists in the binary
// directory, we check its timestamp against the timestamp of the
// compreg.dat file. If the .autoreg file is newer, we autoregister.
static PRBool CheckUpdateFile()
{
nsresult rv;
nsCOMPtr<nsIFile> compregFile;
rv = nsDirectoryService::gService->Get(NS_XPCOM_COMPONENT_REGISTRY_FILE,
NS_GET_IID(nsIFile),
getter_AddRefs(compregFile));
if (NS_FAILED(rv)) {
NS_WARNING("Getting NS_XPCOM_COMPONENT_REGISTRY_FILE failed");
return PR_FALSE;
}
PRInt64 compregModTime;
rv = compregFile->GetLastModifiedTime(&compregModTime);
if (NS_FAILED(rv))
return PR_TRUE;
nsCOMPtr<nsIFile> file;
rv = nsDirectoryService::gService->Get(NS_XPCOM_CURRENT_PROCESS_DIR,
NS_GET_IID(nsIFile),
getter_AddRefs(file));
if (NS_FAILED(rv)) {
NS_WARNING("Getting NS_XPCOM_CURRENT_PROCESS_DIR failed");
return PR_FALSE;
}
file->AppendNative(nsDependentCString(".autoreg"));
// superfluous cast
PRInt64 nowTime = PR_Now() / PR_USEC_PER_MSEC;
PRInt64 autoregModTime;
rv = file->GetLastModifiedTime(&autoregModTime);
if (NS_FAILED(rv))
goto next;
if (autoregModTime > compregModTime) {
if (autoregModTime < nowTime) {
return PR_TRUE;
} else {
NS_WARNING("Screwy timestamps, ignoring .autoreg");
}
}
next:
nsCOMPtr<nsIFile> greFile;
rv = nsDirectoryService::gService->Get(NS_GRE_DIR,
NS_GET_IID(nsIFile),
getter_AddRefs(greFile));
if (NS_FAILED(rv)) {
NS_WARNING("Getting NS_GRE_DIR failed");
return PR_FALSE;
}
greFile->AppendNative(nsDependentCString(".autoreg"));
PRBool equals;
rv = greFile->Equals(file, &equals);
if (NS_SUCCEEDED(rv) && equals)
return PR_FALSE;
rv = greFile->GetLastModifiedTime(&autoregModTime);
if (NS_FAILED(rv))
return PR_FALSE;
if (autoregModTime > nowTime) {
NS_WARNING("Screwy timestamps, ignoring .autoreg");
return PR_FALSE;
}
return autoregModTime > compregModTime;
}
nsComponentManagerImpl* nsComponentManagerImpl::gComponentManager = NULL;
PRBool gXPCOMShuttingDown = PR_FALSE;
@ -684,8 +605,9 @@ NS_InitXPCOM3(nsIServiceManager* *result,
nsIInterfaceInfoManager* iim =
xptiInterfaceInfoManager::GetInterfaceInfoManagerNoAddRef();
if (CheckUpdateFile() || NS_FAILED(
nsComponentManagerImpl::gComponentManager->ReadPersistentRegistry())) {
// "Re-register the world" if compreg.dat doesn't exist
rv = nsComponentManagerImpl::gComponentManager->ReadPersistentRegistry();
if (NS_FAILED(rv)) {
// If the component registry is out of date, malformed, or incomplete,
// autoregister the default component directories.
(void) iim->AutoRegisterInterfaces();

Просмотреть файл

@ -3006,11 +3006,19 @@ nsComponentManagerImpl::AutoRegisterComponent(nsILocalFile* aComponentFile,
}
PRInt64 modTime = 0;
if (NS_SUCCEEDED(aComponentFile->GetLastModifiedTime(&modTime))) {
PRInt64 cachedModTime;
if (mAutoRegEntries.Get(lfhash, &cachedModTime) &&
cachedModTime == modTime)
PRInt64 cachedModTime;
// If it's in the cache, it should be valid.
// The cache file is removed if files are modified.
if (mAutoRegEntries.Get(lfhash, &cachedModTime)) {
#ifdef DEBUG
if (NS_SUCCEEDED(aComponentFile->GetLastModifiedTime(&modTime))
&& cachedModTime == modTime) {
return NS_OK;
}
#else
return NS_OK;
#endif
}
const char *registryType = nsnull;

Просмотреть файл

@ -728,21 +728,20 @@ nsFastLoadFileReader::ReadFooter(nsFastLoadFooter *aFooter)
rv = NS_NewNativeLocalFile(filename, PR_TRUE, getter_AddRefs(file));
if (NS_FAILED(rv))
return rv;
#ifdef DEBUG
PRInt64 currentMtime;
rv = file->GetLastModifiedTime(&currentMtime);
if (NS_FAILED(rv))
return rv;
if (LL_NE(fastLoadMtime, currentMtime)) {
#ifdef DEBUG
nsCAutoString path;
file->GetNativePath(path);
printf("%s mtime changed, invalidating FastLoad file\n",
path.get());
#endif
return NS_ERROR_FAILURE;
}
#endif
rv = readDeps->AppendElement(file);
if (NS_FAILED(rv))

Просмотреть файл

@ -44,7 +44,7 @@
* stable/frozen, please contact Benjamin Smedberg.
*/
[scriptable, uuid(17311145-97da-49eb-b984-965bdee8879c)]
[scriptable, uuid(C61D0C09-05AD-4E72-BAC5-203F3F380352)]
interface nsIXULRuntime : nsISupports
{
/**
@ -86,4 +86,11 @@ interface nsIXULRuntime : nsISupports
* This is taken from the MOZ_WIDGET_TOOLKIT configure variable.
*/
readonly attribute AUTF8String widgetToolkit;
/**
* Signal the apprunner to invalidate caches on the next restart.
* This will cause components to be autoregistered and all
* fastload data to be re-created.
*/
void invalidateCachesOnRestart();
};

Просмотреть файл

@ -261,9 +261,6 @@ ifeq ($(OS_ARCH),OS2)
cp $(srcdir)/xulrunner-os2.ico $(DIST)/branding/xulrunner.ico
endif
libs::
touch $(DIST)/bin/.autoreg
ifeq (cocoa,$(MOZ_WIDGET_TOOLKIT))
FRAMEWORK_NAME = XUL