···11use std::{
22- collections::HashMap,
22+ collections::{HashMap, HashSet},
33 fmt::Debug,
44 io::Cursor,
55 ops::{Bound, Deref, RangeBounds},
···165165 pub fn sync(&self, all: bool) -> AppResult<()> {
166166 let start = CLOCK.now();
167167 // prepare all the data
168168- let mut data = Vec::with_capacity(self.hits.len());
168168+ let nsids_len = self.hits.len();
169169+ let mut data = Vec::with_capacity(nsids_len);
170170+ let mut nsids = HashSet::with_capacity(nsids_len);
169171 let _guard = scc::ebr::Guard::new();
170170- for (_, handle) in self.hits.iter(&_guard) {
172172+ for (nsid, handle) in self.hits.iter(&_guard) {
171173 let mut nsid_data = Vec::with_capacity(2);
172174 let mut total_count = 0;
173175 let is_too_old = handle.since_last_activity() > self.cfg.max_last_activity;
···201203 {blocks = %nsid_data.len(), count = %total_count},
202204 "will encode & sync",
203205 );
206206+ nsids.insert(nsid.clone());
204207 data.push(nsid_data);
205208 }
206209 }
···228231 for (block, handle) in chunk {
229232 self.sync_pool.execute(move || {
230233 let _span = handle.span().entered();
231231- match handle.insert(block.key, block.data) {
234234+ let written = block.written;
235235+ match handle.insert_block(block) {
232236 Ok(_) => {
233233- tracing::info!({count = %block.written}, "synced")
237237+ tracing::info!({count = %written}, "synced")
234238 }
235239 Err(err) => tracing::error!({ err = %err }, "failed to sync block"),
236240 }
···239243 AppResult::Ok(())
240244 })?;
241245 self.sync_pool.join();
246246+247247+ // update snapshots for all (changed) handles
248248+ for nsid in nsids {
249249+ self.hits.peek_with(&nsid, |_, handle| handle.update_tree());
250250+ }
251251+242252 tracing::info!(time = %start.elapsed().as_secs_f64(), "synced all blocks");
243253244254 Ok(())
···254264 let Some(handle) = self.get_handle(nsid) else {
255265 return Ok(());
256266 };
257257- handle.compact(max_count, range, sort)
267267+ handle.compact(max_count, range, sort)?;
268268+ handle.update_tree();
269269+ Ok(())
258270 }
259271260272 pub fn compact_all(
···363375 let Some(handle) = self.get_handle(&nsid) else {
364376 continue;
365377 };
366366- let block_lens = handle.iter().rev().try_fold(Vec::new(), |mut acc, item| {
367367- let (key, value) = item?;
368368- let mut timestamps = Cursor::new(key);
369369- let start_timestamp = timestamps.read_varint()?;
370370- let decoder = ItemDecoder::new(Cursor::new(value), start_timestamp)?;
371371- acc.push(decoder.item_count());
372372- AppResult::Ok(acc)
373373- })?;
378378+ let block_lens = handle
379379+ .read()
380380+ .iter()
381381+ .rev()
382382+ .try_fold(Vec::new(), |mut acc, item| {
383383+ let (key, value) = item?;
384384+ let mut timestamps = Cursor::new(key);
385385+ let start_timestamp = timestamps.read_varint()?;
386386+ let decoder = ItemDecoder::new(Cursor::new(value), start_timestamp)?;
387387+ acc.push(decoder.item_count());
388388+ AppResult::Ok(acc)
389389+ })?;
374390 nsids.insert(nsid.to_smolstr(), block_lens);
375391 }
376392 Ok(DbInfo {
···438454 ))
439455 };
440456441441- let (blocks, counted) = handle
457457+ let (blocks, _counted) = handle
458458+ .read()
442459 .range(..end_key)
443460 .map(|res| res.map_err(AppError::from))
444461 .rev()
···462479 )
463480 .into_inner();
464481465465- tracing::info!(
466466- "got blocks with size {}, item count {counted}",
467467- blocks.len()
468468- );
482482+ // tracing::info!(
483483+ // "got blocks with size {}, item count {counted}",
484484+ // blocks.len()
485485+ // );
469486470487 Either::Left(blocks.into_iter().rev().flatten().flatten())
471488 }
···476493 let Some(handle) = self.get_handle("app.bsky.feed.like") else {
477494 return Ok(0);
478495 };
479479- let Some((timestamps_raw, _)) = handle.first_key_value()? else {
496496+ let Some((timestamps_raw, _)) = handle.read().first_key_value()? else {
480497 return Ok(0);
481498 };
482499 let mut timestamp_reader = Cursor::new(timestamps_raw);
+66
server/src/utils.rs
···11use std::io::{self, Read, Write};
22+use std::ops::Deref;
23use std::sync::atomic::{AtomicU64, Ordering};
34use std::time::Duration;
4566+use arc_swap::RefCnt;
57use byteview::ByteView;
68use ordered_varint::Variable;
99+use rclite::Arc;
710811pub fn get_time() -> Duration {
912 std::time::SystemTime::now()
···320323 }
321324 }
322325}
326326+327327+pub type ArcliteSwap<T> = arc_swap::ArcSwapAny<ArcRefCnt<T>>;
328328+329329+pub struct ArcRefCnt<T>(Arc<T>);
330330+331331+impl<T> ArcRefCnt<T> {
332332+ pub fn new(value: T) -> Self {
333333+ Self(Arc::new(value))
334334+ }
335335+}
336336+337337+impl<T> Deref for ArcRefCnt<T> {
338338+ type Target = T;
339339+340340+ fn deref(&self) -> &Self::Target {
341341+ &self.0
342342+ }
343343+}
344344+345345+impl<T> Clone for ArcRefCnt<T> {
346346+ fn clone(&self) -> Self {
347347+ Self(self.0.clone())
348348+ }
349349+}
350350+351351+// SAFETY: uhhhhhhhh copied the Arc impl from arc_swap xd
352352+unsafe impl<T> RefCnt for ArcRefCnt<T> {
353353+ type Base = T;
354354+355355+ fn into_ptr(me: Self) -> *mut Self::Base {
356356+ Arc::into_raw(me.0) as *mut T
357357+ }
358358+359359+ fn as_ptr(me: &Self) -> *mut Self::Base {
360360+ // Slightly convoluted way to do this, but this avoids stacked borrows violations. The same
361361+ // intention as
362362+ //
363363+ // me as &T as *const T as *mut T
364364+ //
365365+ // We first create a "shallow copy" of me - one that doesn't really own its ref count
366366+ // (that's OK, me _does_ own it, so it can't be destroyed in the meantime).
367367+ // Then we can use into_raw (which preserves not having the ref count).
368368+ //
369369+ // We need to "revert" the changes we did. In current std implementation, the combination
370370+ // of from_raw and forget is no-op. But formally, into_raw shall be paired with from_raw
371371+ // and that read shall be paired with forget to properly "close the brackets". In future
372372+ // versions of STD, these may become something else that's not really no-op (unlikely, but
373373+ // possible), so we future-proof it a bit.
374374+375375+ // SAFETY: &T cast to *const T will always be aligned, initialised and valid for reads
376376+ let ptr = Arc::into_raw(unsafe { std::ptr::read(&me.0) });
377377+ let ptr = ptr as *mut T;
378378+379379+ // SAFETY: We got the pointer from into_raw just above
380380+ std::mem::forget(unsafe { Arc::from_raw(ptr) });
381381+382382+ ptr
383383+ }
384384+385385+ unsafe fn from_ptr(ptr: *const Self::Base) -> Self {
386386+ Self(unsafe { Arc::from_raw(ptr) })
387387+ }
388388+}