<commit_before>// Copyright 2014 Google Inc. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

//! Combines data chunks into larger blobs to be stored externally.

use std::sync::{Arc, Mutex};

use serialize::{json, Encodable, Decodable};
use serialize::hex::{ToHex};
use serialize::json::{Json, ToJson, Decoder, from_str};

use std::collections::treemap::{TreeMap};
use std::collections::lru_cache::{LruCache};

use std::io::{File};
use std::str;

use process::{Process, MsgHandler};

use blob_index;
use blob_index::{BlobIndexProcess};

#[cfg(test)]
use blob_index::{BlobIndex};

pub type BlobStoreProcess<B> = Process<Msg, Reply, BlobStore<B>>;

pub trait BlobStoreBackend {
  fn store(&mut self, name: &[u8], data: &[u8]) -> Result<(), String>;
  fn retrieve(&mut self, name: &[u8]) -> Result<Vec<u8>, String>;
}

#[deriving(Clone)]
pub struct FileBackend {
  root: Path,
  read_cache: Arc<Mutex<LruCache<Vec<u8>, Result<Vec<u8>, String>>>>,
}

impl FileBackend {

  pub fn new(root: Path) -> FileBackend {
    FileBackend{root: root, read_cache: Arc::new(Mutex::new(LruCache::new(10)))}
  }

}

impl BlobStoreBackend for FileBackend {

  fn store(&mut self, name: &[u8], data: &[u8]) -> Result<(), String> {
    let mut path = self.root.clone();
    path.push(name.to_hex());

    let mut file = match File::create(&path) {
      Err(e) => return Err(e.to_str()),
      Ok(f) => f,
    };

    match file.write(data) {
      Err(e) => Err(e.to_str()),
      Ok(()) => Ok(()),
    }
  }

  fn retrieve(&mut self, name: &[u8]) -> Result<Vec<u8>, String> {
    // Check for key in cache:
    let value_opt = {
      let mut guarded_cache = self.read_cache.lock();
      guarded_cache.get(&name.clone().into_owned()).map(|v| v.clone())
    };
    match value_opt {
      Some(result) => return result.clone(),
      None => (),
    }

    // Read key:
    let path = { let mut p = self.root.clone();
                 p.push(name.to_hex());
                 p };

    let mut fd = File::open(&path).unwrap();

    let res = fd.read_to_end().and_then(|data| {
      Ok(data.as_slice().into_owned()) }).or_else(|e| Err(e.to_str()));

    // Update cache to contain key:
    {
      let mut guarded_cache = self.read_cache.lock();
      guarded_cache.put(name.clone().to_owned(), res.clone());
    }

    return res;
  }

}

#[deriving(Show, Clone, Eq, PartialEq, Encodable, Decodable)]
pub struct BlobID {
  name: Vec<u8>,
  begin: uint,
  end: uint,
}

impl BlobID {

  pub fn from_bytes(bytes: Vec<u8>) -> BlobID {
    let mut decoder = Decoder::new(from_str(
      str::from_utf8(bytes.as_slice()).unwrap()).unwrap());
    Decodable::decode(&mut decoder).unwrap()
  }

  pub fn as_bytes(&self) -> Vec<u8> {
    self.to_json().to_str().as_bytes().into_owned()
  }

}

impl ToJson for BlobID {
  fn to_json(&self) -> Json {
    let mut m = box TreeMap::new();
    m.insert("name".to_string(), self.name.to_json());
    m.insert("begin".to_string(), self.begin.to_json());
    m.insert("end".to_string(), self.end.to_json());
    json::Object(m).to_json()
  }
}

pub enum Msg {
  /// Store a new data chunk into the current blob. The callback is triggered after the blob
  /// containing the chunk has been committed to persistent storage (it is then safe to use the
  /// `BlobID` as persistent reference).
  Store(Vec<u8>, proc(BlobID):Send -> ()),
  /// Retrieve the data chunk identified by `BlobID`.
  Retrieve(BlobID),
  /// Flush the current blob, independent of its size.
  Flush,
}

#[deriving(Eq, PartialEq, Show)]
pub enum Reply {
  StoreOK(BlobID),
  RetrieveOK(Vec<u8>),
  FlushOK,
}

pub struct BlobStore<B> {
  backend: B,

  blob_index: Box<BlobIndexProcess>,
  blob_desc: blob_index::BlobDesc,

  buffer_data: Vec<(BlobID, Vec<u8>, proc(BlobID):Send -> ())>,
  buffer_data_len: uint,

  max_blob_size: uint,
}

fn empty_blob_desc() -> blob_index::BlobDesc {
  blob_index::BlobDesc{name: b"".into_owned(), id: 0}
}

impl <B: BlobStoreBackend> BlobStore<B> {

  pub fn new(index: Box<BlobIndexProcess>, backend: B,
             max_blob_size: uint) -> BlobStore<B> {
    let mut bs = BlobStore{
      backend: backend,
      blob_index: index,
      blob_desc: empty_blob_desc(),
      buffer_data: Vec::new(),
      buffer_data_len: 0,
      max_blob_size: max_blob_size,
    };
    bs.reserve_new_blob();
    bs
  }

  #[cfg(test)]
  pub fn newForTesting(backend: B, max_blob_size: uint) -> BlobStore<B> {
    let biP = Process::new(proc() { BlobIndex::newForTesting() });
    let mut bs = BlobStore{backend: backend,
                           blob_index: biP,
                           blob_desc: empty_blob_desc(),
                           buffer_data: Vec::new(),
                           buffer_data_len: 0,
                           max_blob_size: max_blob_size,
                          };
    bs.reserve_new_blob();
    bs
  }

  fn reserve_new_blob(&mut self) -> blob_index::BlobDesc {
    let old_blob_desc = self.blob_desc.clone();

    let res = self.blob_index.sendReply(blob_index::Reserve);
    match res {
      blob_index::Reserved(blob_desc) => {
        self.blob_desc = blob_desc;
      },
      _ => fail!("Could not reserve blob."),
    }

    old_blob_desc
  }

  fn backend_store(&mut self, name: &[u8], blob: &[u8]) {
    match self.backend.store(name, blob) {
      Ok(()) => (),
      Err(s) => fail!(s),
    }
  }

  fn backend_read(&mut self, name: &[u8]) -> Vec<u8> {
    match self.backend.retrieve(name) {
      Ok(data) => data,
      Err(s) => fail!(s),
    }
  }

  fn flush(&mut self) {
    if self.buffer_data_len == 0 { return }

    // Replace blob id
    let old_blob_desc = self.reserve_new_blob();
    self.buffer_data_len = 0;

    // Prepare blob
    let mut ready_callback = Vec::new();
    let mut blob = Vec::new();
    loop {
      match self.buffer_data.shift() {
        Some((chunk_ref, chunk, cb)) => {
          ready_callback.push((chunk_ref, cb));
          blob.push_all(chunk.as_slice());
        },
        None => break,
      }
    }

    self.blob_index.sendReply(blob_index::InAir(old_blob_desc.clone()));
    self.backend_store(old_blob_desc.name.as_slice(), blob.as_slice());
    self.blob_index.sendReply(blob_index::CommitDone(old_blob_desc));

    // Go through callbacks
    for (blobid, cb) in ready_callback.move_iter() {
      cb(blobid);
    }
  }

  fn maybeFlush(&mut self) {
    if self.buffer_data_len >= self.max_blob_size {
      self.flush();
    }
  }
}

impl <B: BlobStoreBackend> MsgHandler<Msg, Reply> for BlobStore<B> {

  fn handle(&mut self, msg: Msg, reply: |Reply|) {
    match msg {

      Store(blob, cb) => {
        if blob.len() == 0 {
          let id = BlobID{name: vec!(0), begin: 0, end: 0};
          let cb_id = id.clone();
          spawn(proc(){ cb(cb_id) });
          return reply(StoreOK(id));
        }

        let new_size = self.buffer_data_len + blob.len();
        let id = BlobID{name: self.blob_desc.name.clone(),
                        begin: self.buffer_data_len,
                        end: new_size};

        self.buffer_data_len = new_size;
        self.buffer_data.push((id.clone(), blob.as_slice().into_owned(), cb));

        // To avoid unnecessary blocking, we reply with the ID *before* possibly flushing.
        reply(StoreOK(id));

        // Flushing can be expensive, so try not block on it.
        self.maybeFlush();
       },

      Retrieve(id) => {
        if id.begin == 0 && id.end == 0 {
          return reply(RetrieveOK(vec![].as_slice().into_owned()));
        }
        let blob = self.backend_read(id.name.as_slice());
        let chunk = blob.slice(id.begin, id.end);
        return reply(RetrieveOK(chunk.as_slice().into_owned()));
      },

      Flush => {
        self.flush();
        return reply(FlushOK)
      },

    }
  }

}

#[cfg(test)]
pub mod tests {
  use super::*;
  use std::rand::{task_rng};
  use quickcheck::{Config, Testable, gen};
  use quickcheck::{quickcheck_config};

  use process::{Process};

  use std::sync::{Arc, Mutex};
  use std::collections::treemap::{TreeMap};

  #[deriving(Clone)]
  pub struct MemoryBackend {
    files: Arc<Mutex<TreeMap<Vec<u8>, Vec<u8>>>>
  }

  impl MemoryBackend {
    pub fn new() -> MemoryBackend {
      MemoryBackend{files: Arc::new(Mutex::new(TreeMap::new()))}
    }
  }

  impl BlobStoreBackend for MemoryBackend {

    fn store(&mut self, name: &[u8], data: &[u8]) -> Result<(), String> {
      let key = name.to_owned();

      {
        let mut guarded_files = self.files.lock();
        if guarded_files.contains_key(&key) {
          return Err(format!("Key already exists: '{}'", name));
        }
        guarded_files.insert(key, data.into_owned());
      }

      return Ok(());
    }

    fn retrieve(&mut self, name: &[u8]) -> Result<Vec<u8>, String> {
      let key = name.to_owned();

      let value_opt = {
        let mut guarded_files = self.files.lock();
        guarded_files.find(&key).map(|v| v.clone())
      };
      return value_opt.map(|v| Ok(v)).unwrap_or_else(|| Err(format!("Unknown key: '{}'", name)));
    }
  }

  #[deriving(Clone)]
  pub struct DevNullBackend;

  impl BlobStoreBackend for DevNullBackend {
    fn store(&mut self, _name: &[u8], _data: &[u8]) -> Result<(), String> {
      Ok(())
    }
    fn retrieve(&mut self, name: &[u8]) -> Result<Vec<u8>, String> {
      Err(format!("Unknown key: '{}'", name))
    }
  }

  // QuickCheck configuration
  static SIZE: uint = 100;
  static CONFIG: Config = Config {
    tests: 200,
    max_tests: 1000,
  };

  // QuickCheck helpers:
  fn qcheck<A: Testable>(f: A) {
    quickcheck_config(CONFIG, &mut gen(task_rng(), SIZE), f)
  }

  #[test]
  fn identity() {
    fn prop(chunks: Vec<Vec<u8>>) -> bool {
      let mut backend = MemoryBackend::new();

      let local_backend = backend.clone();
      let bsP : Box<BlobStoreProcess<MemoryBackend>> =
        Process::new(proc() { BlobStore::newForTesting(local_backend, 1024) });

      let mut ids = Vec::new();
      for chunk in chunks.iter() {
        match bsP.sendReply(Store(chunk.as_slice().into_owned(), proc(_){})) {
          StoreOK(id) => { ids.push((id, chunk)); },
          _ => fail!("Unexpected reply from blob store."),
        }
      }

      assert_eq!(bsP.sendReply(Flush), FlushOK);

      // Non-empty chunks must be in the backend now:
      for &(ref id, chunk) in ids.iter() {
        if chunk.len() > 0 {
          match backend.retrieve(id.name.as_slice()) {
            Ok(_) => (),
            Err(e) => fail!(e),
          }
        }
      }

      // All chunks must be available through the blob store:
      for &(ref id, chunk) in ids.iter() {
        match bsP.sendReply(Retrieve(id.clone())) {
          RetrieveOK(found_chunk) => assert_eq!(found_chunk,
                                                chunk.as_slice().into_owned()),
          _ => fail!("Unexpected reply from blob store."),
        }
      }

      return true;
    }
    qcheck(prop);
  }

