diff --git a/index-scheduler/src/index_mapper.rs b/index-scheduler/src/index_mapper.rs new file mode 100644 index 000000000..1a5339f06 --- /dev/null +++ b/index-scheduler/src/index_mapper.rs @@ -0,0 +1,66 @@ +use std::collections::hash_map::Entry; +use std::sync::Arc; + +use index::Index; +use milli::heed::RoTxn; +use milli::heed::RwTxn; +use uuid::Uuid; + +use crate::Error; +use crate::IndexScheduler; +use crate::Result; + +impl IndexScheduler { + pub fn create_index(&self, rwtxn: &mut RwTxn, name: &str) -> Result { + let index = match self.index_txn(rwtxn, name) { + Ok(index) => index, + Err(Error::IndexNotFound(_)) => { + let uuid = Uuid::new_v4(); + // TODO: TAMO: take the arguments from somewhere + Index::open(uuid.to_string(), name.to_string(), 100000, Arc::default())? + } + error => return error, + }; + + Ok(index) + } + + pub fn index_txn(&self, rtxn: &RoTxn, name: &str) -> Result { + let uuid = self + .index_mapping + .get(&rtxn, name)? + .ok_or(Error::IndexNotFound(name.to_string()))?; + + // we clone here to drop the lock before entering the match + let index = self.index_map.read().unwrap().get(&uuid).cloned(); + let index = match index { + Some(index) => index, + // since we're lazy, it's possible that the index has not been opened yet. + None => { + let mut index_map = self.index_map.write().unwrap(); + // between the read lock and the write lock it's not impossible + // that someone already opened the index (eg if two search happens + // at the same time), thus before opening it we check a second time + // if it's not already there. + // Since there is a good chance it's not already there we can use + // the entry method. + match index_map.entry(uuid) { + Entry::Vacant(entry) => { + // TODO: TAMO: get the args from somewhere. + let index = Index::open( + uuid.to_string(), + name.to_string(), + 100_000_000, + Arc::default(), + )?; + entry.insert(index.clone()); + index + } + Entry::Occupied(entry) => entry.get().clone(), + } + } + }; + + Ok(index) + } +} diff --git a/index-scheduler/src/lib.rs b/index-scheduler/src/lib.rs index cd62d4fb3..695ceae06 100644 --- a/index-scheduler/src/lib.rs +++ b/index-scheduler/src/lib.rs @@ -1,6 +1,7 @@ mod autobatcher; mod batch; pub mod error; +mod index_mapper; pub mod task; mod utils; @@ -79,52 +80,12 @@ pub struct IndexScheduler { } impl IndexScheduler { - pub fn create_index(&self, rwtxn: &mut RwTxn, name: &str) -> Result { - todo!() - } - /// Return the index corresponding to the name. If it wasn't opened before /// it'll be opened. But if it doesn't exist on disk it'll throw an /// `IndexNotFound` error. pub fn index(&self, name: &str) -> Result { let rtxn = self.env.read_txn()?; - - let uuid = self - .index_mapping - .get(&rtxn, name)? - .ok_or(Error::IndexNotFound(name.to_string()))?; - - // we clone here to drop the lock before entering the match - let index = self.index_map.read().unwrap().get(&uuid).cloned(); - let index = match index { - Some(index) => index, - // since we're lazy, it's possible that the index has not been opened yet. - None => { - let mut index_map = self.index_map.write().unwrap(); - // between the read lock and the write lock it's not impossible - // that someone already opened the index (eg if two search happens - // at the same time), thus before opening it we check a second time - // if it's not already there. - // Since there is a good chance it's not already there we can use - // the entry method. - match index_map.entry(uuid) { - Entry::Vacant(entry) => { - // TODO: TAMO: get the args from somewhere. - let index = Index::open( - name.to_string(), - name.to_string(), - 100_000_000, - Arc::default(), - )?; - entry.insert(index.clone()); - index - } - Entry::Occupied(entry) => entry.get().clone(), - } - } - }; - - Ok(index) + self.index_txn(&rtxn, name) } /// Returns the tasks corresponding to the query.