Bug 599978 - Part 2: Asynchronous isVisited checks should use a read-only cloned connection

Changes to create and use the read-only cloned connection.
r=mak
This commit is contained in:
Shawn Wilsher 2010-10-06 08:21:31 -07:00
parent 3fe0fe5fc9
commit 3002b8b720
2 changed files with 67 additions and 13 deletions

View File

@ -170,7 +170,7 @@ public:
// If we are a content process, always remote the request to the
// parent process.
if (XRE_GetProcessType() == GeckoProcessType_Content) {
mozilla::dom::ContentChild * cpc =
mozilla::dom::ContentChild* cpc =
mozilla::dom::ContentChild::GetSingleton();
NS_ASSERTION(cpc, "Content Protocol is NULL!");
(void)cpc->SendStartVisitedQuery(aURI);
@ -178,9 +178,8 @@ public:
}
#endif
nsNavHistory* navHist = nsNavHistory::GetHistoryService();
NS_ENSURE_TRUE(navHist, NS_ERROR_FAILURE);
mozIStorageStatement* stmt = navHist->GetStatementById(DB_IS_PAGE_VISITED);
mozIStorageAsyncStatement* stmt =
History::GetService()->GetIsVisitedStatement();
NS_ENSURE_STATE(stmt);
// Bind by index for performance.
@ -260,7 +259,7 @@ class FailSafeFinishTask
{
public:
FailSafeFinishTask()
: mAppended(false)
: mAppended(false)
{
}
@ -952,6 +951,37 @@ History::NotifyVisited(nsIURI* aURI)
mObservers.RemoveEntry(aURI);
}
mozIStorageAsyncStatement*
History::GetIsVisitedStatement()
{
if (mIsVisitedStatement) {
return mIsVisitedStatement;
}
// If we don't yet have a database connection, go ahead and clone it now.
if (!mReadOnlyDBConn) {
nsNavHistory* history = nsNavHistory::GetHistoryService();
NS_ENSURE_TRUE(history, nsnull);
nsCOMPtr<mozIStorageConnection> dbConn;
(void)history->GetDBConnection(getter_AddRefs(dbConn));
NS_ENSURE_TRUE(dbConn, nsnull);
(void)dbConn->Clone(PR_TRUE, getter_AddRefs(mReadOnlyDBConn));
NS_ENSURE_TRUE(mReadOnlyDBConn, nsnull);
}
// Now we can create our cached statement.
nsresult rv = mReadOnlyDBConn->CreateAsyncStatement(NS_LITERAL_CSTRING(
"SELECT h.id "
"FROM moz_places h "
"WHERE url = ?1 "
"AND EXISTS(SELECT id FROM moz_historyvisits WHERE place_id = h.id LIMIT 1) "
), getter_AddRefs(mIsVisitedStatement));
NS_ENSURE_SUCCESS(rv, nsnull);
return mIsVisitedStatement;
}
/* static */
History*
History::GetService()
@ -1006,6 +1036,10 @@ History::Shutdown()
nsCOMPtr<Step> deadTaskWalking =
dont_AddRef(static_cast<Step*>(mPendingVisits.PopFront()));
}
if (mReadOnlyDBConn) {
(void)mReadOnlyDBConn->AsyncClose(nsnull);
}
}
////////////////////////////////////////////////////////////////////////////////

View File

@ -48,6 +48,7 @@
#include "nsTArray.h"
#include "nsDeque.h"
#include "nsIObserver.h"
#include "mozIStorageConnection.h"
namespace mozilla {
namespace places {
@ -71,7 +72,7 @@ public:
* @param aURI
* The URI to notify about.
*/
void NotifyVisited(nsIURI *aURI);
void NotifyVisited(nsIURI* aURI);
/**
* Append a task to the queue for SQL queries that need to happen
@ -93,19 +94,38 @@ public:
*/
void CurrentTaskFinished();
/**
* Obtains the statement to use to check if a URI is visited or not.
*/
mozIStorageAsyncStatement* GetIsVisitedStatement();
/**
* Obtains a pointer to this service.
*/
static History *GetService();
static History* GetService();
/**
* Obtains a pointer that has had AddRef called on it. Used by the service
* manager only.
*/
static History *GetSingleton();
static History* GetSingleton();
private:
~History();
virtual ~History();
/**
* A read-only database connection used for checking if a URI is visited.
*
* @note this should only be accessed by GetIsVisistedStatement and Shutdown.
*/
nsCOMPtr<mozIStorageConnection> mReadOnlyDBConn;
/**
* An asynchronous statement to query if a URI is visited or not.
*
* @note this should only be accessed by GetIsVisistedStatement.
*/
nsCOMPtr<mozIStorageAsyncStatement> mIsVisitedStatement;
/**
* Since visits rapidly fire at once, it's very likely to have race
@ -132,21 +152,21 @@ private:
*/
void Shutdown();
static History *gService;
static History* gService;
// Ensures new tasks aren't started on destruction.
bool mShuttingDown;
typedef nsTArray<mozilla::dom::Link *> ObserverArray;
typedef nsTArray<mozilla::dom::Link* > ObserverArray;
class KeyClass : public nsURIHashKey
{
public:
KeyClass(const nsIURI *aURI)
KeyClass(const nsIURI* aURI)
: nsURIHashKey(aURI)
{
}
KeyClass(const KeyClass &aOther)
KeyClass(const KeyClass& aOther)
: nsURIHashKey(aOther)
{
NS_NOTREACHED("Do not call me!");