@@ -27,6 +27,7 @@ use super::StateGroupEntry;
27
27
/// specific room.
28
28
///
29
29
/// Returns with the state_group map and the id of the last group that was used
30
+ /// Or None if there are no state groups within the range given
30
31
///
31
32
/// # Arguments
32
33
///
@@ -36,6 +37,8 @@ use super::StateGroupEntry;
36
37
/// * `min_state_group` - If specified, then only fetch the entries for state
37
38
/// groups greater than (but not equal) to this number. It
38
39
/// also requires groups_to_compress to be specified
40
+ /// * `max_state_group` - If specified, then only fetch the entries for state
41
+ /// groups lower than or equal to this number.
39
42
/// * 'groups_to_compress' - The number of groups to get from the database before stopping
40
43
41
44
pub fn get_data_from_db (
@@ -44,7 +47,7 @@ pub fn get_data_from_db(
44
47
min_state_group : Option < i64 > ,
45
48
groups_to_compress : Option < i64 > ,
46
49
max_state_group : Option < i64 > ,
47
- ) -> ( BTreeMap < i64 , StateGroupEntry > , i64 ) {
50
+ ) -> Option < ( BTreeMap < i64 , StateGroupEntry > , i64 ) > {
48
51
// connect to the database
49
52
let mut builder = SslConnector :: builder ( SslMethod :: tls ( ) ) . unwrap ( ) ;
50
53
builder. set_verify ( SslVerifyMode :: NONE ) ;
@@ -53,16 +56,27 @@ pub fn get_data_from_db(
53
56
let mut client = Client :: connect ( db_url, connector)
54
57
. unwrap_or_else ( |e| panic ! ( "Error connecting to the database: {}" , e) ) ;
55
58
56
- let state_group_map: BTreeMap < i64 , StateGroupEntry > = BTreeMap :: new ( ) ;
59
+ // Search for the group id of the groups_to_compress'th group after min_state_group
60
+ // If this is saved, then the compressor can continue by having min_state_group being
61
+ // set to this maximum. If no such group can be found then return None.
57
62
58
- load_map_from_db (
63
+ let max_group_found = find_max_group (
59
64
& mut client,
60
65
room_id,
61
66
min_state_group,
62
67
groups_to_compress,
63
68
max_state_group,
69
+ ) ?;
70
+
71
+ let state_group_map: BTreeMap < i64 , StateGroupEntry > = BTreeMap :: new ( ) ;
72
+
73
+ Some ( load_map_from_db (
74
+ & mut client,
75
+ room_id,
76
+ min_state_group,
77
+ max_group_found,
64
78
state_group_map,
65
- )
79
+ ) )
66
80
}
67
81
68
82
/// Fetch the entries in state_groups_state (and their prev groups) for a
@@ -71,6 +85,7 @@ pub fn get_data_from_db(
71
85
/// of each of the levels (as they were at the end of the last run of the compressor)
72
86
///
73
87
/// Returns with the state_group map and the id of the last group that was used
88
+ /// Or None if there are no state groups within the range given
74
89
///
75
90
/// # Arguments
76
91
///
@@ -81,8 +96,6 @@ pub fn get_data_from_db(
81
96
/// groups greater than (but not equal) to this number. It
82
97
/// also requires groups_to_compress to be specified
83
98
/// * 'groups_to_compress' - The number of groups to get from the database before stopping
84
- /// * `max_state_group` - If specified, then only fetch the entries for state
85
- /// groups lower than or equal to this number.
86
99
/// * 'level_info' - The maximum size, current length and current head for each
87
100
/// level (as it was when the compressor last finished for this
88
101
/// room)
@@ -92,7 +105,7 @@ pub fn reload_data_from_db(
92
105
min_state_group : Option < i64 > ,
93
106
groups_to_compress : Option < i64 > ,
94
107
level_info : & [ Level ] ,
95
- ) -> ( BTreeMap < i64 , StateGroupEntry > , i64 ) {
108
+ ) -> Option < ( BTreeMap < i64 , StateGroupEntry > , i64 ) > {
96
109
// connect to the database
97
110
let mut builder = SslConnector :: builder ( SslMethod :: tls ( ) ) . unwrap ( ) ;
98
111
builder. set_verify ( SslVerifyMode :: NONE ) ;
@@ -101,20 +114,30 @@ pub fn reload_data_from_db(
101
114
let mut client = Client :: connect ( db_url, connector)
102
115
. unwrap_or_else ( |e| panic ! ( "Error connecting to the database: {}" , e) ) ;
103
116
117
+ // Search for the group id of the groups_to_compress'th group after min_state_group
118
+ // If this is saved, then the compressor can continue by having min_state_group being
119
+ // set to this maximum.If no such group can be found then return None.
120
+ let max_group_found = find_max_group (
121
+ & mut client,
122
+ room_id,
123
+ min_state_group,
124
+ groups_to_compress,
125
+ // max state group not used when saving and loading
126
+ None ,
127
+ ) ?;
128
+
104
129
// load just the state_groups at the head of each level
105
130
// this doesn't load their predecessors as that will be done at the end of
106
131
// load_map_from_db()
107
132
let state_group_map: BTreeMap < i64 , StateGroupEntry > = load_level_heads ( & mut client, level_info) ;
108
133
109
- load_map_from_db (
134
+ Some ( load_map_from_db (
110
135
& mut client,
111
136
room_id,
112
137
min_state_group,
113
- groups_to_compress,
114
- // max state group not used when saving and loading
115
- None ,
138
+ max_group_found,
116
139
state_group_map,
117
- )
140
+ ) )
118
141
}
119
142
120
143
/// Finds the state_groups that are at the head of each compressor level
@@ -181,28 +204,16 @@ fn load_level_heads(client: &mut Client, level_info: &[Level]) -> BTreeMap<i64,
181
204
/// * `min_state_group` - If specified, then only fetch the entries for state
182
205
/// groups greater than (but not equal) to this number. It
183
206
/// also requires groups_to_compress to be specified
184
- /// * 'groups_to_compress ' - The number of groups to get from the database before stopping
207
+ /// * 'max_group_found ' - The last group to get from the database before stopping
185
208
/// * 'state_group_map' - The map to populate with the entries from the database
186
209
187
210
fn load_map_from_db (
188
211
client : & mut Client ,
189
212
room_id : & str ,
190
213
min_state_group : Option < i64 > ,
191
- groups_to_compress : Option < i64 > ,
192
- max_state_group : Option < i64 > ,
214
+ max_group_found : i64 ,
193
215
mut state_group_map : BTreeMap < i64 , StateGroupEntry > ,
194
216
) -> ( BTreeMap < i64 , StateGroupEntry > , i64 ) {
195
- // Search for the group id of the groups_to_compress'th group after min_state_group
196
- // If this is saved, then the compressor can continue by having min_state_group being
197
- // set to this maximum
198
- let max_group_found = find_max_group (
199
- client,
200
- room_id,
201
- min_state_group,
202
- groups_to_compress,
203
- max_state_group,
204
- ) ;
205
-
206
217
state_group_map. append ( & mut get_initial_data_from_db (
207
218
client,
208
219
room_id,
@@ -261,7 +272,8 @@ fn load_map_from_db(
261
272
/// Returns the group ID of the last group to be compressed
262
273
///
263
274
/// This can be saved so that future runs of the compressor only
264
- /// continue from after this point
275
+ /// continue from after this point. If no groups can be found in
276
+ /// the range specified it returns None.
265
277
///
266
278
/// # Arguments
267
279
///
@@ -276,7 +288,7 @@ fn find_max_group(
276
288
min_state_group : Option < i64 > ,
277
289
groups_to_compress : Option < i64 > ,
278
290
max_state_group : Option < i64 > ,
279
- ) -> i64 {
291
+ ) -> Option < i64 > {
280
292
// Get list of state_id's in a certain room
281
293
let mut query_chunk_of_ids = "SELECT id FROM state_groups WHERE room_id = $1" . to_string ( ) ;
282
294
let params: Vec < & ( dyn ToSql + Sync ) > ;
@@ -285,22 +297,33 @@ fn find_max_group(
285
297
query_chunk_of_ids = format ! ( "{} AND id <= {}" , query_chunk_of_ids, max)
286
298
}
287
299
288
- // Adds additional constraint if a groups_to_compress has been specified
300
+ // Adds additional constraint if a groups_to_compress or min_state_group have been specified
301
+ // Note a min state group is only used if groups_to_compress also is
289
302
if min_state_group. is_some ( ) && groups_to_compress. is_some ( ) {
290
303
params = vec ! [ & room_id, & min_state_group, & groups_to_compress] ;
291
304
query_chunk_of_ids = format ! ( r"{} AND id > $2 LIMIT $3" , query_chunk_of_ids) ;
305
+ } else if groups_to_compress. is_some ( ) {
306
+ params = vec ! [ & room_id, & groups_to_compress] ;
307
+ query_chunk_of_ids = format ! ( r"{} LIMIT $2" , query_chunk_of_ids) ;
292
308
} else {
293
309
params = vec ! [ & room_id] ;
294
- query_chunk_of_ids = format ! ( r"{} ORDER BY id DESC LIMIT 1" , query_chunk_of_ids) ;
295
310
}
296
311
297
312
let sql_query = format ! (
298
313
"SELECT id FROM ({}) AS ids ORDER BY ids.id DESC LIMIT 1" ,
299
314
query_chunk_of_ids
300
315
) ;
301
- let final_row = client. query ( sql_query. as_str ( ) , & params) . unwrap ( ) ;
302
316
303
- final_row. last ( ) . unwrap ( ) . get ( 0 )
317
+ // This vector should have length 0 or 1
318
+ let rows = client
319
+ . query ( sql_query. as_str ( ) , & params)
320
+ . expect ( "Something went wrong while querying the database" ) ;
321
+
322
+ // If no row can be found then return None
323
+ let final_row = rows. last ( ) ?;
324
+
325
+ // Else return the id of the group found
326
+ Some ( final_row. get :: < _ , i64 > ( 0 ) )
304
327
}
305
328
306
329
/// Fetch the entries in state_groups_state and immediate predecessors for
@@ -330,22 +353,18 @@ fn get_initial_data_from_db(
330
353
FROM state_groups AS m
331
354
LEFT JOIN state_groups_state AS s ON (m.id = s.state_group)
332
355
LEFT JOIN state_group_edges AS e ON (m.id = e.state_group)
333
- WHERE m.room_id = $1
356
+ WHERE m.room_id = $1 AND m.id <= $2
334
357
"# ;
335
358
336
359
// Adds additional constraint if minimum state_group has been specified.
337
- // note that the maximum group only affects queries if there is also a minimum
338
- // otherwise it is assumed that ALL groups should be fetched
339
360
let mut rows = if let Some ( min) = min_state_group {
340
- let params: Vec < & dyn ToSql > = vec ! [ & room_id, & min, & max_group_found] ;
341
- client. query_raw (
342
- format ! ( r"{} AND m.id > $2 AND m.id <= $3" , sql) . as_str ( ) ,
343
- params,
344
- )
361
+ let params: Vec < & dyn ToSql > = vec ! [ & room_id, & max_group_found, & min] ;
362
+ client. query_raw ( format ! ( r"{} AND m.id > $3" , sql) . as_str ( ) , params)
345
363
} else {
346
- client. query_raw ( sql, & [ room_id] )
364
+ let params: Vec < & dyn ToSql > = vec ! [ & room_id, & max_group_found] ;
365
+ client. query_raw ( sql, params)
347
366
}
348
- . unwrap ( ) ;
367
+ . expect ( "Something went wrong while querying the database" ) ;
349
368
350
369
// Copy the data from the database into a map
351
370
let mut state_group_map: BTreeMap < i64 , StateGroupEntry > = BTreeMap :: new ( ) ;
@@ -481,13 +500,16 @@ fn test_pg_escape() {
481
500
assert_eq ! ( & s[ start_pos - 1 ..start_pos] , "$" ) ;
482
501
}
483
502
503
+ /// Send changes to the database
504
+ ///
484
505
/// Note that currently ignores config.transactions and wraps every state
485
506
/// group in it's own transaction (i.e. as if config.transactions was true)
486
507
///
487
508
/// # Arguments
488
509
///
489
- /// * `config` - A Config struct that contains information
490
- /// about the run (e.g. room_id and database url)
510
+ /// * `db_url` - The URL of a Postgres database. This should be of the
511
+ /// form: "postgresql://user:pass@domain:port/database"
512
+ /// * `room_id` - The ID of the room in the database
491
513
/// * `old_map` - The state group data originally in the database
492
514
/// * `new_map` - The state group data generated by the compressor to
493
515
/// replace replace the old contents
0 commit comments