1extern crate llmosafe;
7
8pub mod bloom;
9pub mod builder;
10pub mod config;
11pub mod decompress;
12pub mod archive;
13pub mod error;
14pub mod executor;
15pub mod format;
16#[cfg(feature = "notify")]
17pub mod idle;
18pub mod planner;
19pub mod posting;
20pub mod reader;
21pub mod scanner;
22pub mod string_pool;
23pub mod trigram;
24pub mod varint;
25#[cfg(feature = "notify")]
26pub mod watcher;
27
28#[cfg(feature = "notify")]
29pub use crate::watcher::Watcher;
30#[cfg(feature = "notify")]
31pub use crate::idle::IdleTracker;
32#[cfg(feature = "notify")]
33pub use crate::builder::Builder;
34#[cfg(feature = "notify")]
35pub use crate::format::Beacon;
36
37#[cfg(feature = "notify")]
38pub fn run_daemon(path: &std::path::Path) -> crate::error::Result<()> {
39 use std::fs;
40 use std::sync::Arc;
41 use std::sync::atomic::{AtomicBool, Ordering};
42 use std::time::Duration;
43
44 let root = path.canonicalize().map_err(crate::error::Error::Io)?;
45
46 println!("ixd: watching {}...", root.display());
47
48 let mut builder = Builder::new(&root)?;
49
50 let ix_dir = root.join(".ix");
52 let index_file = ix_dir.join("shard.ix");
53 if index_file.exists() {
54 println!("ixd: existing index found, performing startup update...");
55 builder.build()?;
59 } else {
60 builder.build()?;
61 }
62
63 println!(
64 "ixd: initial index ready ({} files, {} trigrams)",
65 builder.files_len(),
66 builder.trigrams_len()
67 );
68
69 let mut watcher = Watcher::new(&root)?;
70 let rx = watcher.start()?;
71
72 let ix_dir = root.join(".ix");
73 if !ix_dir.exists() {
74 fs::create_dir_all(&ix_dir)?;
75 }
76 let mut beacon = Beacon::new(&root);
77 beacon.write_to(&ix_dir)?;
78
79 let mut idle = IdleTracker::new();
80
81 let running = Arc::new(AtomicBool::new(true));
82 let r = running.clone();
83 ctrlc::set_handler(move || {
84 r.store(false, Ordering::SeqCst);
85 })
86 .expect("Error setting Ctrl-C handler");
87
88 while running.load(Ordering::SeqCst) {
89 match rx.recv_timeout(Duration::from_secs(5)) {
90 Ok(changed_files) => {
91 println!(
92 "ixd: {} files changed, updating index...",
93 changed_files.len()
94 );
95
96 beacon.status = "indexing".to_string();
97 beacon.last_event_at = std::time::SystemTime::now()
98 .duration_since(std::time::UNIX_EPOCH)
99 .unwrap_or_default()
100 .as_secs();
101 let _ = beacon.write_to(&ix_dir);
102
103 idle.record_change();
104 builder.update(&changed_files)?;
105
106 beacon.status = "idle".to_string();
107 let _ = beacon.write_to(&ix_dir);
108 }
109 Err(crossbeam_channel::RecvTimeoutError::Timeout) => {
110 continue;
111 }
112 Err(crossbeam_channel::RecvTimeoutError::Disconnected) => break,
113 }
114 }
115
116 println!("ixd: shutting down");
117 let _ = fs::remove_file(ix_dir.join("beacon.json"));
118 watcher.stop();
119 Ok(())
120}