1
use std::io::{Read, Write};
2

            
3
use bonsaidb_core::connection::Connection;
4
use bonsaidb_core::schema::{CollectionName, Qualified, Schema, SchemaName, Schematic};
5
use bonsaidb_files::{BonsaiFiles, FileConfig};
6
use bonsaidb_local::config::{Builder, StorageConfiguration};
7
use bonsaidb_local::Database;
8

            
9
#[derive(Debug)]
10
enum MultipleConfigs {}
11

            
12
impl Schema for MultipleConfigs {
13
5
    fn schema_name() -> SchemaName {
14
5
        SchemaName::private("multiple-configs")
15
5
    }
16

            
17
    fn define_collections(schema: &mut Schematic) -> Result<(), bonsaidb_core::Error> {
18
2
        BonsaiFiles::register_collections(schema)?;
19
2
        ProcessedFiles::register_collections(schema)?;
20

            
21
2
        Ok(())
22
2
    }
23
}
24

            
25
#[derive(Debug)]
26
enum ProcessedFiles {}
27

            
28
impl FileConfig for ProcessedFiles {
29
    type Metadata = ();
30

            
31
    const BLOCK_SIZE: usize = 16_384;
32

            
33
26
    fn files_name() -> CollectionName {
34
26
        CollectionName::private("processed-files")
35
26
    }
36

            
37
9
    fn blocks_name() -> CollectionName {
38
9
        CollectionName::private("processed-file-blocks")
39
9
    }
40
}
41

            
42
1
#[cfg_attr(test, test)]
43
1
fn main() -> anyhow::Result<()> {
44
1
    let database =
45
1
        Database::open::<MultipleConfigs>(StorageConfiguration::new("file-configs.bonsaidb"))?;
46

            
47
1
    cleanup_old_job(&database)?;
48
    // When using two separate configurations where the `CollectionName`s are
49
    // unique, we can have two unique "filesystems" stored within a single
50
    // database.
51
    //
52
    // This could be used to store files that need to be processed in one
53
    // location while storing the processed results in another location.
54
1
    BonsaiFiles::build("job1")
55
1
        .contents(b"some contents")
56
1
        .create(&database)?;
57

            
58
1
    process_file("/job1", &database)?;
59

            
60
1
    Ok(())
61
1
}
62

            
63
1
fn process_file<Database: Connection + Clone>(
64
1
    path: &str,
65
1
    database: &Database,
66
1
) -> anyhow::Result<()> {
67
1
    let input_file = BonsaiFiles::load(path, database)?.expect("Input file not found");
68
1
    let mut output_file = ProcessedFiles::build(path).create(database)?;
69

            
70
1
    if let Err(err) = process_input(input_file.contents()?, output_file.append_buffered()) {
71
        output_file.delete()?;
72
        anyhow::bail!(err);
73
1
    }
74
1

            
75
1
    Ok(())
76
1
}
77

            
78
1
fn process_input<Reader: Read, Writer: Write>(
79
1
    mut input: Reader,
80
1
    mut output: Writer,
81
1
) -> std::io::Result<u64> {
82
1
    // This could be something other than a simple copy.
83
1
    std::io::copy(&mut input, &mut output)
84
1
}
85

            
86
1
fn cleanup_old_job<Database: Connection + Clone>(database: &Database) -> anyhow::Result<()> {
87
1
    if let Some(file) = BonsaiFiles::load("/job1", database)? {
88
        file.delete()?;
89
1
    }
90

            
91
1
    if let Some(file) = ProcessedFiles::load("/job1", database)? {
92
        file.delete()?;
93
1
    }
94
1
    Ok(())
95
1
}