void ExtCommandsHandler::run() { while (1) { QStringList args; if (!readRequest(&args)) { qWarning ("failed to read request from shell extension: %s", formatErrorMessage().c_str()); break; } QString cmd = args.takeAt(0); QString resp; if (cmd == "list-repos") { resp = handleListRepos(args); } else if (cmd == "get-share-link") { handleGenShareLink(args); } else if (cmd == "get-file-status") { resp = handleGetFileStatus(args); } else { qWarning ("[ext] unknown request command: %s", cmd.toUtf8().data()); } if (!sendResponse(resp)) { qWarning ("failed to write response to shell extension: %s", formatErrorMessage().c_str()); break; } } qWarning ("An extension client is disconnected: GLE=%lu\n", GetLastError()); DisconnectNamedPipe(pipe_); CloseHandle(pipe_); }
void XercesParserLiaison::error(const SAXParseExceptionType& e) { XalanDOMString theMessage = XalanMessageLoader::getMessage(XalanMessages::Error2); formatErrorMessage(e, theMessage); if (m_executionContext != 0) { // We call warn() because we don't want the execution // context to potentially throw an exception. m_executionContext->warn(theMessage); } else { XALAN_USING_STD(cerr) XALAN_USING_STD(endl) cerr << endl << theMessage << endl; } if (m_useValidation == true) { throw e; } }
bool checkLastError() { DWORD last_error = GetLastError(); if (last_error != ERROR_IO_PENDING && last_error != ERROR_SUCCESS) { if (last_error == ERROR_BROKEN_PIPE || last_error == ERROR_NO_DATA || last_error == ERROR_PIPE_NOT_CONNECTED) { seaf_ext_log ("connection broken with error: %s", formatErrorMessage().c_str()); } else { seaf_ext_log ("failed to communicate with seafile client: %s", formatErrorMessage().c_str()); } return false; } return true; }
void DatabaseBackendBase::incrementalVacuumIfNeeded() { int64_t freeSpaceSize = m_sqliteDatabase.freeSpaceSize(); int64_t totalSize = m_sqliteDatabase.totalSize(); if (totalSize <= 10 * freeSpaceSize) { int result = m_sqliteDatabase.runIncrementalVacuumCommand(); reportVacuumDatabaseResult(result); if (result != SQLResultOk) m_frontend->logErrorMessage(formatErrorMessage("error vacuuming database", result, m_sqliteDatabase.lastErrorMsg())); } }
void DatabaseBackendBase::incrementalVacuumIfNeeded() { SQLiteTransactionInProgressAutoCounter transactionCounter; int64_t freeSpaceSize = m_sqliteDatabase.freeSpaceSize(); int64_t totalSize = m_sqliteDatabase.totalSize(); if (totalSize <= 10 * freeSpaceSize) { int result = m_sqliteDatabase.runIncrementalVacuumCommand(); if (result != SQLResultOk) m_frontend->logErrorMessage(formatErrorMessage("error vacuuming database", result, m_sqliteDatabase.lastErrorMsg())); } }
void TransportSecurityInfo::GetErrorLogMessage(PRErrorCode errorCode, SSLErrorMessageType errorMessageType, nsString &result) { if (!NS_IsMainThread()) { NS_ERROR("nsNSSSocketInfo::GetErrorLogMessage called off the main thread"); return; } MutexAutoLock lock(mMutex); (void) formatErrorMessage(lock, errorCode, errorMessageType, false, false, result); }
bool doPipeWait (HANDLE pipe, OVERLAPPED *ol, DWORD len) { DWORD bytes_rw, result; result = WaitForSingleObject (ol->hEvent, kPipeWaitTimeMSec); if (result == WAIT_OBJECT_0) { if (!GetOverlappedResult(pipe, ol, &bytes_rw, false) || bytes_rw != len) { seaf_ext_log ("async read failed: %s", formatErrorMessage().c_str()); return false; } } else if (result == WAIT_TIMEOUT) { seaf_ext_log ("connection timeout"); return false; } else { seaf_ext_log ("failed to communicate with seafil client: %s", formatErrorMessage().c_str()); return false; } return true; }
void XercesParserLiaison::warning(const SAXParseExceptionType& e) { XalanDOMString theMessage = XalanMessageLoader::getMessage(XalanMessages::Warning2); formatErrorMessage(e, theMessage); if (m_executionContext != 0) { m_executionContext->warn(theMessage); } else { XALAN_USING_STD(cerr) XALAN_USING_STD(endl) cerr << endl << theMessage << endl; } }
NS_IMETHODIMP TransportSecurityInfo::Write(nsIObjectOutputStream* stream) { nsresult rv = stream->WriteID(kTransportSecurityInfoMagic); if (NS_FAILED(rv)) { return rv; } MutexAutoLock lock(mMutex); rv = stream->Write32(mSecurityState); if (NS_FAILED(rv)) { return rv; } rv = stream->Write32(mSubRequestsBrokenSecurity); if (NS_FAILED(rv)) { return rv; } rv = stream->Write32(mSubRequestsNoSecurity); if (NS_FAILED(rv)) { return rv; } // XXX: uses nsNSSComponent string bundles off the main thread rv = formatErrorMessage(lock, mErrorCode, mErrorMessageType, true, true, mErrorMessageCached); if (NS_FAILED(rv)) { return rv; } rv = stream->WriteWStringZ(mErrorMessageCached.get()); if (NS_FAILED(rv)) { return rv; } nsCOMPtr<nsISerializable> serializable(mSSLStatus); rv = stream->WriteCompoundObject(serializable, NS_GET_IID(nsISSLStatus), true); if (NS_FAILED(rv)) { return rv; } return NS_OK; }
NS_IMETHODIMP TransportSecurityInfo::GetErrorMessage(char16_t** aText) { NS_ENSURE_ARG_POINTER(aText); *aText = nullptr; if (!NS_IsMainThread()) { NS_ERROR("nsNSSSocketInfo::GetErrorMessage called off the main thread"); return NS_ERROR_NOT_SAME_THREAD; } MutexAutoLock lock(mMutex); if (mErrorMessageCached.IsEmpty()) { nsresult rv = formatErrorMessage(lock, mErrorCode, mErrorMessageType, true, true, mErrorMessageCached); NS_ENSURE_SUCCESS(rv, rv); } *aText = ToNewUnicode(mErrorMessageCached); return *aText ? NS_OK : NS_ERROR_OUT_OF_MEMORY; }
NS_IMETHODIMP TransportSecurityInfo::Write(nsIObjectOutputStream* stream) { nsresult rv = stream->WriteID(kTransportSecurityInfoMagic); if (NS_FAILED(rv)) { return rv; } MutexAutoLock lock(mMutex); rv = stream->Write32(mSecurityState); if (NS_FAILED(rv)) { return rv; } rv = stream->Write32(mSubRequestsBrokenSecurity); if (NS_FAILED(rv)) { return rv; } rv = stream->Write32(mSubRequestsNoSecurity); if (NS_FAILED(rv)) { return rv; } rv = stream->Write32(static_cast<uint32_t>(mErrorCode)); if (NS_FAILED(rv)) { return rv; } if (mErrorMessageCached.IsEmpty()) { // XXX: uses nsNSSComponent string bundles off the main thread rv = formatErrorMessage(lock, mErrorCode, mErrorMessageType, true, true, mErrorMessageCached); if (NS_FAILED(rv)) { return rv; } } rv = stream->WriteWStringZ(mErrorMessageCached.get()); if (NS_FAILED(rv)) { return rv; } // For successful connections and for connections with overridable errors, // mSSLStatus will be non-null. However, for connections with non-overridable // errors, it will be null. nsCOMPtr<nsISerializable> serializable(mSSLStatus); rv = NS_WriteOptionalCompoundObject(stream, serializable, NS_GET_IID(nsISSLStatus), true); if (NS_FAILED(rv)) { return rv; } rv = NS_WriteOptionalCompoundObject(stream, mFailedCertChain, NS_GET_IID(nsIX509CertList), true); if (NS_FAILED(rv)) { return rv; } return NS_OK; }
virtual void run() { fTraceInfo = 1; LocalPointer<NumberFormat> percentFormatter; UErrorCode status = U_ZERO_ERROR; #if 0 // debugging code, for (int i=0; i<4000; i++) { status = U_ZERO_ERROR; UDataMemory *data1 = udata_openChoice(0, "res", "en_US", isAcceptable, 0, &status); UDataMemory *data2 = udata_openChoice(0, "res", "fr", isAcceptable, 0, &status); udata_close(data1); udata_close(data2); if (U_FAILURE(status)) { error("udata_openChoice failed.\n"); break; } } return; #endif #if 0 // debugging code, int m; for (m=0; m<4000; m++) { status = U_ZERO_ERROR; UResourceBundle *res = NULL; const char *localeName = NULL; Locale loc = Locale::getEnglish(); localeName = loc.getName(); // localeName = "en"; // ResourceBundle bund = ResourceBundle(0, loc, status); //umtx_lock(&gDebugMutex); res = ures_open(NULL, localeName, &status); //umtx_unlock(&gDebugMutex); //umtx_lock(&gDebugMutex); ures_close(res); //umtx_unlock(&gDebugMutex); if (U_FAILURE(status)) { error("Resource bundle construction failed.\n"); break; } } return; #endif // Keep this data here to avoid static initialization. FormatThreadTestData kNumberFormatTestData[] = { FormatThreadTestData((double)5.0, UnicodeString("5", "")), FormatThreadTestData( 6.0, UnicodeString("6", "")), FormatThreadTestData( 20.0, UnicodeString("20", "")), FormatThreadTestData( 8.0, UnicodeString("8", "")), FormatThreadTestData( 8.3, UnicodeString("8.3", "")), FormatThreadTestData( 12345, UnicodeString("12,345", "")), FormatThreadTestData( 81890.23, UnicodeString("81,890.23", "")), }; int32_t kNumberFormatTestDataLength = (int32_t)(sizeof(kNumberFormatTestData) / sizeof(kNumberFormatTestData[0])); // Keep this data here to avoid static initialization. FormatThreadTestData kPercentFormatTestData[] = { FormatThreadTestData((double)5.0, CharsToUnicodeString("500\\u00a0%")), FormatThreadTestData( 1.0, CharsToUnicodeString("100\\u00a0%")), FormatThreadTestData( 0.26, CharsToUnicodeString("26\\u00a0%")), FormatThreadTestData( 16384.99, CharsToUnicodeString("1\\u00a0638\\u00a0499\\u00a0%")), // U+00a0 = NBSP FormatThreadTestData( 81890.23, CharsToUnicodeString("8\\u00a0189\\u00a0023\\u00a0%")), }; int32_t kPercentFormatTestDataLength = (int32_t)(sizeof(kPercentFormatTestData) / sizeof(kPercentFormatTestData[0])); int32_t iteration; status = U_ZERO_ERROR; LocalPointer<NumberFormat> formatter(NumberFormat::createInstance(Locale::getEnglish(),status)); if(U_FAILURE(status)) { error("Error on NumberFormat::createInstance()."); goto cleanupAndReturn; } percentFormatter.adoptInstead(NumberFormat::createPercentInstance(Locale::getFrench(),status)); if(U_FAILURE(status)) { error("Error on NumberFormat::createPercentInstance()."); goto cleanupAndReturn; } for(iteration = 0;!getError() && iteration<kFormatThreadIterations;iteration++) { int32_t whichLine = (iteration + fOffset)%kNumberFormatTestDataLength; UnicodeString output; formatter->format(kNumberFormatTestData[whichLine].number, output); if(0 != output.compare(kNumberFormatTestData[whichLine].string)) { error("format().. expected " + kNumberFormatTestData[whichLine].string + " got " + output); goto cleanupAndReturn; } // Now check percent. output.remove(); whichLine = (iteration + fOffset)%kPercentFormatTestDataLength; percentFormatter->format(kPercentFormatTestData[whichLine].number, output); if(0 != output.compare(kPercentFormatTestData[whichLine].string)) { error("percent format().. \n" + showDifference(kPercentFormatTestData[whichLine].string,output)); goto cleanupAndReturn; } // Test message error const int kNumberOfMessageTests = 3; UErrorCode statusToCheck; UnicodeString patternToCheck; Locale messageLocale; Locale countryToCheck; double currencyToCheck; UnicodeString expected; // load the cases. switch((iteration+fOffset) % kNumberOfMessageTests) { default: case 0: statusToCheck= U_FILE_ACCESS_ERROR; patternToCheck= "0:Someone from {2} is receiving a #{0}" " error - {1}. Their telephone call is costing " "{3,number,currency}."; // number,currency messageLocale= Locale("en","US"); countryToCheck= Locale("","HR"); currencyToCheck= 8192.77; expected= "0:Someone from Croatia is receiving a #4 error - " "U_FILE_ACCESS_ERROR. Their telephone call is costing $8,192.77."; break; case 1: statusToCheck= U_INDEX_OUTOFBOUNDS_ERROR; patternToCheck= "1:A customer in {2} is receiving a #{0} error - {1}. Their telephone call is costing {3,number,currency}."; // number,currency messageLocale= Locale("de","DE@currency=DEM"); countryToCheck= Locale("","BF"); currencyToCheck= 2.32; expected= CharsToUnicodeString( "1:A customer in Burkina Faso is receiving a #8 error - U_INDEX_OUTOFBOUNDS_ERROR. Their telephone call is costing 2,32\\u00A0DM."); break; case 2: statusToCheck= U_MEMORY_ALLOCATION_ERROR; patternToCheck= "2:user in {2} is receiving a #{0} error - {1}. " "They insist they just spent {3,number,currency} " "on memory."; // number,currency messageLocale= Locale("de","AT@currency=ATS"); // Austrian German countryToCheck= Locale("","US"); // hmm currencyToCheck= 40193.12; expected= CharsToUnicodeString( "2:user in Vereinigte Staaten is receiving a #7 error" " - U_MEMORY_ALLOCATION_ERROR. They insist they just spent" " \\u00f6S\\u00A040.193,12 on memory."); break; } UnicodeString result; UErrorCode status = U_ZERO_ERROR; formatErrorMessage(status,patternToCheck,messageLocale,statusToCheck, countryToCheck,currencyToCheck,result); if(U_FAILURE(status)) { UnicodeString tmp(u_errorName(status)); error("Failure on message format, pattern=" + patternToCheck + ", error = " + tmp); goto cleanupAndReturn; } if(result != expected) { error("PatternFormat: \n" + showDifference(expected,result)); goto cleanupAndReturn; } } /* end of for loop */ cleanupAndReturn: // while (fNum == 4) {SimpleThread::sleep(10000);} // Force a failure by preventing thread from finishing fTraceInfo = 2; }
XalanDocument* XercesParserLiaison::parseXMLStream( const InputSourceType& reader, const XalanDOMString& /* identifier */) { XalanAutoPtr<DOMParserType> theParser(CreateDOMParser()); if (m_errorHandler == 0) { theParser->setErrorHandler(this); } else { theParser->setErrorHandler(m_errorHandler); } theParser->parse(reader); #if XERCES_VERSION_MAJOR >= 2 DOMDocument_Type* const theXercesDocument = theParser->getDocument(); theXercesDocument->normalize(); #else DOM_Document_Type theXercesDocument = theParser->getDocument(); theXercesDocument.normalize(); #endif #if XERCES_VERSION_MAJOR >= 2 XercesDocumentWrapper* theNewDocument = 0; if (theXercesDocument != 0) { theNewDocument = doCreateDocument(theXercesDocument, m_threadSafe, m_buildWrapper, m_buildMaps, true); theParser->adoptDocument(); #else XercesDocumentBridge* theNewDocument = 0; if (theXercesDocument.isNull() == false) { theNewDocument = doCreateDocument(theXercesDocument, m_threadSafe, m_buildBridge, true); #endif } return theNewDocument; } void XercesParserLiaison::destroyDocument(XalanDocument* theDocument) { const DocumentMapType::iterator i = m_documentMap.find(theDocument); if (i != m_documentMap.end()) { const XalanAutoPtr<XalanDocument> theGuard(theDocument); m_documentMap.erase(i); } } int XercesParserLiaison::getIndent() const { return m_indent; } void XercesParserLiaison::setIndent(int i) { m_indent = i; } bool XercesParserLiaison::getUseValidation() const { return m_useValidation; } void XercesParserLiaison::setUseValidation(bool b) { m_useValidation = b; } const XalanDOMString XercesParserLiaison::getParserDescription() const { return StaticStringToDOMString(XALAN_STATIC_UCODE_STRING("Xerces")); } DOMDocument_Type* XercesParserLiaison::createDOMFactory() { DOMDocument_Type* const theXercesDocument = DOMImplementationType::getImplementation()->createDocument(); createDocument(theXercesDocument, false, false); return theXercesDocument; } void XercesParserLiaison::destroyDocument(DOMDocument_Type* theDocument) { // Delete any live documents... for(DocumentMapType::iterator i = m_documentMap.begin(); i != m_documentMap.end(); ++i) { if ((*i).second.isDeprecated() == false && (*i).second.m_wrapper->getXercesDocument() == theDocument) { destroyDocument((XalanDocument*)(*i).first); } } } bool XercesParserLiaison::getIncludeIgnorableWhitespace() const { return m_includeIgnorableWhitespace; } void XercesParserLiaison::setIncludeIgnorableWhitespace(bool include) { m_includeIgnorableWhitespace = include; } ErrorHandlerType* XercesParserLiaison::getErrorHandler() const { return m_errorHandler; } void XercesParserLiaison::setErrorHandler(ErrorHandlerType* handler) { m_errorHandler = handler; } bool XercesParserLiaison::getDoNamespaces() const { return m_doNamespaces; } void XercesParserLiaison::setDoNamespaces(bool newState) { m_doNamespaces = newState; } bool XercesParserLiaison::getExitOnFirstFatalError() const { return m_exitOnFirstFatalError; } void XercesParserLiaison::setExitOnFirstFatalError(bool newState) { m_exitOnFirstFatalError = newState; } EntityResolverType* XercesParserLiaison::getEntityResolver() const { return m_entityResolver; } void XercesParserLiaison::setEntityResolver(EntityResolverType* resolver) { m_entityResolver = resolver; } const XalanDOMChar* XercesParserLiaison::getExternalSchemaLocation() const { return m_externalSchemaLocation.length() == 0 ? 0 : m_externalSchemaLocation.c_str(); } void XercesParserLiaison::setExternalSchemaLocation(const XalanDOMChar* location) { if (location == 0) { m_externalSchemaLocation.clear(); } else { m_externalSchemaLocation = location; } } const XalanDOMChar* XercesParserLiaison::getExternalNoNamespaceSchemaLocation() const { return m_externalNoNamespaceSchemaLocation.length() == 0 ? 0 : m_externalNoNamespaceSchemaLocation.c_str(); } void XercesParserLiaison::setExternalNoNamespaceSchemaLocation(const XalanDOMChar* location) { if (location == 0) { m_externalNoNamespaceSchemaLocation.clear(); } else { m_externalNoNamespaceSchemaLocation= location; } } #if defined(XALAN_BUILD_DEPRECATED_DOM_BRIDGE) XalanDocument* XercesParserLiaison::createDocument( const DOM_Document_Type& theXercesDocument, bool threadSafe, bool buildBridge) { return doCreateDocument(theXercesDocument, threadSafe, buildBridge); } #endif XalanDocument* XercesParserLiaison::createDocument( const DOMDocument_Type* theXercesDocument, bool threadSafe, bool buildWrapper, bool buildMaps) { // As we did not create the underlying DOMDocument - ensure we don't // delete it later. return doCreateDocument(theXercesDocument, threadSafe, buildWrapper, buildMaps, false); } #if defined(XALAN_BUILD_DEPRECATED_DOM_BRIDGE) XercesDocumentBridge* XercesParserLiaison::mapDocument(const XalanDocument* theDocument) const { const DocumentMapType::const_iterator i = m_documentMap.find(theDocument); return i != m_documentMap.end() ? (*i).second.m_isDeprecated == true ? (*i).second.m_bridge : 0 : 0; } #endif XercesDocumentWrapper* XercesParserLiaison::mapDocumentToWrapper(const XalanDocument* theDocument) const { const DocumentMapType::const_iterator i = m_documentMap.find(theDocument); return i != m_documentMap.end() ? (*i).second.isDeprecated() == false ? (*i).second.m_wrapper : 0 : 0; } #if defined(XALAN_BUILD_DEPRECATED_DOM_BRIDGE) DOM_Document_Type XercesParserLiaison::mapXercesDocument(const XalanDocument* theDocument) const { const DocumentMapType::const_iterator i = m_documentMap.find(theDocument); return i != m_documentMap.end() ? (*i).second.isDeprecated() == true ? (*i).second.m_bridge->getXercesDocument() : DOM_Document_Type() : DOM_Document_Type(); } #endif const DOMDocument_Type* XercesParserLiaison::mapToXercesDocument(const XalanDocument* theDocument) const { const DocumentMapType::const_iterator i = m_documentMap.find(theDocument); return i != m_documentMap.end() ? (*i).second.isDeprecated() == false ? (*i).second.m_wrapper->getXercesDocument() : 0 : 0; } void XercesParserLiaison::fatalError(const SAXParseExceptionType& e) { XalanDOMString theMessage = XalanMessageLoader::getMessage(XalanMessages::FatalError); formatErrorMessage(e, theMessage); if (m_executionContext != 0) { // We call warning() because we don't want the execution // context to potentially throw an exception. m_executionContext->warn(theMessage); } else { XALAN_USING_STD(cerr) XALAN_USING_STD(endl) cerr << endl << theMessage << endl; } throw e; }
bool DatabaseBackendBase::performOpenAndVerify(bool shouldSetVersionInNewDatabase, DatabaseError& error, String& errorMessage) { DoneCreatingDatabaseOnExitCaller onExitCaller(this); ASSERT(errorMessage.isEmpty()); ASSERT(error == DatabaseError::None); // Better not have any errors already. error = DatabaseError::InvalidDatabaseState; // Presumed failure. We'll clear it if we succeed below. const int maxSqliteBusyWaitTime = 30000; #if PLATFORM(IOS) { // Make sure we wait till the background removal of the empty database files finished before trying to open any database. MutexLocker locker(DatabaseTracker::openDatabaseMutex()); } #endif SQLiteTransactionInProgressAutoCounter transactionCounter; if (!m_sqliteDatabase.open(m_filename, true)) { errorMessage = formatErrorMessage("unable to open database", m_sqliteDatabase.lastError(), m_sqliteDatabase.lastErrorMsg()); return false; } if (!m_sqliteDatabase.turnOnIncrementalAutoVacuum()) LOG_ERROR("Unable to turn on incremental auto-vacuum (%d %s)", m_sqliteDatabase.lastError(), m_sqliteDatabase.lastErrorMsg()); m_sqliteDatabase.setBusyTimeout(maxSqliteBusyWaitTime); String currentVersion; { std::lock_guard<std::mutex> locker(guidMutex()); auto entry = guidToVersionMap().find(m_guid); if (entry != guidToVersionMap().end()) { // Map null string to empty string (see updateGuidVersionMap()). currentVersion = entry->value.isNull() ? emptyString() : entry->value.isolatedCopy(); LOG(StorageAPI, "Current cached version for guid %i is %s", m_guid, currentVersion.ascii().data()); } else { LOG(StorageAPI, "No cached version for guid %i", m_guid); SQLiteTransaction transaction(m_sqliteDatabase); transaction.begin(); if (!transaction.inProgress()) { errorMessage = formatErrorMessage("unable to open database, failed to start transaction", m_sqliteDatabase.lastError(), m_sqliteDatabase.lastErrorMsg()); m_sqliteDatabase.close(); return false; } String tableName(infoTableName); if (!m_sqliteDatabase.tableExists(tableName)) { m_new = true; if (!m_sqliteDatabase.executeCommand("CREATE TABLE " + tableName + " (key TEXT NOT NULL ON CONFLICT FAIL UNIQUE ON CONFLICT REPLACE,value TEXT NOT NULL ON CONFLICT FAIL);")) { errorMessage = formatErrorMessage("unable to open database, failed to create 'info' table", m_sqliteDatabase.lastError(), m_sqliteDatabase.lastErrorMsg()); transaction.rollback(); m_sqliteDatabase.close(); return false; } } else if (!getVersionFromDatabase(currentVersion, false)) { errorMessage = formatErrorMessage("unable to open database, failed to read current version", m_sqliteDatabase.lastError(), m_sqliteDatabase.lastErrorMsg()); transaction.rollback(); m_sqliteDatabase.close(); return false; } if (currentVersion.length()) { LOG(StorageAPI, "Retrieved current version %s from database %s", currentVersion.ascii().data(), databaseDebugName().ascii().data()); } else if (!m_new || shouldSetVersionInNewDatabase) { LOG(StorageAPI, "Setting version %s in database %s that was just created", m_expectedVersion.ascii().data(), databaseDebugName().ascii().data()); if (!setVersionInDatabase(m_expectedVersion, false)) { errorMessage = formatErrorMessage("unable to open database, failed to write current version", m_sqliteDatabase.lastError(), m_sqliteDatabase.lastErrorMsg()); transaction.rollback(); m_sqliteDatabase.close(); return false; } currentVersion = m_expectedVersion; } updateGuidVersionMap(m_guid, currentVersion); transaction.commit(); } } if (currentVersion.isNull()) { LOG(StorageAPI, "Database %s does not have its version set", databaseDebugName().ascii().data()); currentVersion = ""; } // If the expected version isn't the empty string, ensure that the current database version we have matches that version. Otherwise, set an exception. // If the expected version is the empty string, then we always return with whatever version of the database we have. if ((!m_new || shouldSetVersionInNewDatabase) && m_expectedVersion.length() && m_expectedVersion != currentVersion) { errorMessage = "unable to open database, version mismatch, '" + m_expectedVersion + "' does not match the currentVersion of '" + currentVersion + "'"; m_sqliteDatabase.close(); return false; } ASSERT(m_databaseAuthorizer); m_sqliteDatabase.setAuthorizer(m_databaseAuthorizer); // See comment at the top this file regarding calling addOpenDatabase(). DatabaseTracker::tracker().addOpenDatabase(this); m_opened = true; // Declare success: error = DatabaseError::None; // Clear the presumed error from above. onExitCaller.setOpenSucceeded(); if (m_new && !shouldSetVersionInNewDatabase) m_expectedVersion = ""; // The caller provided a creationCallback which will set the expected version. return true; }
bool DatabaseBackendBase::performOpenAndVerify(bool shouldSetVersionInNewDatabase, DatabaseError& error, String& errorMessage) { DoneCreatingDatabaseOnExitCaller onExitCaller(this); ASSERT(errorMessage.isEmpty()); ASSERT(error == DatabaseError::None); // Better not have any errors already. error = DatabaseError::InvalidDatabaseState; // Presumed failure. We'll clear it if we succeed below. const int maxSqliteBusyWaitTime = 30000; if (!m_sqliteDatabase.open(m_filename, true)) { reportOpenDatabaseResult(1, INVALID_STATE_ERR, m_sqliteDatabase.lastError()); errorMessage = formatErrorMessage("unable to open database", m_sqliteDatabase.lastError(), m_sqliteDatabase.lastErrorMsg()); return false; } if (!m_sqliteDatabase.turnOnIncrementalAutoVacuum()) LOG_ERROR("Unable to turn on incremental auto-vacuum (%d %s)", m_sqliteDatabase.lastError(), m_sqliteDatabase.lastErrorMsg()); m_sqliteDatabase.setBusyTimeout(maxSqliteBusyWaitTime); String currentVersion; { MutexLocker locker(guidMutex()); GuidVersionMap::iterator entry = guidToVersionMap().find(m_guid); if (entry != guidToVersionMap().end()) { // Map null string to empty string (see updateGuidVersionMap()). currentVersion = entry->value.isNull() ? emptyString() : entry->value.isolatedCopy(); LOG(StorageAPI, "Current cached version for guid %i is %s", m_guid, currentVersion.ascii().data()); // Note: In multi-process browsers the cached value may be inaccurate, but // we cannot read the actual version from the database without potentially // inducing a form of deadlock, a busytimeout error when trying to // access the database. So we'll use the cached value if we're unable to read // the value from the database file without waiting. // FIXME: Add an async openDatabase method to the DatabaseAPI. const int noSqliteBusyWaitTime = 0; m_sqliteDatabase.setBusyTimeout(noSqliteBusyWaitTime); String versionFromDatabase; if (getVersionFromDatabase(versionFromDatabase, false)) { currentVersion = versionFromDatabase; updateGuidVersionMap(m_guid, currentVersion); } m_sqliteDatabase.setBusyTimeout(maxSqliteBusyWaitTime); } else { LOG(StorageAPI, "No cached version for guid %i", m_guid); SQLiteTransaction transaction(m_sqliteDatabase); transaction.begin(); if (!transaction.inProgress()) { reportOpenDatabaseResult(2, INVALID_STATE_ERR, m_sqliteDatabase.lastError()); errorMessage = formatErrorMessage("unable to open database, failed to start transaction", m_sqliteDatabase.lastError(), m_sqliteDatabase.lastErrorMsg()); m_sqliteDatabase.close(); return false; } String tableName(infoTableName); if (!m_sqliteDatabase.tableExists(tableName)) { m_new = true; if (!m_sqliteDatabase.executeCommand("CREATE TABLE " + tableName + " (key TEXT NOT NULL ON CONFLICT FAIL UNIQUE ON CONFLICT REPLACE,value TEXT NOT NULL ON CONFLICT FAIL);")) { reportOpenDatabaseResult(3, INVALID_STATE_ERR, m_sqliteDatabase.lastError()); errorMessage = formatErrorMessage("unable to open database, failed to create 'info' table", m_sqliteDatabase.lastError(), m_sqliteDatabase.lastErrorMsg()); transaction.rollback(); m_sqliteDatabase.close(); return false; } } else if (!getVersionFromDatabase(currentVersion, false)) { reportOpenDatabaseResult(4, INVALID_STATE_ERR, m_sqliteDatabase.lastError()); errorMessage = formatErrorMessage("unable to open database, failed to read current version", m_sqliteDatabase.lastError(), m_sqliteDatabase.lastErrorMsg()); transaction.rollback(); m_sqliteDatabase.close(); return false; } if (currentVersion.length()) { LOG(StorageAPI, "Retrieved current version %s from database %s", currentVersion.ascii().data(), databaseDebugName().ascii().data()); } else if (!m_new || shouldSetVersionInNewDatabase) { LOG(StorageAPI, "Setting version %s in database %s that was just created", m_expectedVersion.ascii().data(), databaseDebugName().ascii().data()); if (!setVersionInDatabase(m_expectedVersion, false)) { reportOpenDatabaseResult(5, INVALID_STATE_ERR, m_sqliteDatabase.lastError()); errorMessage = formatErrorMessage("unable to open database, failed to write current version", m_sqliteDatabase.lastError(), m_sqliteDatabase.lastErrorMsg()); transaction.rollback(); m_sqliteDatabase.close(); return false; } currentVersion = m_expectedVersion; } updateGuidVersionMap(m_guid, currentVersion); transaction.commit(); } } if (currentVersion.isNull()) { LOG(StorageAPI, "Database %s does not have its version set", databaseDebugName().ascii().data()); currentVersion = ""; } // If the expected version isn't the empty string, ensure that the current database version we have matches that version. Otherwise, set an exception. // If the expected version is the empty string, then we always return with whatever version of the database we have. if ((!m_new || shouldSetVersionInNewDatabase) && m_expectedVersion.length() && m_expectedVersion != currentVersion) { reportOpenDatabaseResult(6, INVALID_STATE_ERR, 0); errorMessage = "unable to open database, version mismatch, '" + m_expectedVersion + "' does not match the currentVersion of '" + currentVersion + "'"; m_sqliteDatabase.close(); return false; } ASSERT(m_databaseAuthorizer); m_sqliteDatabase.setAuthorizer(m_databaseAuthorizer); // See comment at the top this file regarding calling addOpenDatabase(). DatabaseTracker::tracker().addOpenDatabase(this); m_opened = true; // Declare success: error = DatabaseError::None; // Clear the presumed error from above. onExitCaller.setOpenSucceeded(); if (m_new && !shouldSetVersionInNewDatabase) m_expectedVersion = ""; // The caller provided a creationCallback which will set the expected version. reportOpenDatabaseResult(0, -1, 0); // OK return true; }