  #[test]
  fn identity_with_excessive_flushing() {
    fn prop(chunks: Vec<Vec<u8>>) -> bool {
      let mut backend = MemoryBackend::new();

      let local_backend = backend.clone();
      let bsP: Box<BlobStoreProcess<MemoryBackend>> = Process::new(proc() {
        BlobStore::newForTesting(local_backend, 1024) });

      let mut ids = Vec::new();
      for chunk in chunks.iter() {
        match bsP.sendReply(Store(chunk.as_slice().into_owned(), proc(_){})) {
          StoreOK(id) => { ids.push((id, chunk)); },
          _ => fail!("Unexpected reply from blob store."),
        }
        assert_eq!(bsP.sendReply(Flush), FlushOK);
        let &(ref id, chunk) = ids.last().unwrap();
        assert_eq!(bsP.sendReply(Retrieve(id.clone())), RetrieveOK(chunk.clone().into_owned()));
      }

      // Non-empty chunks must be in the backend now:
      for &(ref id, chunk) in ids.iter() {
        if chunk.len() > 0 {
          match backend.retrieve(id.name.as_slice()) {
            Ok(_) => (),
            Err(e) => fail!(e),
          }
        }
      }

      // All chunks must be available through the blob store:
      for &(ref id, chunk) in ids.iter() {
        match bsP.sendReply(Retrieve(id.clone())) {
          RetrieveOK(found_chunk) => assert_eq!(found_chunk,
                                                chunk.as_slice().into_owned()),
          _ => fail!("Unexpected reply from blob store."),
        }
      }

      return true;
    }
    qcheck(prop);
  }

  #[test]
  fn blobid_identity() {
    fn prop(name: Vec<u8>, begin: uint, end: uint) -> bool {
      let blob_id = BlobID{name: name.as_slice().into_owned(),
                           begin: begin, end: end};
      BlobID::from_bytes(blob_id.as_bytes()) == blob_id
    }
    qcheck(prop);
  }

}
<commit_msg>Promote some lock requiring code into "guarded_*" functions.<commit_after>// Copyright 2014 Google Inc. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

//! Combines data chunks into larger blobs to be stored externally.

use std::sync::{Arc, Mutex};

use serialize::{json, Encodable, Decodable};
use serialize::hex::{ToHex};
use serialize::json::{Json, ToJson, Decoder, from_str};

use std::collections::treemap::{TreeMap};
use std::collections::lru_cache::{LruCache};

use std::io::{File};
use std::str;

use process::{Process, MsgHandler};

use blob_index;
use blob_index::{BlobIndexProcess};

#[cfg(test)]
use blob_index::{BlobIndex};

pub type BlobStoreProcess<B> = Process<Msg, Reply, BlobStore<B>>;

pub trait BlobStoreBackend {
  fn store(&mut self, name: &[u8], data: &[u8]) -> Result<(), String>;
  fn retrieve(&mut self, name: &[u8]) -> Result<Vec<u8>, String>;
}

#[deriving(Clone)]
pub struct FileBackend {
  root: Path,
  read_cache: Arc<Mutex<LruCache<Vec<u8>, Result<Vec<u8>, String>>>>,
}

impl FileBackend {

  pub fn new(root: Path) -> FileBackend {
    FileBackend{root: root, read_cache: Arc::new(Mutex::new(LruCache::new(10)))}
  }

  fn guarded_cache_get(&self, name: &Vec<u8>) -> Option<Result<Vec<u8>, String>> {
    self.read_cache.lock().get(name).map(|v| v.clone())
  }

  fn guarded_cache_put(&mut self, name: Vec<u8>, result: Result<Vec<u8>, String>) {
    self.read_cache.lock().put(name, result);
  }
}

impl BlobStoreBackend for FileBackend {

  fn store(&mut self, name: &[u8], data: &[u8]) -> Result<(), String> {
    let mut path = self.root.clone();
    path.push(name.to_hex());

    let mut file = match File::create(&path) {
      Err(e) => return Err(e.to_str()),
      Ok(f) => f,
    };

    match file.write(data) {
      Err(e) => Err(e.to_str()),
      Ok(()) => Ok(()),
    }
  }

  fn retrieve(&mut self, name: &[u8]) -> Result<Vec<u8>, String> {
    // Check for key in cache:
    let name = name.clone().into_owned();
    let value_opt = self.guarded_cache_get(&name);
    match value_opt {
      Some(result) => return result.clone(),
      None => (),
    }

    // Read key:
    let path = { let mut p = self.root.clone();
                 p.push(name.as_slice().to_hex());
                 p };

    let mut fd = File::open(&path).unwrap();

    let res = fd.read_to_end().and_then(|data| {
      Ok(data.as_slice().into_owned()) }).or_else(|e| Err(e.to_str()));

    // Update cache to contain key:
    self.guarded_cache_put(name, res.clone());

    return res;
  }

}

#[deriving(Show, Clone, Eq, PartialEq, Encodable, Decodable)]
pub struct BlobID {
  name: Vec<u8>,
  begin: uint,
  end: uint,
}

impl BlobID {

  pub fn from_bytes(bytes: Vec<u8>) -> BlobID {
    let mut decoder = Decoder::new(from_str(
      str::from_utf8(bytes.as_slice()).unwrap()).unwrap());
    Decodable::decode(&mut decoder).unwrap()
  }

  pub fn as_bytes(&self) -> Vec<u8> {
    self.to_json().to_str().as_bytes().into_owned()
  }

}

impl ToJson for BlobID {
  fn to_json(&self) -> Json {
    let mut m = box TreeMap::new();
    m.insert("name".to_string(), self.name.to_json());
    m.insert("begin".to_string(), self.begin.to_json());
    m.insert("end".to_string(), self.end.to_json());
    json::Object(m).to_json()
  }
}

pub enum Msg {
  /// Store a new data chunk into the current blob. The callback is triggered after the blob
  /// containing the chunk has been committed to persistent storage (it is then safe to use the
  /// `BlobID` as persistent reference).
  Store(Vec<u8>, proc(BlobID):Send -> ()),
  /// Retrieve the data chunk identified by `BlobID`.
  Retrieve(BlobID),
  /// Flush the current blob, independent of its size.
  Flush,
}

#[deriving(Eq, PartialEq, Show)]
pub enum Reply {
  StoreOK(BlobID),
  RetrieveOK(Vec<u8>),
  FlushOK,
}

pub struct BlobStore<B> {
  backend: B,

  blob_index: Box<BlobIndexProcess>,
  blob_desc: blob_index::BlobDesc,

  buffer_data: Vec<(BlobID, Vec<u8>, proc(BlobID):Send -> ())>,
  buffer_data_len: uint,

  max_blob_size: uint,
}

fn empty_blob_desc() -> blob_index::BlobDesc {
  blob_index::BlobDesc{name: b"".into_owned(), id: 0}
}

impl <B: BlobStoreBackend> BlobStore<B> {

  pub fn new(index: Box<BlobIndexProcess>, backend: B,
             max_blob_size: uint) -> BlobStore<B> {
    let mut bs = BlobStore{
      backend: backend,
      blob_index: index,
      blob_desc: empty_blob_desc(),
      buffer_data: Vec::new(),
      buffer_data_len: 0,
      max_blob_size: max_blob_size,
    };
    bs.reserve_new_blob();
    bs
  }

  #[cfg(test)]
  pub fn newForTesting(backend: B, max_blob_size: uint) -> BlobStore<B> {
    let biP = Process::new(proc() { BlobIndex::newForTesting() });
    let mut bs = BlobStore{backend: backend,
                           blob_index: biP,
                           blob_desc: empty_blob_desc(),
                           buffer_data: Vec::new(),
                           buffer_data_len: 0,
                           max_blob_size: max_blob_size,
                          };
    bs.reserve_new_blob();
    bs
  }

  fn reserve_new_blob(&mut self) -> blob_index::BlobDesc {
    let old_blob_desc = self.blob_desc.clone();

    let res = self.blob_index.sendReply(blob_index::Reserve);
    match res {
      blob_index::Reserved(blob_desc) => {
        self.blob_desc = blob_desc;
      },
      _ => fail!("Could not reserve blob."),
    }

    old_blob_desc
  }

  fn backend_store(&mut self, name: &[u8], blob: &[u8]) {
    match self.backend.store(name, blob) {
      Ok(()) => (),
      Err(s) => fail!(s),
    }
  }

  fn backend_read(&mut self, name: &[u8]) -> Vec<u8> {
    match self.backend.retrieve(name) {
      Ok(data) => data,
      Err(s) => fail!(s),
    }
  }

  fn flush(&mut self) {
    if self.buffer_data_len == 0 { return }

    // Replace blob id
    let old_blob_desc = self.reserve_new_blob();
    self.buffer_data_len = 0;

    // Prepare blob
    let mut ready_callback = Vec::new();
    let mut blob = Vec::new();
    loop {
      match self.buffer_data.shift() {
        Some((chunk_ref, chunk, cb)) => {
          ready_callback.push((chunk_ref, cb));
          blob.push_all(chunk.as_slice());
        },
        None => break,
      }
    }

    self.blob_index.sendReply(blob_index::InAir(old_blob_desc.clone()));
    self.backend_store(old_blob_desc.name.as_slice(), blob.as_slice());
    self.blob_index.sendReply(blob_index::CommitDone(old_blob_desc));

    // Go through callbacks
    for (blobid, cb) in ready_callback.move_iter() {
      cb(blobid);
    }
  }

  fn maybeFlush(&mut self) {
    if self.buffer_data_len >= self.max_blob_size {
      self.flush();
    }
  }
}

impl <B: BlobStoreBackend> MsgHandler<Msg, Reply> for BlobStore<B> {

  fn handle(&mut self, msg: Msg, reply: |Reply|) {
    match msg {

      Store(blob, cb) => {
        if blob.len() == 0 {
          let id = BlobID{name: vec!(0), begin: 0, end: 0};
          let cb_id = id.clone();
          spawn(proc(){ cb(cb_id) });
          return reply(StoreOK(id));
        }

        let new_size = self.buffer_data_len + blob.len();
        let id = BlobID{name: self.blob_desc.name.clone(),
                        begin: self.buffer_data_len,
                        end: new_size};

        self.buffer_data_len = new_size;
        self.buffer_data.push((id.clone(), blob.as_slice().into_owned(), cb));

        // To avoid unnecessary blocking, we reply with the ID *before* possibly flushing.
        reply(StoreOK(id));

        // Flushing can be expensive, so try not block on it.
        self.maybeFlush();
       },

      Retrieve(id) => {
        if id.begin == 0 && id.end == 0 {
          return reply(RetrieveOK(vec![].as_slice().into_owned()));
        }
        let blob = self.backend_read(id.name.as_slice());
        let chunk = blob.slice(id.begin, id.end);
        return reply(RetrieveOK(chunk.as_slice().into_owned()));
      },

      Flush => {
        self.flush();
        return reply(FlushOK)
      },

    }
  }

}

#[cfg(test)]
pub mod tests {
  use super::*;
  use std::rand::{task_rng};
  use quickcheck::{Config, Testable, gen};
  use quickcheck::{quickcheck_config};

  use process::{Process};

  use std::sync::{Arc, Mutex};
  use std::collections::treemap::{TreeMap};

  #[deriving(Clone)]
  pub struct MemoryBackend {
    files: Arc<Mutex<TreeMap<Vec<u8>, Vec<u8>>>>
  }

  impl MemoryBackend {
    pub fn new() -> MemoryBackend {
      MemoryBackend{files: Arc::new(Mutex::new(TreeMap::new()))}
    }

    fn guarded_insert(&mut self, key: Vec<u8>, value: Vec<u8>) -> Result<(), String>{
      let mut guarded_files = self.files.lock();
      if guarded_files.contains_key(&key) {
        return Err(format!("Key already exists: '{}'", key));
      }
      guarded_files.insert(key, value);
      Ok(())
    }

