Anforderungen  |   Konzepte  |   Entwurf  |   Entwicklung  |   Qualitätssicherung  |   Lebenszyklus  |   Steuerung
 
 
 
 


Quelle  kvstore.sys.mjs   Sprache: unbekannt

 
/* 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/. */

/**
 * This module wraps the nsIKeyValue* interfaces in a Promise-based API.
 * To use it, import it, then call the KeyValueService.getOrCreate() method
 * with a database's path and (optionally) its name:
 *
 * ```
 *     let { keyValueService } =
 *       ChromeUtils.importESModule("resource://gre/modules/kvstore.sys.mjs");
 *     let database = await KeyValueService.getOrCreate(path, name);
 * ```
 *
 * See the documentation in nsIKeyValue.idl for more information about the API
 * for key/value storage.
 */

function promisify(fn, ...args) {
  return new Promise((resolve, reject) => {
    fn({ resolve, reject }, ...args);
  });
}

export class KeyValueService {
  static RecoveryStrategy = {
    ERROR: Ci.nsIKeyValueService.ERROR,
    DISCARD: Ci.nsIKeyValueService.DISCARD,
    RENAME: Ci.nsIKeyValueService.RENAME,
  };

  static #service = Cc["@mozilla.org/key-value-service;1"].getService(
    Ci.nsIKeyValueService
  );

  static async getOrCreate(dir, name) {
    return new KeyValueDatabase(
      await promisify(this.#service.getOrCreate, dir, name)
    );
  }

  static async getOrCreateWithOptions(
    dir,
    name,
    { strategy = Ci.nsIKeyValueService.RENAME } = {}
  ) {
    return new KeyValueDatabase(
      await promisify(this.#service.getOrCreateWithOptions, dir, name, strategy)
    );
  }
}

/**
 * An experimental key-value storage service that uses
 * SQLite for persistence.
 */
export class SQLiteKeyValueService {
  static Importer = {
    RKV_SAFE_MODE: "rkv-safe-mode",
  };

  static #service = Cc["@mozilla.org/sqlite-key-value-service;1"].getService(
    Ci.nsIKeyValueService
  );

  static async getOrCreate(dir, name) {
    return new KeyValueDatabase(
      await promisify(this.#service.getOrCreate, dir, name)
    );
  }

  static createImporter(type, dir) {
    return new KeyValueImporter(this.#service.createImporter(type, dir));
  }
}

export class KeyValueImporter {
  static ConflictPolicy = {
    ERROR: Ci.nsIKeyValueImporter.ERROR_ON_CONFLICT,
    IGNORE: Ci.nsIKeyValueImporter.IGNORE_ON_CONFLICT,
    REPLACE: Ci.nsIKeyValueImporter.REPLACE_ON_CONFLICT,
  };

  static CleanupPolicy = {
    KEEP: Ci.nsIKeyValueImporter.KEEP_AFTER_IMPORT,
    DELETE: Ci.nsIKeyValueImporter.DELETE_AFTER_IMPORT,
  };

  #importer;

  constructor(importer) {
    this.#importer = importer;
  }

  get type() {
    return this.#importer.type;
  }

  get path() {
    return this.#importer.path;
  }

  addPath(dir) {
    return this.#importer.addPath(dir);
  }

  addDatabase(name) {
    return this.#importer.addDatabase(name);
  }

  addAllDatabases() {
    return this.#importer.addAllDatabases();
  }

  import() {
    return promisify(this.#importer.import);
  }
}

/**
 * A class that wraps an nsIKeyValueDatabase in a Promise-based API.
 *
 * This class isn't exported, so you can't instantiate it directly, but you
 * can retrieve an instance of this class via KeyValueService.getOrCreate():
 *
 * ```
 *     const database = await KeyValueService.getOrCreate(path, name);
 * ```
 *
 * You can then call its put(), get(), has(), and delete() methods to access
 * and manipulate key/value pairs:
 *
 * ```
 *     await database.put("foo", 1);
 *     await database.get("foo") === 1; // true
 *     await database.has("foo"); // true
 *     await database.delete("foo");
 *     await database.has("foo"); // false
 * ```
 *
 * You can also call writeMany() to put/delete multiple key/value pairs:
 *
 * ```
 *     await database.writeMany({
 *       key1: "value1",
 *       key2: "value2",
 *       key3: "value3",
 *       key4: null, // delete
 *     });
 * ```
 *
 * And you can call its enumerate() method to retrieve a KeyValueEnumerator,
 * which is described below.
 */
class KeyValueDatabase {
  constructor(database) {
    this.database = database;
  }

  isEmpty() {
    return promisify(this.database.isEmpty);
  }

  count() {
    return promisify(this.database.count);
  }

  size() {
    return promisify(this.database.size);
  }

  put(key, value) {
    return promisify(this.database.put, key, value);
  }

  /**
   * Writes multiple key/value pairs to the database.
   *
   * Note:
   *   * Each write could be either put or delete.
   *   * Given multiple values with the same key, only the last value will be stored.
   *   * If the same key gets put and deleted for multiple times, the final state
   *     of that key is subject to the ordering of the put(s) and delete(s).
   *
   * @param pairs Pairs could be any of following types:
   *        * An Object, all its properties and the corresponding values will
   *          be used as key value pairs. A property with null or undefined indicating
   *          a deletion.
   *        * An Array or an iterable whose elements are key-value pairs. such as
   *          [["key1", "value1"], ["key2", "value2"]]. Use a pair with value null
   *          to delete a key-value pair, e.g. ["delete-key", null].
   *        * A Map. A key with null or undefined value indicating a deletion.
   * @return A promise that is fulfilled when all the key/value pairs are written
   *         to the database.
   */
  writeMany(pairs) {
    if (!pairs) {
      throw new Error("writeMany(): unexpected argument.");
    }

    let entries;

    if (
      pairs instanceof Map ||
      pairs instanceof Array ||
      typeof pairs[Symbol.iterator] === "function"
    ) {
      try {
        // Let Map constructor validate the argument. Note that Map remembers
        // the original insertion order of the keys, which satisfies the ordering
        // premise of this function.
        const map = pairs instanceof Map ? pairs : new Map(pairs);
        entries = Array.from(map, ([key, value]) => ({ key, value }));
      } catch (error) {
        throw new Error("writeMany(): unexpected argument.");
      }
    } else if (typeof pairs === "object") {
      entries = Array.from(Object.entries(pairs), ([key, value]) => ({
        key,
        value,
      }));
    } else {
      throw new Error("writeMany(): unexpected argument.");
    }

    if (entries.length) {
      return promisify(this.database.writeMany, entries);
    }
    return Promise.resolve();
  }

  has(key) {
    return promisify(this.database.has, key);
  }

  get(key, defaultValue) {
    return promisify(this.database.get, key, defaultValue);
  }

  delete(key) {
    return promisify(this.database.delete, key);
  }

  deleteRange(fromKey, toKey) {
    return promisify(this.database.deleteRange, fromKey, toKey);
  }

  clear() {
    return promisify(this.database.clear);
  }

  async enumerate(fromKey, toKey) {
    return new KeyValueEnumerator(
      await promisify(this.database.enumerate, fromKey, toKey)
    );
  }

  async close() {
    return promisify(this.database.close);
  }
}

/**
 * A class that wraps an nsIKeyValueEnumerator in a Promise-based API.
 *
 * This class isn't exported, so you can't instantiate it directly, but you
 * can retrieve an instance of this class by calling enumerate() on an instance
 * of KeyValueDatabase:
 *
 * ```
 *     const database = await KeyValueService.getOrCreate(path, name);
 *     const enumerator = await database.enumerate();
 * ```
 *
 * And then iterate pairs via its hasMoreElements() and getNext() methods:
 *
 * ```
 *     while (enumerator.hasMoreElements()) {
 *       const { key, value } = enumerator.getNext();
 *       …
 *     }
 * ```
 *
 * Or with a `for...of` statement:
 *
 * ```
 *     for (const { key, value } of enumerator) {
 *         …
 *     }
 * ```
 */
class KeyValueEnumerator {
  constructor(enumerator) {
    this.enumerator = enumerator;
  }

  hasMoreElements() {
    return this.enumerator.hasMoreElements();
  }

  getNext() {
    return this.enumerator.getNext();
  }

  *[Symbol.iterator]() {
    while (this.enumerator.hasMoreElements()) {
      yield this.enumerator.getNext();
    }
  }
}

[ Dauer der Verarbeitung: 0.28 Sekunden  (vorverarbeitet)  ]

                                                                                                                                                                                                                                                                                                                                                                                                     


Neuigkeiten

     Aktuelles
     Motto des Tages

Software

     Produkte
     Quellcodebibliothek

Aktivitäten

     Artikel über Sicherheit
     Anleitung zur Aktivierung von SSL

Muße

     Gedichte
     Musik
     Bilder

Jenseits des Üblichen ....
    

Besucherstatistik

Besucherstatistik

Monitoring

Montastic status badge