db_core/
lib.rs

1//! Minimal schema-less database management system with ACID guaranties.
2//!
3//! # Examples
4//!
5//! ```
6//! use db_core::instance::Instance;
7//! use db_core::FileState;
8//! use db_core::FileType;
9//! use db_core::FileDesc;
10//! use db_core::instance::Read;
11//! use db_core::instance::Write;
12//! use db_core::config::ConfigMt;
13//! use std::path::Path;
14//!
15//!
16//! //
17//! // Database initialization (this is one-time action).
18//! // 
19//!
20//!
21//! // Block size for the database.
22//! let block_size = 8192;
23//!
24//!
25//! // Create an empty directory for the database files.
26//! let dspath = "/tmp/db-core-test-db";
27//! if Path::new(dspath).exists() {
28//!     std::fs::remove_dir_all(dspath).expect("Failed to delete test dir on cleanup");
29//! }
30//! std::fs::create_dir(dspath).expect("Failed to create test dir");
31//!
32//! // Transaction log directory.
33//! let log_dir = "/tmp/db-core-test-tranlog";
34//! if Path::new(log_dir).exists() {
35//!     std::fs::remove_dir_all(log_dir).expect("Failed to delete test dir on cleanup");
36//! }
37//! std::fs::create_dir(log_dir).expect("Failed to create test dir");
38//!
39//!
40//! // Define initial database files. There should be at least one file of each type (data store,
41//! // versioning store, checkpont store). 
42//! let mut fdset = vec![];
43//! let desc1 = FileDesc {
44//!     state:          FileState::InUse,
45//!     file_id:        3,
46//!     extent_size:    16,
47//!     extent_num:     3,
48//!     max_extent_num: 65500,
49//!     file_type:      FileType::DataStoreFile,
50//! };
51//! let desc2 = FileDesc {
52//!     state:          FileState::InUse,
53//!     file_id:        4,
54//!     extent_size:    10,
55//!     extent_num:     3,
56//!     max_extent_num: 65500,
57//!     file_type:      FileType::VersioningStoreFile,
58//! };
59//! let desc3 = FileDesc {
60//!     state:          FileState::InUse,
61//!     file_id:        5,
62//!     extent_size:    10,
63//!     extent_num:     3,
64//!     max_extent_num: 65500,
65//!     file_type:      FileType::CheckpointStoreFile,
66//! };
67//!
68//! fdset.push(desc1);
69//! fdset.push(desc2);
70//! fdset.push(desc3);
71//!
72//! // Create a database.
73//! Instance::initialize_datastore(dspath, block_size, &fdset).expect("Failed to init datastore");
74//!
75//!
76//! //
77//! // Startup and termination, transaction management, read and write data.
78//! //
79//!
80//!
81//! // Some random data.
82//! let data = b"Hello, world!";
83//!
84//!
85//! // Prepare configuration.
86//! let conf = ConfigMt::new();
87//! let mut c = conf.get_conf();
88//! c.set_log_dir(log_dir.to_owned());
89//! c.set_datastore_path(dspath.to_owned());
90//! drop(c);
91//!
92//! // Start instance and open existing database.
93//! let instance = Instance::new(conf.clone()).expect("Failed to create instance");
94//!
95//! // Begin transaction.
96//! let mut trn = instance.begin_transaction().expect("Failed to begin transaction");
97//!
98//! // Create a new object.
99//! let file_id = 3;
100//! let mut obj = instance.open_create(file_id, &mut trn, data.len()).expect("Failed to create object");
101//! let obj_id = obj.get_id();
102//!
103//! // Write some data.
104//! obj.write_next(data).expect("Failed to write");
105//! drop(obj);
106//!
107//! // Commit transaction.
108//! instance.commit(trn).expect("Failed to commit");
109//!
110//! // Begin transaction.
111//! let mut trn = instance.begin_transaction().expect("Failed to begin transaction");
112//!
113//! // Open object for reading and read some data.
114//! let mut obj = instance.open_read(&obj_id, &trn).expect("Failed to open for reading");
115//! let mut read_buf = vec![0u8;data.len()];
116//! let mut read = 0;
117//! let len = read_buf.len();
118//! while read < len {
119//!     let r = obj.read_next(&mut read_buf[read..len]).expect("Failed to read");
120//!     if r == 0 {break;}
121//!     read += r;
122//! }
123//! assert_eq!(read_buf, data);
124//! drop(obj);
125//!
126//! // Delete object (if object is in use wait for other transaction to finish for 1 second).
127//! let wait_lock_ms = 1000;
128//! instance.delete(&obj_id, &mut trn, wait_lock_ms).expect("Failed to delete object");
129//!
130//! // Rollback transaction.
131//! instance.rollback(trn).expect("Failed to rollback");
132//!
133//! // Spawn another instance in a different thread.
134//! let ss = instance.get_shared_state().expect("Failed to get shared state");
135//!
136//! let th = std::thread::spawn(move || {
137//!     let instance2 = Instance::from_shared_state(ss).expect("Failed to create instance");
138//!     // ...
139//!     instance2.terminate();
140//! });
141//!
142//! // Add a database file.
143//! let new_file_id = instance.add_datafile(FileType::DataStoreFile, 1000, 10, 1000).expect("Failed to add data file");
144//!
145//! // Terminate instance.
146//! instance.terminate();
147//!
148//! ```
149//!
150//! ### Notes.
151//!
152//! 1. Block size is defined at the moment of database creation and can't be changed later.
153//! 2. Each `file_id` must be unique. `file_id` 0, 1, and 2 are reserved and can't be used.
154//!
155
156mod buf_mgr;
157mod common;
158mod log_mgr;
159mod storage;
160mod system;
161mod tran_mgr;
162mod block_mgr;
163
164pub use system::config;
165pub use system::instance;
166pub use common::errors;
167
168pub use common::defs::ObjectId;
169pub use common::defs::SeekFrom;
170pub use storage::datastore::FileState;
171pub use storage::datastore::FileType;
172pub use storage::datastore::FileDesc;
173