    fn guarded_retrieve(&mut self, key: &[u8]) -> Result<Vec<u8>, String> {
      let value_opt = self.files.lock().find(&key.into_owned()).map(|v| v.clone());
      value_opt.map(|v| Ok(v)).unwrap_or_else(|| Err(format!("Unknown key: '{}'", key)))
    }
  }

  impl BlobStoreBackend for MemoryBackend {

    fn store(&mut self, name: &[u8], data: &[u8]) -> Result<(), String> {
      self.guarded_insert(name.to_owned(), data.clone().into_owned())
    }

    fn retrieve(&mut self, name: &[u8]) -> Result<Vec<u8>, String> {
      self.guarded_retrieve(name)
    }
  }

  #[deriving(Clone)]
  pub struct DevNullBackend;

  impl BlobStoreBackend for DevNullBackend {
    fn store(&mut self, _name: &[u8], _data: &[u8]) -> Result<(), String> {
      Ok(())
    }
    fn retrieve(&mut self, name: &[u8]) -> Result<Vec<u8>, String> {
      Err(format!("Unknown key: '{}'", name))
    }
  }

  // QuickCheck configuration
  static SIZE: uint = 100;
  static CONFIG: Config = Config {
    tests: 200,
    max_tests: 1000,
  };

  // QuickCheck helpers:
  fn qcheck<A: Testable>(f: A) {
    quickcheck_config(CONFIG, &mut gen(task_rng(), SIZE), f)
  }

  #[test]
  fn identity() {
    fn prop(chunks: Vec<Vec<u8>>) -> bool {
      let mut backend = MemoryBackend::new();

      let local_backend = backend.clone();
      let bsP : Box<BlobStoreProcess<MemoryBackend>> =
        Process::new(proc() { BlobStore::newForTesting(local_backend, 1024) });

      let mut ids = Vec::new();
      for chunk in chunks.iter() {
        match bsP.sendReply(Store(chunk.as_slice().into_owned(), proc(_){})) {
          StoreOK(id) => { ids.push((id, chunk)); },
          _ => fail!("Unexpected reply from blob store."),
        }
      }

      assert_eq!(bsP.sendReply(Flush), FlushOK);

      // Non-empty chunks must be in the backend now:
      for &(ref id, chunk) in ids.iter() {
        if chunk.len() > 0 {
          match backend.retrieve(id.name.as_slice()) {
            Ok(_) => (),
            Err(e) => fail!(e),
          }
        }
      }

      // All chunks must be available through the blob store:
      for &(ref id, chunk) in ids.iter() {
        match bsP.sendReply(Retrieve(id.clone())) {
          RetrieveOK(found_chunk) => assert_eq!(found_chunk,
                                                chunk.as_slice().into_owned()),
          _ => fail!("Unexpected reply from blob store."),
        }
      }

      return true;
    }
    qcheck(prop);
  }

  #[test]
  fn identity_with_excessive_flushing() {
    fn prop(chunks: Vec<Vec<u8>>) -> bool {
      let mut backend = MemoryBackend::new();

      let local_backend = backend.clone();
      let bsP: Box<BlobStoreProcess<MemoryBackend>> = Process::new(proc() {
        BlobStore::newForTesting(local_backend, 1024) });

      let mut ids = Vec::new();
      for chunk in chunks.iter() {
        match bsP.sendReply(Store(chunk.as_slice().into_owned(), proc(_){})) {
          StoreOK(id) => { ids.push((id, chunk)); },
          _ => fail!("Unexpected reply from blob store."),
        }
        assert_eq!(bsP.sendReply(Flush), FlushOK);
        let &(ref id, chunk) = ids.last().unwrap();
        assert_eq!(bsP.sendReply(Retrieve(id.clone())), RetrieveOK(chunk.clone().into_owned()));
      }

      // Non-empty chunks must be in the backend now:
      for &(ref id, chunk) in ids.iter() {
        if chunk.len() > 0 {
          match backend.retrieve(id.name.as_slice()) {
            Ok(_) => (),
            Err(e) => fail!(e),
          }
        }
      }

      // All chunks must be available through the blob store:
      for &(ref id, chunk) in ids.iter() {
        match bsP.sendReply(Retrieve(id.clone())) {
          RetrieveOK(found_chunk) => assert_eq!(found_chunk,
                                                chunk.as_slice().into_owned()),
          _ => fail!("Unexpected reply from blob store."),
        }
      }

      return true;
    }
    qcheck(prop);
  }

  #[test]
  fn blobid_identity() {
    fn prop(name: Vec<u8>, begin: uint, end: uint) -> bool {
      let blob_id = BlobID{name: name.as_slice().into_owned(),
                           begin: begin, end: end};
      BlobID::from_bytes(blob_id.as_bytes()) == blob_id
    }
    qcheck(prop);
  }

}
<|endoftext|>


<commit_before>// Options
// Space before /
// Quote style
// Ordering of attributes

#[cfg(test)]
mod test {
    use std::io::{IoResult,MemWriter};

    use super::super::{Document,Element,Text,Comment};
    use super::super::{ElementElementChild,TextElementChild,CommentElementChild,PIElementChild};

    macro_rules! assert_str_eq(
        ($l:expr, $r:expr) => (assert_eq!($l.as_slice(), $r.as_slice()));
    )

    enum Content {
        WElement(Element),
        WElementEnd(String),
        WText(Text),
        WComment(Comment),
    }

    fn format_element<W : Writer>(element: Element, todo: &mut Vec<Content>, writer: &mut W) -> IoResult<()> {
        try!(write!(writer, "<{}", element.name()));

        for attr in element.attributes().iter() {
            try!(write!(writer, " {}='{}'", attr.name(), attr.value()));
        }

        let mut children = element.children();
        if children.is_empty() {
            writer.write_str("/>")
        } else {
            try!(writer.write_str(">"));

            todo.push(WElementEnd(element.name()));
            children.reverse();
            let x = children.move_iter().map(|c| match c {
                ElementElementChild(element) => WElement(element),
                TextElementChild(t) => WText(t),
                CommentElementChild(c) => WComment(c),
                PIElementChild(_) => fail!("PI?"),
            }).collect();
            todo.push_all_move(x);

            Ok(())
        }
    }

    fn format_document<W : Writer>(doc: &Document, writer: &mut W) -> IoResult<()> {
        let mut todo = Vec::new();

        try!(writer.write_str("<?xml version='1.0'?>"));
        let e = doc.root().children()[0].element().expect("not an element?");

        todo.push(WElement(e));

        while ! todo.is_empty() {
            match todo.pop().unwrap() {
                WElement(e) => try!(format_element(e, &mut todo, writer)),
                WElementEnd(name) => try!(write!(writer, "</{}>", name)),
                WText(t) => try!(writer.write_str(t.text().as_slice())),
                WComment(c) => try!(write!(writer, "<!--{}-->", c.text())),
            }
        }

        Ok(())
    }

    fn format_xml(doc: &Document) -> String {
        let mut w = MemWriter::new();
        format_document(doc, &mut w).ok().expect("Not formatted");
        String::from_utf8(w.unwrap()).ok().expect("Not a string")
    }

    #[test]
    fn top_element() {
        let d = Document::new();
        let e = d.new_element("hello".to_string());
        d.root().append_child(e);

        let xml = format_xml(&d);
        assert_str_eq!(xml, "<?xml version='1.0'?><hello/>");
    }

    #[test]
    fn element_with_attributes() {
        let d = Document::new();
        let e = d.new_element("hello".to_string());
        e.set_attribute("a".to_string(), "b".to_string());
        d.root().append_child(e);

        let xml = format_xml(&d);
        assert_str_eq!(xml, "<?xml version='1.0'?><hello a='b'/>");
    }

    #[test]
    fn nested_element() {
        let d = Document::new();
        let hello = d.new_element("hello".to_string());
        let world = d.new_element("world".to_string());
        hello.append_child(world);
        d.root().append_child(hello);

        let xml = format_xml(&d);
        assert_str_eq!(xml, "<?xml version='1.0'?><hello><world/></hello>");
    }

    #[test]
    fn nested_text() {
        let d = Document::new();
        let hello = d.new_element("hello".to_string());
        let text = d.new_text("A fine day to you!".to_string());
        hello.append_child(text);
        d.root().append_child(hello);

        let xml = format_xml(&d);
        assert_str_eq!(xml, "<?xml version='1.0'?><hello>A fine day to you!</hello>");
    }

    #[test]
    fn nested_comment() {
        let d = Document::new();
        let hello = d.new_element("hello".to_string());
        let comment = d.new_comment(" Fill this in ".to_string());
        hello.append_child(comment);
        d.root().append_child(hello);

        let xml = format_xml(&d);
        assert_str_eq!(xml, "<?xml version='1.0'?><hello><!-- Fill this in --></hello>");
    }
}
<commit_msg>Write processing instructions without values<commit_after>// Options
// Space before /
// Quote style
// Ordering of attributes

#[cfg(test)]
mod test {
    use std::io::{IoResult,MemWriter};

    use super::super::{Document,Element,Text,Comment,ProcessingInstruction};
    use super::super::{ElementElementChild,TextElementChild,CommentElementChild,PIElementChild};

    macro_rules! assert_str_eq(
        ($l:expr, $r:expr) => (assert_eq!($l.as_slice(), $r.as_slice()));
    )

    enum Content {
        WElement(Element),
        WElementEnd(String),
        WText(Text),
        WComment(Comment),
        WProcessingInstruction(ProcessingInstruction),
    }

    fn format_element<W : Writer>(element: Element, todo: &mut Vec<Content>, writer: &mut W) -> IoResult<()> {
        try!(write!(writer, "<{}", element.name()));

        for attr in element.attributes().iter() {
            try!(write!(writer, " {}='{}'", attr.name(), attr.value()));
        }

        let mut children = element.children();
        if children.is_empty() {
            writer.write_str("/>")
        } else {
            try!(writer.write_str(">"));

            todo.push(WElementEnd(element.name()));
            children.reverse();
            let x = children.move_iter().map(|c| match c {
                ElementElementChild(element) => WElement(element),
                TextElementChild(t) => WText(t),
                CommentElementChild(c) => WComment(c),
                PIElementChild(p) => WProcessingInstruction(p),
            }).collect();
            todo.push_all_move(x);

            Ok(())
        }
    }

    fn format_document<W : Writer>(doc: &Document, writer: &mut W) -> IoResult<()> {
        let mut todo = Vec::new();

        try!(writer.write_str("<?xml version='1.0'?>"));
        let e = doc.root().children()[0].element().expect("not an element?");

        todo.push(WElement(e));

        while ! todo.is_empty() {
            match todo.pop().unwrap() {
                WElement(e) => try!(format_element(e, &mut todo, writer)),
                WElementEnd(name) => try!(write!(writer, "</{}>", name)),
                WText(t) => try!(writer.write_str(t.text().as_slice())),
                WComment(c) => try!(write!(writer, "<!--{}-->", c.text())),
                WProcessingInstruction(p) => try!(write!(writer, "<?{}?>", p.target())),
            }
        }

        Ok(())
    }

    fn format_xml(doc: &Document) -> String {
        let mut w = MemWriter::new();
        format_document(doc, &mut w).ok().expect("Not formatted");
        String::from_utf8(w.unwrap()).ok().expect("Not a string")
    }

    #[test]
    fn top_element() {
        let d = Document::new();
        let e = d.new_element("hello".to_string());
        d.root().append_child(e);

        let xml = format_xml(&d);
        assert_str_eq!(xml, "<?xml version='1.0'?><hello/>");
    }

    #[test]
    fn element_with_attributes() {
        let d = Document::new();
        let e = d.new_element("hello".to_string());
        e.set_attribute("a".to_string(), "b".to_string());
        d.root().append_child(e);

        let xml = format_xml(&d);
        assert_str_eq!(xml, "<?xml version='1.0'?><hello a='b'/>");
    }

    #[test]
    fn nested_element() {
        let d = Document::new();
        let hello = d.new_element("hello".to_string());
        let world = d.new_element("world".to_string());
        hello.append_child(world);
        d.root().append_child(hello);

        let xml = format_xml(&d);
        assert_str_eq!(xml, "<?xml version='1.0'?><hello><world/></hello>");
    }

