//
// imag - the personal information management suite for the commandline
// Copyright (C) 2015-2019 Matthias Beyer <mail@beyermatthias.de> and contributors
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; version
// 2.1 of the License.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
//
use std::collections::HashMap;
use std::ops::Drop;
use std::path::PathBuf;
use std::result::Result as RResult;
use std::sync::Arc;
use std::sync::RwLock;
use std::io::Read;
use std::ops::Deref;
use std::ops::DerefMut;
use std::fmt::Formatter;
use std::fmt::Debug;
use std::fmt::Error as FMTError;
use libimagerror::errors::ErrorMsg as EM;
use toml::Value;
use toml_query::read::TomlValueReadExt;
use toml_query::read::TomlValueReadTypeExt;
use failure::Fallible as Result;
use failure::ResultExt;
use failure::err_msg;
use failure::Error;
use crate::storeid::{IntoStoreId, StoreId};
use crate::iter::Entries;
use crate::file_abstraction::FileAbstraction;
use crate::file_abstraction::FileAbstractionInstance;
use crate::file_abstraction::fs::FSFileAbstraction;
use crate::file_abstraction::inmemory::InMemoryFileAbstraction;
use libimagutil::debug_result::*;
#[derive(Debug, PartialEq)]
enum StoreEntryStatus {
Present,
Borrowed
}
/// A store entry, depending on the option type it is either borrowed currently
/// or not.
#[derive(Debug)]
struct StoreEntry {
id: StoreId,
store_base: PathBuf, // small sacrefice over lifetimes on the Store type
file: Box<dyn FileAbstractionInstance>,
status: StoreEntryStatus,
}
impl StoreEntry {
fn new(store_base: PathBuf, id: StoreId, backend: &Arc<dyn FileAbstraction>) -> Result<StoreEntry> {
let pb = id.clone().with_base(&store_base).into_pathbuf()?;
#[cfg(feature = "fs-lock")]
{
open_file(pb.clone())
.and_then(|f| f.lock_exclusive())
.with_context(|| EM::IO)?;
}
Ok(StoreEntry {
id,
store_base,
file: backend.new_instance(pb),
status: StoreEntryStatus::Present,
})
}
/// The entry is currently borrowed, meaning that some thread is currently
/// mutating it
fn is_borrowed(&self) -> bool {
self.status == StoreEntryStatus::Borrowed
}
fn get_entry(&mut self) -> Result<Entry> {
if !self.is_borrowed() {
match self.file.get_file_content(self.id.clone().with_base(&self.store_base))? {