Quellcodebibliothek Statistik Leitseite products/sources/formale Sprachen/C/Firefox/storage/   (Browser von der Mozilla Stiftung Version 136.0.1©)  Datei vom 10.2.2025 mit Größe 7 kB image not shown  

Quelle  StorageBaseStatementInternal.cpp   Sprache: C

 
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
 * vim: sw=2 ts=2 sts=2 expandtab
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */


#include "StorageBaseStatementInternal.h"

#include "nsProxyRelease.h"

#include "mozStorageBindingParamsArray.h"
#include "mozStorageStatementData.h"
#include "mozStorageAsyncStatementExecution.h"

namespace mozilla {
namespace storage {

////////////////////////////////////////////////////////////////////////////////
//// Local Classes

/**
 * Used to finalize an asynchronous statement on the background thread.
 */

class AsyncStatementFinalizer : public Runnable {
 public:
  /**
   * Constructor for the event.
   *
   * @param aStatement
   *        We need the AsyncStatement to be able to get at the sqlite3_stmt;
   *        we only access/create it on the async event target.
   * @param aConnection
   *        We need the connection to know what event target to release the
   *        statement on. We release the statement on that event target since
   *        releasing the statement might end up releasing the connection too.
   */

  AsyncStatementFinalizer(StorageBaseStatementInternal* aStatement,
                          Connection* aConnection)
      : Runnable("storage::AsyncStatementFinalizer"),
        mStatement(aStatement),
        mConnection(aConnection) {}

  NS_IMETHOD Run() override {
    if (mStatement->mAsyncStatement) {
      sqlite3_finalize(mStatement->mAsyncStatement);
      mStatement->mAsyncStatement = nullptr;
    }

    nsCOMPtr<nsIEventTarget> target(mConnection->eventTargetOpenedOn);
    NS_ProxyRelease("AsyncStatementFinalizer::mStatement", target,
                    mStatement.forget());
    return NS_OK;
  }

 private:
  RefPtr<StorageBaseStatementInternal> mStatement;
  RefPtr<Connection> mConnection;
};

/**
 * Finalize a sqlite3_stmt on the background thread for a statement whose
 * destructor was invoked and the statement was non-null.
 */

class LastDitchSqliteStatementFinalizer : public Runnable {
 public:
  /**
   * Event constructor.
   *
   * @param aConnection
   *        Used to keep the connection alive.  If we failed to do this, it
   *        is possible that the statement going out of scope invoking us
   *        might have the last reference to the connection and so trigger
   *        an attempt to close the connection which is doomed to fail
   *        (because the asynchronous execution event target must exist which
   *        will trigger the failure case).
   * @param aStatement
   *        The sqlite3_stmt to finalize.  This object takes ownership /
   *        responsibility for the instance and all other references to it
   *        should be forgotten.
   */

  LastDitchSqliteStatementFinalizer(RefPtr<Connection>& aConnection,
                                    sqlite3_stmt* aStatement)
      : Runnable("storage::LastDitchSqliteStatementFinalizer"),
        mConnection(aConnection),
        mAsyncStatement(aStatement) {
    MOZ_ASSERT(aConnection, "You must provide a Connection");
  }

  NS_IMETHOD Run() override {
    (void)::sqlite3_finalize(mAsyncStatement);
    mAsyncStatement = nullptr;

    nsCOMPtr<nsIEventTarget> target(mConnection->eventTargetOpenedOn);
    (void)::NS_ProxyRelease("LastDitchSqliteStatementFinalizer::mConnection",
                            target, mConnection.forget());
    return NS_OK;
  }