    #[test]
    fn nested_text() {
        let d = Document::new();
        let hello = d.new_element("hello".to_string());
        let text = d.new_text("A fine day to you!".to_string());
        hello.append_child(text);
        d.root().append_child(hello);

        let xml = format_xml(&d);
        assert_str_eq!(xml, "<?xml version='1.0'?><hello>A fine day to you!</hello>");
    }

    #[test]
    fn nested_comment() {
        let d = Document::new();
        let hello = d.new_element("hello".to_string());
        let comment = d.new_comment(" Fill this in ".to_string());
        hello.append_child(comment);
        d.root().append_child(hello);

        let xml = format_xml(&d);
        assert_str_eq!(xml, "<?xml version='1.0'?><hello><!-- Fill this in --></hello>");
    }

    #[test]
    fn nested_processing_instruction_without_value() {
        let d = Document::new();
        let hello = d.new_element("hello".to_string());
        let pi = d.new_processing_instruction("display".to_string(), None);
        hello.append_child(pi);
        d.root().append_child(hello);

        let xml = format_xml(&d);
        assert_str_eq!(xml, "<?xml version='1.0'?><hello><?display?></hello>");
    }
}
<|endoftext|>


<commit_before>#![feature(asm)]
#![feature(no_std)]
#![feature(const_fn)]
#![feature(core_str_ext)]
#![no_std]

mod intrinsics;
mod hypercall;

pub mod defs;

pub mod memory;
pub mod event;
pub mod sched;

pub mod console;

pub mod arch;

extern "C" {
    // This symbol must be present in code using libxen
    pub static mut shared_info: self::defs::SharedInfo;
}
<commit_msg>libxen: Add enable_upcalls and disable_upcalls<commit_after>#![feature(asm)]
#![feature(no_std)]
#![feature(const_fn)]
#![feature(core_str_ext)]
#![no_std]

mod intrinsics;
mod hypercall;

pub mod defs;

pub mod memory;
pub mod event;
pub mod sched;

pub mod console;

pub mod arch;

extern "C" {
    // This symbol must be present in code using libxen
    pub static mut shared_info: self::defs::SharedInfo;
}

pub fn enable_upcalls() -> u8 {
    unsafe {
        let ret = shared_info.vcpu_info[0].evtchn_upcall_mask;

        self::intrinsics::wmb();
        shared_info.vcpu_info[0].evtchn_upcall_mask = 0;
        self::intrinsics::wmb();

        ret
    }
}

pub fn disable_upcalls() -> u8 {
    unsafe {
        let ret = shared_info.vcpu_info[0].evtchn_upcall_mask;

        shared_info.vcpu_info[0].evtchn_upcall_mask = 1;
        self::intrinsics::wmb();

        ret
    }
}
<|endoftext|>


<commit_before>#![no_std]

#![allow(improper_ctypes)]

#![feature(asm)]

extern crate core;

use core::iter::Iterator;
use core::str::StrExt;
use core::str;
use core::option::Option;

use core::marker::Copy;
use core::slice::AsSlice;

impl Copy for Color {}

#[allow(dead_code)]
enum Color {
    Black      = 0,
    Blue       = 1,
    Green      = 2,
    Cyan       = 3,
    Red        = 4,
    Pink       = 5,
    Brown      = 6,
    LightGray  = 7,
    DarkGray   = 8,
    LightBlue  = 9,
    LightGreen = 10,
    LightCyan  = 11,
    LightRed   = 12,
    LightPink  = 13,
    Yellow     = 14,
    White      = 15,
}

struct IntRange {
    cur: isize,
    max: isize
}

impl IntRange {
    fn next(&mut self) -> Option<isize> {
        if self.cur < self.max {
            self.cur += 1;
            Option::Some(self.cur - 1)
        } else {
            Option::None
        }
    }
}

fn range(lo: isize, hi: isize) -> IntRange {
    IntRange { cur: lo, max: hi }
}

fn clear_screen(background: Color) {
    let mut r = range(0, 80 * 25);
    loop {
        match r.next() {
            Option::Some(x) => {
                unsafe {
                    *((0xb8000 + x * 2) as *mut u16) = (background as u16) << 12;
                }
            },
            Option::None =>{break}
        }
    }
}

fn print_string(string: &str) {
    let mut bytes = string.bytes();
    let mut count = 0;
    loop {
        match bytes.next() {
            Option::Some(x) => {
                unsafe {
                    *((0xb8000 + count) as *mut u8) = x;
                    *((0xb8000 + count + 1) as *mut u8) = 0x0f;
                }
                count = count + 2;
            },
            Option::None =>{break}
        }
    }
    move_cursor(0,string.len() as u8);
}

fn move_cursor(row: u8, col: u8) {
    let pos:u16 = (row*80 + col) as u16;
    outb(0x3D4,15);
    outb(0x3D5,(pos & 0xff) as u8);
    outb(0x3D4,14);
    outb(0x3D5,((pos >> 8) & 0xff) as u8);
}

fn outb(port:u16, value:u8) {
    unsafe {
        asm!(
        "out $0,$1"
        :
        : "{ax}"(value), "{dx}"(port)
        )
    }
}

struct IDTEntry {
    offset_lo: u16,
    selector: u16,
    zero: u8,
    type_attr: u8,
    offset_hi: u16
}

impl Copy for IDTEntry {}

struct IDT {
    entries: [IDTEntry; 256]
}
struct IDTR {
    length: u16,
    base: u32
}

static mut idt : IDT = IDT {entries: [IDTEntry {offset_lo: 0, selector: 0, zero: 0, type_attr: 0, offset_hi: 0};256]};

fn lidt() {
    unsafe {
        let idt_addr:*mut IDT = &mut idt;
        let idtr = IDTR {length: 256*8-1, base: (idt_addr) as u32};
        asm!("lidt ($0)"::"{ax}"(&idtr))
    }
}

extern {
    fn asm_int_handler();
}

fn init_int_49() {
    unsafe {
        let fnptr:unsafe extern fn() = asm_int_handler;
        let fnptr_addr = fnptr as u32;
        idt.entries[49] = IDTEntry {
            offset_lo: fnptr_addr as u16,
            selector: 0,
            zero: 0,
            type_attr: 0x8e,
            offset_hi: (fnptr_addr >> 16) as u16
        };
    }
}

extern {
    fn asm_int_49(foo : u32);
}

fn int_49(handler:unsafe extern fn()) {
    unsafe {
        asm_int_49(handler as u32);
    }
}

#[no_mangle]
#[no_stack_check]
pub fn main() {
    clear_screen(Color::LightRed);
    print_string("Hello world");
//    lidt();
//    init_int_49();
//    int_49(asm_int_handler);
    print_int(1234567890);
}

fn int_handler() {
    clear_screen(Color::Blue);
}

fn int_handler2() {
    clear_screen(Color::Green);
}

fn print_int(x:u32) {
    let mut left = x;
    let mut out:[u8;20] = [10;20];
    let mut pos = 0;

    loop {
        let rem = (left % 10) as u8;
        out[pos] = rem;
        pos = pos + 1;
        if (left < 10) {
            break;
        } else {
            left = left / 10;
        }
    }

    let mut i = 0;
    loop {
        if (i == 20) {
            break
        }
        unsafe {
            *((0xb8000 + i*2) as *mut u8) = out[20-1-i] + 48;
            *((0xb8000 + i*2 + 1) as *mut u8) = 0x0f;
        }
        i = i + 1;
    }
}
<commit_msg>Print hex<commit_after>#![no_std]

#![allow(improper_ctypes)]

#![feature(asm)]

extern crate core;

use core::iter::Iterator;
use core::str::StrExt;
use core::str;
use core::option::Option;

use core::marker::Copy;
use core::slice::AsSlice;

impl Copy for Color {}

#[allow(dead_code)]
enum Color {
    Black      = 0,
    Blue       = 1,
    Green      = 2,
    Cyan       = 3,
    Red        = 4,
    Pink       = 5,
    Brown      = 6,
    LightGray  = 7,
    DarkGray   = 8,
    LightBlue  = 9,
    LightGreen = 10,
    LightCyan  = 11,
    LightRed   = 12,
    LightPink  = 13,
    Yellow     = 14,
    White      = 15,
}

struct IntRange {
    cur: isize,
    max: isize
}

impl IntRange {
    fn next(&mut self) -> Option<isize> {
        if self.cur < self.max {
            self.cur += 1;
            Option::Some(self.cur - 1)
        } else {
            Option::None
        }
    }
}

fn range(lo: isize, hi: isize) -> IntRange {
    IntRange { cur: lo, max: hi }
}

fn clear_screen(background: Color) {
    let mut r = range(0, 80 * 25);
    loop {
        match r.next() {
            Option::Some(x) => {
                unsafe {
                    *((0xb8000 + x * 2) as *mut u16) = (background as u16) << 12;
                }
            },
            Option::None =>{break}
        }
    }
}

fn print_string(string: &str) {
    let mut bytes = string.bytes();
    let mut count = 0;
    loop {
        match bytes.next() {
            Option::Some(x) => {
                unsafe {
                    *((0xb8000 + count) as *mut u8) = x;
                    *((0xb8000 + count + 1) as *mut u8) = 0x0f;
                }
                count = count + 2;
            },
            Option::None =>{break}
        }
    }
    move_cursor(0,string.len() as u8);
}

fn move_cursor(row: u8, col: u8) {
    let pos:u16 = (row*80 + col) as u16;
    outb(0x3D4,15);
    outb(0x3D5,(pos & 0xff) as u8);
    outb(0x3D4,14);
    outb(0x3D5,((pos >> 8) & 0xff) as u8);
}

fn outb(port:u16, value:u8) {
    unsafe {
        asm!(
        "out $0,$1"
        :
        : "{ax}"(value), "{dx}"(port)
        )
    }
}

struct IDTEntry {
    offset_lo: u16,
    selector: u16,
    zero: u8,
    type_attr: u8,
    offset_hi: u16
}

impl Copy for IDTEntry {}

struct IDT {
    entries: [IDTEntry; 256]
}
struct IDTR {
    length: u16,
    base: u32
}

static mut idt : IDT = IDT {entries: [IDTEntry {offset_lo: 0, selector: 0, zero: 0, type_attr: 0, offset_hi: 0};256]};

fn lidt() {
    unsafe {
        let idt_addr:*mut IDT = &mut idt;
        let idtr = IDTR {length: 256*8-1, base: (idt_addr) as u32};
        asm!("lidt ($0)"::"{ax}"(&idtr))
    }
}

extern {
    fn asm_int_handler();
}

fn init_int_49() {
    unsafe {
        let fnptr:unsafe extern fn() = asm_int_handler;
        let fnptr_addr = fnptr as u32;
        idt.entries[49] = IDTEntry {
            offset_lo: fnptr_addr as u16,
            selector: 0,
            zero: 0,
            type_attr: 0x8e,
            offset_hi: (fnptr_addr >> 16) as u16
        };
    }
}

extern {
    fn asm_int_49(foo : u32);
}

fn int_49(handler:unsafe extern fn()) {
    unsafe {
        asm_int_49(handler as u32);
    }
}

#[no_mangle]
#[no_stack_check]
pub fn main() {
    clear_screen(Color::LightRed);
    print_string("Hello world");
//    lidt();
//    init_int_49();
//    int_49(asm_int_handler);
    print_int(0xDEADBEEF);
}

fn int_handler() {
    clear_screen(Color::Blue);
}

fn int_handler2() {
    clear_screen(Color::Green);
}

fn print_int(x:u32) {
    let mut left = x;
    let mut out:[u8;8] = [10;8];
    let mut pos = 0;

    loop {
        let rem = (left % 16) as u8;
        out[pos] = rem;
        pos = pos + 1;
        if (left < 16) {
            break;
        } else {
            left = left / 16;
        }
    }

    let mut i = 0;
    loop {
        if (i == 8) {
            break
        }
        unsafe {
            let val = out[8-1-i];
            if (val < 10) {
                *((0xb8000 + i*2) as *mut u8) = val + 48;
            } else {
                *((0xb8000 + i*2) as *mut u8) = (val - 10) + 65;
            }
            *((0xb8000 + i*2 + 1) as *mut u8) = 0x0f;
        }
        i = i + 1;
    }
}
<|endoftext|>


