semilattice_database_session/
session.rs

1mod data;
2mod operation;
3mod relation;
4mod search;
5mod sequence;
6mod sort;
7mod temporary_data;
8
9pub use data::SessionData;
10pub use operation::{Depends, Pend, SessionOperation, SessionRecord};
11pub use search::SessionSearchResult;
12use semilattice_database::{FieldName, Fields};
13pub use sort::{SessionCustomOrder, SessionOrder, SessionOrderKey};
14pub use temporary_data::{TemporaryData, TemporaryDataEntity};
15
16use std::{io::Write, path::Path};
17
18use crate::{CollectionRow, Depend, Field, IdxFile, SessionDatabase};
19
20use relation::SessionRelation;
21use sequence::SequenceNumber;
22use serde::Serialize;
23
24use self::sequence::SequenceCursor;
25
26#[derive(Serialize)]
27pub struct SessionInfo {
28    pub(super) name: String,
29    pub(super) access_at: u64,
30    pub(super) expire: i64,
31}
32
33impl SessionInfo {
34    pub fn name(&self) -> &str {
35        &self.name
36    }
37    pub fn access_at(&self) -> u64 {
38        self.access_at
39    }
40    pub fn expire(&self) -> i64 {
41        self.expire
42    }
43}
44
45pub struct Session {
46    name: String,
47    pub(super) session_data: Option<SessionData>,
48    pub(super) temporary_data: TemporaryData,
49}
50impl Session {
51    pub(super) fn new(
52        main_database: &SessionDatabase,
53        name: impl Into<String>,
54        expire_interval_sec: Option<i64>,
55    ) -> Self {
56        let mut name: String = name.into();
57        assert!(name != "");
58        if name == "" {
59            name = "untitiled".to_owned();
60        }
61        let session_dir = main_database.session_dir(&name);
62        if !session_dir.exists() {
63            std::fs::create_dir_all(&session_dir).unwrap();
64        }
65        let session_data = Self::new_data(&session_dir, expire_interval_sec);
66        let temporary_data = session_data.init_temporary_data();
67        Self {
68            name,
69            session_data: Some(session_data),
70            temporary_data,
71        }
72    }
73
74    pub fn name(&self) -> &str {
75        &self.name
76    }
77
78    pub fn set_sequence_cursor(&mut self, current: usize) {
79        if let Some(session_data) = &mut self.session_data {
80            session_data.sequence_number.set_current(current);
81        }
82    }
83
84    pub fn sequence_cursor(&self) -> Option<SequenceCursor> {
85        self.session_data
86            .as_ref()
87            .map(|session_data| SequenceCursor {
88                max: session_data.sequence_number.max(),
89                current: session_data.sequence_number.current(),
90            })
91    }
92
93    pub fn new_data(session_dir: &Path, expire_interval_sec: Option<i64>) -> SessionData {
94        let mut access = session_dir.to_path_buf();
95        access.push("expire");
96        let mut file = std::fs::OpenOptions::new()
97            .create(true)
98            .write(true)
99            .open(access)
100            .unwrap();
101        let expire = expire_interval_sec.unwrap_or(-1);
102        file.write(&expire.to_be_bytes()).unwrap();
103
104        let mut fields = Fields::new();
105        let mut fields_dir = session_dir.to_path_buf();
106        fields_dir.push("fields");
107        if !fields_dir.exists() {
108            std::fs::create_dir_all(&fields_dir.to_owned()).unwrap();
109        }
110        for p in fields_dir.read_dir().unwrap().into_iter() {
111            let p = p.unwrap();
112            let path = p.path();
113            if path.is_dir() {
114                if let Some(fname) = p.file_name().to_str() {
115                    let field = Field::new(path, 1);
116                    fields.insert(FieldName::new(fname.into()), field);
117                }
118            }
119        }
120
121        SessionData {
122            sequence_number: SequenceNumber::new({
123                let mut path = session_dir.to_path_buf();
124                path.push("sequence_number.i");
125                path
126            }),
127            sequence: IdxFile::new(
128                {
129                    let mut path = session_dir.to_path_buf();
130                    path.push("sequence.i");
131                    path
132                },
133                1,
134            ),
135            collection_id: IdxFile::new(
136                {
137                    let mut path = session_dir.to_path_buf();
138                    path.push("collection_id.i");
139                    path
140                },
141                1,
142            ),
143            row: IdxFile::new(
144                {
145                    let mut path = session_dir.to_path_buf();
146                    path.push("row.i");
147                    path
148                },
149                1,
150            ),
151            operation: IdxFile::new(
152                {
153                    let mut path = session_dir.to_path_buf();
154                    path.push("operation.i");
155                    path
156                },
157                1,
158            ),
159            activity: IdxFile::new(
160                {
161                    let mut path = session_dir.to_path_buf();
162                    path.push("activity.i");
163                    path
164                },
165                1,
166            ),
167            term_begin: IdxFile::new(
168                {
169                    let mut path = session_dir.to_path_buf();
170                    path.push("term_begin.i");
171                    path
172                },
173                1,
174            ),
175            term_end: IdxFile::new(
176                {
177                    let mut path = session_dir.to_path_buf();
178                    path.push("term_end.i");
179                    path
180                },
181                1,
182            ),
183            uuid: IdxFile::new(
184                {
185                    let mut path = session_dir.to_path_buf();
186                    path.push("uuid.i");
187                    path
188                },
189                1,
190            ),
191            fields,
192            relation: SessionRelation::new(session_dir, 1),
193        }
194    }
195}