semilattice_database_session/
session.rs1mod 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}