<commit_before>use Conn;
use conn::futures::new_raw_query_result::NewRawQueryResult;
use conn::futures::query_result::RawQueryResult;
use conn::futures::query_result::TextQueryResult;
use conn::futures::query_result::TextResult;
use conn::futures::write_packet::WritePacket;
use errors::*;
use lib_futures::Async;
use lib_futures::Async::Ready;
use lib_futures::Future;
use lib_futures::Poll;

enum Step {
    WriteCommandData(WritePacket),
    HandleResultSet(NewRawQueryResult<TextResult>),
}

enum Out {
    WriteCommandData(Conn),
    HandleResultSet(RawQueryResult<TextResult>),
}

/// Future that resolves to result of a query execution.
pub struct Query {
    step: Step,
}

pub fn new_new(write_packet: WritePacket) -> Query {
    Query {
        step: Step::WriteCommandData(write_packet),
    }
}

impl Query {
    fn either_poll(&mut self) -> Result<Async<Out>> {
        match self.step {
            Step::WriteCommandData(ref mut fut) => {
                let val = try_ready!(fut.poll());
                Ok(Ready(Out::WriteCommandData(val)))
            },
            Step::HandleResultSet(ref mut fut) => {
                let val = try_ready!(fut.poll());
                Ok(Ready(Out::HandleResultSet(val)))
            }
        }
    }
}

impl Future for Query {
    type Item = TextQueryResult;
    type Error = Error;

    fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
        match try_ready!(self.either_poll()) {
            Out::WriteCommandData(conn) => {
                self.step = Step::HandleResultSet(conn.handle_result_set(None));
                self.poll()
            },
            Out::HandleResultSet(raw_query_result) => {
                Ok(Ready(raw_query_result.into()))
            }
        }
    }
}
<commit_msg>Use steps! for Query future<commit_after>use conn::futures::new_raw_query_result::NewRawQueryResult;
use conn::futures::query_result::TextQueryResult;
use conn::futures::query_result::TextResult;
use conn::futures::write_packet::WritePacket;
use errors::*;
use lib_futures::Async;
use lib_futures::Async::Ready;
use lib_futures::Future;
use lib_futures::Poll;

steps! {
    Query {
        WriteCommandData(WritePacket),
        HandleResultSet(NewRawQueryResult<TextResult>),
    }
}

/// Future that resolves to result of a query execution.
pub struct Query {
    step: Step,
}

pub fn new_new(write_packet: WritePacket) -> Query {
    Query {
        step: Step::WriteCommandData(write_packet),
    }
}

impl Future for Query {
    type Item = TextQueryResult;
    type Error = Error;

    fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
        match try_ready!(self.either_poll()) {
            Out::WriteCommandData(conn) => {
                self.step = Step::HandleResultSet(conn.handle_result_set(None));
                self.poll()
            },
            Out::HandleResultSet(raw_query_result) => {
                Ok(Ready(raw_query_result.into()))
            }
        }
    }
}
<|endoftext|>


<commit_before>use super::allocators::{Allocator, DefaultHeap};
use super::compact::Compact;
use super::compact_vec::CompactVec;
use super::compact_dict::CompactDict;
use super::compact_array::{CompactArray, IntoIter as ArrayIntoIter};
use std::iter::{Iterator, Map};
use std::collections::hash_map::DefaultHasher;
use std::hash::Hasher;
use std::hash::Hash;
use std::marker::PhantomData;

#[derive(Clone)]
struct Entry<K: Copy + Hash + Eq, V: Compact + Clone> {
    key: K,
    hash: u64,
    value: V,
    used: bool,
}

impl<K: Copy + Hash + Eq, V: Compact + Clone> Compact for Entry<K, V> {
    fn is_still_compact(&self) -> bool {
        self.value.is_still_compact()
    }

    fn dynamic_size_bytes(&self) -> usize {
        self.value.dynamic_size_bytes()
    }

    unsafe fn compact_from(&mut self, source: &Self, new_dynamic_part: *mut u8) {
        self.value.compact_from(&source.value, new_dynamic_part);
    }

    unsafe fn decompact(&self) -> Entry<K, V> {
        Entry {
            key: self.key.clone(),
            value: self.value.decompact(),
            hash: self.hash,
            used: self.used
        }
    }
}

struct OpenAddressingMap<K: Copy + Eq + Hash, V: Compact + Clone, A: Allocator = DefaultHeap> {
    size: usize,
    entries: CompactArray<Entry<K, V>, A>,
}

impl<K: Copy + Eq + Hash, V: Compact + Clone, A: Allocator> OpenAddressingMap<K, V, A> {

    pub fn new() -> Self {
        Self::with_capacity(100)
    }
    pub fn with_capacity(l: usize) -> Self {
        OpenAddressingMap {
            entries: CompactArray::with_capacity(l),
            size: l,
        }
    }

    /// Amount of entries in the dictionary
    pub fn len(&self) -> usize {
        self.size
    }

    /// Is the dictionary empty?
    pub fn is_empty(&self) -> bool {
        self.size == 0
    }

    /// Look up the value for key `query`, if it exists
    pub fn get(&self, query: K) -> Option<&V> {
        self.get_inner(query).map(|e|{&e.value})
    }

    pub fn get_mru(&self, query: K) -> Option<&V> {
        self.get_inner(query).map(|e|{&e.value})
    }

    pub fn get_mfu(&self, query: K) -> Option<&V> {
        self.get_inner(query).map(|e|{&e.value})
    }

    pub fn get_mut(&mut self, query: K) -> Option<&mut V> {
        self.get_inner_mut(query).map(|e|{& mut e.value})
    }

    /// Does the dictionary contain a value for `query`?
    pub fn contains_key(&self, query: K) -> bool {
        self.get(query).map_or(false, |i|{true})
    }

    /// Insert new value at key `query` and return the previous value at that key, if any existed
    pub fn insert(&mut self, query: K, value: V) -> Option<V> {
        self.ensure_capacity();
        let len = self.entries.capacity();
        let hash = self.hash(query);
        let h = hash as usize;
        for i in 0..len {
            let index = (h + i*i) % len;
            let entry = &mut self.entries[index];
            if !entry.used {
                entry.key = query;
                entry.value = value;
                entry.used = true;
                entry.hash = hash;
                return None
            } else if entry.key == query {
                let old_val: V = entry.value.clone();
                entry.value = value;
                entry.hash = hash;
                return Some(old_val)
            }
        }
        panic!("should always have place");
    }

    /// Remove value at key `query` and return it, if it existed
    pub fn remove(&mut self, query: K) -> Option<V> {
         self.remove_inner(query)
    }

    /// Iterator over all keys in the dictionary
    pub fn keys(&self) -> ::std::slice::Iter<K> {
         unimplemented!();
    }

    /// Iterator over all values in the dictionary
    pub fn values(&self) -> ::std::slice::Iter<V> {
         unimplemented!();
    }

    /// Iterator over mutable references to all values in the dictionary
    pub fn values_mut(&mut self) -> ::std::slice::IterMut<V> {
         unimplemented!();
    }

    /// Iterator over all key-value pairs in the dictionary
    pub fn pairs<'a>(&'a self) -> impl Iterator<Item = (&'a K, &'a V)>  + 'a {
        self.entries.iter().filter(|e| {e.used}).map(|e|{(&e.key, &e.value)})
    }

    fn hash(&self, key: K) -> u64 {
        let mut hasher = DefaultHasher::new();
        key.hash(&mut hasher);
        hasher.finish()
    }

    fn get_inner(&self, query: K) -> Option<&Entry<K,V>> {
        self.find_pos(query).map(move |i| {&self.entries[i]})
    }

    fn get_inner_mut(&mut self, query: K) -> Option<&mut Entry<K,V>> {
        self.find_pos(query).map(move |i| {&mut self.entries[i]})
    }

    fn remove_inner(&mut self, query: K) -> Option<V> {
        let len = self.entries.capacity();
        let h = self.hash(query) as usize;
        for i in 0..len {
            let index = (h + i*i) % len;
            if self.entries[index].used && (self.entries[index].key == query) {
                self.entries[index].used = false;
                return Some(self.entries[index].value.clone());
            }
        }
        None
    }

    fn ensure_capacity(&mut self) {
        if 10 * self.size > 7 * self.entries.capacity() {
            let old_entries = self.entries.clone();
            self.entries = CompactArray::with_capacity(old_entries.capacity() * 2);
            for entry in old_entries {
                self.insert(entry.key, entry.value);
            }
        }
    }

    fn find_pos(&self, query: K) -> Option<usize> {
        let len = self.entries.capacity();
        let h = self.hash(query) as usize;
        for i in 0..len {
            let index = (h + i*i) % len;
            if self.entries[index].used && (self.entries[index].key == query) {
                return Some(i);
            } else if !self.entries[index].used {
                return Some(i);
            }
        }
        None
    }
}

impl<K: Copy + Eq + Hash, V: Compact + Clone, A: Allocator> Compact for OpenAddressingMap<K, V, A> {
    fn is_still_compact(&self) -> bool {
        self.entries.is_still_compact()
    }

    fn dynamic_size_bytes(&self) -> usize {
        self.entries.dynamic_size_bytes()
    }

    unsafe fn compact_from(&mut self, source: &Self, new_dynamic_part: *mut u8) {
        self.entries.compact_from(
            &source.entries,
            new_dynamic_part,
        );
        self.size.compact_from(
            &source.size,
            new_dynamic_part.offset(
                (self.entries.dynamic_size_bytes()) as isize,
            ),
        )
    }

    unsafe fn decompact(&self) -> OpenAddressingMap<K, V, A> {
        OpenAddressingMap {
            entries: self.entries.decompact(),
            size: self.size,
        }
    }
}

impl<K: Copy + Eq + Hash, V: Compact + Clone, A: Allocator> Clone for OpenAddressingMap<K, V, A> {
    fn clone(&self) -> Self {
        OpenAddressingMap {
            entries: self.entries.clone(),
            size: self.size,
        }
    }
}

impl<K: Copy + Eq + Hash, V: Compact + Clone, A: Allocator> Default for OpenAddressingMap<K, V, A> {
    fn default() -> Self {
        OpenAddressingMap::with_capacity(100)
    }
}

impl<K: Copy + Eq + Hash, V: Compact + Clone, A: Allocator> ::std::iter::FromIterator<(K, V)>
    for OpenAddressingMap<K, V, A> {
    /// Construct a compact dictionary from an interator over key-value pairs
    fn from_iter<T: IntoIterator<Item = (K, V)>>(iter: T) -> Self {
        let mut map = Self::with_capacity(100);
        for (key, value) in iter {
            map.insert(key, value);
        }
        map
    }
}

struct OpenAddressingMapIter<'a, K: 'a + Copy + Compact + Eq + Hash, V: 'a + Clone + Compact> {
    idx: usize,
    left: usize,
    _k: PhantomData<K>,
    _v: PhantomData<V>,
    arr_iter: Iterator<Item=(&'a(Entry<K,V>))>,
}

impl <'a, K: Copy + Eq + Hash,V: Clone + Compact> Iterator for OpenAddressingMapIter<'a, K, V> {
    type Item = &'a(Entry<K, V>);

    fn next(&mut self) -> Option<Self::Item> {
        if self.left == 0 {
            return None;
        }
        loop {
            let res = self.arr_iter
                .next().unwrap();
            self.idx += 1;
            if res.used {
                self.left -= 1;
                return Some(res);
            }
        }
    }
}

impl<K: Hash + Eq + Copy, I: Compact, A1: Allocator, A2: Allocator> OpenAddressingMap<K, CompactVec<I, A1>, A2> {
    /// Push a value onto the `CompactVec` at the key `query`
    pub fn push_at(&mut self, query: K, item: I) {
        let index = self.find_pos(query);
        match index {
            Some(i) => {
                if self.entries[i].used {
                    self.entries[i].value.push(item);
                } else {
                    let mut vec = CompactVec::new();
                    vec.push(item);
                    self.entries[i].used = true;
                    self.entries[i].value = vec;
                }
            },
            None => {
                panic!("should always have place");
            }
        }
    }

