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


Quelle  manager.rs   Sprache: unbekannt

 
Spracherkennung für: .rs vermutete Sprache: Unknown {[0] [0] [0]} [Methode: Schwerpunktbildung, einfache Gewichte, sechs Dimensionen]

// Copyright 2018-2019 Mozilla
//
// Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
// Unless required by applicable law or agreed to in writing, software distributed
// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
// CONDITIONS OF ANY KIND, either express or implied. See the License for the
// specific language governing permissions and limitations under the License.

use std::{fs, sync::Arc};

use tempfile::Builder;

#[cfg(feature = "lmdb")]
use rkv::backend::{Lmdb, LmdbEnvironment};
use rkv::{
    backend::{BackendEnvironmentBuilder, RecoveryStrategy, SafeMode, SafeModeEnvironment},
    CloseOptions, Rkv, StoreOptions, Value,
};

/// Test that a manager can be created with simple type inference.
#[cfg(feature = "lmdb")]
#[test]
#[allow(clippy::let_underscore_lock)]
fn test_simple() {
    type Manager = rkv::Manager<LmdbEnvironment>;

    let _unused = Manager::singleton().write().unwrap();
}

/// Test that a manager can be created with simple type inference.
#[test]
#[allow(clippy::let_underscore_lock)]
fn test_simple_safe() {
    type Manager = rkv::Manager<SafeModeEnvironment>;

    let _unused = Manager::singleton().write().unwrap();
}

/// Test that a shared Rkv instance can be created with simple type inference.
#[cfg(feature = "lmdb")]
#[test]
fn test_simple_2() {
    type Manager = rkv::Manager<LmdbEnvironment>;

    let root = Builder::new()
        .prefix("test_simple_2")
        .tempdir()
        .expect("tempdir");
    fs::create_dir_all(root.path()).expect("dir created");

    let mut manager = Manager::singleton().write().unwrap();
    let _ = manager
        .get_or_create(root.path(), Rkv::new::<Lmdb>)
        .unwrap();
}

/// Test that a shared Rkv instance can be created with simple type inference.
#[test]
fn test_simple_safe_2() {
    type Manager = rkv::Manager<SafeModeEnvironment>;

    let root = Builder::new()
        .prefix("test_simple_safe_2")
        .tempdir()
        .expect("tempdir");
    fs::create_dir_all(root.path()).expect("dir created");

    let mut manager = Manager::singleton().write().unwrap();
    let _ = manager
        .get_or_create(root.path(), Rkv::new::<SafeMode>)
        .unwrap();
}

/// Test that the manager will return the same Rkv instance each time for each path.
#[cfg(feature = "lmdb")]
#[test]
fn test_same() {
    type Manager = rkv::Manager<LmdbEnvironment>;

    let root = Builder::new()
        .prefix("test_same")
        .tempdir()
        .expect("tempdir");
    fs::create_dir_all(root.path()).expect("dir created");

    let p = root.path();
    assert!(Manager::singleton()
        .read()
        .unwrap()
        .get(p)
        .expect("success")
        .is_none());

    let created_arc = Manager::singleton()
        .write()
        .unwrap()
        .get_or_create(p, Rkv::new::<Lmdb>)
        .expect("created");
    let fetched_arc = Manager::singleton()
        .read()
        .unwrap()
        .get(p)
        .expect("success")
        .expect("existed");
    assert!(Arc::ptr_eq(&created_arc, &fetched_arc));
}

/// Test that the manager will return the same Rkv instance each time for each path.
#[test]
fn test_same_safe() {
    type Manager = rkv::Manager<SafeModeEnvironment>;

    let root = Builder::new()
        .prefix("test_same_safe")
        .tempdir()
        .expect("tempdir");
    fs::create_dir_all(root.path()).expect("dir created");

    let p = root.path();
    assert!(Manager::singleton()
        .read()
        .unwrap()
        .get(p)
        .expect("success")
        .is_none());

    let created_arc = Manager::singleton()
        .write()
        .unwrap()
        .get_or_create(p, Rkv::new::<SafeMode>)
        .expect("created");
    let fetched_arc = Manager::singleton()
        .read()
        .unwrap()
        .get(p)
        .expect("success")
        .expect("existed");
    assert!(Arc::ptr_eq(&created_arc, &fetched_arc));
}

/// Test that the manager will return the same Rkv instance each time for each path.
#[cfg(feature = "lmdb")]
#[test]
fn test_same_with_capacity() {
    type Manager = rkv::Manager<LmdbEnvironment>;

    let root = Builder::new()
        .prefix("test_same_with_capacity")
        .tempdir()
        .expect("tempdir");
    fs::create_dir_all(root.path()).expect("dir created");

    let mut manager = Manager::singleton().write().unwrap();

    let p = root.path();
    assert!(manager.get(p).expect("success").is_none());

    let created_arc = manager
        .get_or_create_with_capacity(p, 10, Rkv::with_capacity::<Lmdb>)
        .expect("created");
    let fetched_arc = manager.get(p).expect("success").expect("existed");
    assert!(Arc::ptr_eq(&created_arc, &fetched_arc));
}

