|
@@ -1,101 +0,0 @@
|
|
|
-use std::path::PathBuf;
|
|
|
-use std::io::Read;
|
|
|
-use std::fs::File;
|
|
|
-
|
|
|
-use util::{SpotifyId, FileId, ReadSeek, mkdir_existing};
|
|
|
-use authentication::Credentials;
|
|
|
-use audio_key::AudioKey;
|
|
|
-
|
|
|
-use super::Cache;
|
|
|
-
|
|
|
-pub struct DefaultCache {
|
|
|
- environment: lmdb::Environment,
|
|
|
- root: PathBuf,
|
|
|
-}
|
|
|
-
|
|
|
-impl DefaultCache {
|
|
|
- pub fn new(location: PathBuf) -> Result<DefaultCache, ()> {
|
|
|
- let env = lmdb::EnvBuilder::new().max_dbs(5).open(&location.join("db"), 0o755).unwrap();
|
|
|
-
|
|
|
- mkdir_existing(&location).unwrap();
|
|
|
- mkdir_existing(&location.join("files")).unwrap();
|
|
|
-
|
|
|
- Ok(DefaultCache {
|
|
|
- environment: env,
|
|
|
- root: location
|
|
|
- })
|
|
|
- }
|
|
|
-
|
|
|
- fn audio_keys(&self) -> MdbResult<lmdb::DbHandle> {
|
|
|
- self.environment.create_db("audio-keys", lmdb::DbFlags::empty())
|
|
|
- }
|
|
|
-
|
|
|
- fn file_path(&self, file: FileId) -> PathBuf {
|
|
|
- let name = file.to_base16();
|
|
|
- self.root.join("files").join(&name[0..2]).join(&name[2..])
|
|
|
- }
|
|
|
-
|
|
|
- fn credentials_path(&self) -> PathBuf {
|
|
|
- self.root.join("credentials.json")
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-impl Cache for DefaultCache {
|
|
|
- fn get_audio_key(&self, track: SpotifyId, file: FileId) -> Option<AudioKey> {
|
|
|
- let reader = self.environment.get_reader().unwrap();
|
|
|
- let handle = self.audio_keys().unwrap();
|
|
|
- let db = reader.bind(&handle);
|
|
|
-
|
|
|
- let mut key = Vec::new();
|
|
|
- key.extend_from_slice(&track.to_raw());
|
|
|
- key.extend_from_slice(&file.0);
|
|
|
-
|
|
|
- let value : Option<Vec<_>> = db.get(&key).ok();
|
|
|
- value.and_then(|value| if value.len() == 16 {
|
|
|
- let mut result = [0u8; 16];
|
|
|
- result.clone_from_slice(&value);
|
|
|
- Some(AudioKey(result))
|
|
|
- } else {
|
|
|
- None
|
|
|
- })
|
|
|
- }
|
|
|
-
|
|
|
- fn put_audio_key(&self, track: SpotifyId, file: FileId, audio_key: AudioKey) {
|
|
|
- let xact = self.environment.new_transaction().unwrap();
|
|
|
- let handle = self.audio_keys().unwrap();
|
|
|
-
|
|
|
- {
|
|
|
- let db = xact.bind(&handle);
|
|
|
-
|
|
|
- let mut key = Vec::new();
|
|
|
- key.extend_from_slice(&track.to_raw());
|
|
|
- key.extend_from_slice(&file.0);
|
|
|
-
|
|
|
- db.set(&key, &audio_key.0.as_ref()).unwrap();
|
|
|
- }
|
|
|
-
|
|
|
- xact.commit().unwrap();
|
|
|
- }
|
|
|
-
|
|
|
- fn get_credentials(&self) -> Option<Credentials> {
|
|
|
- let path = self.credentials_path();
|
|
|
- Credentials::from_file(path)
|
|
|
- }
|
|
|
- fn put_credentials(&self, cred: &Credentials) {
|
|
|
- let path = self.credentials_path();
|
|
|
- cred.save_to_file(&path);
|
|
|
- }
|
|
|
-
|
|
|
- fn get_file(&self, file: FileId) -> Option<Box<ReadSeek>> {
|
|
|
- File::open(self.file_path(file)).ok().map(|f| Box::new(f) as Box<ReadSeek>)
|
|
|
- }
|
|
|
-
|
|
|
- fn put_file(&self, file: FileId, contents: &mut Read) {
|
|
|
- let path = self.file_path(file);
|
|
|
-
|
|
|
- mkdir_existing(path.parent().unwrap()).unwrap();
|
|
|
-
|
|
|
- let mut cache_file = File::create(path).unwrap();
|
|
|
- ::std::io::copy(contents, &mut cache_file).unwrap();
|
|
|
- }
|
|
|
-}
|