    /// Iterator over the `CompactVec` at the key `query`
    #[allow(needless_lifetimes)]
    pub fn get_iter<'a>(&'a self, query: K) -> impl Iterator<Item = &'a I> + 'a {
        self.get(query).into_iter().flat_map(|vec_in_option| {
            vec_in_option.iter()
        })
    }

    /// Remove the `CompactVec` at the key `query` and iterate over its elements (if it existed)
    #[allow(needless_lifetimes)]
    pub fn remove_iter<'a>(&'a mut self, query: K) -> impl Iterator<Item = I> + 'a {
        self.remove(query).into_iter().flat_map(|vec_in_option| {
            vec_in_option.into_iter()
        })
    }
}

type EntryIter<K,V,A> = ArrayIntoIter<Entry<K,V>,A>;

impl <T: Hash> Hash for CompactVec<T> {
    fn hash<H: Hasher>(&self, state: &mut H) {
        for elem in self {
            elem.hash(state);
        }
    }
}

fn elem(n: u32) -> u32 {
    (n * n) as u32
}

#[test]
fn basic() {
    let n: u32 = 3000;
    let mut map: OpenAddressingMap<u32, u32> = OpenAddressingMap::new();
    assert!(map.is_empty() == true);
    for i in 0..n {
        map.insert(i, elem(i));
    }
    assert!(map.is_empty() == false);
    for i in 0..n {
        assert!(*map.get(i).unwrap() == i * i);
    }
    assert!(map.len() == n as usize);
    assert!(*map.get_mru(n - 1).unwrap() == elem(n - 1));
    assert!(*map.get_mfu(n - 100).unwrap() == elem(n - 100));
    assert!(map.contains_key(n - 300) == true);
    assert!(map.contains_key(n + 1) == false);
    assert!(map.remove(500) == Some(elem(500)));
    assert!(map.get_mru(500).is_none());
}

#[test]
fn iter() {
    let mut map: OpenAddressingMap<u32, u32> = OpenAddressingMap::new();
    assert!(map.is_empty() == true);
    for n in 0..100 {
        map.insert(n, n * n);
    }
    let mut sum = 0;
    let mut keys = map.keys();
    for n in 0..100 {
        assert!(keys.find(|i| **i == n).is_some());
    }
    let mut values = map.values();
    for n in 0..100 {
        assert!(values.find(|i| **i == elem(n)).is_some());
    }

}
#[test]
fn values_mut() {
    let mut map: OpenAddressingMap<u32, u32> = OpenAddressingMap::new();
    assert!(map.is_empty() == true);
    for n in 0..100 {
        map.insert(n, n * n);
    }
    {
        let mut values_mut = map.values_mut();
        for i in &mut values_mut {
            *i = *i + 1;
        }
    }
    for i in 0..100 {
        assert!(*map.get(i).unwrap() == i * i + 1);
    }
}

#[test]
fn pairs() {
    let mut map: OpenAddressingMap<u32, u32> = OpenAddressingMap::new();
    assert!(map.is_empty() == true);
    for n in 0..100 {
        map.insert(n, n * n);
    }
    for (key, value) in map.pairs() {
        assert!( elem(*key) == *value);
    }
}

#[test]
fn push_at() {
    let mut map: OpenAddressingMap<u32, CompactVec<u32>> = OpenAddressingMap::new();
    assert!(map.is_empty() == true);
    for n in 0..100 {
        map.push_at(n, elem(n));
        map.push_at(n, elem(n)+1);
    }

    for n in 0..100 {
        let mut iter = map.get_iter(n);
        assert!(iter.find(|i|{ **i == elem(n)}).is_some());
        assert!(iter.find(|i|{ **i == elem(n) + 1}).is_some());
    }
}

#[test]
fn remove_iter() {
    let mut map: OpenAddressingMap<u32, CompactVec<u32>> = OpenAddressingMap::new();
    assert!(map.is_empty() == true);
    for n in 0..100 {
        map.push_at(n, elem(n));
        map.push_at(n, elem(n)+1);
    }
    let mut iter = map.remove_iter(50);
    assert!(iter.find(|i|{ *i == elem(50)}).is_some());
    assert!(iter.find(|i|{ *i == elem(50) + 1}).is_some());
}<commit_msg>fixed bugs<commit_after>use super::allocators::{Allocator, DefaultHeap};
use super::compact::Compact;
use super::compact_vec::CompactVec;
use super::compact_dict::CompactDict;
use super::compact_array::{CompactArray, IntoIter as ArrayIntoIter};
use std::iter::{Iterator, Map};
use std::collections::hash_map::DefaultHasher;
use std::hash::Hasher;
use std::hash::Hash;
use std::marker::PhantomData;

#[derive(Clone)]
struct Entry<K: Copy + Hash + Eq, V: Compact + Clone> {
    key: K,
    hash: u64,
    value: V,
    used: bool,
}

impl<K: Copy + Hash + Eq, V: Compact + Clone> Compact for Entry<K, V> {
    fn is_still_compact(&self) -> bool {
        self.value.is_still_compact()
    }

    fn dynamic_size_bytes(&self) -> usize {
        self.value.dynamic_size_bytes()
    }

    unsafe fn compact_from(&mut self, source: &Self, new_dynamic_part: *mut u8) {
        self.value.compact_from(&source.value, new_dynamic_part);
    }

    unsafe fn decompact(&self) -> Entry<K, V> {
        Entry {
            key: self.key.clone(),
            value: self.value.decompact(),
            hash: self.hash,
            used: self.used
        }
    }
}

struct OpenAddressingMap<K: Copy + Eq + Hash, V: Compact + Clone, A: Allocator = DefaultHeap> {
    size: usize,
    entries: CompactArray<Entry<K, V>, A>,
}

impl<K: Copy + Eq + Hash, V: Compact + Clone, A: Allocator> OpenAddressingMap<K, V, A> {

    pub fn new() -> Self {
        Self::with_capacity(100)
    }
    pub fn with_capacity(l: usize) -> Self {
        OpenAddressingMap {
            entries: CompactArray::with_capacity(l),
            size: 0,
        }
    }

    /// Amount of entries in the dictionary
    pub fn len(&self) -> usize {
        self.size
    }

    /// Is the dictionary empty?
    pub fn is_empty(&self) -> bool {
        self.size == 0
    }

    /// Look up the value for key `query`, if it exists
    pub fn get(&self, query: K) -> Option<&V> {
        self.get_inner(query).map(|e|{&e.value})
    }

    pub fn get_mru(&self, query: K) -> Option<&V> {
        self.get_inner(query).map(|e|{&e.value})
    }

    pub fn get_mfu(&self, query: K) -> Option<&V> {
        self.get_inner(query).map(|e|{&e.value})
    }

    pub fn get_mut(&mut self, query: K) -> Option<&mut V> {
        self.get_inner_mut(query).map(|e|{& mut e.value})
    }

    /// Does the dictionary contain a value for `query`?
    pub fn contains_key(&self, query: K) -> bool {
        self.get(query).map_or(false, |i|{true})
    }

    /// Insert new value at key `query` and return the previous value at that key, if any existed
    pub fn insert(&mut self, query: K, value: V) -> Option<V> {
        self.ensure_capacity();
        let len = self.entries.capacity();
        let hash = self.hash(query);
        let h = hash as usize;
        for i in 0..len {
            let index = (h + i*i) % len;
            let entry = &mut self.entries[index];
            if !entry.used {
                entry.key = query;
                entry.value = value;
                entry.used = true;
                entry.hash = hash;
                self.size += 1;
                return None
            } else if entry.key == query {
                let old_val: V = entry.value.clone();
                entry.value = value;
                entry.hash = hash;
                self.size += 1;
                return Some(old_val)
            }
        }
        panic!("should always have place");
    }

    /// Remove value at key `query` and return it, if it existed
    pub fn remove(&mut self, query: K) -> Option<V> {
         self.remove_inner(query)
    }

    /// Iterator over all keys in the dictionary
    pub fn keys(&self) -> ::std::slice::Iter<K> {
         unimplemented!();
    }

    /// Iterator over all values in the dictionary
    pub fn values(&self) -> ::std::slice::Iter<V> {
         unimplemented!();
    }

    /// Iterator over mutable references to all values in the dictionary
    pub fn values_mut(&mut self) -> ::std::slice::IterMut<V> {
         unimplemented!();
    }

    /// Iterator over all key-value pairs in the dictionary
    pub fn pairs<'a>(&'a self) -> impl Iterator<Item = (&'a K, &'a V)>  + 'a {
        self.entries.iter().filter(|e| {e.used}).map(|e|{(&e.key, &e.value)})
    }

    fn hash(&self, key: K) -> u64 {
        let mut hasher = DefaultHasher::new();
        key.hash(&mut hasher);
        hasher.finish()
    }

    fn get_inner(&self, query: K) -> Option<&Entry<K,V>> {
        self.find_pos(query).map(move |i| {&self.entries[i]})
    }

    fn get_inner_mut(&mut self, query: K) -> Option<&mut Entry<K,V>> {
        self.find_pos(query).map(move |i| {&mut self.entries[i]})
    }

    fn remove_inner(&mut self, query: K) -> Option<V> {
        let len = self.entries.capacity();
        let h = self.hash(query) as usize;
        for i in 0..len {
            let index = (h + i*i) % len;
            if self.entries[index].used && (self.entries[index].key == query) {
                self.entries[index].used = false;
                return Some(self.entries[index].value.clone());
            }
        }
        None
    }

    fn ensure_capacity(&mut self) {
        if 10 * self.size > 7 * self.entries.capacity() {
            let old_entries = self.entries.clone();
            self.entries = CompactArray::with_capacity(old_entries.capacity() * 2);
            self.size = 0;
            for entry in old_entries {
                if entry.used {
                    self.insert(entry.key, entry.value);
                }
            }
        }
    }

    fn find_pos(&self, query: K) -> Option<usize> {
        let len = self.entries.capacity();
        let h = self.hash(query) as usize;
        for i in 0..len {
            let index = (h + i*i) % len;
            if self.entries[index].used && (self.entries[index].key == query) {
                return Some(i);
            } else if !self.entries[index].used {
                return Some(i);
            }
        }
        None
    }
}

impl<K: Copy + Eq + Hash, V: Compact + Clone, A: Allocator> Compact for OpenAddressingMap<K, V, A> {
    fn is_still_compact(&self) -> bool {
        self.entries.is_still_compact()
    }

    fn dynamic_size_bytes(&self) -> usize {
        self.entries.dynamic_size_bytes()
    }

    unsafe fn compact_from(&mut self, source: &Self, new_dynamic_part: *mut u8) {
        self.entries.compact_from(
            &source.entries,
            new_dynamic_part,
        );
        self.size.compact_from(
            &source.size,
            new_dynamic_part.offset(
                (self.entries.dynamic_size_bytes()) as isize,
            ),
        )
    }

    unsafe fn decompact(&self) -> OpenAddressingMap<K, V, A> {
        OpenAddressingMap {
            entries: self.entries.decompact(),
            size: self.size,
        }
    }
}

impl<K: Copy + Eq + Hash, V: Compact + Clone, A: Allocator> Clone for OpenAddressingMap<K, V, A> {
    fn clone(&self) -> Self {
        OpenAddressingMap {
            entries: self.entries.clone(),
            size: self.size,
        }
    }
}

impl<K: Copy + Eq + Hash, V: Compact + Clone, A: Allocator> Default for OpenAddressingMap<K, V, A> {
    fn default() -> Self {
        OpenAddressingMap::with_capacity(100)
    }
}

impl<K: Copy + Eq + Hash, V: Compact + Clone, A: Allocator> ::std::iter::FromIterator<(K, V)>
    for OpenAddressingMap<K, V, A> {
    /// Construct a compact dictionary from an interator over key-value pairs
    fn from_iter<T: IntoIterator<Item = (K, V)>>(iter: T) -> Self {
        let mut map = Self::with_capacity(100);
        for (key, value) in iter {
            map.insert(key, value);
        }
        map
    }
}