 private:
  RefPtr<Connection> mConnection;
  sqlite3_stmt* mAsyncStatement;
};

////////////////////////////////////////////////////////////////////////////////
//// StorageBaseStatementInternal

StorageBaseStatementInternal::StorageBaseStatementInternal()
    : mNativeConnection(nullptr), mAsyncStatement(nullptr) {}

void StorageBaseStatementInternal::asyncFinalize() {
  nsIEventTarget* target = mDBConnection->getAsyncExecutionTarget();
  if (target) {
    // Attempt to finalize asynchronously
    nsCOMPtr<nsIRunnable> event =
        new AsyncStatementFinalizer(this, mDBConnection);

    // Dispatch. Note that dispatching can fail, typically if
    // we have a race condition with asyncClose(). It's ok,
    // let asyncClose() win.
    (void)target->Dispatch(event, NS_DISPATCH_NORMAL);
  }
  // If we cannot get the background thread,
  // mozStorageConnection::AsyncClose() has already been called and
  // the statement either has been or will be cleaned up by
  // internalClose().
}

void StorageBaseStatementInternal::destructorAsyncFinalize() {
  if (!mAsyncStatement) return;

  if (IsOnCurrentSerialEventTarget(mDBConnection->eventTargetOpenedOn)) {
    // If we are the owning event target (currently that means we're also the
    // main thread), then we can get the async target and just dispatch to it.
    nsIEventTarget* target = mDBConnection->getAsyncExecutionTarget();
    if (target) {
      nsCOMPtr<nsIRunnable> event =
          new LastDitchSqliteStatementFinalizer(mDBConnection, mAsyncStatement);
      (void)target->Dispatch(event, NS_DISPATCH_NORMAL);
    }
  } else {
    // If we're not the owning event target, assume we're the async event
    // target, and just run the statement.
    nsCOMPtr<nsIRunnable> event =
        new LastDitchSqliteStatementFinalizer(mDBConnection, mAsyncStatement);
    (void)event->Run();
  }

  // We might not be able to dispatch to the background thread,
  // presumably because it is being shutdown. Since said shutdown will
  // finalize the statement, we just need to clean-up around here.
  mAsyncStatement = nullptr;
}

NS_IMETHODIMP
StorageBaseStatementInternal::NewBindingParamsArray(
    mozIStorageBindingParamsArray** _array) {
  nsCOMPtr<mozIStorageBindingParamsArray> array = new BindingParamsArray(this);
  NS_ENSURE_TRUE(array, NS_ERROR_OUT_OF_MEMORY);

  array.forget(_array);
  return NS_OK;
}

NS_IMETHODIMP
StorageBaseStatementInternal::ExecuteAsync(
    mozIStorageStatementCallback* aCallback,
    mozIStoragePendingStatement** _stmt) {
  // We used to call Connection::ExecuteAsync but it takes a
  // mozIStorageBaseStatement signature because it is also a public API.  Since
  // our 'this' has no static concept of mozIStorageBaseStatement and Connection
  // would just QI it back across to a StorageBaseStatementInternal and the
  // actual logic is very simple, we now roll our own.
  nsTArray<StatementData> stmts(1);
  StatementData data;
  nsresult rv = getAsynchronousStatementData(data);
  NS_ENSURE_SUCCESS(rv, rv);
  stmts.AppendElement(data);

  // Dispatch to the background
  return AsyncExecuteStatements::execute(std::move(stmts), mDBConnection,
                                         mNativeConnection, aCallback, _stmt);
}

template <typename T>
void EscapeStringForLIKEInternal(const T& aValue,
                                 const typename T::char_type aEscapeChar,
                                 T& aResult) {
  const typename T::char_type MATCH_ALL('%');
  const typename T::char_type MATCH_ONE('_');

  aResult.Truncate(0);

  for (uint32_t i = 0; i < aValue.Length(); i++) {
    if (aValue[i] == aEscapeChar || aValue[i] == MATCH_ALL ||
        aValue[i] == MATCH_ONE) {
      aResult += aEscapeChar;
    }
    aResult += aValue[i];
  }
}

NS_IMETHODIMP
StorageBaseStatementInternal::EscapeStringForLIKE(const nsAString& aValue,
                                                  const char16_t aEscapeChar,
                                                  nsAString& _escapedString) {
  EscapeStringForLIKEInternal(aValue, aEscapeChar, _escapedString);

  return NS_OK;
}

NS_IMETHODIMP
StorageBaseStatementInternal::EscapeUTF8StringForLIKE(
    const nsACString& aValue, const char aEscapeChar,
    nsACString& _escapedString) {
  EscapeStringForLIKEInternal(aValue, aEscapeChar, _escapedString);

  return NS_OK;
}

}  // namespace storage
}  // namespace mozilla

97%


¤ Dauer der Verarbeitung: 0.24 Sekunden  (vorverarbeitet)  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung ist noch experimentell.