1use std::{
11 collections::{BTreeSet, HashMap},
12 ops::Deref,
13 sync::{
14 atomic::{AtomicI64, Ordering},
15 Arc,
16 },
17 time::{SystemTime, UNIX_EPOCH},
18};
19
20use async_lock::{Semaphore, SemaphoreGuard};
21use futures::{future::join_all, StreamExt as _};
22use linera_base::{ensure, util::future::FutureSyncExt as _};
23use scylla::{
24 client::{
25 execution_profile::{ExecutionProfile, ExecutionProfileHandle},
26 session::Session,
27 session_builder::SessionBuilder,
28 },
29 deserialize::{DeserializationError, TypeCheckError},
30 errors::{
31 DbError, ExecutionError, IntoRowsResultError, NewSessionError, NextPageError, NextRowError,
32 PagerExecutionError, PrepareError, RequestAttemptError, RequestError, RowsError,
33 },
34 policies::{
35 load_balancing::{DefaultPolicy, LoadBalancingPolicy},
36 retry::DefaultRetryPolicy,
37 },
38 response::PagingState,
39 statement::{batch::BatchType, prepared::PreparedStatement, Consistency},
40 value::CqlValue,
41};
42use serde::{Deserialize, Serialize};
43use static_assertions as sa;
44use thiserror::Error;
45
46#[cfg(with_metrics)]
47use crate::metering::MeteredDatabase;
48#[cfg(with_testing)]
49use crate::store::TestKeyValueDatabase;
50use crate::{
51 batch::{SimpleUnorderedBatch, UnorderedBatch},
52 common::{get_uleb128_size, get_upper_bound_option},
53 journaling::{JournalingError, JournalingKeyValueDatabase},
54 lru_caching::{LruCachingConfig, LruCachingDatabase},
55 store::{
56 DirectWritableKeyValueStore, KeyValueDatabase, KeyValueStoreError, ReadableKeyValueStore,
57 WithError,
58 },
59};
60
61const MAX_MULTI_KEYS: usize = 100 - 1;
64
65const MAX_OPERATION_SIZE: usize = 16 * 1024 * 1024;
70
71const BATCH_STATEMENT_OVERHEAD: usize = 256;
74
75const RAW_MAX_VALUE_SIZE: usize =
78 MAX_OPERATION_SIZE - MAX_KEY_SIZE - MAX_BATCH_SIZE * BATCH_STATEMENT_OVERHEAD;
79const MAX_KEY_SIZE: usize = 10 * 1024;
80const MAX_BATCH_TOTAL_SIZE: usize = RAW_MAX_VALUE_SIZE + MAX_KEY_SIZE;
81
82sa::const_assert!(
84 MAX_BATCH_TOTAL_SIZE + MAX_BATCH_SIZE * BATCH_STATEMENT_OVERHEAD <= MAX_OPERATION_SIZE
85);
86
87const MAX_VALUE_SIZE: usize = RAW_MAX_VALUE_SIZE
100 - MAX_KEY_SIZE
101 - get_uleb128_size(RAW_MAX_VALUE_SIZE)
102 - get_uleb128_size(MAX_KEY_SIZE)
103 - 3;
104
105const MAX_BATCH_SIZE: usize = 5000;
108
109const KEYSPACE: &str = "kv";
111
112struct ScyllaDbClient {
117 session: Session,
118 namespace: String,
119 read_value: PreparedStatement,
120 read_writetime: PreparedStatement,
121 contains_key: PreparedStatement,
122 write_batch_delete_prefix_unbounded: PreparedStatement,
123 write_batch_delete_prefix_bounded: PreparedStatement,
124 write_batch_deletion: PreparedStatement,
125 write_batch_insertion: PreparedStatement,
126 write_batch_delete_prefix_unbounded_ts: PreparedStatement,
129 write_batch_delete_prefix_bounded_ts: PreparedStatement,
130 write_batch_deletion_ts: PreparedStatement,
131 write_batch_insertion_ts: PreparedStatement,
132 find_keys_by_prefix_unbounded: PreparedStatement,
133 find_keys_by_prefix_bounded: PreparedStatement,
134 find_key_values_by_prefix_unbounded: PreparedStatement,
135 find_key_values_by_prefix_bounded: PreparedStatement,
136 multi_key_values: papaya::HashMap<usize, PreparedStatement>,
137 multi_keys: papaya::HashMap<usize, PreparedStatement>,
138}
139
140impl ScyllaDbClient {
141 async fn new(session: Session, namespace: &str) -> Result<Self, ScyllaDbStoreInternalError> {
142 let namespace = namespace.to_string();
143 let read_value = session
144 .prepare(format!(
145 "SELECT v FROM {KEYSPACE}.\"{namespace}\" WHERE root_key = ? AND k = ?"
146 ))
147 .await?;
148
149 let read_writetime = session
150 .prepare(format!(
151 "SELECT WRITETIME(v) FROM {KEYSPACE}.\"{namespace}\" WHERE root_key = ? AND k = ?"
152 ))
153 .await?;
154
155 let contains_key = session
156 .prepare(format!(
157 "SELECT root_key FROM {KEYSPACE}.\"{namespace}\" WHERE root_key = ? AND k = ?"
158 ))
159 .await?;
160
161 let write_batch_delete_prefix_unbounded = session
162 .prepare(format!(
163 "DELETE FROM {KEYSPACE}.\"{namespace}\" WHERE root_key = ? AND k >= ?"
164 ))
165 .await?;
166
167 let write_batch_delete_prefix_bounded = session
168 .prepare(format!(
169 "DELETE FROM {KEYSPACE}.\"{namespace}\" WHERE root_key = ? AND k >= ? AND k < ?"
170 ))
171 .await?;
172
173 let write_batch_deletion = session
174 .prepare(format!(
175 "DELETE FROM {KEYSPACE}.\"{namespace}\" WHERE root_key = ? AND k = ?"
176 ))
177 .await?;
178
179 let write_batch_insertion = session
180 .prepare(format!(
181 "INSERT INTO {KEYSPACE}.\"{namespace}\" (root_key, k, v) VALUES (?, ?, ?)"
182 ))
183 .await?;
184
185 let write_batch_delete_prefix_unbounded_ts = session
190 .prepare(format!(
191 "DELETE FROM {KEYSPACE}.\"{namespace}\" USING TIMESTAMP ? WHERE root_key = ? AND k >= ?"
192 ))
193 .await?;
194
195 let write_batch_delete_prefix_bounded_ts = session
196 .prepare(format!(
197 "DELETE FROM {KEYSPACE}.\"{namespace}\" USING TIMESTAMP ? \
198 WHERE root_key = ? AND k >= ? AND k < ?"
199 ))
200 .await?;
201
202 let write_batch_deletion_ts = session
203 .prepare(format!(
204 "DELETE FROM {KEYSPACE}.\"{namespace}\" USING TIMESTAMP ? WHERE root_key = ? AND k = ?"
205 ))
206 .await?;
207
208 let write_batch_insertion_ts = session
209 .prepare(format!(
210 "INSERT INTO {KEYSPACE}.\"{namespace}\" (root_key, k, v) VALUES (?, ?, ?) \
211 USING TIMESTAMP ?"
212 ))
213 .await?;
214
215 let find_keys_by_prefix_unbounded = session
216 .prepare(format!(
217 "SELECT k FROM {KEYSPACE}.\"{namespace}\" WHERE root_key = ? AND k >= ?"
218 ))
219 .await?;
220
221 let find_keys_by_prefix_bounded = session
222 .prepare(format!(
223 "SELECT k FROM {KEYSPACE}.\"{namespace}\" WHERE root_key = ? AND k >= ? AND k < ?"
224 ))
225 .await?;
226
227 let find_key_values_by_prefix_unbounded = session
228 .prepare(format!(
229 "SELECT k,v FROM {KEYSPACE}.\"{namespace}\" WHERE root_key = ? AND k >= ?"
230 ))
231 .await?;
232
233 let find_key_values_by_prefix_bounded = session
234 .prepare(format!(
235 "SELECT k,v FROM {KEYSPACE}.\"{namespace}\" WHERE root_key = ? AND k >= ? AND k < ?"
236 ))
237 .await?;
238
239 Ok(Self {
240 session,
241 namespace,
242 read_value,
243 read_writetime,
244 contains_key,
245 write_batch_delete_prefix_unbounded,
246 write_batch_delete_prefix_bounded,
247 write_batch_deletion,
248 write_batch_insertion,
249 write_batch_delete_prefix_unbounded_ts,
250 write_batch_delete_prefix_bounded_ts,
251 write_batch_deletion_ts,
252 write_batch_insertion_ts,
253 find_keys_by_prefix_unbounded,
254 find_keys_by_prefix_bounded,
255 find_key_values_by_prefix_unbounded,
256 find_key_values_by_prefix_bounded,
257 multi_key_values: papaya::HashMap::new(),
258 multi_keys: papaya::HashMap::new(),
259 })
260 }
261
262 fn build_default_policy() -> Arc<dyn LoadBalancingPolicy> {
263 DefaultPolicy::builder().token_aware(true).build()
264 }
265
266 fn build_default_execution_profile_handle(
267 policy: Arc<dyn LoadBalancingPolicy>,
268 ) -> ExecutionProfileHandle {
269 let default_profile = ExecutionProfile::builder()
270 .load_balancing_policy(policy)
271 .retry_policy(Arc::new(DefaultRetryPolicy::new()))
272 .consistency(Consistency::LocalQuorum)
273 .build();
274 default_profile.into_handle()
275 }
276
277 async fn build_default_session(uri: &str) -> Result<Session, ScyllaDbStoreInternalError> {
278 SessionBuilder::new()
281 .known_node(uri)
282 .default_execution_profile_handle(Self::build_default_execution_profile_handle(
283 Self::build_default_policy(),
284 ))
285 .build()
286 .boxed_sync()
287 .await
288 .map_err(Into::into)
289 }
290
291 async fn get_multi_key_values_statement(
292 &self,
293 num_markers: usize,
294 ) -> Result<PreparedStatement, ScyllaDbStoreInternalError> {
295 if let Some(prepared_statement) = self.multi_key_values.pin().get(&num_markers) {
296 return Ok(prepared_statement.clone());
297 }
298 let markers = std::iter::repeat_n("?", num_markers)
299 .collect::<Vec<_>>()
300 .join(",");
301 let prepared_statement = self
302 .session
303 .prepare(format!(
304 "SELECT k,v FROM {}.\"{}\" WHERE root_key = ? AND k IN ({})",
305 KEYSPACE, self.namespace, markers
306 ))
307 .await?;
308 self.multi_key_values
309 .pin()
310 .insert(num_markers, prepared_statement.clone());
311 Ok(prepared_statement)
312 }
313
314 async fn get_multi_keys_statement(
315 &self,
316 num_markers: usize,
317 ) -> Result<PreparedStatement, ScyllaDbStoreInternalError> {
318 if let Some(prepared_statement) = self.multi_keys.pin().get(&num_markers) {
319 return Ok(prepared_statement.clone());
320 };
321 let markers = std::iter::repeat_n("?", num_markers)
322 .collect::<Vec<_>>()
323 .join(",");
324 let prepared_statement = self
325 .session
326 .prepare(format!(
327 "SELECT k FROM {}.\"{}\" WHERE root_key = ? AND k IN ({})",
328 KEYSPACE, self.namespace, markers
329 ))
330 .await?;
331 self.multi_keys
332 .pin()
333 .insert(num_markers, prepared_statement.clone());
334 Ok(prepared_statement)
335 }
336
337 fn check_key_size(key: &[u8]) -> Result<(), ScyllaDbStoreInternalError> {
338 ensure!(
339 key.len() <= MAX_KEY_SIZE,
340 ScyllaDbStoreInternalError::KeyTooLong
341 );
342 Ok(())
343 }
344
345 fn check_value_size(value: &[u8]) -> Result<(), ScyllaDbStoreInternalError> {
346 ensure!(
347 value.len() <= RAW_MAX_VALUE_SIZE,
348 ScyllaDbStoreInternalError::ValueTooLong
349 );
350 Ok(())
351 }
352
353 fn check_batch_key(key: &[u8]) -> Result<(), ScyllaDbStoreInternalError> {
359 Self::check_key_size(key)?;
360 ensure!(!key.is_empty(), ScyllaDbStoreInternalError::ZeroLengthKey);
361 Ok(())
362 }
363
364 fn check_batch_len(batch: &UnorderedBatch) -> Result<(), ScyllaDbStoreInternalError> {
365 ensure!(
366 batch.len() <= MAX_BATCH_SIZE,
367 ScyllaDbStoreInternalError::BatchTooLong
368 );
369 Ok(())
370 }
371
372 async fn read_value_internal(
373 &self,
374 root_key: &[u8],
375 key: Vec<u8>,
376 ) -> Result<Option<Vec<u8>>, ScyllaDbStoreInternalError> {
377 Self::check_key_size(&key)?;
378 let session = &self.session;
379 let values = (root_key.to_vec(), key);
381
382 let (result, _) = session
383 .execute_single_page(&self.read_value, &values, PagingState::start())
384 .await
385 .map_err(ScyllaDbStoreInternalError::ExecutionError)?;
386 let rows = result.into_rows_result()?;
387 let mut rows = rows.rows::<(Vec<u8>,)>()?;
388 Ok(match rows.next() {
389 Some(row) => Some(row?.0),
390 None => None,
391 })
392 }
393
394 fn get_occurrences_map(
395 keys: &[Vec<u8>],
396 ) -> Result<HashMap<&[u8], Vec<usize>>, ScyllaDbStoreInternalError> {
397 let mut map = HashMap::<&[u8], Vec<usize>>::new();
398 for (i_key, key) in keys.iter().enumerate() {
399 Self::check_key_size(key)?;
400 map.entry(key).or_default().push(i_key);
401 }
402 Ok(map)
403 }
404
405 async fn read_multi_values_internal(
406 &self,
407 root_key: &[u8],
408 keys: &[Vec<u8>],
409 ) -> Result<Vec<Option<Vec<u8>>>, ScyllaDbStoreInternalError> {
410 let mut values = vec![None; keys.len()];
411 let map = Self::get_occurrences_map(keys)?;
412 let statement = self.get_multi_key_values_statement(map.len()).await?;
413 let mut inputs = vec![root_key];
414 inputs.extend(map.keys().copied());
415 let mut rows = Box::pin(self.session.execute_iter(statement, &inputs))
416 .await?
417 .rows_stream::<(Vec<u8>, Vec<u8>)>()?;
418
419 while let Some(row) = rows.next().await {
420 let (key, value) = row?;
421 if let Some((&last, rest)) = map[key.as_slice()].split_last() {
422 for position in rest {
423 values[*position] = Some(value.clone());
424 }
425 values[last] = Some(value);
426 }
427 }
428 Ok(values)
429 }
430
431 async fn contains_keys_internal(
432 &self,
433 root_key: &[u8],
434 keys: &[Vec<u8>],
435 ) -> Result<Vec<bool>, ScyllaDbStoreInternalError> {
436 let mut values = vec![false; keys.len()];
437 let map = Self::get_occurrences_map(keys)?;
438 let statement = self.get_multi_keys_statement(map.len()).await?;
439 let mut inputs = vec![root_key];
440 inputs.extend(map.keys().copied());
441 let mut rows = Box::pin(self.session.execute_iter(statement, &inputs))
442 .await?
443 .rows_stream::<(Vec<u8>,)>()?;
444
445 while let Some(row) = rows.next().await {
446 let (key,) = row?;
447 for i_key in &map[key.as_slice()] {
448 values[*i_key] = true;
449 }
450 }
451
452 Ok(values)
453 }
454
455 async fn contains_key_internal(
456 &self,
457 root_key: &[u8],
458 key: Vec<u8>,
459 ) -> Result<bool, ScyllaDbStoreInternalError> {
460 Self::check_key_size(&key)?;
461 let session = &self.session;
462 let values = (root_key.to_vec(), key);
464
465 let (result, _) = session
466 .execute_single_page(&self.contains_key, &values, PagingState::start())
467 .await
468 .map_err(ScyllaDbStoreInternalError::ExecutionError)?;
469 let rows = result.into_rows_result()?;
470 let mut rows = rows.rows::<(Vec<u8>,)>()?;
471 Ok(rows.next().is_some())
472 }
473
474 async fn read_writetime_internal(
477 &self,
478 root_key: &[u8],
479 key: Vec<u8>,
480 ) -> Result<Option<i64>, ScyllaDbStoreInternalError> {
481 Self::check_key_size(&key)?;
482 let session = &self.session;
483 let values = (root_key.to_vec(), key);
484 let (result, _) = session
485 .execute_single_page(&self.read_writetime, &values, PagingState::start())
486 .await
487 .map_err(ScyllaDbStoreInternalError::ExecutionError)?;
488 let rows = result.into_rows_result()?;
489 let mut rows = rows.rows::<(Option<i64>,)>()?;
490 Ok(match rows.next() {
491 Some(row) => row?.0,
492 None => None,
493 })
494 }
495
496 async fn write_batch_prefix_deletes_shared(
499 &self,
500 root_key: &[u8],
501 key_prefix_deletions: Vec<Vec<u8>>,
502 ) -> Result<(), ScyllaDbStoreInternalError> {
503 if key_prefix_deletions.is_empty() {
504 return Ok(());
505 }
506 let session = &self.session;
507 let mut batch_query = scylla::statement::batch::Batch::new(BatchType::Unlogged);
508 let mut batch_values = Vec::new();
509 let q_unbounded = &self.write_batch_delete_prefix_unbounded;
510 let q_bounded = &self.write_batch_delete_prefix_bounded;
511 for key_prefix in key_prefix_deletions {
512 Self::check_key_size(&key_prefix)?;
513 match get_upper_bound_option(&key_prefix) {
514 None => {
515 batch_values.push(vec![root_key.to_vec(), key_prefix]);
516 batch_query.append_statement(q_unbounded.clone());
517 }
518 Some(upper_bound) => {
519 batch_values.push(vec![root_key.to_vec(), key_prefix, upper_bound]);
520 batch_query.append_statement(q_bounded.clone());
521 }
522 }
523 }
524 session
525 .batch(&batch_query, batch_values)
526 .await
527 .map_err(ScyllaDbStoreInternalError::SharedWriteBatchExecutionError)?;
528 Ok(())
529 }
530
531 async fn write_simple_batch_shared(
534 &self,
535 root_key: &[u8],
536 batch: SimpleUnorderedBatch,
537 ) -> Result<(), ScyllaDbStoreInternalError> {
538 if batch.deletions.is_empty() && batch.insertions.is_empty() {
539 return Ok(());
540 }
541 let session = &self.session;
542 let mut batch_query = scylla::statement::batch::Batch::new(BatchType::Unlogged);
543 let mut batch_values = Vec::new();
544 let q_deletion = &self.write_batch_deletion;
545 for key in batch.deletions {
546 Self::check_batch_key(&key)?;
547 batch_values.push(vec![root_key.to_vec(), key]);
548 batch_query.append_statement(q_deletion.clone());
549 }
550 let q_insertion = &self.write_batch_insertion;
551 for (key, value) in batch.insertions {
552 Self::check_batch_key(&key)?;
553 Self::check_value_size(&value)?;
554 batch_values.push(vec![root_key.to_vec(), key, value]);
555 batch_query.append_statement(q_insertion.clone());
556 }
557 session
558 .batch(&batch_query, batch_values)
559 .await
560 .map_err(ScyllaDbStoreInternalError::SharedWriteBatchExecutionError)?;
561 Ok(())
562 }
563
564 async fn write_batch_exclusive(
576 &self,
577 root_key: &[u8],
578 batch: UnorderedBatch,
579 t: i64,
580 ) -> Result<(), ScyllaDbStoreInternalError> {
581 let UnorderedBatch {
582 key_prefix_deletions,
583 simple_unordered_batch:
584 SimpleUnorderedBatch {
585 deletions,
586 insertions,
587 },
588 } = batch;
589 let session = &self.session;
590 let mut batch_query = scylla::statement::batch::Batch::new(BatchType::Unlogged);
591 let mut batch_values = Vec::new();
592
593 for key_prefix in key_prefix_deletions {
595 Self::check_key_size(&key_prefix)?;
596 match get_upper_bound_option(&key_prefix) {
597 None => {
598 batch_values.push(vec![
599 CqlValue::BigInt(t),
600 CqlValue::Blob(root_key.to_vec()),
601 CqlValue::Blob(key_prefix),
602 ]);
603 batch_query
604 .append_statement(self.write_batch_delete_prefix_unbounded_ts.clone());
605 }
606 Some(upper_bound) => {
607 batch_values.push(vec![
608 CqlValue::BigInt(t),
609 CqlValue::Blob(root_key.to_vec()),
610 CqlValue::Blob(key_prefix),
611 CqlValue::Blob(upper_bound),
612 ]);
613 batch_query.append_statement(self.write_batch_delete_prefix_bounded_ts.clone());
614 }
615 }
616 }
617
618 let t_data = t + 1;
620 for key in deletions {
621 Self::check_batch_key(&key)?;
622 batch_values.push(vec![
623 CqlValue::BigInt(t_data),
624 CqlValue::Blob(root_key.to_vec()),
625 CqlValue::Blob(key),
626 ]);
627 batch_query.append_statement(self.write_batch_deletion_ts.clone());
628 }
629 for (key, value) in insertions {
630 Self::check_batch_key(&key)?;
631 Self::check_value_size(&value)?;
632 batch_values.push(vec![
633 CqlValue::Blob(root_key.to_vec()),
634 CqlValue::Blob(key),
635 CqlValue::Blob(value),
636 CqlValue::BigInt(t_data),
637 ]);
638 batch_query.append_statement(self.write_batch_insertion_ts.clone());
639 }
640 batch_values.push(vec![
641 CqlValue::Blob(root_key.to_vec()),
642 CqlValue::Blob(WRITETIME_SENTINEL_KEY.to_vec()),
643 CqlValue::Blob(Vec::new()),
644 CqlValue::BigInt(t_data),
645 ]);
646 batch_query.append_statement(self.write_batch_insertion_ts.clone());
647
648 session
649 .batch(&batch_query, batch_values)
650 .await
651 .map_err(ScyllaDbStoreInternalError::ExclusiveWriteBatchExecutionError)?;
652 Ok(())
653 }
654
655 async fn find_keys_by_prefix_internal(
656 &self,
657 root_key: &[u8],
658 key_prefix: Vec<u8>,
659 ) -> Result<Vec<Vec<u8>>, ScyllaDbStoreInternalError> {
660 Self::check_key_size(&key_prefix)?;
661 let session = &self.session;
662 let len = key_prefix.len();
664 let query_unbounded = &self.find_keys_by_prefix_unbounded;
665 let query_bounded = &self.find_keys_by_prefix_bounded;
666 let rows = match get_upper_bound_option(&key_prefix) {
667 None => {
668 let values = (root_key.to_vec(), key_prefix.clone());
669 Box::pin(session.execute_iter(query_unbounded.clone(), values)).await?
670 }
671 Some(upper_bound) => {
672 let values = (root_key.to_vec(), key_prefix.clone(), upper_bound);
673 Box::pin(session.execute_iter(query_bounded.clone(), values)).await?
674 }
675 };
676 let mut rows = rows.rows_stream::<(Vec<u8>,)>()?;
677 let mut keys = Vec::new();
678 while let Some(row) = rows.next().await {
679 let (key,) = row?;
680 if key == WRITETIME_SENTINEL_KEY {
684 continue;
685 }
686 let short_key = key[len..].to_vec();
687 keys.push(short_key);
688 }
689 Ok(keys)
690 }
691
692 async fn find_key_values_by_prefix_internal(
693 &self,
694 root_key: &[u8],
695 key_prefix: Vec<u8>,
696 ) -> Result<Vec<(Vec<u8>, Vec<u8>)>, ScyllaDbStoreInternalError> {
697 Self::check_key_size(&key_prefix)?;
698 let session = &self.session;
699 let len = key_prefix.len();
701 let query_unbounded = &self.find_key_values_by_prefix_unbounded;
702 let query_bounded = &self.find_key_values_by_prefix_bounded;
703 let rows = match get_upper_bound_option(&key_prefix) {
704 None => {
705 let values = (root_key.to_vec(), key_prefix.clone());
706 Box::pin(session.execute_iter(query_unbounded.clone(), values)).await?
707 }
708 Some(upper_bound) => {
709 let values = (root_key.to_vec(), key_prefix.clone(), upper_bound);
710 Box::pin(session.execute_iter(query_bounded.clone(), values)).await?
711 }
712 };
713 let mut rows = rows.rows_stream::<(Vec<u8>, Vec<u8>)>()?;
714 let mut key_values = Vec::new();
715 while let Some(row) = rows.next().await {
716 let (key, value) = row?;
717 if key == WRITETIME_SENTINEL_KEY {
719 continue;
720 }
721 let short_key = key[len..].to_vec();
722 key_values.push((short_key, value));
723 }
724 Ok(key_values)
725 }
726}
727
728#[derive(Clone)]
730pub struct ScyllaDbStoreInternal {
731 store: Arc<ScyllaDbClient>,
732 semaphore: Option<Arc<Semaphore>>,
733 root_key: Vec<u8>,
734 is_exclusive: bool,
739 ts_floor: Arc<AtomicI64>,
743}
744
745#[derive(Clone)]
747pub struct ScyllaDbDatabaseInternal {
748 store: Arc<ScyllaDbClient>,
749 semaphore: Option<Arc<Semaphore>>,
750}
751
752impl WithError for ScyllaDbDatabaseInternal {
753 type Error = ScyllaDbStoreInternalError;
754}
755
756#[derive(Error, Debug)]
758pub enum ScyllaDbStoreInternalError {
759 #[error(transparent)]
761 BcsError(#[from] bcs::Error),
762
763 #[error(transparent)]
765 DeserializationError(#[from] DeserializationError),
766
767 #[error(transparent)]
769 RowsError(#[from] RowsError),
770
771 #[error(transparent)]
773 IntoRowsResultError(#[from] IntoRowsResultError),
774
775 #[error(transparent)]
777 TypeCheckError(#[from] TypeCheckError),
778
779 #[error(transparent)]
781 PagerExecutionError(#[from] PagerExecutionError),
782
783 #[error(transparent)]
785 PrepareError(#[from] PrepareError),
786
787 #[error("query execution error: {0}")]
789 ExecutionError(#[source] ExecutionError),
790
791 #[error("write batch execution error (exclusive mode): {0}")]
794 ExclusiveWriteBatchExecutionError(#[source] ExecutionError),
795
796 #[error("write batch execution error (shared mode): {0}")]
799 SharedWriteBatchExecutionError(#[source] ExecutionError),
800
801 #[error(transparent)]
803 NewSessionError(#[from] NewSessionError),
804
805 #[error(transparent)]
807 NextRowError(#[from] NextRowError),
808
809 #[error("Namespace contains forbidden characters")]
811 InvalidNamespace,
812
813 #[error("The key must have at most MAX_KEY_SIZE")]
815 KeyTooLong,
816
817 #[error("The value must have at most RAW_MAX_VALUE_SIZE")]
819 ValueTooLong,
820
821 #[error("The batch is too long to be written")]
823 BatchTooLong,
824
825 #[error("The key must be of nonzero length")]
828 ZeroLengthKey,
829}
830
831impl KeyValueStoreError for ScyllaDbStoreInternalError {
832 const BACKEND: &'static str = "scylla_db";
833
834 fn must_reload_view(&self) -> bool {
835 matches!(self, Self::ExclusiveWriteBatchExecutionError(_))
840 }
841}
842
843impl WithError for ScyllaDbStoreInternal {
844 type Error = ScyllaDbStoreInternalError;
845}
846
847impl ReadableKeyValueStore for ScyllaDbStoreInternal {
848 const MAX_KEY_SIZE: usize = MAX_KEY_SIZE;
849
850 fn root_key(&self) -> Result<Vec<u8>, ScyllaDbStoreInternalError> {
851 Ok(self.root_key[1..].to_vec())
852 }
853
854 async fn read_value_bytes(
855 &self,
856 key: &[u8],
857 ) -> Result<Option<Vec<u8>>, ScyllaDbStoreInternalError> {
858 let store = self.store.deref();
859 let _guard = self.acquire().await;
860 Box::pin(store.read_value_internal(&self.root_key, key.to_vec())).await
861 }
862
863 async fn contains_key(&self, key: &[u8]) -> Result<bool, ScyllaDbStoreInternalError> {
864 let store = self.store.deref();
865 let _guard = self.acquire().await;
866 Box::pin(store.contains_key_internal(&self.root_key, key.to_vec())).await
867 }
868
869 async fn contains_keys(
870 &self,
871 keys: &[Vec<u8>],
872 ) -> Result<Vec<bool>, ScyllaDbStoreInternalError> {
873 if keys.is_empty() {
874 return Ok(Vec::new());
875 }
876 let store = self.store.deref();
877 let _guard = self.acquire().await;
878 let handles = keys
879 .chunks(MAX_MULTI_KEYS)
880 .map(|keys| store.contains_keys_internal(&self.root_key, keys));
881 let results: Vec<_> = join_all(handles)
882 .await
883 .into_iter()
884 .collect::<Result<_, _>>()?;
885 Ok(results.into_iter().flatten().collect())
886 }
887
888 async fn read_multi_values_bytes(
889 &self,
890 keys: &[Vec<u8>],
891 ) -> Result<Vec<Option<Vec<u8>>>, ScyllaDbStoreInternalError> {
892 if keys.is_empty() {
893 return Ok(Vec::new());
894 }
895 let store = self.store.deref();
896 let _guard = self.acquire().await;
897 let handles = keys
898 .chunks(MAX_MULTI_KEYS)
899 .map(|keys| store.read_multi_values_internal(&self.root_key, keys));
900 let results: Vec<_> = join_all(handles)
901 .await
902 .into_iter()
903 .collect::<Result<_, _>>()?;
904 Ok(results.into_iter().flatten().collect())
905 }
906
907 async fn find_keys_by_prefix(
908 &self,
909 key_prefix: &[u8],
910 ) -> Result<Vec<Vec<u8>>, ScyllaDbStoreInternalError> {
911 let store = self.store.deref();
912 let _guard = self.acquire().await;
913 Box::pin(store.find_keys_by_prefix_internal(&self.root_key, key_prefix.to_vec())).await
914 }
915
916 async fn find_key_values_by_prefix(
917 &self,
918 key_prefix: &[u8],
919 ) -> Result<Vec<(Vec<u8>, Vec<u8>)>, ScyllaDbStoreInternalError> {
920 let store = self.store.deref();
921 let _guard = self.acquire().await;
922 Box::pin(store.find_key_values_by_prefix_internal(&self.root_key, key_prefix.to_vec()))
923 .await
924 }
925}
926
927impl DirectWritableKeyValueStore for ScyllaDbStoreInternal {
928 const MAX_BATCH_SIZE: usize = MAX_BATCH_SIZE;
929 const MAX_BATCH_TOTAL_SIZE: usize = MAX_BATCH_TOTAL_SIZE;
930 const MAX_VALUE_SIZE: usize = MAX_VALUE_SIZE;
931
932 type Batch = UnorderedBatch;
945
946 async fn write_batch(&self, batch: Self::Batch) -> Result<(), ScyllaDbStoreInternalError> {
947 let store = self.store.deref();
948 let _guard = self.acquire().await;
949 ScyllaDbClient::check_batch_len(&batch)?;
950 if self.is_exclusive {
951 let t = self.next_batch_ts().await?;
953 store.write_batch_exclusive(&self.root_key, batch, t).await
954 } else {
955 store
956 .write_batch_prefix_deletes_shared(&self.root_key, batch.key_prefix_deletions)
957 .await?;
958 store
959 .write_simple_batch_shared(&self.root_key, batch.simple_unordered_batch)
960 .await?;
961 Ok(())
962 }
963 }
964}
965
966impl ScyllaDbStoreInternal {
967 async fn ensure_ts_seeded(&self) -> Result<(), ScyllaDbStoreInternalError> {
973 if self.ts_floor.load(Ordering::Relaxed) > 0 {
974 return Ok(());
975 }
976 let writetime = self
977 .store
978 .read_writetime_internal(&self.root_key, WRITETIME_SENTINEL_KEY.to_vec())
979 .await?
980 .unwrap_or(0);
981 let now_us = SystemTime::now()
982 .duration_since(UNIX_EPOCH)
983 .ok()
984 .and_then(|d| i64::try_from(d.as_micros()).ok())
985 .unwrap_or(0);
986 let seed = now_us.max(writetime);
989 if self
990 .ts_floor
991 .compare_exchange(0, seed, Ordering::Relaxed, Ordering::Relaxed)
992 .is_err()
993 {
994 }
996 Ok(())
997 }
998
999 async fn next_batch_ts(&self) -> Result<i64, ScyllaDbStoreInternalError> {
1003 self.ensure_ts_seeded().await?;
1004 loop {
1005 let prev = self.ts_floor.load(Ordering::Relaxed);
1006 let now_us = SystemTime::now()
1007 .duration_since(UNIX_EPOCH)
1008 .ok()
1009 .and_then(|d| i64::try_from(d.as_micros()).ok())
1010 .unwrap_or(prev);
1011 let next = std::cmp::max(now_us, prev + 1);
1012 if self
1015 .ts_floor
1016 .compare_exchange_weak(prev, next + 1, Ordering::Relaxed, Ordering::Relaxed)
1017 .is_ok()
1018 {
1019 return Ok(next);
1020 }
1021 }
1022 }
1023}
1024
1025fn get_big_root_key(root_key: &[u8]) -> Vec<u8> {
1027 let mut big_key = vec![0];
1028 big_key.extend(root_key);
1029 big_key
1030}
1031
1032const WRITETIME_SENTINEL_KEY: &[u8] = &[];
1038
1039#[derive(Clone, Debug, Deserialize, Serialize)]
1041pub struct ScyllaDbStoreInternalConfig {
1042 pub uri: String,
1044 pub max_concurrent_queries: Option<usize>,
1046 pub replication_factor: u32,
1048}
1049
1050impl KeyValueDatabase for ScyllaDbDatabaseInternal {
1051 type Config = ScyllaDbStoreInternalConfig;
1052 type Store = ScyllaDbStoreInternal;
1053
1054 fn get_name() -> String {
1055 "scylladb internal".to_string()
1056 }
1057
1058 async fn connect(
1059 config: &Self::Config,
1060 namespace: &str,
1061 ) -> Result<Self, ScyllaDbStoreInternalError> {
1062 Self::check_namespace(namespace)?;
1063 let session = ScyllaDbClient::build_default_session(&config.uri).await?;
1064 let store = ScyllaDbClient::new(session, namespace).await?;
1065 let store = Arc::new(store);
1066 let semaphore = config
1067 .max_concurrent_queries
1068 .map(|n| Arc::new(Semaphore::new(n)));
1069 Ok(Self { store, semaphore })
1070 }
1071
1072 fn open_shared(&self, root_key: &[u8]) -> Result<Self::Store, ScyllaDbStoreInternalError> {
1073 let store = self.store.clone();
1074 let semaphore = self.semaphore.clone();
1075 let root_key = get_big_root_key(root_key);
1076 Ok(ScyllaDbStoreInternal {
1077 store,
1078 semaphore,
1079 root_key,
1080 is_exclusive: false,
1081 ts_floor: Arc::new(AtomicI64::new(0)),
1082 })
1083 }
1084
1085 fn open_exclusive(&self, root_key: &[u8]) -> Result<Self::Store, ScyllaDbStoreInternalError> {
1086 let store = self.store.clone();
1087 let semaphore = self.semaphore.clone();
1088 let root_key = get_big_root_key(root_key);
1089 Ok(ScyllaDbStoreInternal {
1090 store,
1091 semaphore,
1092 root_key,
1093 is_exclusive: true,
1094 ts_floor: Arc::new(AtomicI64::new(0)),
1095 })
1096 }
1097
1098 async fn list_all(config: &Self::Config) -> Result<Vec<String>, ScyllaDbStoreInternalError> {
1099 let session = ScyllaDbClient::build_default_session(&config.uri).await?;
1100 let statement = session
1101 .prepare(format!("DESCRIBE KEYSPACE {KEYSPACE}"))
1102 .await?;
1103 let result = Box::pin(session.execute_iter(statement, &[])).await;
1104 let miss_msg = format!("'{KEYSPACE}' not found in keyspaces");
1105 let result = match result {
1106 Ok(result) => result,
1107 Err(error) => {
1108 let invalid_or_keyspace_not_found = match &error {
1109 PagerExecutionError::NextPageError(NextPageError::RequestFailure(
1110 RequestError::LastAttemptError(RequestAttemptError::DbError(db_error, msg)),
1111 )) => *db_error == DbError::Invalid && msg.as_str() == miss_msg,
1112 _ => false,
1113 };
1114 if invalid_or_keyspace_not_found {
1115 return Ok(Vec::new());
1116 } else {
1117 return Err(ScyllaDbStoreInternalError::PagerExecutionError(error));
1118 }
1119 }
1120 };
1121 let mut namespaces = Vec::new();
1122 let mut rows_stream = result.rows_stream::<(String, String, String, String)>()?;
1123 while let Some(row) = rows_stream.next().await {
1124 let (_, object_kind, name, _) = row?;
1125 if object_kind == "table" {
1126 namespaces.push(name);
1127 }
1128 }
1129 Ok(namespaces)
1130 }
1131
1132 async fn list_root_keys(&self) -> Result<Vec<Vec<u8>>, ScyllaDbStoreInternalError> {
1133 let statement = self
1134 .store
1135 .session
1136 .prepare(format!(
1137 "SELECT root_key FROM {}.\"{}\" ALLOW FILTERING",
1138 KEYSPACE, self.store.namespace
1139 ))
1140 .await?;
1141
1142 let rows = Box::pin(self.store.session.execute_iter(statement, &[])).await?;
1144 let mut rows = rows.rows_stream::<(Vec<u8>,)>()?;
1145 let mut root_keys = BTreeSet::new();
1146 while let Some(row) = rows.next().await {
1147 let (root_key,) = row?;
1148 let root_key = root_key[1..].to_vec();
1149 root_keys.insert(root_key);
1150 }
1151 Ok(root_keys.into_iter().collect::<Vec<_>>())
1152 }
1153
1154 async fn delete_all(store_config: &Self::Config) -> Result<(), ScyllaDbStoreInternalError> {
1155 let session = ScyllaDbClient::build_default_session(&store_config.uri).await?;
1156 let statement = session
1157 .prepare(format!("DROP KEYSPACE IF EXISTS {KEYSPACE}"))
1158 .await?;
1159
1160 session
1161 .execute_single_page(&statement, &[], PagingState::start())
1162 .await
1163 .map_err(ScyllaDbStoreInternalError::ExecutionError)?;
1164 Ok(())
1165 }
1166
1167 async fn exists(
1168 config: &Self::Config,
1169 namespace: &str,
1170 ) -> Result<bool, ScyllaDbStoreInternalError> {
1171 Self::check_namespace(namespace)?;
1172 let session = ScyllaDbClient::build_default_session(&config.uri).await?;
1173
1174 let result = session
1176 .prepare(format!(
1177 "SELECT root_key FROM {KEYSPACE}.\"{namespace}\" LIMIT 1 ALLOW FILTERING"
1178 ))
1179 .await;
1180
1181 let miss_msg1 = format!("unconfigured table {namespace}");
1183 let miss_msg1 = miss_msg1.as_str();
1184 let miss_msg2 = "Undefined name root_key in selection clause";
1185 let miss_msg3 = format!("Keyspace {KEYSPACE} does not exist");
1186 let Err(error) = result else {
1187 return Ok(true);
1189 };
1190 let missing_table = match &error {
1191 PrepareError::AllAttemptsFailed {
1192 first_attempt: RequestAttemptError::DbError(db_error, msg),
1193 } => {
1194 if *db_error != DbError::Invalid {
1195 false
1196 } else {
1197 msg.as_str() == miss_msg1
1198 || msg.as_str() == miss_msg2
1199 || msg.as_str() == miss_msg3
1200 }
1201 }
1202 _ => false,
1203 };
1204 if missing_table {
1205 Ok(false)
1206 } else {
1207 Err(ScyllaDbStoreInternalError::PrepareError(error))
1208 }
1209 }
1210
1211 async fn create(
1212 config: &Self::Config,
1213 namespace: &str,
1214 ) -> Result<(), ScyllaDbStoreInternalError> {
1215 Self::check_namespace(namespace)?;
1216 let session = ScyllaDbClient::build_default_session(&config.uri).await?;
1217
1218 let statement = session
1220 .prepare(format!(
1221 "CREATE KEYSPACE IF NOT EXISTS {} WITH REPLICATION = {{ \
1222 'class' : 'NetworkTopologyStrategy', \
1223 'replication_factor' : {} \
1224 }}",
1225 KEYSPACE, config.replication_factor
1226 ))
1227 .await?;
1228 session
1229 .execute_single_page(&statement, &[], PagingState::start())
1230 .await
1231 .map_err(ScyllaDbStoreInternalError::ExecutionError)?;
1232
1233 let statement = session
1236 .prepare(format!(
1237 "CREATE TABLE {KEYSPACE}.\"{namespace}\" (\
1238 root_key blob, \
1239 k blob, \
1240 v blob, \
1241 PRIMARY KEY (root_key, k) \
1242 ) \
1243 WITH compaction = {{ \
1244 'class' : 'LeveledCompactionStrategy', \
1245 'sstable_size_in_mb' : 160 \
1246 }} \
1247 AND compression = {{ \
1248 'sstable_compression': 'LZ4Compressor', \
1249 'chunk_length_in_kb':'4' \
1250 }} \
1251 AND caching = {{ \
1252 'enabled': 'true' \
1253 }} \
1254 AND gc_grace_seconds = 0 \
1255 AND tombstone_gc = {{'mode': 'immediate'}}"
1256 ))
1257 .await?;
1258 session
1259 .execute_single_page(&statement, &[], PagingState::start())
1260 .await
1261 .map_err(ScyllaDbStoreInternalError::ExecutionError)?;
1262 Ok(())
1263 }
1264
1265 async fn delete(
1266 config: &Self::Config,
1267 namespace: &str,
1268 ) -> Result<(), ScyllaDbStoreInternalError> {
1269 Self::check_namespace(namespace)?;
1270 let session = ScyllaDbClient::build_default_session(&config.uri).await?;
1271 let statement = session
1272 .prepare(format!("DROP TABLE IF EXISTS {KEYSPACE}.\"{namespace}\";"))
1273 .await?;
1274 session
1275 .execute_single_page(&statement, &[], PagingState::start())
1276 .await
1277 .map_err(ScyllaDbStoreInternalError::ExecutionError)?;
1278 Ok(())
1279 }
1280}
1281
1282impl ScyllaDbStoreInternal {
1283 async fn acquire(&self) -> Option<SemaphoreGuard<'_>> {
1285 match &self.semaphore {
1286 None => None,
1287 Some(count) => Some(count.acquire().await),
1288 }
1289 }
1290}
1291
1292impl ScyllaDbDatabaseInternal {
1293 fn check_namespace(namespace: &str) -> Result<(), ScyllaDbStoreInternalError> {
1294 if !namespace.is_empty()
1295 && namespace.len() <= 48
1296 && namespace
1297 .chars()
1298 .all(|c| c.is_ascii_alphanumeric() || c == '_')
1299 {
1300 return Ok(());
1301 }
1302 Err(ScyllaDbStoreInternalError::InvalidNamespace)
1303 }
1304}
1305
1306#[cfg(with_testing)]
1307impl TestKeyValueDatabase for JournalingKeyValueDatabase<ScyllaDbDatabaseInternal> {
1308 async fn new_test_config(
1309 ) -> Result<ScyllaDbStoreInternalConfig, JournalingError<ScyllaDbStoreInternalError>> {
1310 let uri = "localhost:9042".to_string();
1312 Ok(ScyllaDbStoreInternalConfig {
1313 uri,
1314 max_concurrent_queries: Some(10),
1315 replication_factor: 1,
1316 })
1317 }
1318}
1319
1320#[cfg(with_metrics)]
1322pub type ScyllaDbDatabase = MeteredDatabase<
1323 LruCachingDatabase<MeteredDatabase<JournalingKeyValueDatabase<ScyllaDbDatabaseInternal>>>,
1324>;
1325
1326#[cfg(not(with_metrics))]
1328pub type ScyllaDbDatabase =
1329 LruCachingDatabase<JournalingKeyValueDatabase<ScyllaDbDatabaseInternal>>;
1330
1331pub type ScyllaDbStoreConfig = LruCachingConfig<ScyllaDbStoreInternalConfig>;
1333
1334pub type ScyllaDbStoreError = JournalingError<ScyllaDbStoreInternalError>;
1336
1337#[cfg(test)]
1338mod tests {
1339 use scylla::errors::ExecutionError;
1340
1341 use super::*;
1342
1343 #[test]
1346 fn write_batch_error_reloads_the_view_only_in_exclusive_mode() {
1347 assert!(
1348 ScyllaDbStoreInternalError::ExclusiveWriteBatchExecutionError(
1349 ExecutionError::EmptyPlan
1350 )
1351 .must_reload_view()
1352 );
1353 assert!(!ScyllaDbStoreInternalError::SharedWriteBatchExecutionError(
1354 ExecutionError::EmptyPlan
1355 )
1356 .must_reload_view());
1357 }
1358
1359 #[test]
1361 fn other_errors_do_not_reload_the_view() {
1362 assert!(!ScyllaDbStoreInternalError::ZeroLengthKey.must_reload_view());
1363 assert!(
1364 !ScyllaDbStoreInternalError::ExecutionError(ExecutionError::EmptyPlan)
1365 .must_reload_view()
1366 );
1367 }
1368}