struct OpenAddressingMapIter<'a, K: 'a + Copy + Compact + Eq + Hash, V: 'a + Clone + Compact> {
    idx: usize,
    left: usize,
    _k: PhantomData<K>,
    _v: PhantomData<V>,
    arr_iter: Iterator<Item=(&'a(Entry<K,V>))>,
}

impl <'a, K: Copy + Eq + Hash,V: Clone + Compact> Iterator for OpenAddressingMapIter<'a, K, V> {
    type Item = &'a(Entry<K, V>);

    fn next(&mut self) -> Option<Self::Item> {
        if self.left == 0 {
            return None;
        }
        loop {
            let res = self.arr_iter
                .next().unwrap();
            self.idx += 1;
            if res.used {
                self.left -= 1;
                return Some(res);
            }
        }
    }
}

impl<K: Hash + Eq + Copy, I: Compact, A1: Allocator, A2: Allocator> OpenAddressingMap<K, CompactVec<I, A1>, A2> {
    /// Push a value onto the `CompactVec` at the key `query`
    pub fn push_at(&mut self, query: K, item: I) {
        let index = self.find_pos(query);
        match index {
            Some(i) => {
                if self.entries[i].used {
                    self.entries[i].value.push(item);
                } else {
                    let mut vec = CompactVec::new();
                    vec.push(item);
                    self.entries[i].used = true;
                    self.entries[i].value = vec;
                }
            },
            None => {
                panic!("should always have place");
            }
        }
    }

    /// Iterator over the `CompactVec` at the key `query`
    #[allow(needless_lifetimes)]
    pub fn get_iter<'a>(&'a self, query: K) -> impl Iterator<Item = &'a I> + 'a {
        self.get(query).into_iter().flat_map(|vec_in_option| {
            vec_in_option.iter()
        })
    }

    /// Remove the `CompactVec` at the key `query` and iterate over its elements (if it existed)
    #[allow(needless_lifetimes)]
    pub fn remove_iter<'a>(&'a mut self, query: K) -> impl Iterator<Item = I> + 'a {
        self.remove(query).into_iter().flat_map(|vec_in_option| {
            vec_in_option.into_iter()
        })
    }
}

type EntryIter<K,V,A> = ArrayIntoIter<Entry<K,V>,A>;

impl <T: Hash> Hash for CompactVec<T> {
    fn hash<H: Hasher>(&self, state: &mut H) {
        for elem in self {
            elem.hash(state);
        }
    }
}

fn elem(n: u32) -> u32 {
    (n * n) as u32
}

#[test]
fn basic() {
    let n: u32 = 3000;
    let mut map: OpenAddressingMap<u32, u32> = OpenAddressingMap::new();
    assert!(map.is_empty() == true);
    for i in 0..n {
        map.insert(i, elem(i));
    }
    assert!(map.is_empty() == false);
    for i in 0..n {
        let test = *map.get(i).unwrap();
        let exp = i * i;
        assert!( test == exp);
    }
    assert!(map.len() == n as usize);
    assert!(*map.get_mru(n - 1).unwrap() == elem(n - 1));
    assert!(*map.get_mfu(n - 100).unwrap() == elem(n - 100));
    assert!(map.contains_key(n - 300) == true);
    assert!(map.contains_key(n + 1) == false);
    assert!(map.remove(500) == Some(elem(500)));
    assert!(map.get_mru(500).is_none());
}

#[test]
fn iter() {
    let mut map: OpenAddressingMap<u32, u32> = OpenAddressingMap::new();
    assert!(map.is_empty() == true);
    for n in 0..100 {
        map.insert(n, n * n);
    }
    let mut sum = 0;
    let mut keys = map.keys();
    for n in 0..100 {
        assert!(keys.find(|i| **i == n).is_some());
    }
    let mut values = map.values();
    for n in 0..100 {
        assert!(values.find(|i| **i == elem(n)).is_some());
    }

}
#[test]
fn values_mut() {
    let mut map: OpenAddressingMap<u32, u32> = OpenAddressingMap::new();
    assert!(map.is_empty() == true);
    for n in 0..100 {
        map.insert(n, n * n);
    }
    {
        let mut values_mut = map.values_mut();
        for i in &mut values_mut {
            *i = *i + 1;
        }
    }
    for i in 0..100 {
        assert!(*map.get(i).unwrap() == i * i + 1);
    }
}

#[test]
fn pairs() {
    let mut map: OpenAddressingMap<u32, u32> = OpenAddressingMap::new();
    assert!(map.is_empty() == true);
    for n in 0..100 {
        map.insert(n, n * n);
    }
    for (key, value) in map.pairs() {
        assert!( elem(*key) == *value);
    }
}

#[test]
fn push_at() {
    let mut map: OpenAddressingMap<u32, CompactVec<u32>> = OpenAddressingMap::new();
    assert!(map.is_empty() == true);
    for n in 0..100 {
        map.push_at(n, elem(n));
        map.push_at(n, elem(n)+1);
    }

    for n in 0..100 {
        let mut iter = map.get_iter(n);
        assert!(iter.find(|i|{ **i == elem(n)}).is_some());
        assert!(iter.find(|i|{ **i == elem(n) + 1}).is_some());
    }
}

#[test]
fn remove_iter() {
    let mut map: OpenAddressingMap<u32, CompactVec<u32>> = OpenAddressingMap::new();
    assert!(map.is_empty() == true);
    for n in 0..100 {
        map.push_at(n, elem(n));
        map.push_at(n, elem(n)+1);
    }
    let mut iter = map.remove_iter(50);
    assert!(iter.find(|i|{ *i == elem(50)}).is_some());
    assert!(iter.find(|i|{ *i == elem(50) + 1}).is_some());
}<|endoftext|>


<commit_before>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

use glutin::{self, GlContext};
use std::cell::RefCell;
use std::collections::HashMap;
use std::rc::Rc;
use super::GlutinWindow;
use traits::view::*;

pub struct View {
    id: glutin::WindowId,
    windows: Rc<RefCell<HashMap<glutin::WindowId, GlutinWindow>>>,
}

impl View {
    pub fn new(id: glutin::WindowId, windows: Rc<RefCell<HashMap<glutin::WindowId, GlutinWindow>>>) -> View {
        View { id, windows }
    }

    #[cfg(not(target_os = "windows"))]
    fn hidpi_factor(&self) -> f32 {
        let windows = self.windows.borrow();
        let win = windows.get(&self.id).unwrap();
        win.glutin_window.hidpi_factor()
    }

    #[cfg(target_os = "windows")]
    fn hidpi_factor(&self) -> f32 {
        super::utils::windows_hidpi_factor()
    }
}

impl ViewMethods for View {
    fn get_geometry(&self) -> DrawableGeometry {
        let windows = self.windows.borrow();
        let win = windows.get(&self.id).unwrap();
        let (mut width, mut height) = win.glutin_window.get_inner_size().expect("Failed to get window inner size.");

        #[cfg(target_os = "windows")]
        let factor = super::utils::windows_hidpi_factor();
        #[cfg(not(target_os = "windows"))]
        let factor = 1.0;

        width /= factor as u32;
        height /= factor as u32;

        DrawableGeometry {
            view_size: (width, height),
            margins: (0, 0, 0, 0),
            position: win.glutin_window.get_position().expect("Failed to get window position."),
            hidpi_factor: self.hidpi_factor(),
        }
    }

    fn update_drawable(&self) {
        let windows = self.windows.borrow();
        let win = windows.get(&self.id).unwrap();
        let (w, h) = win.glutin_window.get_inner_size().expect("Failed to get window inner size.");
        win.glutin_window.resize(w, h);
    }

    // FIXME: should be controlled by state
    fn enter_fullscreen(&self) {
    }

    // FIXME: should be controlled by state
    fn exit_fullscreen(&self) {
        self.windows.borrow().get(&self.id).unwrap().glutin_window.swap_buffers().unwrap();
    }

    fn set_live_resize_callback(&self, _callback: &FnMut()) {
        // FIXME
    }

    fn gl(&self) -> Rc<gl::Gl> {
        self.windows.borrow().get(&self.id).unwrap().gl.clone()
    }

    fn get_events(&self) -> Vec<ViewEvent> {
        let mut windows = self.windows.borrow_mut();
        let win = windows.get_mut(&self.id).unwrap();
        let events = win.view_events.drain(..).collect();
        events
    }

    fn swap_buffers(&self) {
        self.windows.borrow().get(&self.id).unwrap().glutin_window.swap_buffers().unwrap();
    }
}
<commit_msg>useless swap_buffers call<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

use glutin::{self, GlContext};
use std::cell::RefCell;
use std::collections::HashMap;
use std::rc::Rc;
use super::GlutinWindow;
use traits::view::*;

pub struct View {
    id: glutin::WindowId,
    windows: Rc<RefCell<HashMap<glutin::WindowId, GlutinWindow>>>,
}

impl View {
    pub fn new(id: glutin::WindowId, windows: Rc<RefCell<HashMap<glutin::WindowId, GlutinWindow>>>) -> View {
        View { id, windows }
    }

    #[cfg(not(target_os = "windows"))]
    fn hidpi_factor(&self) -> f32 {
        let windows = self.windows.borrow();
        let win = windows.get(&self.id).unwrap();
        win.glutin_window.hidpi_factor()
    }

    #[cfg(target_os = "windows")]
    fn hidpi_factor(&self) -> f32 {
        super::utils::windows_hidpi_factor()
    }
}

impl ViewMethods for View {
    fn get_geometry(&self) -> DrawableGeometry {
        let windows = self.windows.borrow();
        let win = windows.get(&self.id).unwrap();
        let (mut width, mut height) = win.glutin_window.get_inner_size().expect("Failed to get window inner size.");

        #[cfg(target_os = "windows")]
        let factor = super::utils::windows_hidpi_factor();
        #[cfg(not(target_os = "windows"))]
        let factor = 1.0;

        width /= factor as u32;
        height /= factor as u32;

        DrawableGeometry {
            view_size: (width, height),
            margins: (0, 0, 0, 0),
            position: win.glutin_window.get_position().expect("Failed to get window position."),
            hidpi_factor: self.hidpi_factor(),
        }
    }

    fn update_drawable(&self) {
        let windows = self.windows.borrow();
        let win = windows.get(&self.id).unwrap();
        let (w, h) = win.glutin_window.get_inner_size().expect("Failed to get window inner size.");
        win.glutin_window.resize(w, h);
    }

    // FIXME: should be controlled by state
    fn enter_fullscreen(&self) {
    }

    // FIXME: should be controlled by state
    fn exit_fullscreen(&self) {
    }

    fn set_live_resize_callback(&self, _callback: &FnMut()) {
        // FIXME
    }

    fn gl(&self) -> Rc<gl::Gl> {
        self.windows.borrow().get(&self.id).unwrap().gl.clone()
    }

    fn get_events(&self) -> Vec<ViewEvent> {
        let mut windows = self.windows.borrow_mut();
        let win = windows.get_mut(&self.id).unwrap();
        let events = win.view_events.drain(..).collect();
        events
    }

    fn swap_buffers(&self) {
        self.windows.borrow().get(&self.id).unwrap().glutin_window.swap_buffers().unwrap();
    }
}
<|endoftext|>


<commit_before>use crate::{
    adapters::json,
    core::{
        prelude::*,
        usecases,
        util::{self, geo},
    },
    infrastructure::{db::tantivy, error::AppError},
};

use rocket::{self, request::Form};
use rocket_contrib::json::Json;
use std::result;

#[derive(FromForm, Clone)]
pub struct SearchQuery {
    bbox: String,
    categories: Option<String>,
    ids: Option<String>,
    tags: Option<String>,
    text: Option<String>,
    status: Option<String>,
    limit: Option<usize>,
}

type Result<T> = result::Result<Json<T>, AppError>;

const DEFAULT_RESULT_LIMIT: usize = 100;
const MAX_RESULT_LIMIT: usize = 500;