/// Test that the manager will return the same Rkv instance each time for each path.
#[test]
fn test_same_with_capacity_safe() {
    type Manager = rkv::Manager<SafeModeEnvironment>;

    let root = Builder::new()
        .prefix("test_same_with_capacity_safe")
        .tempdir()
        .expect("tempdir");
    fs::create_dir_all(root.path()).expect("dir created");

    let mut manager = Manager::singleton().write().unwrap();

    let p = root.path();
    assert!(manager.get(p).expect("success").is_none());

    let created_arc = manager
        .get_or_create_with_capacity(p, 10, Rkv::with_capacity::<SafeMode>)
        .expect("created");
    let fetched_arc = manager.get(p).expect("success").expect("existed");
    assert!(Arc::ptr_eq(&created_arc, &fetched_arc));
}

/// Some storage drivers are able to discard when the database is corrupted at runtime.
/// Test how these managers can discard corrupted databases and re-open.
#[test]
fn test_safe_mode_corrupt_while_open_1() {
    type Manager = rkv::Manager<SafeModeEnvironment>;

    let root = Builder::new()
        .prefix("test_safe_mode_corrupt_while_open_1")
        .tempdir()
        .expect("tempdir");
    fs::create_dir_all(root.path()).expect("dir created");

    // Create environment.
    let mut manager = Manager::singleton().write().unwrap();
    let shared_env = manager
        .get_or_create(root.path(), Rkv::new::<SafeMode>)
        .expect("created");
    let env = shared_env.read().unwrap();

    // Write some data.
    let store = env
        .open_single("store", StoreOptions::create())
        .expect("opened");
    let mut writer = env.write().expect("writer");
    store
        .put(&mut writer, "foo", &Value::I64(1234))
        .expect("wrote");
    store
        .put(&mut writer, "bar", &Value::Bool(true))
        .expect("wrote");
    store
        .put(&mut writer, "baz", &Value::Str("héllo, yöu"))
        .expect("wrote");
    writer.commit().expect("committed");
    env.sync(true).expect("synced");

    // Verify it was flushed to disk.
    let mut safebin = root.path().to_path_buf();
    safebin.push("data.safe.bin");
    assert!(safebin.exists());

    // Oops, corruption.
    fs::write(&safebin, "bogus").expect("dbfile corrupted");

    // Close everything.
    drop(env);
    drop(shared_env);
    manager
        .try_close(root.path(), CloseOptions::default())
        .expect("closed without deleting");
    assert!(manager.get(root.path()).expect("success").is_none());

    // Recreating environment fails.
    manager
        .get_or_create(root.path(), Rkv::new::<SafeMode>)
        .expect_err("not created");
    assert!(manager.get(root.path()).expect("success").is_none());

    // But we can use a builder and pass `discard_if_corrupted` to deal with it.
    let mut builder = Rkv::environment_builder::<SafeMode>();
    builder.set_corruption_recovery_strategy(RecoveryStrategy::Discard);
    manager
        .get_or_create_from_builder(root.path(), builder, Rkv::from_builder::<SafeMode>)
        .expect("created");
    assert!(manager.get(root.path()).expect("success").is_some());
}

/// Some storage drivers are able to recover when the database is corrupted at runtime.
/// Test how these managers can recover corrupted databases while open.
#[test]
fn test_safe_mode_corrupt_while_open_2() {
    type Manager = rkv::Manager<SafeModeEnvironment>;

    let root = Builder::new()
        .prefix("test_safe_mode_corrupt_while_open_2")
        .tempdir()
        .expect("tempdir");
    fs::create_dir_all(root.path()).expect("dir created");

    // Create environment.
    let mut manager = Manager::singleton().write().unwrap();
    let shared_env = manager
        .get_or_create(root.path(), Rkv::new::<SafeMode>)
        .expect("created");
    let env = shared_env.read().unwrap();

    // Write some data.
    let store = env
        .open_single("store", StoreOptions::create())
        .expect("opened");
    let mut writer = env.write().expect("writer");
    store
        .put(&mut writer, "foo", &Value::I64(1234))
        .expect("wrote");
    store
        .put(&mut writer, "bar", &Value::Bool(true))
        .expect("wrote");
    store
        .put(&mut writer, "baz", &Value::Str("héllo, yöu"))
        .expect("wrote");
    writer.commit().expect("committed");
    env.sync(true).expect("synced");

    // Verify it was flushed to disk.
    let mut safebin = root.path().to_path_buf();
    safebin.push("data.safe.bin");
    assert!(safebin.exists());

    // Oops, corruption.
    fs::write(&safebin, "bogus").expect("dbfile corrupted");

    // Reading still works. Magic.
    let store = env
        .open_single("store", StoreOptions::default())
        .expect("opened");
    let reader = env.read().expect("reader");
    assert_eq!(
        store.get(&reader, "foo").expect("read"),
        Some(Value::I64(1234))
    );
    assert_eq!(
        store.get(&reader, "bar").expect("read"),
        Some(Value::Bool(true))
    );
    assert_eq!(
        store.get(&reader, "baz").expect("read"),
        Some(Value::Str("héllo, yöu"))
    );
    reader.abort();

    // Writing still works, dbfile will be un-corrupted.
    let store = env
        .open_single("store", StoreOptions::default())
        .expect("opened");
    let mut writer = env.write().expect("writer");
    store
        .put(&mut writer, "foo2", &Value::I64(5678))
        .expect("wrote");
    store
        .put(&mut writer, "bar2", &Value::Bool(false))
        .expect("wrote");
    store
        .put(&mut writer, "baz2", &Value::Str("byé, yöu"))
        .expect("wrote");
    writer.commit().expect("committed");
    env.sync(true).expect("synced");

    // Close everything.
    drop(env);
    drop(shared_env);
    manager
        .try_close(root.path(), CloseOptions::default())
        .expect("closed without deleting");
    assert!(manager.get(root.path()).expect("success").is_none());

    // Recreate environment.
    let shared_env = manager
        .get_or_create(root.path(), Rkv::new::<SafeMode>)
        .expect("created");
    let env = shared_env.read().unwrap();

    // Verify that the dbfile is not corrupted.
    let store = env
        .open_single("store", StoreOptions::default())
        .expect("opened");
    let reader = env.read().expect("reader");
    assert_eq!(
        store.get(&reader, "foo").expect("read"),
        Some(Value::I64(1234))
    );
    assert_eq!(
        store.get(&reader, "bar").expect("read"),
        Some(Value::Bool(true))
    );
    assert_eq!(
        store.get(&reader, "baz").expect("read"),
        Some(Value::Str("héllo, yöu"))
    );
    assert_eq!(
        store.get(&reader, "foo2").expect("read"),
        Some(Value::I64(5678))
    );
    assert_eq!(
        store.get(&reader, "bar2").expect("read"),
        Some(Value::Bool(false))
    );
    assert_eq!(
        store.get(&reader, "baz2").expect("read"),
        Some(Value::Str("byé, yöu"))
    );
}

