guardian_db/stores/document_store/
index.rs

1use crate::ipfs_log::{entry::Entry, log::Log};
2use crate::traits::{CreateDocumentDBOptions, StoreIndex};
3use std::collections::{HashMap, HashSet};
4use std::sync::{Arc, RwLock};
5
6#[allow(dead_code)]
7type Result<T> = std::result::Result<T, crate::error::GuardianError>;
8
9/// DocumentIndex mantém um índice de chave-valor em memória para a DocumentStore.
10pub struct DocumentIndex {
11    // O índice principal, protegido por um RwLock para acesso concorrente seguro.
12    index: RwLock<HashMap<String, Vec<u8>>>,
13    // Opções de configuração da store, compartilhadas via Arc.
14    #[allow(dead_code)]
15    opts: Arc<CreateDocumentDBOptions>,
16}
17
18impl DocumentIndex {
19    /// Cria uma nova instância de DocumentIndex.
20    pub fn new(opts: Arc<CreateDocumentDBOptions>) -> Self {
21        Self {
22            index: RwLock::new(HashMap::new()),
23            opts,
24        }
25    }
26
27    /// Retorna uma cópia de todas as chaves presentes no índice.
28    pub fn keys(&self) -> Vec<String> {
29        // Adquire um bloqueio de leitura. O unwrap trata casos de "poisoning" do mutex.
30        let index_lock = self
31            .index
32            .read()
33            .expect("Failed to acquire read lock on document index");
34        // Coleta as chaves do mapa. `.keys()` retorna um iterador de &String,
35        // então `.cloned()` cria novas Strings a partir das referências.
36        index_lock.keys().cloned().collect()
37    }
38
39    /// Método específico para obter Vec<u8> do índice
40    /// Usado internamente pela DocumentStore
41    pub fn get_bytes(&self, key: &str) -> Option<Vec<u8>> {
42        let index_lock = self
43            .index
44            .read()
45            .expect("Failed to acquire read lock on document index");
46        index_lock.get(key).cloned()
47    }
48}
49
50// Implementa o trait StoreIndex para DocumentIndex
51impl StoreIndex for DocumentIndex {
52    type Error = crate::error::GuardianError;
53
54    /// Verifica se uma chave existe no índice.
55    fn contains_key(&self, key: &str) -> std::result::Result<bool, Self::Error> {
56        let index_lock = self
57            .index
58            .read()
59            .expect("Failed to acquire read lock on document index");
60        Ok(index_lock.contains_key(key))
61    }
62
63    /// Retorna uma cópia dos dados para uma chave específica como bytes.
64    fn get_bytes(&self, key: &str) -> std::result::Result<Option<Vec<u8>>, Self::Error> {
65        let index_lock = self
66            .index
67            .read()
68            .expect("Failed to acquire read lock on document index");
69        Ok(index_lock.get(key).cloned())
70    }
71
72    /// Retorna todas as chaves disponíveis no índice.
73    fn keys(&self) -> std::result::Result<Vec<String>, Self::Error> {
74        let index_lock = self
75            .index
76            .read()
77            .expect("Failed to acquire read lock on document index");
78        Ok(index_lock.keys().cloned().collect())
79    }
80
81    /// Retorna o número de entradas no índice.
82    fn len(&self) -> std::result::Result<usize, Self::Error> {
83        let index_lock = self
84            .index
85            .read()
86            .expect("Failed to acquire read lock on document index");
87        Ok(index_lock.len())
88    }
89
90    /// Verifica se o índice está vazio.
91    fn is_empty(&self) -> std::result::Result<bool, Self::Error> {
92        let index_lock = self
93            .index
94            .read()
95            .expect("Failed to acquire read lock on document index");
96        Ok(index_lock.is_empty())
97    }
98
99    /// Atualiza o índice processando as entradas do log de operações (oplog).
100    fn update_index(
101        &mut self,
102        _log: &Log,
103        entries: &[Entry],
104    ) -> std::result::Result<(), Self::Error> {
105        // Um conjunto para rastrear chaves já processadas, garantindo que
106        // apenas a operação mais recente para cada chave seja aplicada.
107        let mut handled = HashSet::new();
108
109        // Adquire um bloqueio de escrita, pois vamos modificar o índice.
110        let mut index = self
111            .index
112            .write()
113            .expect("Failed to acquire write lock on document index");
114
115        // Itera sobre as entradas fornecidas em ordem reversa (do mais novo para o mais antigo).
116        for entry in entries.iter().rev() {
117            let operation = crate::stores::operation::operation::parse_operation(entry.clone())
118                .map_err(|e| {
119                    crate::error::GuardianError::Store(format!("Erro ao parsear operação: {}", e))
120                })?;
121
122            // Para operações normais, obtém a chave principal.
123            let key = match operation.key() {
124                Some(k) if !k.is_empty() => k,
125                _ => continue, // Ignora entradas com chave nula ou vazia.
126            };
127
128            if handled.contains(key) {
129                continue;
130            }
131            handled.insert(key.clone());
132
133            // Aplica a operação (PUT ou DEL).
134            match operation.op() {
135                "PUT" => {
136                    let value = operation.value();
137                    if !value.is_empty() {
138                        index.insert(key.clone(), value.to_vec());
139                    }
140                }
141                "DEL" => {
142                    index.remove(key);
143                }
144                _ => {} // Ignora outras operações.
145            }
146        }
147
148        Ok(())
149    }
150
151    /// Limpa todos os dados do índice.
152    fn clear(&mut self) -> std::result::Result<(), Self::Error> {
153        let mut index = self
154            .index
155            .write()
156            .expect("Failed to acquire write lock on document index");
157        index.clear();
158        Ok(())
159    }
160}