#[get("/search?<search..>")]
#[allow(clippy::absurd_extreme_comparisons)]
pub fn get_search(
    search_engine: tantivy::SearchEngine,
    search: Form<SearchQuery>,
) -> Result<json::SearchResponse> {
    let bbox = search
        .bbox
        .parse::<geo::MapBbox>()
        .map_err(|_| ParameterError::Bbox)
        .map_err(Error::Parameter)
        .map_err(AppError::Business)?;

    let ids = search
        .ids
        .as_ref()
        .map(String::as_str)
        .map(util::split_ids)
        .unwrap_or_default();

    let categories = search
        .categories
        .as_ref()
        .map(String::as_str)
        .map(util::split_ids)
        .map(|ids| {
            ids.into_iter()
                // Only places, not events
                .filter(|id| id != &Category::ID_EVENT)
                .collect()
        })
        .unwrap_or_default();

    let hash_tags = search
        .tags
        .as_ref()
        .map(String::as_str)
        .map(util::split_ids)
        .unwrap_or_default();

    let text = search.text.as_ref().map(String::as_str);

    let status = search
        .status
        .as_ref()
        .map(String::as_str)
        .map(util::split_ids)
        .unwrap_or_default()
        .into_iter()
        .filter_map(|s| {
            serde_json::from_str::<json::ReviewStatus>(&format!("\"{}\"", s))
                .map_err(|e| {
                    log::warn!("Failed to parse status '{}' from search query: {}", s, e);
                    e
                })
                .map(ReviewStatus::from)
                .ok()
        })
        .collect();

    let req = usecases::SearchRequest {
        bbox,
        ids,
        categories,
        hash_tags,
        text,
        status,
    };

    let search_limit = if let Some(limit) = search.limit {
        if limit > MAX_RESULT_LIMIT {
            info!(
                "Requested limit {} exceeds maximum limit {} for search results",
                limit, MAX_RESULT_LIMIT
            );
            MAX_RESULT_LIMIT
        } else if limit <= 0 {
            warn!("Invalid search limit: {}", limit);
            return Err(AppError::Business(Error::Parameter(
                ParameterError::InvalidLimit,
            )));
        } else {
            limit
        }
    } else {
        info!(
            "No limit requested - Using default limit {} for search results",
            DEFAULT_RESULT_LIMIT
        );
        DEFAULT_RESULT_LIMIT
    };

    let (visible, invisible) = usecases::search(&search_engine, req, search_limit)?;

    let visible: Vec<json::PlaceSearchResult> = visible.into_iter().map(Into::into).collect();

    let invisible: Vec<json::PlaceSearchResult> = invisible.into_iter().map(Into::into).collect();

    Ok(Json(json::SearchResponse { visible, invisible }))
}
<commit_msg>Add function for parsing search queries<commit_after>use crate::{
    adapters::json,
    core::{
        prelude::*,
        usecases,
        util::{self, geo},
    },
    infrastructure::{db::tantivy, error::AppError},
};

use rocket::{self, request::Form};
use rocket_contrib::json::Json;
use std::result;

#[derive(FromForm, Clone)]
pub struct SearchQuery {
    bbox: String,
    categories: Option<String>,
    ids: Option<String>,
    tags: Option<String>,
    text: Option<String>,
    status: Option<String>,
    limit: Option<usize>,
}

pub fn parse_search_query<'a>(
    query: &'a SearchQuery,
) -> result::Result<(usecases::SearchRequest<'a, 'a, 'a, 'a>, Option<usize>), AppError> {
    let SearchQuery {
        bbox,
        ids,
        categories,
        tags,
        text,
        status,
        limit,
    } = query;

    let bbox = bbox
        .parse::<geo::MapBbox>()
        .map_err(|_| ParameterError::Bbox)
        .map_err(Error::Parameter)
        .map_err(AppError::Business)?;

    let ids = ids
        .as_ref()
        .map(String::as_str)
        .map(util::split_ids)
        .unwrap_or_default();

    let categories = categories
        .as_ref()
        .map(String::as_str)
        .map(util::split_ids)
        .map(|ids| {
            ids.into_iter()
                // Only places, not events
                .filter(|id| id != &Category::ID_EVENT)
                .collect()
        })
        .unwrap_or_default();

    let hash_tags = tags
        .as_ref()
        .map(String::as_str)
        .map(util::split_ids)
        .unwrap_or_default();

    let text = text.as_ref().map(String::as_str);

    let status = status
        .as_ref()
        .map(String::as_str)
        .map(util::split_ids)
        .unwrap_or_default()
        .into_iter()
        .filter_map(|s| {
            serde_json::from_str::<json::ReviewStatus>(&format!("\"{}\"", s))
                .map_err(|e| {
                    log::warn!("Failed to parse status '{}' from search query: {}", s, e);
                    e
                })
                .map(ReviewStatus::from)
                .ok()
        })
        .collect();

    Ok((
        usecases::SearchRequest {
            bbox,
            ids,
            categories,
            hash_tags,
            text,
            status,
        },
        *limit,
    ))
}

type Result<T> = result::Result<Json<T>, AppError>;

const DEFAULT_RESULT_LIMIT: usize = 100;
const MAX_RESULT_LIMIT: usize = 500;

#[get("/search?<query..>")]
#[allow(clippy::absurd_extreme_comparisons)]
pub fn get_search(
    search_engine: tantivy::SearchEngine,
    query: Form<SearchQuery>,
) -> Result<json::SearchResponse> {
    let query = query.into_inner();
    let (req, limit) = parse_search_query(&query)?;

    let limit = if let Some(limit) = limit {
        if limit > MAX_RESULT_LIMIT {
            info!(
                "Requested limit {} exceeds maximum limit {} for search results",
                limit, MAX_RESULT_LIMIT
            );
            MAX_RESULT_LIMIT
        } else if limit <= 0 {
            warn!("Invalid search limit: {}", limit);
            return Err(AppError::Business(Error::Parameter(
                ParameterError::InvalidLimit,
            )));
        } else {
            limit
        }
    } else {
        info!(
            "No limit requested - Using default limit {} for search results",
            DEFAULT_RESULT_LIMIT
        );
        DEFAULT_RESULT_LIMIT
    };

    let (visible, invisible) = usecases::search(&search_engine, req, limit)?;

    let visible: Vec<json::PlaceSearchResult> = visible.into_iter().map(Into::into).collect();

    let invisible: Vec<json::PlaceSearchResult> = invisible.into_iter().map(Into::into).collect();

    Ok(Json(json::SearchResponse { visible, invisible }))
}
<|endoftext|>


<commit_before>use progress::Timestamp;
use progress::frontier::MutableAntichain;
use progress::count_map::CountMap;

// Notificator is meant to manage the delivery of requested notifications in the presence of
// inputs that may have outstanding messages to deliver. The notificator tracks the frontiers,
// as presented from the outside, for each input. Requested notifications can be served only
// once there are no frontier elements less-or-equal to them, and there are no other pending
// notification requests less than them. Each with be less-or-equal to itself, so we want to
// dodge that corner case.

#[derive(Default)]
pub struct Notificator<T: Timestamp> {
    pending:        MutableAntichain<T>,        // notification requests not yet been delivered
    frontier:       Vec<MutableAntichain<T>>,   // outstanding input, preventing notification
    available:      CountMap<T>,                // notifications available for delivery
    changes:        CountMap<T>,                // change to report through pull_progress
}

impl<T: Timestamp> Notificator<T> {
    pub fn update_frontier_from_cm(&mut self, count_map: &mut [CountMap<T>]) {

        while self.frontier.len() < count_map.len() {
            self.frontier.push(MutableAntichain::new());
        }

        for (index, counts) in count_map.iter_mut().enumerate() {
            while let Some((time, delta)) = counts.pop() {
                self.frontier[index].update(&time, delta);
            }
        }
    }

    pub fn notify_at(&mut self, time: &T) {
        // println!("notify at: {:?}", time);
        self.changes.update(time, 1);
        self.pending.update(time, 1);

        // if !self.frontier.iter().any(|x| x.le(time)) {
            // TODO : Technically you should be permitted to send and notify at the current notification
            // TODO : but this would panic because we have already removed it from the frontier.
            // TODO : A RAII capability for sending/notifying would be good, but the time is almost
            // TODO : exactly that.

            // println!("notificator error? notify_at called with time not le the frontier. {:?}", time);
            // println!("notificator error? {:?} vs {:?}", time, self.frontier);
            // panic!("");
            // self.available.update(time, 1);
        // }
    }

    pub fn pull_progress(&mut self, internal: &mut CountMap<T>) {
        while let Some((time, delta)) = self.changes.pop() {
            internal.update(&time, delta);
        }
    }
}

impl<T: Timestamp> Iterator for Notificator<T> {
    type Item = (T, i64);

    fn next(&mut self) -> Option<(T, i64)> {

        // if nothing obvious available, scan for options
        if self.available.len() == 0 {
            for pend in self.pending.elements.iter() {
                if !self.frontier.iter().any(|x| x.le(pend)) {
                    if let Some(val) = self.pending.count(pend) {
                        self.available.update(pend, val);
                    }
                }
            }
        }

        // return an available notification, after cleaning up
        if let Some((time, delta)) =  self.available.pop() {
            // println!("serving notification at {:?}", time);
            self.changes.update(&time, -delta);
            self.pending.update(&time, -delta);
            Some((time, delta))
        }
        else { None }
    }
}
<commit_msg>different status messages<commit_after>use progress::Timestamp;
use progress::frontier::MutableAntichain;
use progress::count_map::CountMap;

// Notificator is meant to manage the delivery of requested notifications in the presence of
// inputs that may have outstanding messages to deliver. The notificator tracks the frontiers,
// as presented from the outside, for each input. Requested notifications can be served only
// once there are no frontier elements less-or-equal to them, and there are no other pending
// notification requests less than them. Each with be less-or-equal to itself, so we want to
// dodge that corner case.

#[derive(Default)]
pub struct Notificator<T: Timestamp> {
    pending:        MutableAntichain<T>,        // notification requests not yet been delivered
    frontier:       Vec<MutableAntichain<T>>,   // outstanding input, preventing notification
    available:      CountMap<T>,                // notifications available for delivery
    changes:        CountMap<T>,                // change to report through pull_progress
}

impl<T: Timestamp> Notificator<T> {
    pub fn update_frontier_from_cm(&mut self, count_map: &mut [CountMap<T>]) {
        // println!("notificator: frontier update {:?}", count_map);
        while self.frontier.len() < count_map.len() {
            self.frontier.push(MutableAntichain::new());
        }

        for (index, counts) in count_map.iter_mut().enumerate() {
            while let Some((time, delta)) = counts.pop() {
                self.frontier[index].update(&time, delta);
            }
        }
    }

    pub fn notify_at(&mut self, time: &T) {
        // println!("notificator: notify at: {:?}", time);
        self.changes.update(time, 1);
        self.pending.update(time, 1);

        // if !self.frontier.iter().any(|x| x.le(time)) {
            // TODO : Technically you should be permitted to send and notify at the current notification
            // TODO : but this would panic because we have already removed it from the frontier.
            // TODO : A RAII capability for sending/notifying would be good, but the time is almost
            // TODO : exactly that.

            // println!("notificator error? notify_at called with time not le the frontier. {:?}", time);
            // println!("notificator error? {:?} vs {:?}", time, self.frontier);
            // panic!("");
            // self.available.update(time, 1);
        // }
    }

    pub fn pull_progress(&mut self, internal: &mut CountMap<T>) {
        while let Some((time, delta)) = self.changes.pop() {
            internal.update(&time, delta);
        }
    }
}

impl<T: Timestamp> Iterator for Notificator<T> {
    type Item = (T, i64);

    fn next(&mut self) -> Option<(T, i64)> {

        // if nothing obvious available, scan for options
        if self.available.len() == 0 {
            for pend in self.pending.elements.iter() {
                if !self.frontier.iter().any(|x| x.le(pend)) {
                    if let Some(val) = self.pending.count(pend) {
                        self.available.update(pend, val);
                    }
                }
            }
        }

        // return an available notification, after cleaning up
        if let Some((time, delta)) =  self.available.pop() {
            // println!("notificator: serving notification at {:?}", time);
            self.changes.update(&time, -delta);
            self.pending.update(&time, -delta);
            Some((time, delta))
        }
        else { None }
    }
}
<|endoftext|>