/// Test how the manager can discard corrupted databases, while moving the corrupted one aside for
/// later inspection.
#[test]
fn test_safe_mode_corrupt_while_open_3() {
    type Manager = rkv::Manager<SafeModeEnvironment>;

    let root = Builder::new()
        .prefix("test_safe_mode_corrupt_while_open_3")
        .tempdir()
        .expect("tempdir");
    fs::create_dir_all(root.path()).expect("dir created");

    let mut safebin = root.path().to_path_buf();
    safebin.push("data.safe.bin");

    // Oops, corruption.
    fs::write(&safebin, "bogus").expect("dbfile corrupted");
    assert!(safebin.exists(), "Corrupted database file was written to");

    // Create environment.
    let mut manager = Manager::singleton().write().unwrap();

    // Recreating environment fails.
    manager
        .get_or_create(root.path(), Rkv::new::<SafeMode>)
        .expect_err("not created");
    assert!(manager.get(root.path()).expect("success").is_none());

    // But we can use a builder and pass `RecoveryStrategy::Rename` to deal with it.
    let mut builder = Rkv::environment_builder::<SafeMode>();
    builder.set_corruption_recovery_strategy(RecoveryStrategy::Rename);
    manager
        .get_or_create_from_builder(root.path(), builder, Rkv::from_builder::<SafeMode>)
        .expect("created");
    assert!(manager.get(root.path()).expect("success").is_some());

    assert!(!safebin.exists(), "Database file was moved out of the way");

    let mut corruptbin = root.path().to_path_buf();
    corruptbin.push("data.safe.bin.corrupt");
    assert!(corruptbin.exists(), "Corrupted database file exists");

    let shared_env = manager
        .get_or_create(root.path(), Rkv::new::<SafeMode>)
        .expect("created");
    let env = shared_env.read().unwrap();

    // Writing still works.
    let store = env
        .open_single("store", StoreOptions::create())
        .expect("opened");

    let reader = env.read().expect("reader");
    assert_eq!(store.get(&reader, "foo").expect("read"), None, "Nothing to be read");

    // We can write.
    let mut writer = env.write().expect("writer");
    store
        .put(&mut writer, "foo", &Value::I64(5678))
        .expect("wrote");
    writer.commit().expect("committed");
    env.sync(true).expect("synced");

    assert!(safebin.exists(), "Database file exists");

    // Close everything.
    drop(env);
    drop(shared_env);
    manager
        .try_close(root.path(), CloseOptions::default())
        .expect("closed without deleting");
    assert!(manager.get(root.path()).expect("success").is_none());

    // Recreate environment.
    let shared_env = manager
        .get_or_create(root.path(), Rkv::new::<SafeMode>)
        .expect("created");
    let env = shared_env.read().unwrap();

    // Verify that the dbfile is not corrupted.
    let store = env
        .open_single("store", StoreOptions::default())
        .expect("opened");
    let reader = env.read().expect("reader");
    assert_eq!(
        store.get(&reader, "foo").expect("read"),
        Some(Value::I64(5678)),
        "Database contains expected value"
    );
}

[ Dauer der Verarbeitung: 0.38 Sekunden  ]

                                                                                                                                                                                                                                                                                                                                                                                                     


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