4个版本

0.2.1 2021年12月21日
0.2.0 2021年11月11日
0.1.1 2021年2月19日
0.1.0 2021年2月19日

#73 in 数据库实现

MIT许可证

400KB
9K SLoC

DB-Core

Rust

具有ACID保证的极简无模式数据库管理系统。

当前状态:进行中(详细信息请见路线图部分)

用法

客户端应用程序创建db-core的一个实例。当实例创建时,它打开数据存储,初始化其内部组件,并从最后一个检查点恢复状态。使用创建的实例,客户端应用程序可以发起事务,创建或打开现有对象,读写数据,删除对象,然后提交或回滚更改。实例可以被克隆并移动到多线程应用程序中的其他线程。最后,应用程序可以关闭所有实例。

数据库初始化(这是一个一次性操作)

use db_core::instance::Instance;
use db_core::FileState;
use db_core::FileType;
use db_core::FileDesc;
use db_core::instance::Read;
use db_core::instance::Write;
use db_core::config::ConfigMt;
use std::path::Path;



// Block size for the database.
let block_size = 8192;


// Create an empty directory for the database files.
let dspath = "/tmp/db-core-test-db";
if Path::new(dspath).exists() {
    std::fs::remove_dir_all(dspath).expect("Failed to delete test dir on cleanup");
}
std::fs::create_dir(dspath).expect("Failed to create test dir");

// Transaction log directory.
let log_dir = "/tmp/db-core-test-tranlog";
if Path::new(log_dir).exists() {
    std::fs::remove_dir_all(log_dir).expect("Failed to delete test dir on cleanup");
}
std::fs::create_dir(log_dir).expect("Failed to create test dir");


// Define initial database files. There should be at least one file of each type (data store,
// versioning store, checkpont store). 
let mut fdset = vec![];
let desc1 = FileDesc {
    state:          FileState::InUse,
    file_id:        3,
    extent_size:    16,
    extent_num:     3,
    max_extent_num: 65500,
    file_type:      FileType::DataStoreFile,
};
let desc2 = FileDesc {
    state:          FileState::InUse,
    file_id:        4,
    extent_size:    10,
    extent_num:     3,
    max_extent_num: 65500,
    file_type:      FileType::VersioningStoreFile,
};
let desc3 = FileDesc {
    state:          FileState::InUse,
    file_id:        5,
    extent_size:    10,
    extent_num:     3,
    max_extent_num: 65500,
    file_type:      FileType::CheckpointStoreFile,
};

fdset.push(desc1);
fdset.push(desc2);
fdset.push(desc3);

// Create a database.
Instance::initialize_datastore(dspath, block_size, &fdset).expect("Failed to init datastore");

实例启动和终止,事务管理,读写数据

// Some random data.
let data = b"Hello, world!";


// Prepare configuration.
let conf = ConfigMt::new();
let mut c = conf.get_conf();
c.set_log_dir(log_dir.to_owned());
c.set_datastore_path(dspath.to_owned());
drop(c);

// Start instance and open existing database.
let instance = Instance::new(conf.clone()).expect("Failed to create instance");

// Begin transaction.
let mut trn = instance.begin_transaction().expect("Failed to begin transaction");

// Create a new object.
let file_id = 3;
let mut obj = instance.open_create(file_id, &mut trn, data.len()).expect("Failed to create object");
let obj_id = obj.get_id();

// Write some data.
obj.write_next(data).expect("Failed to write");
drop(obj);

// Commit transaction.
instance.commit(trn).expect("Failed to commit");

// Begin transaction.
let mut trn = instance.begin_transaction().expect("Failed to begin transaction");

// Open object for reading and read some data.
let mut obj = instance.open_read(&obj_id, &trn).expect("Failed to open for reading");
let mut read_buf = vec![0u8;data.len()];
let mut read = 0;
let len = read_buf.len();
while read < len {
    let r = obj.read_next(&mut read_buf[read..len]).expect("Failed to read");
    if r == 0 {break;}
    read += r;
}
assert_eq!(read_buf, data);
drop(obj);

// Delete object (if object is in use wait for other transaction to finish for 1 second).
let wait_lock_ms = 1000;
instance.delete(&obj_id, &mut trn, wait_lock_ms).expect("Failed to delete object");

// Rollback transaction.
instance.rollback(trn).expect("Failed to rollback");

// Spawn another instance in a different thread.
let ss = instance.get_shared_state().expect("Failed to get shared state");

let th = std::thread::spawn(move || {
    let instance2 = Instance::from_shared_state(ss).expect("Failed to create instance");
    // ...
    instance2.terminate();
});

// Add a database file.
let new_file_id = instance.add_datafile(FileType::DataStoreFile, 1000, 10, 1000).expect("Failed to add data file");

// Terminate instance.
instance.terminate();

路线图

  1. 允许直接在块设备上存储数据。
  2. 实现真空操作。
  3. 添加更多测试。

有关详细信息,请参阅问题

贡献

欢迎贡献!请参阅CONTRIBUTING.md以获取详细信息。

依赖关系