mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-28 23:31:56 +00:00
Bug 334675 r=darin a=mconnor Notify users on async IO errors
This commit is contained in:
parent
ccce510651
commit
0653b5c604
37
dom/locales/en-US/chrome/storage.properties
Normal file
37
dom/locales/en-US/chrome/storage.properties
Normal file
@ -0,0 +1,37 @@
|
||||
# ***** BEGIN LICENSE BLOCK *****
|
||||
# Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
#
|
||||
# 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 Storage code.
|
||||
#
|
||||
# The Initial Developer of the Original Code is Google Inc.
|
||||
# Portions created by the Initial Developer are Copyright (C) 2006
|
||||
# the Initial Developer. All Rights Reserved.
|
||||
#
|
||||
# Contributor(s):
|
||||
# Brett Wilson <brettw@gmail.com>
|
||||
#
|
||||
# Alternatively, the contents of this file may be used under the terms of
|
||||
# either of the GNU General Public License Version 2 or later (the "GPL"),
|
||||
# or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
# in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
# of those above. If you wish to allow use of your version of this file only
|
||||
# under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
# use your version of this file under the terms of the MPL, indicate your
|
||||
# decision by deleting the provisions above and replace them with the notice
|
||||
# and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
# the provisions above, a recipient may use your version of this file under
|
||||
# the terms of any one of the MPL, the GPL or the LGPL.
|
||||
#
|
||||
# ***** END LICENSE BLOCK *****
|
||||
|
||||
storageWriteError=There was an error writing data to the disk. This error is sometimes caused by a full disk.\n\nPlease restart this application
|
@ -25,3 +25,4 @@
|
||||
locale/@AB_CD@/global-platform/win/accessible.properties (%chrome/accessibility/win/accessible.properties)
|
||||
locale/@AB_CD@/global-platform/mac/accessible.properties (%chrome/accessibility/mac/accessible.properties)
|
||||
locale/@AB_CD@/global-platform/unix/accessible.properties (%chrome/accessibility/unix/accessible.properties)
|
||||
locale/@AB_CD@/global/storage.properties (%chrome/storage.properties)
|
||||
|
@ -51,6 +51,8 @@ GRE_MODULE = 1
|
||||
LIBXUL_LIBRARY = 1
|
||||
|
||||
REQUIRES = xpcom \
|
||||
intl \
|
||||
necko \
|
||||
string \
|
||||
sqlite3 \
|
||||
js \
|
||||
|
@ -232,11 +232,16 @@
|
||||
|
||||
#include "mozStorageService.h"
|
||||
#include "nsAutoLock.h"
|
||||
#include "nsThreadUtils.h"
|
||||
#include "nsIConsoleService.h"
|
||||
#include "nsIPrompt.h"
|
||||
#include "nsIRunnable.h"
|
||||
#include "nsIStringBundle.h"
|
||||
#include "nsIThread.h"
|
||||
#include "nsMemory.h"
|
||||
#include "nsNetCID.h"
|
||||
#include "nsProxyRelease.h"
|
||||
#include "nsThreadUtils.h"
|
||||
#include "nsXPCOMCIDInternal.h"
|
||||
#include "plstr.h"
|
||||
#include "prlock.h"
|
||||
#include "prcvar.h"
|
||||
@ -264,9 +269,19 @@
|
||||
// AsyncOsFile
|
||||
//
|
||||
// This is a wrapper around the sqlite interal OsFile.
|
||||
//
|
||||
// ======
|
||||
// DANGER
|
||||
// ======
|
||||
//
|
||||
// This function is allocated on my Alloc(), and NOT by new. This means that
|
||||
// any C++ objects in here will not get their constructor called.
|
||||
|
||||
struct AsyncOsFile : public OsFile
|
||||
{
|
||||
// This is the filename of the file when it was opened.
|
||||
nsCString* mFilename;
|
||||
|
||||
// This keeps track of the current file offset. Seek operations change this
|
||||
// offset instead of actually changing the file because we will do stuff to
|
||||
// the file in the background. We store this offset for each operation such
|
||||
@ -402,6 +417,7 @@ static int AppendNewAsyncMessage(AsyncOsFile* aFile, PRUint32 aOp,
|
||||
sqlite_int64 aOffset, PRInt32 aDataSize,
|
||||
const char *aData);
|
||||
static int AsyncWriteError = SQLITE_OK; // set on write error
|
||||
static void DisplayAsyncWriteError();
|
||||
|
||||
// threading
|
||||
// serializes access to the queue, AsyncWriteThreadInstance = nsnull means
|
||||
@ -641,6 +657,7 @@ AsyncOpenFile(const char* aName, AsyncOsFile** aFile,
|
||||
}
|
||||
memset(*aFile, 0, sizeof(AsyncOsFile));
|
||||
|
||||
(*aFile)->mFilename = new nsCString(aName);
|
||||
(*aFile)->pMethod = &iomethod;
|
||||
(*aFile)->mOpen = PR_TRUE;
|
||||
(*aFile)->mBaseRead = aBaseRead;
|
||||
@ -1323,7 +1340,10 @@ ProcessOneMessage(AsyncMessage* aMessage)
|
||||
// two handles matters here)
|
||||
sqliteOrigClose(&aMessage->mFile->mBaseWrite);
|
||||
sqliteOrigClose(&aMessage->mFile->mBaseRead);
|
||||
if (aMessage->mFile->mFilename)
|
||||
delete aMessage->mFile->mFilename;
|
||||
nsMemory::Free(aMessage->mFile);
|
||||
aMessage->mFile = nsnull;
|
||||
break;
|
||||
|
||||
case ASYNC_OPENDIRECTORY:
|
||||
@ -1423,9 +1443,30 @@ ProcessAsyncMessages()
|
||||
// put it back when it's done
|
||||
rc = ProcessOneMessage(message);
|
||||
|
||||
// check for error
|
||||
if (rc != SQLITE_OK) {
|
||||
AsyncWriteError = rc;
|
||||
NS_NOTREACHED("FILE ERROR");
|
||||
|
||||
// log error to console
|
||||
nsresult rv;
|
||||
nsCOMPtr<nsIConsoleService> consoleSvc =
|
||||
do_GetService("@mozilla.org/consoleservice;1", &rv);
|
||||
if (NS_FAILED(rv)) {
|
||||
NS_WARNING("Couldn't get the console service for logging file error");
|
||||
} else {
|
||||
nsAutoString logMessage;
|
||||
logMessage.AssignLiteral("mozStorage: error code ");
|
||||
logMessage.AppendInt(rc);
|
||||
logMessage.AppendLiteral(" for database ");
|
||||
if (message->mFile && message->mFile->mFilename)
|
||||
logMessage.Append(NS_ConvertUTF8toUTF16(*message->mFile->mFilename));
|
||||
rv = consoleSvc->LogStringMessage(logMessage.get());
|
||||
NS_WARN_IF_FALSE(NS_SUCCEEDED(rv), "Couldn't log message on async error");
|
||||
}
|
||||
|
||||
// tell user to restart
|
||||
DisplayAsyncWriteError();
|
||||
return;
|
||||
}
|
||||
|
||||
@ -1451,3 +1492,56 @@ ProcessAsyncMessages()
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// nsAsyncWriteErrorDisplayer
|
||||
//
|
||||
// This gets dispatched to the main thread so that we can do all the UI
|
||||
// calls there. The prompt service must be called from the main thread.
|
||||
|
||||
class nsAsyncWriteErrorDisplayer : public nsRunnable
|
||||
{
|
||||
public:
|
||||
NS_IMETHOD Run()
|
||||
{
|
||||
nsresult rv;
|
||||
nsCOMPtr<nsIPrompt> prompt = do_CreateInstance(
|
||||
NS_DEFAULTPROMPT_CONTRACTID, &rv);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsCOMPtr<nsIStringBundleService> bundleService = do_GetService(
|
||||
"@mozilla.org/intl/stringbundle;1", &rv);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsCOMPtr<nsIStringBundle> bundle;
|
||||
rv = bundleService->CreateBundle(
|
||||
"chrome://global/locale/storage.properties", getter_AddRefs(bundle));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsXPIDLString message;
|
||||
rv = bundle->GetStringFromName(NS_LITERAL_STRING("storageWriteError").get(),
|
||||
getter_Copies(message));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
return prompt->Alert(nsnull, message.get());
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
// DisplayAsyncWriteError
|
||||
//
|
||||
// Displays a general message box informing the user of the I/O error. The
|
||||
// problem is that this is called from the I/O thread, which can't display
|
||||
// UI. Therefore, we proxy to the UI thread.
|
||||
|
||||
void
|
||||
DisplayAsyncWriteError()
|
||||
{
|
||||
nsCOMPtr<nsIRunnable> displayer(new nsAsyncWriteErrorDisplayer);
|
||||
if (! displayer) {
|
||||
NS_WARNING("Unable to create displayer");
|
||||
return;
|
||||
}
|
||||
nsresult rv = NS_DispatchToMainThread(displayer);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "Can't call main thread");
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user