<commit_before>use crate::errors::BeaconChainError;
use crate::head_tracker::HeadTracker;
use parking_lot::Mutex;
use slog::{debug, warn, Logger};
use std::collections::{HashMap, HashSet};
use std::mem;
use std::sync::mpsc;
use std::sync::Arc;
use std::thread;
use store::hot_cold_store::{process_finalization, HotColdDBError};
use store::iter::{ParentRootBlockIterator, RootsIterator};
use store::{Error, Store, StoreOp};
pub use store::{HotColdDB, MemoryStore};
use types::*;
use types::{BeaconState, EthSpec, Hash256, Slot};

/// Trait for migration processes that update the database upon finalization.
pub trait Migrate<E: EthSpec>: Send + Sync + 'static {
    fn new(db: Arc<HotColdDB<E>>, log: Logger) -> Self;

    fn process_finalization(
        &self,
        _state_root: Hash256,
        _new_finalized_state: BeaconState<E>,
        _max_finality_distance: u64,
        _head_tracker: Arc<HeadTracker>,
        _old_finalized_block_hash: SignedBeaconBlockHash,
        _new_finalized_block_hash: SignedBeaconBlockHash,
    ) {
    }

    /// Traverses live heads and prunes blocks and states of chains that we know can't be built
    /// upon because finalization would prohibit it.  This is a optimisation intended to save disk
    /// space.
    ///
    /// Assumptions:
    ///  * It is called after every finalization.
    fn prune_abandoned_forks(
        store: Arc<HotColdDB<E>>,
        head_tracker: Arc<HeadTracker>,
        old_finalized_block_hash: SignedBeaconBlockHash,
        new_finalized_block_hash: SignedBeaconBlockHash,
        new_finalized_slot: Slot,
    ) -> Result<(), BeaconChainError> {
        let old_finalized_slot = store
            .get_block(&old_finalized_block_hash.into())?
            .ok_or_else(|| BeaconChainError::MissingBeaconBlock(old_finalized_block_hash.into()))?
            .slot();

        // Collect hashes from new_finalized_block back to old_finalized_block (inclusive)
        let mut found_block = false; // hack for `take_until`
        let newly_finalized_blocks: HashMap<SignedBeaconBlockHash, Slot> =
            ParentRootBlockIterator::new(&*store, new_finalized_block_hash.into())
                .take_while(|result| match result {
                    Ok((block_hash, _)) => {
                        if found_block {
                            false
                        } else {
                            found_block |= *block_hash == old_finalized_block_hash.into();
                            true
                        }
                    }
                    Err(_) => true,
                })
                .map(|result| result.map(|(block_hash, block)| (block_hash.into(), block.slot())))
                .collect::<Result<_, _>>()?;

        // We don't know which blocks are shared among abandoned chains, so we buffer and delete
        // everything in one fell swoop.
        let mut abandoned_blocks: HashSet<SignedBeaconBlockHash> = HashSet::new();
        let mut abandoned_states: HashSet<(Slot, BeaconStateHash)> = HashSet::new();
        let mut abandoned_heads: HashSet<Hash256> = HashSet::new();

        for (head_hash, head_slot) in head_tracker.heads() {
            let mut potentially_abandoned_head: Option<Hash256> = Some(head_hash);
            let mut potentially_abandoned_blocks: Vec<(
                Slot,
                Option<SignedBeaconBlockHash>,
                Option<BeaconStateHash>,
            )> = Vec::new();

            let head_state_hash = store
                .get_block(&head_hash)?
                .ok_or_else(|| BeaconStateError::MissingBeaconBlock(head_hash.into()))?
                .state_root();

            let iter = std::iter::once(Ok((head_hash, head_state_hash, head_slot)))
                .chain(RootsIterator::from_block(Arc::clone(&store), head_hash)?);
            for maybe_tuple in iter {
                let (block_hash, state_hash, slot) = maybe_tuple?;
                if slot < old_finalized_slot {
                    // We must assume here any candidate chains include old_finalized_block_hash,
                    // i.e. there aren't any forks starting at a block that is a strict ancestor of
                    // old_finalized_block_hash.
                    break;
                }
                match newly_finalized_blocks.get(&block_hash.into()).copied() {
                    // Block is not finalized, mark it and its state for deletion
                    None => {
                        potentially_abandoned_blocks.push((
                            slot,
                            Some(block_hash.into()),
                            Some(state_hash.into()),
                        ));
                    }
                    Some(finalized_slot) => {
                        // Block root is finalized, and we have reached the slot it was finalized
                        // at: we've hit a shared part of the chain.
                        if finalized_slot == slot {
                            // The first finalized block of a candidate chain lies after (in terms
                            // of slots order) the newly finalized block.  It's not a candidate for
                            // prunning.
                            if finalized_slot == new_finalized_slot {
                                potentially_abandoned_blocks.clear();
                                potentially_abandoned_head.take();
                            }

                            break;
                        }
                        // Block root is finalized, but we're at a skip slot: delete the state only.
                        else {
                            potentially_abandoned_blocks.push((
                                slot,
                                None,
                                Some(state_hash.into()),
                            ));
                        }
                    }
                }
            }

            abandoned_heads.extend(potentially_abandoned_head.into_iter());
            if !potentially_abandoned_blocks.is_empty() {
                abandoned_blocks.extend(
                    potentially_abandoned_blocks
                        .iter()
                        .filter_map(|(_, maybe_block_hash, _)| *maybe_block_hash),
                );
                abandoned_states.extend(potentially_abandoned_blocks.iter().filter_map(
                    |(slot, _, maybe_state_hash)| match maybe_state_hash {
                        None => None,
                        Some(state_hash) => Some((*slot, *state_hash)),
                    },
                ));
            }
        }

        let batch: Vec<StoreOp> = abandoned_blocks
            .into_iter()
            .map(|block_hash| StoreOp::DeleteBlock(block_hash))
            .chain(
                abandoned_states
                    .into_iter()
                    .map(|(slot, state_hash)| StoreOp::DeleteState(state_hash, slot)),
            )
            .collect();
        store.do_atomically(&batch)?;
        for head_hash in abandoned_heads.into_iter() {
            head_tracker.remove_head(head_hash);
        }

        Ok(())
    }
}

/// Migrator that does nothing, for stores that don't need migration.
pub struct NullMigrator;

impl<E: EthSpec> Migrate<E> for NullMigrator {
    fn new(_: Arc<HotColdDB<E>>, _: Logger) -> Self {
        NullMigrator
    }
}

/// Migrator that immediately calls the store's migration function, blocking the current execution.
///
/// Mostly useful for tests.
pub struct BlockingMigrator<E: EthSpec> {
    db: Arc<HotColdDB<E>>,
}

impl<E: EthSpec> Migrate<E> for BlockingMigrator<E> {
    fn new(db: Arc<HotColdDB<E>>, _: Logger) -> Self {
        BlockingMigrator { db }
    }

    fn process_finalization(
        &self,
        state_root: Hash256,
        new_finalized_state: BeaconState<E>,
        _max_finality_distance: u64,
        head_tracker: Arc<HeadTracker>,
        old_finalized_block_hash: SignedBeaconBlockHash,
        new_finalized_block_hash: SignedBeaconBlockHash,
    ) {
        if let Err(e) = process_finalization(self.db.clone(), state_root, &new_finalized_state) {
            // This migrator is only used for testing, so we just log to stderr without a logger.
            eprintln!("Migration error: {:?}", e);
        }

        if let Err(e) = Self::prune_abandoned_forks(
            self.db.clone(),
            head_tracker,
            old_finalized_block_hash,
            new_finalized_block_hash,
            new_finalized_state.slot,
        ) {
            eprintln!("Pruning error: {:?}", e);
        }
    }
}

type MpscSender<E> = mpsc::Sender<(
    Hash256,
    BeaconState<E>,
    Arc<HeadTracker>,
    SignedBeaconBlockHash,
    SignedBeaconBlockHash,
    Slot,
)>;

/// Migrator that runs a background thread to migrate state from the hot to the cold database.
pub struct BackgroundMigrator<E: EthSpec> {
    db: Arc<HotColdDB<E>>,
    tx_thread: Mutex<(MpscSender<E>, thread::JoinHandle<()>)>,
    log: Logger,
}

impl<E: EthSpec> Migrate<E> for BackgroundMigrator<E> {
    fn new(db: Arc<HotColdDB<E>>, log: Logger) -> Self {
        let tx_thread = Mutex::new(Self::spawn_thread(db.clone(), log.clone()));
        Self { db, tx_thread, log }
    }

    /// Perform the freezing operation on the database,
    fn process_finalization(
        &self,
        finalized_state_root: Hash256,
        new_finalized_state: BeaconState<E>,
        max_finality_distance: u64,
        head_tracker: Arc<HeadTracker>,
        old_finalized_block_hash: SignedBeaconBlockHash,
        new_finalized_block_hash: SignedBeaconBlockHash,
    ) {
        if !self.needs_migration(new_finalized_state.slot, max_finality_distance) {
            return;
        }

        let (ref mut tx, ref mut thread) = *self.tx_thread.lock();

        let new_finalized_slot = new_finalized_state.slot;
        if let Err(tx_err) = tx.send((
            finalized_state_root,
            new_finalized_state,
            head_tracker,
            old_finalized_block_hash,
            new_finalized_block_hash,
            new_finalized_slot,
        )) {
            let (new_tx, new_thread) = Self::spawn_thread(self.db.clone(), self.log.clone());

            drop(mem::replace(tx, new_tx));
            let old_thread = mem::replace(thread, new_thread);

            // Join the old thread, which will probably have panicked, or may have
            // halted normally just now as a result of us dropping the old `mpsc::Sender`.
            if let Err(thread_err) = old_thread.join() {
                warn!(
                    self.log,
                    "Migration thread died, so it was restarted";
                    "reason" => format!("{:?}", thread_err)
                );
            }

            // Retry at most once, we could recurse but that would risk overflowing the stack.
            let _ = tx.send(tx_err.0);
        }
    }
}

impl<E: EthSpec> BackgroundMigrator<E> {
    /// Return true if a migration needs to be performed, given a new `finalized_slot`.
    fn needs_migration(&self, finalized_slot: Slot, max_finality_distance: u64) -> bool {
        let finality_distance = finalized_slot - self.db.get_split_slot();
        finality_distance > max_finality_distance
    }

    /// Spawn a new child thread to run the migration process.
    ///
    /// Return a channel handle for sending new finalized states to the thread.
    fn spawn_thread(
        db: Arc<HotColdDB<E>>,
        log: Logger,
    ) -> (
        mpsc::Sender<(
            Hash256,
            BeaconState<E>,
            Arc<HeadTracker>,
            SignedBeaconBlockHash,
            SignedBeaconBlockHash,
            Slot,
        )>,
        thread::JoinHandle<()>,
    ) {
        let (tx, rx) = mpsc::channel();
        let thread = thread::spawn(move || {
            while let Ok((
                state_root,
                state,
                head_tracker,
                old_finalized_block_hash,
                new_finalized_block_hash,
                new_finalized_slot,
            )) = rx.recv()
            {
                match process_finalization(db.clone(), state_root, &state) {
                    Ok(()) => {}
                    Err(Error::HotColdDBError(HotColdDBError::FreezeSlotUnaligned(slot))) => {
                        debug!(
                            log,
                            "Database migration postponed, unaligned finalized block";
                            "slot" => slot.as_u64()
                        );
                    }
                    Err(e) => {
                        warn!(
                            log,
                            "Database migration failed";
                            "error" => format!("{:?}", e)
                        );
                    }
                };

                match Self::prune_abandoned_forks(
                    db.clone(),
                    head_tracker,
                    old_finalized_block_hash,
                    new_finalized_block_hash,
                    new_finalized_slot,
                ) {
                    Ok(()) => {}
                    Err(e) => warn!(log, "Block pruning failed: {:?}", e),
                }
            }
        });

        (tx, thread)
    }
}
<commit_msg>Avoid pruning when there are no forks (#1268)<commit_after>use crate::errors::BeaconChainError;
use crate::head_tracker::HeadTracker;
use parking_lot::Mutex;
use slog::{debug, warn, Logger};
use std::collections::{HashMap, HashSet};
use std::mem;
use std::sync::mpsc;
use std::sync::Arc;
use std::thread;
use store::hot_cold_store::{process_finalization, HotColdDBError};
use store::iter::{ParentRootBlockIterator, RootsIterator};
use store::{Error, Store, StoreOp};
pub use store::{HotColdDB, MemoryStore};
use types::*;
use types::{BeaconState, EthSpec, Hash256, Slot};

/// Trait for migration processes that update the database upon finalization.
pub trait Migrate<E: EthSpec>: Send + Sync + 'static {
    fn new(db: Arc<HotColdDB<E>>, log: Logger) -> Self;

    fn process_finalization(
        &self,
        _state_root: Hash256,
        _new_finalized_state: BeaconState<E>,
        _max_finality_distance: u64,
        _head_tracker: Arc<HeadTracker>,
        _old_finalized_block_hash: SignedBeaconBlockHash,
        _new_finalized_block_hash: SignedBeaconBlockHash,
    ) {
    }

    /// Traverses live heads and prunes blocks and states of chains that we know can't be built
    /// upon because finalization would prohibit it.  This is a optimisation intended to save disk
    /// space.
    ///
    /// Assumptions:
    ///  * It is called after every finalization.
    fn prune_abandoned_forks(
        store: Arc<HotColdDB<E>>,
        head_tracker: Arc<HeadTracker>,
        old_finalized_block_hash: SignedBeaconBlockHash,
        new_finalized_block_hash: SignedBeaconBlockHash,
        new_finalized_slot: Slot,
    ) -> Result<(), BeaconChainError> {
        // There will never be any blocks to prune if there is only a single head in the chain.
        if head_tracker.heads().len() == 1 {
            return Ok(());
        }

        let old_finalized_slot = store
            .get_block(&old_finalized_block_hash.into())?
            .ok_or_else(|| BeaconChainError::MissingBeaconBlock(old_finalized_block_hash.into()))?
            .slot();

        // Collect hashes from new_finalized_block back to old_finalized_block (inclusive)
        let mut found_block = false; // hack for `take_until`
        let newly_finalized_blocks: HashMap<SignedBeaconBlockHash, Slot> =
            ParentRootBlockIterator::new(&*store, new_finalized_block_hash.into())
                .take_while(|result| match result {
                    Ok((block_hash, _)) => {
                        if found_block {
                            false
                        } else {
                            found_block |= *block_hash == old_finalized_block_hash.into();
                            true
                        }
                    }
                    Err(_) => true,
                })
                .map(|result| result.map(|(block_hash, block)| (block_hash.into(), block.slot())))
                .collect::<Result<_, _>>()?;

        // We don't know which blocks are shared among abandoned chains, so we buffer and delete
        // everything in one fell swoop.
        let mut abandoned_blocks: HashSet<SignedBeaconBlockHash> = HashSet::new();
        let mut abandoned_states: HashSet<(Slot, BeaconStateHash)> = HashSet::new();
        let mut abandoned_heads: HashSet<Hash256> = HashSet::new();

        for (head_hash, head_slot) in head_tracker.heads() {
            let mut potentially_abandoned_head: Option<Hash256> = Some(head_hash);
            let mut potentially_abandoned_blocks: Vec<(
                Slot,
                Option<SignedBeaconBlockHash>,
                Option<BeaconStateHash>,
            )> = Vec::new();

            let head_state_hash = store
                .get_block(&head_hash)?
                .ok_or_else(|| BeaconStateError::MissingBeaconBlock(head_hash.into()))?
                .state_root();

            let iter = std::iter::once(Ok((head_hash, head_state_hash, head_slot)))
                .chain(RootsIterator::from_block(Arc::clone(&store), head_hash)?);
            for maybe_tuple in iter {
                let (block_hash, state_hash, slot) = maybe_tuple?;
                if slot < old_finalized_slot {
                    // We must assume here any candidate chains include old_finalized_block_hash,
                    // i.e. there aren't any forks starting at a block that is a strict ancestor of
                    // old_finalized_block_hash.
                    break;
                }
                match newly_finalized_blocks.get(&block_hash.into()).copied() {
                    // Block is not finalized, mark it and its state for deletion
                    None => {
                        potentially_abandoned_blocks.push((
                            slot,
                            Some(block_hash.into()),
                            Some(state_hash.into()),
                        ));
                    }
                    Some(finalized_slot) => {
                        // Block root is finalized, and we have reached the slot it was finalized
                        // at: we've hit a shared part of the chain.
                        if finalized_slot == slot {
                            // The first finalized block of a candidate chain lies after (in terms
                            // of slots order) the newly finalized block.  It's not a candidate for
                            // prunning.
                            if finalized_slot == new_finalized_slot {
                                potentially_abandoned_blocks.clear();
                                potentially_abandoned_head.take();
                            }

                            break;
                        }
                        // Block root is finalized, but we're at a skip slot: delete the state only.
                        else {
                            potentially_abandoned_blocks.push((
                                slot,
                                None,
                                Some(state_hash.into()),
                            ));
                        }
                    }
                }
            }

            abandoned_heads.extend(potentially_abandoned_head.into_iter());
            if !potentially_abandoned_blocks.is_empty() {
                abandoned_blocks.extend(
                    potentially_abandoned_blocks
                        .iter()
                        .filter_map(|(_, maybe_block_hash, _)| *maybe_block_hash),
                );
                abandoned_states.extend(potentially_abandoned_blocks.iter().filter_map(
                    |(slot, _, maybe_state_hash)| match maybe_state_hash {
                        None => None,
                        Some(state_hash) => Some((*slot, *state_hash)),
                    },
                ));
            }
        }

        let batch: Vec<StoreOp> = abandoned_blocks
            .into_iter()
            .map(|block_hash| StoreOp::DeleteBlock(block_hash))
            .chain(
                abandoned_states
                    .into_iter()
                    .map(|(slot, state_hash)| StoreOp::DeleteState(state_hash, slot)),
            )
            .collect();
        store.do_atomically(&batch)?;
        for head_hash in abandoned_heads.into_iter() {
            head_tracker.remove_head(head_hash);
        }

        Ok(())
    }
}

/// Migrator that does nothing, for stores that don't need migration.
pub struct NullMigrator;

impl<E: EthSpec> Migrate<E> for NullMigrator {
    fn new(_: Arc<HotColdDB<E>>, _: Logger) -> Self {
        NullMigrator
    }
}

/// Migrator that immediately calls the store's migration function, blocking the current execution.
///
/// Mostly useful for tests.
pub struct BlockingMigrator<E: EthSpec> {
    db: Arc<HotColdDB<E>>,
}

impl<E: EthSpec> Migrate<E> for BlockingMigrator<E> {
    fn new(db: Arc<HotColdDB<E>>, _: Logger) -> Self {
        BlockingMigrator { db }
    }

    fn process_finalization(
        &self,
        state_root: Hash256,
        new_finalized_state: BeaconState<E>,
        _max_finality_distance: u64,
        head_tracker: Arc<HeadTracker>,
        old_finalized_block_hash: SignedBeaconBlockHash,
        new_finalized_block_hash: SignedBeaconBlockHash,
    ) {
        if let Err(e) = process_finalization(self.db.clone(), state_root, &new_finalized_state) {
            // This migrator is only used for testing, so we just log to stderr without a logger.
            eprintln!("Migration error: {:?}", e);
        }

        if let Err(e) = Self::prune_abandoned_forks(
            self.db.clone(),
            head_tracker,
            old_finalized_block_hash,
            new_finalized_block_hash,
            new_finalized_state.slot,
        ) {
            eprintln!("Pruning error: {:?}", e);
        }
    }
}

type MpscSender<E> = mpsc::Sender<(
    Hash256,
    BeaconState<E>,
    Arc<HeadTracker>,
    SignedBeaconBlockHash,
    SignedBeaconBlockHash,
    Slot,
)>;

/// Migrator that runs a background thread to migrate state from the hot to the cold database.
pub struct BackgroundMigrator<E: EthSpec> {
    db: Arc<HotColdDB<E>>,
    tx_thread: Mutex<(MpscSender<E>, thread::JoinHandle<()>)>,
    log: Logger,
}

impl<E: EthSpec> Migrate<E> for BackgroundMigrator<E> {
    fn new(db: Arc<HotColdDB<E>>, log: Logger) -> Self {
        let tx_thread = Mutex::new(Self::spawn_thread(db.clone(), log.clone()));
        Self { db, tx_thread, log }
    }

    /// Perform the freezing operation on the database,
    fn process_finalization(
        &self,
        finalized_state_root: Hash256,
        new_finalized_state: BeaconState<E>,
        max_finality_distance: u64,
        head_tracker: Arc<HeadTracker>,
        old_finalized_block_hash: SignedBeaconBlockHash,
        new_finalized_block_hash: SignedBeaconBlockHash,
    ) {
        if !self.needs_migration(new_finalized_state.slot, max_finality_distance) {
            return;
        }

        let (ref mut tx, ref mut thread) = *self.tx_thread.lock();

        let new_finalized_slot = new_finalized_state.slot;
        if let Err(tx_err) = tx.send((
            finalized_state_root,
            new_finalized_state,
            head_tracker,
            old_finalized_block_hash,
            new_finalized_block_hash,
            new_finalized_slot,
        )) {
            let (new_tx, new_thread) = Self::spawn_thread(self.db.clone(), self.log.clone());

            drop(mem::replace(tx, new_tx));
            let old_thread = mem::replace(thread, new_thread);

            // Join the old thread, which will probably have panicked, or may have
            // halted normally just now as a result of us dropping the old `mpsc::Sender`.
            if let Err(thread_err) = old_thread.join() {
                warn!(
                    self.log,
                    "Migration thread died, so it was restarted";
                    "reason" => format!("{:?}", thread_err)
                );
            }

            // Retry at most once, we could recurse but that would risk overflowing the stack.
            let _ = tx.send(tx_err.0);
        }
    }
}

impl<E: EthSpec> BackgroundMigrator<E> {
    /// Return true if a migration needs to be performed, given a new `finalized_slot`.
    fn needs_migration(&self, finalized_slot: Slot, max_finality_distance: u64) -> bool {
        let finality_distance = finalized_slot - self.db.get_split_slot();
        finality_distance > max_finality_distance
    }

    /// Spawn a new child thread to run the migration process.
    ///
    /// Return a channel handle for sending new finalized states to the thread.
    fn spawn_thread(
        db: Arc<HotColdDB<E>>,
        log: Logger,
    ) -> (
        mpsc::Sender<(
            Hash256,
            BeaconState<E>,
            Arc<HeadTracker>,
            SignedBeaconBlockHash,
            SignedBeaconBlockHash,
            Slot,
        )>,
        thread::JoinHandle<()>,
    ) {
        let (tx, rx) = mpsc::channel();
        let thread = thread::spawn(move || {
            while let Ok((
                state_root,
                state,
                head_tracker,
                old_finalized_block_hash,
                new_finalized_block_hash,
                new_finalized_slot,
            )) = rx.recv()
            {
                match process_finalization(db.clone(), state_root, &state) {
                    Ok(()) => {}
                    Err(Error::HotColdDBError(HotColdDBError::FreezeSlotUnaligned(slot))) => {
                        debug!(
                            log,
                            "Database migration postponed, unaligned finalized block";
                            "slot" => slot.as_u64()
                        );
                    }
                    Err(e) => {
                        warn!(
                            log,
                            "Database migration failed";
                            "error" => format!("{:?}", e)
                        );
                    }
                };

                match Self::prune_abandoned_forks(
                    db.clone(),
                    head_tracker,
                    old_finalized_block_hash,
                    new_finalized_block_hash,
                    new_finalized_slot,
                ) {
                    Ok(()) => {}
                    Err(e) => warn!(log, "Block pruning failed: {:?}", e),
                }
            }
        });

        (tx, thread)
    }
}
<|endoftext|>


<commit_before>use conduit::{Request, Response};
use diesel::prelude::*;
use time::Timespec;
use serde_json;

use db::RequestTransaction;
use schema::{crate_owner_invitations, users, crates, crate_owners};
use user::RequestUser;
use util::errors::{CargoResult, human};
use util::RequestUtils;
use owner::{CrateOwner, OwnerKind};

/// The model representing a row in the `crate_owner_invitations` database table.
#[derive(Clone, Copy, Debug, PartialEq, Eq, Identifiable, Queryable)]
#[primary_key(invited_user_id, crate_id)]
pub struct CrateOwnerInvitation {
    pub invited_user_id: i32,
    pub invited_by_user_id: i32,
    pub crate_id: i32,
    pub created_at: Timespec,
}

#[derive(Insertable, Clone, Copy, Debug)]
#[table_name = "crate_owner_invitations"]
pub struct NewCrateOwnerInvitation {
    pub invited_user_id: i32,
    pub invited_by_user_id: i32,
    pub crate_id: i32,
}

impl CrateOwnerInvitation {
    pub fn invited_by_username(&self, conn: &PgConnection) -> String {
        users::table
            .find(self.invited_by_user_id)
            .select(users::gh_login)
            .first(&*conn)
            .unwrap_or_else(|_| String::from("(unknown username)"))
    }

    pub fn crate_name(&self, conn: &PgConnection) -> String {
        crates::table
            .find(self.crate_id)
            .select(crates::name)
            .first(&*conn)
            .unwrap_or_else(|_| String::from("(unknown crate name)"))
    }

    pub fn encodable(self, conn: &PgConnection) -> EncodableCrateOwnerInvitation {
        EncodableCrateOwnerInvitation {
            invited_by_username: self.invited_by_username(conn),
            crate_name: self.crate_name(conn),
            crate_id: self.crate_id,
            created_at: ::encode_time(self.created_at),
        }
    }
}

/// The serialization format for the `CrateOwnerInvitation` model.
#[derive(Deserialize, Serialize, Debug)]
pub struct EncodableCrateOwnerInvitation {
    pub invited_by_username: String,
    pub crate_name: String,
    pub crate_id: i32,
    pub created_at: String,
}

/// Handles the `GET /me/crate_owner_invitations` route.
pub fn list(req: &mut Request) -> CargoResult<Response> {
    let conn = &*req.db_conn()?;
    let user_id = req.user()?.id;

    let crate_owner_invitations = crate_owner_invitations::table
        .filter(crate_owner_invitations::invited_user_id.eq(user_id))
        .load::<CrateOwnerInvitation>(&*conn)?
        .into_iter()
        .map(|i| i.encodable(conn))
        .collect();

    #[derive(Serialize)]
    struct R {
        crate_owner_invitations: Vec<EncodableCrateOwnerInvitation>,
    }
    Ok(req.json(&R { crate_owner_invitations }))
}

/// Handles the `PUT /me/accept_owner_invite` route.
pub fn accept_invite(req: &mut Request) -> CargoResult<Response> {
    use diesel::{insert, delete};
    let conn = &*req.db_conn()?;
    let user_id = req.user()?.id;

    let mut body = String::new();
    req.body().read_to_string(&mut body)?;

    #[derive(Deserialize)]
    struct OwnerInvitation {
        crate_owner_invitation: EncodableCrateOwnerInvitation,
    }

    let crate_invite: OwnerInvitation = serde_json::from_str(&body).map_err(
        |_| human("invalid json request"),
    )?;

    let crate_invite = crate_invite.crate_owner_invitation;

    let pending_crate_owner = crate_owner_invitations::table
        .filter(crate_owner_invitations::crate_id.eq(crate_invite.crate_id))
        .filter(crate_owner_invitations::invited_user_id.eq(user_id))
        .first::<CrateOwnerInvitation>(&*conn)?;

    let owner = CrateOwner {
        crate_id: crate_invite.crate_id,
        owner_id: user_id,
        created_by: pending_crate_owner.invited_by_user_id,
        owner_kind: OwnerKind::User as i32,
    };

    conn.transaction(|| {
        insert(&owner).into(crate_owners::table).execute(conn)?;
        delete(crate_owner_invitations::table.filter(crate_owner_invitations::crate_id.eq(crate_invite.crate_id)))
            .execute(conn)?;

        #[derive(Serialize)]
        struct R {
            ok: bool,
        }
        Ok(req.json(&R { ok: true }))
    })
}
<commit_msg>add filter to delete statment such that delete filters by crate_id and invited_user_id<commit_after>use conduit::{Request, Response};
use diesel::prelude::*;
use time::Timespec;
use serde_json;

use db::RequestTransaction;
use schema::{crate_owner_invitations, users, crates, crate_owners};
use user::RequestUser;
use util::errors::{CargoResult, human};
use util::RequestUtils;
use owner::{CrateOwner, OwnerKind};

/// The model representing a row in the `crate_owner_invitations` database table.
#[derive(Clone, Copy, Debug, PartialEq, Eq, Identifiable, Queryable)]
#[primary_key(invited_user_id, crate_id)]
pub struct CrateOwnerInvitation {
    pub invited_user_id: i32,
    pub invited_by_user_id: i32,
    pub crate_id: i32,
    pub created_at: Timespec,
}

#[derive(Insertable, Clone, Copy, Debug)]
#[table_name = "crate_owner_invitations"]
pub struct NewCrateOwnerInvitation {
    pub invited_user_id: i32,
    pub invited_by_user_id: i32,
    pub crate_id: i32,
}

impl CrateOwnerInvitation {
    pub fn invited_by_username(&self, conn: &PgConnection) -> String {
        users::table
            .find(self.invited_by_user_id)
            .select(users::gh_login)
            .first(&*conn)
            .unwrap_or_else(|_| String::from("(unknown username)"))
    }

    pub fn crate_name(&self, conn: &PgConnection) -> String {
        crates::table
            .find(self.crate_id)
            .select(crates::name)
            .first(&*conn)
            .unwrap_or_else(|_| String::from("(unknown crate name)"))
    }

    pub fn encodable(self, conn: &PgConnection) -> EncodableCrateOwnerInvitation {
        EncodableCrateOwnerInvitation {
            invited_by_username: self.invited_by_username(conn),
            crate_name: self.crate_name(conn),
            crate_id: self.crate_id,
            created_at: ::encode_time(self.created_at),
        }
    }
}

/// The serialization format for the `CrateOwnerInvitation` model.
#[derive(Deserialize, Serialize, Debug)]
pub struct EncodableCrateOwnerInvitation {
    pub invited_by_username: String,
    pub crate_name: String,
    pub crate_id: i32,
    pub created_at: String,
}

/// Handles the `GET /me/crate_owner_invitations` route.
pub fn list(req: &mut Request) -> CargoResult<Response> {
    let conn = &*req.db_conn()?;
    let user_id = req.user()?.id;

    let crate_owner_invitations = crate_owner_invitations::table
        .filter(crate_owner_invitations::invited_user_id.eq(user_id))
        .load::<CrateOwnerInvitation>(&*conn)?
        .into_iter()
        .map(|i| i.encodable(conn))
        .collect();

    #[derive(Serialize)]
    struct R {
        crate_owner_invitations: Vec<EncodableCrateOwnerInvitation>,
    }
    Ok(req.json(&R { crate_owner_invitations }))
}

/// Handles the `PUT /me/accept_owner_invite` route.
pub fn accept_invite(req: &mut Request) -> CargoResult<Response> {
    use diesel::{insert, delete};
    let conn = &*req.db_conn()?;
    let user_id = req.user()?.id;

    let mut body = String::new();
    req.body().read_to_string(&mut body)?;

    #[derive(Deserialize)]
    struct OwnerInvitation {
        crate_owner_invitation: EncodableCrateOwnerInvitation,
    }

    let crate_invite: OwnerInvitation = serde_json::from_str(&body).map_err(
        |_| human("invalid json request"),
    )?;

    let crate_invite = crate_invite.crate_owner_invitation;

    let pending_crate_owner = crate_owner_invitations::table
        .filter(crate_owner_invitations::crate_id.eq(crate_invite.crate_id))
        .filter(crate_owner_invitations::invited_user_id.eq(user_id))
        .first::<CrateOwnerInvitation>(&*conn)?;

    let owner = CrateOwner {
        crate_id: crate_invite.crate_id,
        owner_id: user_id,
        created_by: pending_crate_owner.invited_by_user_id,
        owner_kind: OwnerKind::User as i32,
    };

    conn.transaction(|| {
        insert(&owner).into(crate_owners::table).execute(conn)?;
        delete(crate_owner_invitations::table
            .filter(crate_owner_invitations::crate_id.eq(crate_invite.crate_id))
            .filter(crate_owner_invitations::invited_user_id.eq(user_id)))
            .execute(conn)?;

        #[derive(Serialize)]
        struct R {
            ok: bool,
        }
        Ok(req.json(&R { ok: true }))
    })
}
<|endoftext|>


<commit_before>/*
* Huffman table generation:
* HuffTable::huff_decode()
* HuffTable::initialize()
* and used data structures are originally grabbed from the IJG software,
* and adapted by Hubert Figuiere.
*
* Copyright (C) 1991, 1992, Thomas G. Lane.
* Part of the Independent JPEG Group's software.
* See the file Copyright for more details.
*
* Copyright (c) 1993 Brian C. Smith, The Regents of the University
* of California
* All rights reserved.
*
* Copyright (c) 1994 Kongji Huang and Brian C. Smith.
* Cornell University
* All rights reserved.
*
* Permission to use, copy, modify, and distribute this software and its
* documentation for any purpose, without fee, and without written agreement is
* hereby granted, provided that the above copyright notice and the following
* two paragraphs appear in all copies of this software.
*
* IN NO EVENT SHALL CORNELL UNIVERSITY BE LIABLE TO ANY PARTY FOR
* DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
* OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF CORNELL
* UNIVERSITY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* CORNELL UNIVERSITY SPECIFICALLY DISCLAIMS ANY WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
* ON AN "AS IS" BASIS, AND CORNELL UNIVERSITY HAS NO OBLIGATION TO
* PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
*/

use std::fmt;
use decoders::basics::*;

const HUFF_BITMASK: [u32;32] = [0xffffffff, 0x7fffffff,
                                0x3fffffff, 0x1fffffff,
                                0x0fffffff, 0x07ffffff,
                                0x03ffffff, 0x01ffffff,
                                0x00ffffff, 0x007fffff,
                                0x003fffff, 0x001fffff,
                                0x000fffff, 0x0007ffff,
                                0x0003ffff, 0x0001ffff,
                                0x0000ffff, 0x00007fff,
                                0x00003fff, 0x00001fff,
                                0x00000fff, 0x000007ff,
                                0x000003ff, 0x000001ff,
                                0x000000ff, 0x0000007f,
                                0x0000003f, 0x0000001f,
                                0x0000000f, 0x00000007,
                                0x00000003, 0x00000001];

pub struct HuffTable {
  // These two fields directly represent the contents of a JPEG DHT marker
  pub bits: [u32;17],
  pub huffval: [u32;256],

  // The remaining fields are computed from the above to allow more
  // efficient coding and decoding and thus private
  mincode: [u16;17],
  maxcode: [i32;18],
  valptr: [i16;17],
  numbits: [usize;256],
  bigtable: Vec<i32>,
  precision: usize,
  pub use_bigtable: bool,
  pub dng_compatible: bool,
  pub initialized: bool,
}

impl HuffTable {
  pub fn empty(precision: usize) -> HuffTable {
    HuffTable {
      bits: [0;17],
      huffval: [0;256],
      mincode: [0;17],
      maxcode: [0;18],
      valptr: [0;17],
      numbits: [0;256],
      bigtable: Vec::new(),
      precision: precision,
      use_bigtable: true,
      dng_compatible: true,
      initialized: false,
    }
  }

  pub fn initialize(&mut self, use_bigtable: bool) -> Result<(), String> {
    // Figure C.1: make table of Huffman code length for each symbol
    // Note that this is in code-length order.
    let mut p = 0;
    let mut huffsize: [u8;257] = [0;257];
    for l in 1..17 {
      for _ in 1..((self.bits[l] as usize)+1) {
        huffsize[p] = l as u8;
        p += 1;
        if p > 256 {
          return Err("ljpeg: Code length too long. Corrupt data.".to_string())
        }
      }
    }
    huffsize[p] = 0;
    let lastp = p;

    // Figure C.2: generate the codes themselves
    // Note that this is in code-length order.
    let mut code: u16 = 0;
    let mut si: u32 = huffsize[0] as u32;
    let mut huffcode: [u16;257] = [0;257];
    p = 0;
    while huffsize[p] > 0 {
      while (huffsize[p] as u32) == si {
        huffcode[p] = code;
        p += 1;
        code += 1;
      }
      code <<= 1;
      si += 1;
      if p > 256 {
        return Err("ljpeg: Code length too long. Corrupt data.".to_string())
      }
    }

    //Figure F.15: generate decoding tables
    self.mincode[0] = 0;
    self.maxcode[0] = 0;
    p = 0;
    for l in 1..17 {
      if self.bits[l] > 0 {
        self.valptr[l] = p as i16;
        self.mincode[l] = huffcode[p];
        p += self.bits[l] as usize;
        self.maxcode[l] = huffcode[p - 1] as i32;
      } else {
        self.valptr[l] = 0xff;   // This check must be present to avoid crash on junk
        self.maxcode[l] = -1;
      }
      if p > 256 {
        return Err("ljpeg: Code length too long. Corrupt data.".to_string())
      }
    }

    // We put in this value to ensure HuffDecode terminates
    self.maxcode[17] = 0xFFFFF;

    // Build the numbits, value lookup tables.
    // These table allow us to gather 8 bits from the bits stream,
    // and immediately lookup the size and value of the huffman codes.
    // If size is zero, it means that more than 8 bits are in the huffman
    // code (this happens about 3-4% of the time).
    for p in 0..lastp {
      let size = huffsize[p];
      if size <= 8 {
        let value: i32 = self.huffval[p] as i32;
        let code = huffcode[p];
        let ll: i32 = (code << (8 - size)) as i32;
        let ul: i32 = if size < 8 {
          ll | (HUFF_BITMASK[(24+size) as usize]) as i32
        } else {
          ll
        };
        if ul > 256 || ll > ul {
          return Err("ljpeg: Code length too long. Corrupt data.".to_string())
        }
        for i in ll..(ul+1) {
          self.numbits[i as usize] = (size as usize) | ((value as usize) << 4);
        }
      }
    }

    if use_bigtable {
      try!(self.initialize_bigtable());
    }
    self.initialized = true;
    self.use_bigtable = use_bigtable;
    Ok(())
  }

  fn initialize_bigtable(&mut self) -> Result<(), String> {
    let bits: usize = 14; // HuffDecode functions must be changed, if this is modified.
    let size: usize = 1 << bits;

    self.bigtable = vec![0 as i32;size];
    let mut rv: i32;
    for i in 0..size {
      let input = (i << 2) as u16;
      let mut code: i32 = (input >> 8) as i32;
      let val: u32 = self.numbits[code as usize] as u32;
      let mut l: u32 = val & 15;
      if l > 0 {
        rv = (val >> 4) as i32;
      } else {
        l = 8;
        while code > self.maxcode[l as usize] {
          let temp: i32 = (input >> (15 - l) & 1) as i32;
          code = (code << 1) | temp;
          l += 1;
        }

        //With garbage input we may reach the sentinel value l = 17.
        if l > self.precision as u32 || self.valptr[l as usize] == 0xff {
          self.bigtable[i] = 0xff;
          continue
        } else {
          rv = self.huffval[
            self.valptr[l as usize] as usize +
            (code - (self.mincode[l as usize] as i32)) as usize
          ] as i32;
        }
      }

      if rv == 16 {
        self.bigtable[i] = if self.dng_compatible {
          (-(32768 << 8)) | (16 + l as i32)
        } else {
          (-(32768 << 8)) | l as i32
        };
        continue
      }

      if rv + l as i32 > bits as i32 {
        self.bigtable[i] = 0xff;
        continue
      }

      if rv != 0 {
        let mut x = (input >> (16 - (l as i32) - rv) & ((1 << rv) - 1)) as i32;
        if (x & (1 << (rv - 1))) == 0 {
          x -= (1 << rv) - 1;
        }
        self.bigtable[i] = (x << 8) | ((l as i32) + rv);
      } else {
        self.bigtable[i] = l as i32;
      }
    }
    self.use_bigtable = true;
    Ok(())
  }

  // Taken from Figure F.16: extract next coded symbol from input stream
  pub fn huff_decode(&self, pump: &mut BitPump) -> Result<i32,String> {
    if !self.initialized {
      return Err("ljpeg: Trying to read from uninitialized HuffTable".to_string());
    }

    //First attempt to do complete decode, by using the first 14 bits
    let mut code: i32 = pump.peek_bits(14) as i32;
    if self.use_bigtable {
      let val: i32 = self.bigtable[code as usize];
      if val & 0xff != 0xff {
        pump.consume_bits((val & 0xff) as u32);
        return Ok(val >> 8)
      }
    }

    // If the huffman code is less than 8 bits, we can use the fast
    // table lookup to get its value.  It's more than 8 bits about
    // 3-4% of the time.
    let rv: i32;
    code >>= 6;
    let val = self.numbits[code as usize] as i32;
    let mut l = val & 15;
    if l != 0 {
      pump.consume_bits(l as u32);
      rv = val >> 4;
    } else {
      pump.consume_bits(8);
      l = 8;
      while code > self.maxcode[l as usize] {
        let temp = pump.get_bits(1) as i32;
        code = (code << 1) | temp;
        l += 1;
      }

      // With garbage input we may reach the sentinel value l = 17.
      if l > self.precision as i32 || self.valptr[l as usize] == 0xff {
        return Err(format!("ljpeg: bad Huffman code: {}", l).to_string())
      } else {
        rv = self.huffval[
          self.valptr[l as usize] as usize +
          (code - (self.mincode[l as usize] as i32)) as usize
        ] as i32;
      }
    }

    if rv == 16 {
      if self.dng_compatible {
        pump.consume_bits(16);
      }
      return Ok(-32768);
    }

    // Section F.2.2.1: decode the difference and
    // Figure F.12: extend sign bit
    if rv != 0 {
      let mut x: i32 = pump.get_bits(rv as u32) as i32;
      if (x & (1 << (rv - 1))) == 0 {
        x -= (1 << rv) - 1;
      }
      return Ok(x)
    }

    return Ok(0)
  }
}

impl fmt::Debug for HuffTable {
  fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
    if self.initialized {
      write!(f, "HuffTable {{ bits: {:?} huffval: {:?} }}", self.bits, &self.huffval[..])
    } else {
      write!(f, "HuffTable {{ uninitialized }}")
    }
  }
}

<commit_msg>DNG: prevent an underflow in big table generation<commit_after>/*
* Huffman table generation:
* HuffTable::huff_decode()
* HuffTable::initialize()
* and used data structures are originally grabbed from the IJG software,
* and adapted by Hubert Figuiere.
*
* Copyright (C) 1991, 1992, Thomas G. Lane.
* Part of the Independent JPEG Group's software.
* See the file Copyright for more details.
*
* Copyright (c) 1993 Brian C. Smith, The Regents of the University
* of California
* All rights reserved.
*
* Copyright (c) 1994 Kongji Huang and Brian C. Smith.
* Cornell University
* All rights reserved.
*
* Permission to use, copy, modify, and distribute this software and its
* documentation for any purpose, without fee, and without written agreement is
* hereby granted, provided that the above copyright notice and the following
* two paragraphs appear in all copies of this software.
*
* IN NO EVENT SHALL CORNELL UNIVERSITY BE LIABLE TO ANY PARTY FOR
* DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
* OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF CORNELL
* UNIVERSITY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* CORNELL UNIVERSITY SPECIFICALLY DISCLAIMS ANY WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
* ON AN "AS IS" BASIS, AND CORNELL UNIVERSITY HAS NO OBLIGATION TO
* PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
*/

use std::fmt;
use decoders::basics::*;

const HUFF_BITMASK: [u32;32] = [0xffffffff, 0x7fffffff,
                                0x3fffffff, 0x1fffffff,
                                0x0fffffff, 0x07ffffff,
                                0x03ffffff, 0x01ffffff,
                                0x00ffffff, 0x007fffff,
                                0x003fffff, 0x001fffff,
                                0x000fffff, 0x0007ffff,
                                0x0003ffff, 0x0001ffff,
                                0x0000ffff, 0x00007fff,
                                0x00003fff, 0x00001fff,
                                0x00000fff, 0x000007ff,
                                0x000003ff, 0x000001ff,
                                0x000000ff, 0x0000007f,
                                0x0000003f, 0x0000001f,
                                0x0000000f, 0x00000007,
                                0x00000003, 0x00000001];

pub struct HuffTable {
  // These two fields directly represent the contents of a JPEG DHT marker
  pub bits: [u32;17],
  pub huffval: [u32;256],

  // The remaining fields are computed from the above to allow more
  // efficient coding and decoding and thus private
  mincode: [u16;17],
  maxcode: [i32;18],
  valptr: [i16;17],
  numbits: [usize;256],
  bigtable: Vec<i32>,
  precision: usize,
  pub use_bigtable: bool,
  pub dng_compatible: bool,
  pub initialized: bool,
}

impl HuffTable {
  pub fn empty(precision: usize) -> HuffTable {
    HuffTable {
      bits: [0;17],
      huffval: [0;256],
      mincode: [0;17],
      maxcode: [0;18],
      valptr: [0;17],
      numbits: [0;256],
      bigtable: Vec::new(),
      precision: precision,
      use_bigtable: true,
      dng_compatible: true,
      initialized: false,
    }
  }

  pub fn initialize(&mut self, use_bigtable: bool) -> Result<(), String> {
    // Figure C.1: make table of Huffman code length for each symbol
    // Note that this is in code-length order.
    let mut p = 0;
    let mut huffsize: [u8;257] = [0;257];
    for l in 1..17 {
      for _ in 1..((self.bits[l] as usize)+1) {
        huffsize[p] = l as u8;
        p += 1;
        if p > 256 {
          return Err("ljpeg: Code length too long. Corrupt data.".to_string())
        }
      }
    }
    huffsize[p] = 0;
    let lastp = p;

    // Figure C.2: generate the codes themselves
    // Note that this is in code-length order.
    let mut code: u16 = 0;
    let mut si: u32 = huffsize[0] as u32;
    let mut huffcode: [u16;257] = [0;257];
    p = 0;
    while huffsize[p] > 0 {
      while (huffsize[p] as u32) == si {
        huffcode[p] = code;
        p += 1;
        code += 1;
      }
      code <<= 1;
      si += 1;
      if p > 256 {
        return Err("ljpeg: Code length too long. Corrupt data.".to_string())
      }
    }

    //Figure F.15: generate decoding tables
    self.mincode[0] = 0;
    self.maxcode[0] = 0;
    p = 0;
    for l in 1..17 {
      if self.bits[l] > 0 {
        self.valptr[l] = p as i16;
        self.mincode[l] = huffcode[p];
        p += self.bits[l] as usize;
        self.maxcode[l] = huffcode[p - 1] as i32;
      } else {
        self.valptr[l] = 0xff;   // This check must be present to avoid crash on junk
        self.maxcode[l] = -1;
      }
      if p > 256 {
        return Err("ljpeg: Code length too long. Corrupt data.".to_string())
      }
    }

    // We put in this value to ensure HuffDecode terminates
    self.maxcode[17] = 0xFFFFF;

    // Build the numbits, value lookup tables.
    // These table allow us to gather 8 bits from the bits stream,
    // and immediately lookup the size and value of the huffman codes.
    // If size is zero, it means that more than 8 bits are in the huffman
    // code (this happens about 3-4% of the time).
    for p in 0..lastp {
      let size = huffsize[p];
      if size <= 8 {
        let value: i32 = self.huffval[p] as i32;
        let code = huffcode[p];
        let ll: i32 = (code << (8 - size)) as i32;
        let ul: i32 = if size < 8 {
          ll | (HUFF_BITMASK[(24+size) as usize]) as i32
        } else {
          ll
        };
        if ul > 256 || ll > ul {
          return Err("ljpeg: Code length too long. Corrupt data.".to_string())
        }
        for i in ll..(ul+1) {
          self.numbits[i as usize] = (size as usize) | ((value as usize) << 4);
        }
      }
    }

    if use_bigtable {
      try!(self.initialize_bigtable());
    }
    self.initialized = true;
    self.use_bigtable = use_bigtable;
    Ok(())
  }

  fn initialize_bigtable(&mut self) -> Result<(), String> {
    let bits: usize = 14; // HuffDecode functions must be changed, if this is modified.
    let size: usize = 1 << bits;

    self.bigtable = vec![0 as i32;size];
    let mut rv: i32;
    for i in 0..size {
      let input = (i << 2) as u16;
      let mut code: i32 = (input >> 8) as i32;
      let val: u32 = self.numbits[code as usize] as u32;
      let mut l: u32 = val & 15;
      if l > 0 {
        rv = (val >> 4) as i32;
      } else {
        l = 8;
        while code > self.maxcode[l as usize] && l < 16 {
          let temp: i32 = (input >> (15 - l) & 1) as i32;
          code = (code << 1) | temp;
          l += 1;
        }

        //With garbage input we may reach the sentinel value l = 17.
        if l > self.precision as u32 || self.valptr[l as usize] == 0xff {
          self.bigtable[i] = 0xff;
          continue
        } else {
          rv = self.huffval[
            self.valptr[l as usize] as usize +
            (code - (self.mincode[l as usize] as i32)) as usize
          ] as i32;
        }
      }

      if rv == 16 {
        self.bigtable[i] = if self.dng_compatible {
          (-(32768 << 8)) | (16 + l as i32)
        } else {
          (-(32768 << 8)) | l as i32
        };
        continue
      }

      if rv + l as i32 > bits as i32 {
        self.bigtable[i] = 0xff;
        continue
      }

      if rv != 0 {
        let mut x = (input >> (16 - (l as i32) - rv) & ((1 << rv) - 1)) as i32;
        if (x & (1 << (rv - 1))) == 0 {
          x -= (1 << rv) - 1;
        }
        self.bigtable[i] = (x << 8) | ((l as i32) + rv);
      } else {
        self.bigtable[i] = l as i32;
      }
    }
    self.use_bigtable = true;
    Ok(())
  }

  // Taken from Figure F.16: extract next coded symbol from input stream
  pub fn huff_decode(&self, pump: &mut BitPump) -> Result<i32,String> {
    if !self.initialized {
      return Err("ljpeg: Trying to read from uninitialized HuffTable".to_string());
    }

    //First attempt to do complete decode, by using the first 14 bits
    let mut code: i32 = pump.peek_bits(14) as i32;
    if self.use_bigtable {
      let val: i32 = self.bigtable[code as usize];
      if val & 0xff != 0xff {
        pump.consume_bits((val & 0xff) as u32);
        return Ok(val >> 8)
      }
    }

    // If the huffman code is less than 8 bits, we can use the fast
    // table lookup to get its value.  It's more than 8 bits about
    // 3-4% of the time.
    let rv: i32;
    code >>= 6;
    let val = self.numbits[code as usize] as i32;
    let mut l = val & 15;
    if l != 0 {
      pump.consume_bits(l as u32);
      rv = val >> 4;
    } else {
      pump.consume_bits(8);
      l = 8;
      while code > self.maxcode[l as usize] {
        let temp = pump.get_bits(1) as i32;
        code = (code << 1) | temp;
        l += 1;
      }

      // With garbage input we may reach the sentinel value l = 17.
      if l > self.precision as i32 || self.valptr[l as usize] == 0xff {
        return Err(format!("ljpeg: bad Huffman code: {}", l).to_string())
      } else {
        rv = self.huffval[
          self.valptr[l as usize] as usize +
          (code - (self.mincode[l as usize] as i32)) as usize
        ] as i32;
      }
    }

    if rv == 16 {
      if self.dng_compatible {
        pump.consume_bits(16);
      }
      return Ok(-32768);
    }

    // Section F.2.2.1: decode the difference and
    // Figure F.12: extend sign bit
    if rv != 0 {
      let mut x: i32 = pump.get_bits(rv as u32) as i32;
      if (x & (1 << (rv - 1))) == 0 {
        x -= (1 << rv) - 1;
      }
      return Ok(x)
    }

    return Ok(0)
  }
}

impl fmt::Debug for HuffTable {
  fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
    if self.initialized {
      write!(f, "HuffTable {{ bits: {:?} huffval: {:?} }}", self.bits, &self.huffval[..])
    } else {
      write!(f, "HuffTable {{ uninitialized }}")
    }
  }
}

<|endoftext|>


<commit_before>// Cooperative optimization solver
use std::collections::BinaryHeap;
use std::io::Write;
extern crate rand;

#[macro_use(max)]
extern crate gelpia_utils;
extern crate ga;
extern crate gr;

use ga::{ea, Individual};

use gelpia_utils::{Quple, INF, NINF, Flt, Parameters, eps_tol};

use gr::{GI, width_box, split_box, midpoint_box};

use std::sync::{Barrier, RwLock, Arc, RwLockWriteGuard};

use std::sync::atomic::{AtomicBool, Ordering, AtomicUsize};

use std::thread;

use std::time::Duration;

extern crate function;
use function::FuncObj;

extern crate args;
use args::{process_args};

extern crate threadpool;
use threadpool::ThreadPool;
use std::sync::mpsc::channel;
extern crate time;

/// Returns the guaranteed upperbound for the algorithm
/// from the queue.
fn get_upper_bound(q: &RwLockWriteGuard<Vec<Quple>>,
                   f_best_high: f64) -> f64{
    let mut max = f_best_high;
    for qi in q.iter() {
        max = max!{max, qi.fdata.upper()};
    }
    max
}

fn log_max(q: &RwLockWriteGuard<Vec<Quple>>,
           f_best_low: f64,
           f_best_high: f64) {
    let max = get_upper_bound(q, f_best_high);
    let _ = writeln!(&mut std::io::stderr(),
                     "lb: {}, possible ub: {}, guaranteed ub: {}",
                     f_best_low,
                     f_best_high,
                     max);
}

fn print_q(q: &RwLockWriteGuard<BinaryHeap<Quple>>) {
    let mut lq: BinaryHeap<Quple> = (*q).clone();
    while lq.len() != 0 {
        let qi = lq.pop().unwrap();
        let (gen, v, fx) = (qi.pf, qi.p, qi.fdata);
        print!("[{}, {}, {}], ", v, gen, qi.fdata.to_string());
    }
    println!("\n");
}

/// Returns a tuple (function_estimate, eval_interval)
/// # Arguments
/// * `f` - The function to evaluate with
/// * `input` - The input domain
fn est_func(f: &FuncObj, input: &Vec<GI>) -> (Flt, GI) {
    let mid = midpoint_box(input);
    let est_m = f.call(&mid);
    let fsx = f.call(&input);
    let fsx_u = f.call(&input.iter()
                       .map(|&si| GI::new_p(si.upper()))
                       .collect::<Vec<_>>());
    let fsx_l = f.call(&input.iter()
                       .map(|&si| GI::new_p(si.lower()))
                       .collect::<Vec<_>>());
    let est_max = est_m.lower().max(fsx_u.lower()).max(fsx_l.lower());
    (est_max, fsx)
}

// Returns the upper bound, the domain where this bound occurs and a status
// flag indicating whether the answer is complete for the problem.
fn ibba(x_0: Vec<GI>, e_x: Flt, e_f: Flt, e_f_r: Flt,
        f_bestag: Arc<RwLock<Flt>>,
        f_best_shared: Arc<RwLock<Flt>>,
        x_bestbb: Arc<RwLock<Vec<GI>>>,
        b1: Arc<Barrier>, b2: Arc<Barrier>,
        q: Arc<RwLock<Vec<Quple>>>,
        sync: Arc<AtomicBool>, stop: Arc<AtomicBool>,
        f: FuncObj,
        logging: bool, max_iters: u32)
        -> (Flt, Flt, Vec<GI>) {
    let mut best_x = x_0.clone();

    let iters = Arc::new(AtomicUsize::new(0));
    let (est_max, first_val) = est_func(&f, &x_0);
    {
        q.write().unwrap().push(Quple{p: est_max, pf: 0, data: x_0.clone(),
                                      fdata: first_val});
    }
    let mut f_best_low = est_max;
    let mut f_best_high = est_max;

    let n_workers = 11;
    let n_jobs = n_workers;
    let pool = ThreadPool::new(n_workers);

    while q.read().unwrap().len() != 0 && !stop.load(Ordering::Acquire) {
        if max_iters != 0 && iters.load(Ordering::Acquire) as u32 >= max_iters {
            break;
        }
        if sync.load(Ordering::Acquire) {
            // Ugly: Update the update thread's view of the best branch bound.
            *f_best_shared.write().unwrap() = f_best_low;
            b1.wait();
            b2.wait();
        }
        {
            // Take q as writable during an iteration
            let q = q.write().unwrap();

            let fbl_orig = f_best_low;
            f_best_low = max!(f_best_low, *f_bestag.read().unwrap());

            if iters.load(Ordering::Acquire) % 2048 == 0 {
                let guaranteed_bound =
                    get_upper_bound(&q, f_best_high);
                if (guaranteed_bound - f_best_high).abs() < e_f {
                    f_best_high = guaranteed_bound;
                    break;
                }
            }

            if logging && fbl_orig != f_best_low {
                log_max(&q, f_best_low, f_best_high);
            }
        }

        let p_q_len = {
            let mut q = q.write().unwrap();
            q.sort();
            q.len()/n_workers + 1
        };

/*        let mut p_q = vec![];
        {
            let mut total_len = 0;
            let q = q.write().unwrap();
            let q_len = q.len();
            for i in 0..n_workers {
                let mut elems = vec![];
                for j in 0..p_q_len {
                    if i + j*n_workers >= q_len {
                        break;
                    }
                    elems.push(q[i+j*n_workers].clone());
                }
                total_len += elems.len();
                p_q.push(elems);
            }
        } */

        let outer_barr = Arc::new(Barrier::new(n_workers + 1));

        let (qtx, qrx) = channel();
        let (htx, hrx) = channel();
        let (ltx, lrx) = channel();

        for i in 0..n_workers {
            let inner_barr = outer_barr.clone();
//            let elems = p_q[i].clone();
            let _f = f.clone();
            let qtx = qtx.clone();
            let htx = htx.clone();
            let ltx = ltx.clone();
            let f_bestag = f_bestag.clone();
            let iters = iters.clone();
            let lqi = q.clone();
            pool.execute(move || {
                let mut l_f_best_high = f_best_high;
                let mut l_best_x = vec![];

                let mut l_f_best_low = f_best_low;
                let mut l_best_low_x = vec![];

                let mut lqo = vec![];
                let mut used = false;
                let lqi = lqi.read().unwrap();
//                let elems_len = elems.len();

                for j in 0..p_q_len {
                    if i + j*n_workers >= lqi.len() { break };
                    used = true;
                    let ref elem = lqi[i + j*n_workers];
                    let ref x = elem.data;
                    let ref iter_est = elem.p;
                    let ref fx = elem.fdata;
                    let ref gen = elem.pf;
                    //let (ref x, iter_est, fx, gen) = ;

                    if fx.upper() < l_f_best_low ||
                        width_box(&x, e_x) ||
                        eps_tol(*fx, *iter_est, e_f, e_f_r) {
                            if l_f_best_high < fx.upper() {
                                l_f_best_high = fx.upper();
                                l_best_x = x.clone();
                                // htx.send((fx.upper(), x.clone())).unwrap();
                            }
                        }
                    else {
                        let (x_s, is_split) = split_box(&x);
                        for sx in x_s {
                            let (est_max, fsx) = est_func(&_f, &sx);
                            if l_f_best_low < est_max {
                                l_f_best_low = est_max;
                                l_best_low_x = sx.clone();
                                // ltx.send((est_max, sx.clone())).unwrap();
                            }
                            iters.fetch_add(1, Ordering::Release);
                            if is_split && fsx.upper() > f_best_low &&
                                fsx.upper() > *f_bestag.read().unwrap() {
                                    lqo.push(Quple{p: est_max,
                                                   pf: gen+1,
                                                   data: sx,
                                                   fdata: fsx});
                                }
                        }
                    }
                }
                ltx.send((l_f_best_low, l_best_low_x, used)).unwrap();
                htx.send((l_f_best_high, l_best_x, used)).unwrap();
                lqo.sort();
                qtx.send(lqo).unwrap();
                inner_barr.wait();
            });
        }
        outer_barr.wait();
        drop(qtx);
        drop(htx);
        drop(ltx);

        for li in lrx.iter() {
            let (lb, lx, non_empty) = li;
            if non_empty && f_best_low < lb {
                f_best_low = lb;
                *x_bestbb.write().unwrap() = lx.clone();
            }
        }

        for hi in hrx.iter() {
            let (ub, ux, non_empty) = hi;
            if non_empty && f_best_high < ub {
                f_best_high = ub;
                best_x = ux.clone();
            }
        }
        {
            let mut lq = q.write().unwrap();
            *lq = vec![];
            for qis in qrx.iter() {
                for qi in &qis {
                    if qi.fdata.upper() > f_best_low {
                        lq.push(qi.clone());
                    }
                }
            }
        }
    }
    println!("{}", iters.load(Ordering::Acquire));
    stop.store(true, Ordering::Release);
    (f_best_low, f_best_high, best_x)
}

fn update(stop: Arc<AtomicBool>, _sync: Arc<AtomicBool>,
          _b1: Arc<Barrier>, _b2: Arc<Barrier>,
          _f: FuncObj,
          timeout: u32) {
    let start = time::get_time();
    let one_sec = Duration::new(1, 0);
    'out: while !stop.load(Ordering::Acquire) {
        // Timer code...
        thread::sleep(one_sec);
        if timeout > 0 &&
            (time::get_time() - start).num_seconds() >= timeout as i64 {
                let _ = writeln!(&mut std::io::stderr(), "Stopping early...");
                stop.store(true, Ordering::Release);
                break 'out;
            }
    }
}

fn main() {
    let args = process_args();

    let ref x_0 = args.domain;
    let ref fo = args.function;
    let x_err = args.x_error;
    let y_err = args.y_error;
    let y_rel = args.y_error_rel;
    let seed = args.seed;

    // Early out if there are no input variables...
    if x_0.len() == 0 {
        let result = fo.call(&x_0);
        println!("[[{},{}], {{}}]", result.lower(), result.upper());
        return
    }

    let q_inner: Vec<Quple> = Vec::new();
    let q = Arc::new(RwLock::new(q_inner));

    let population_inner: Vec<Individual> = Vec::new();
    let population = Arc::new(RwLock::new(population_inner));

    let b1 = Arc::new(Barrier::new(3));
    let b2 = Arc::new(Barrier::new(3));

    let sync = Arc::new(AtomicBool::new(false));
    let stop = Arc::new(AtomicBool::new(false));

    let f_bestag: Arc<RwLock<Flt>> = Arc::new(RwLock::new(NINF));
    let f_best_shared: Arc<RwLock<Flt>> = Arc::new(RwLock::new(NINF));

    let x_e = x_0.clone();
    let x_i = x_0.clone();

    let x_bestbb = Arc::new(RwLock::new(x_0.clone()));

    let ibba_thread =
    {
        let q = q.clone();
        let b1 = b1.clone();
        let b2 = b2.clone();
        let f_bestag = f_bestag.clone();
        let f_best_shared = f_best_shared.clone();
        let x_bestbb = x_bestbb.clone();
        let sync = sync.clone();
        let stop = stop.clone();
        let fo_c = fo.clone();
        let logging = args.logging;
        let iters= args.iters;
        thread::Builder::new().name("IBBA".to_string()).spawn(move || {
            ibba(x_i, x_err, y_err, y_rel,
                 f_bestag, f_best_shared,
                 x_bestbb,
                 b1, b2, q, sync, stop, fo_c, logging, iters)
        })};

    let ea_thread =
    {
        let population = population.clone();
        let f_bestag = f_bestag.clone();
        let x_bestbb = x_bestbb.clone();
        let sync = sync.clone();
        let stop = stop.clone();
        let b1 = b1.clone();
        let b2 = b2.clone();
        let fo_c = fo.clone();
        let factor = x_e.len();
        thread::Builder::new().name("EA".to_string()).spawn(move || {
            ea(x_e, Parameters{population: 50*factor, //1000,
                               selection: 8, //4,
                               elitism: 5, //2,
                               mutation: 0.4_f64,//0.3_f64,
                               crossover: 0.0_f64, // 0.5_f64
                               seed:  seed,
            },
               population,
               f_bestag,
               x_bestbb,
               b1, b2,
               stop, sync, fo_c)
        })};

    // pending finding out how to kill threads
    //let update_thread =
    {
        let sync = sync.clone();
        let stop = stop.clone();
        let b1 = b1.clone();
        let b2 = b2.clone();
        let fo_c = fo.clone();
        let to = args.timeout.clone();
        let _ = thread::Builder::new().name("Update".to_string()).spawn(move || {
            update(stop, sync, b1, b2, fo_c, to)
        });};

    let result = ibba_thread.unwrap().join();
    let ea_result = ea_thread.unwrap().join();

    // Join EA and Update here pending stop signaling.
    if result.is_ok() {
        let (min, mut max, mut interval) = result.unwrap();
        // Go through all remaining intervals from IBBA to find the true
        // max
        let mut lq = q.write().unwrap();
        while lq.len() != 0 {
            let ref top = lq.pop().unwrap();
            let (ub, dom) = (top.fdata.upper(), &top.data);
            if ub > max {
            max = ub;
            interval = dom.clone();
        }
    }
    println!("[[{},{}], {{", min, max);
    for i in 0..args.names.len() {
        println!("'{}' : {},", args.names[i], interval[i].to_string());
    }
    println!("}}]");

}
else {println!("error")}
}
<commit_msg>Comments+indentation<commit_after>// Cooperative optimization solver
use std::collections::BinaryHeap;
use std::io::Write;
extern crate rand;

#[macro_use(max)]
extern crate gelpia_utils;
extern crate ga;
extern crate gr;

use ga::{ea, Individual};

use gelpia_utils::{Quple, INF, NINF, Flt, Parameters, eps_tol};

use gr::{GI, width_box, split_box, midpoint_box};

use std::sync::{Barrier, RwLock, Arc, RwLockWriteGuard};

use std::sync::atomic::{AtomicBool, Ordering, AtomicUsize};

use std::thread;

use std::time::Duration;

extern crate function;
use function::FuncObj;

extern crate args;
use args::{process_args};

extern crate threadpool;
use threadpool::ThreadPool;
use std::sync::mpsc::channel;
extern crate time;

/// Returns the guaranteed upperbound for the algorithm
/// from the queue.
fn get_upper_bound(q: &RwLockWriteGuard<Vec<Quple>>,
                   f_best_high: f64) -> f64{
    let mut max = f_best_high;
    for qi in q.iter() {
        max = max!{max, qi.fdata.upper()};
    }
    max
}

fn log_max(q: &RwLockWriteGuard<Vec<Quple>>,
           f_best_low: f64,
           f_best_high: f64) {
    let max = get_upper_bound(q, f_best_high);
    let _ = writeln!(&mut std::io::stderr(),
                     "lb: {}, possible ub: {}, guaranteed ub: {}",
                     f_best_low,
                     f_best_high,
                     max);
}

fn print_q(q: &RwLockWriteGuard<BinaryHeap<Quple>>) {
    let mut lq: BinaryHeap<Quple> = (*q).clone();
    while lq.len() != 0 {
        let qi = lq.pop().unwrap();
        let (gen, v, fx) = (qi.pf, qi.p, qi.fdata);
        print!("[{}, {}, {}], ", v, gen, qi.fdata.to_string());
    }
    println!("\n");
}

/// Returns a tuple (function_estimate, eval_interval)
/// # Arguments
/// * `f` - The function to evaluate with
/// * `input` - The input domain
fn est_func(f: &FuncObj, input: &Vec<GI>) -> (Flt, GI) {
    let mid = midpoint_box(input);
    let est_m = f.call(&mid);
    let fsx = f.call(&input);
    let fsx_u = f.call(&input.iter()
                       .map(|&si| GI::new_p(si.upper()))
                       .collect::<Vec<_>>());
    let fsx_l = f.call(&input.iter()
                       .map(|&si| GI::new_p(si.lower()))
                       .collect::<Vec<_>>());
    let est_max = est_m.lower().max(fsx_u.lower()).max(fsx_l.lower());
    (est_max, fsx)
}

// Returns the upper bound, the domain where this bound occurs and a status
// flag indicating whether the answer is complete for the problem.
fn ibba(x_0: Vec<GI>, e_x: Flt, e_f: Flt, e_f_r: Flt,
        f_bestag: Arc<RwLock<Flt>>,
        f_best_shared: Arc<RwLock<Flt>>,
        x_bestbb: Arc<RwLock<Vec<GI>>>,
        b1: Arc<Barrier>, b2: Arc<Barrier>,
        q: Arc<RwLock<Vec<Quple>>>,
        sync: Arc<AtomicBool>, stop: Arc<AtomicBool>,
        f: FuncObj,
        logging: bool, max_iters: u32)
        -> (Flt, Flt, Vec<GI>) {
    let mut best_x = x_0.clone();

    let iters = Arc::new(AtomicUsize::new(0));
    let (est_max, first_val) = est_func(&f, &x_0);
    {
        q.write().unwrap().push(Quple{p: est_max, pf: 0, data: x_0.clone(),
                                      fdata: first_val});
    }
    let mut f_best_low = est_max;
    let mut f_best_high = est_max;

    let n_workers = 11;
    let n_jobs = n_workers;
    let pool = ThreadPool::new(n_workers);

    while q.read().unwrap().len() != 0 && !stop.load(Ordering::Acquire) {
        if max_iters != 0 && iters.load(Ordering::Acquire) as u32 >= max_iters {
            break;
        }
        if sync.load(Ordering::Acquire) {
            // Ugly: Update the update thread's view of the best branch bound.
            *f_best_shared.write().unwrap() = f_best_low;
            b1.wait();
            b2.wait();
        }
        {
            // Take q as writable during an iteration
            let q = q.write().unwrap();

            let fbl_orig = f_best_low;
            f_best_low = max!(f_best_low, *f_bestag.read().unwrap());

            if iters.load(Ordering::Acquire) % 2048 == 0 {
                let guaranteed_bound =
                    get_upper_bound(&q, f_best_high);
                if (guaranteed_bound - f_best_high).abs() < e_f {
                    f_best_high = guaranteed_bound;
                    break;
                }
            }

            if logging && fbl_orig != f_best_low {
                log_max(&q, f_best_low, f_best_high);
            }
        }

        let p_q_len = {
            let mut q = q.write().unwrap();
            q.sort();
            q.len()/n_workers + 1
        };

        let outer_barr = Arc::new(Barrier::new(n_workers + 1));

        let (qtx, qrx) = channel();
        let (htx, hrx) = channel();
        let (ltx, lrx) = channel();

        for i in 0..n_workers {
            let inner_barr = outer_barr.clone();
            let _f = f.clone();
            let qtx = qtx.clone();
            let htx = htx.clone();
            let ltx = ltx.clone();
            let f_bestag = f_bestag.clone();
            let iters = iters.clone();
            let lqi = q.clone();
            pool.execute(move || {
                let mut l_f_best_high = f_best_high;
                let mut l_best_x = vec![];

                let mut l_f_best_low = f_best_low;
                let mut l_best_low_x = vec![];

                let mut lqo = vec![];
                let mut used = false;
                let lqi = lqi.read().unwrap();

                for j in 0..p_q_len {
                    if i + j*n_workers >= lqi.len() { break };
                    used = true;
                    let ref elem = lqi[i + j*n_workers];
                    let ref x = elem.data;
                    let ref iter_est = elem.p;
                    let ref fx = elem.fdata;
                    let ref gen = elem.pf;

                    if fx.upper() < l_f_best_low ||
                        width_box(&x, e_x) ||
                        eps_tol(*fx, *iter_est, e_f, e_f_r) {
                            if l_f_best_high < fx.upper() {
                                l_f_best_high = fx.upper();
                                l_best_x = x.clone();
                            }
                        }
                    else {
                        let (x_s, is_split) = split_box(&x);
                        for sx in x_s {
                            let (est_max, fsx) = est_func(&_f, &sx);
                            if l_f_best_low < est_max {
                                l_f_best_low = est_max;
                                l_best_low_x = sx.clone();
                            }
                            iters.fetch_add(1, Ordering::Release);
                            if is_split && fsx.upper() > f_best_low &&
                                fsx.upper() > *f_bestag.read().unwrap() {
                                    lqo.push(Quple{p: est_max,
                                                   pf: gen+1,
                                                   data: sx,
                                                   fdata: fsx});
                                }
                        }
                    }
                }
                ltx.send((l_f_best_low, l_best_low_x, used)).unwrap();
                htx.send((l_f_best_high, l_best_x, used)).unwrap();

                lqo.sort();
                qtx.send(lqo).unwrap();

                inner_barr.wait();
            });
        }
        outer_barr.wait();

        // Hangup the transmission ends of the channels
        drop(qtx);
        drop(htx);
        drop(ltx);

        for li in lrx.iter() {
            let (lb, lx, non_empty) = li;
            if non_empty && f_best_low < lb {
                f_best_low = lb;
                *x_bestbb.write().unwrap() = lx.clone();
            }
        }

        for hi in hrx.iter() {
            let (ub, ux, non_empty) = hi;
            if non_empty && f_best_high < ub {
                f_best_high = ub;
                best_x = ux.clone();
            }
        }
        {
            let mut lq = q.write().unwrap();
            *lq = vec![];
            for qis in qrx.iter() {
                for qi in &qis {
                    if qi.fdata.upper() > f_best_low {
                        lq.push(qi.clone());
                    }
                }
            }
        }
    }
    println!("{}", iters.load(Ordering::Acquire));
    stop.store(true, Ordering::Release);
    (f_best_low, f_best_high, best_x)
}

fn update(stop: Arc<AtomicBool>, _sync: Arc<AtomicBool>,
          _b1: Arc<Barrier>, _b2: Arc<Barrier>,
          _f: FuncObj,
          timeout: u32) {
    let start = time::get_time();
    let one_sec = Duration::new(1, 0);
    'out: while !stop.load(Ordering::Acquire) {
        // Timer code...
        thread::sleep(one_sec);
        if timeout > 0 &&
            (time::get_time() - start).num_seconds() >= timeout as i64 {
                let _ = writeln!(&mut std::io::stderr(), "Stopping early...");
                stop.store(true, Ordering::Release);
                break 'out;
            }
    }
}

fn main() {
    let args = process_args();

    let ref x_0 = args.domain;
    let ref fo = args.function;
    let x_err = args.x_error;
    let y_err = args.y_error;
    let y_rel = args.y_error_rel;
    let seed = args.seed;

    // Early out if there are no input variables...
    if x_0.len() == 0 {
        let result = fo.call(&x_0);
        println!("[[{},{}], {{}}]", result.lower(), result.upper());
        return
    }

    let q_inner: Vec<Quple> = Vec::new();
    let q = Arc::new(RwLock::new(q_inner));

    let population_inner: Vec<Individual> = Vec::new();
    let population = Arc::new(RwLock::new(population_inner));

    let b1 = Arc::new(Barrier::new(3));
    let b2 = Arc::new(Barrier::new(3));

    let sync = Arc::new(AtomicBool::new(false));
    let stop = Arc::new(AtomicBool::new(false));

    let f_bestag: Arc<RwLock<Flt>> = Arc::new(RwLock::new(NINF));
    let f_best_shared: Arc<RwLock<Flt>> = Arc::new(RwLock::new(NINF));

    let x_e = x_0.clone();
    let x_i = x_0.clone();

    let x_bestbb = Arc::new(RwLock::new(x_0.clone()));

    let ibba_thread =
    {
        let q = q.clone();
        let b1 = b1.clone();
        let b2 = b2.clone();
        let f_bestag = f_bestag.clone();
        let f_best_shared = f_best_shared.clone();
        let x_bestbb = x_bestbb.clone();
        let sync = sync.clone();
        let stop = stop.clone();
        let fo_c = fo.clone();
        let logging = args.logging;
        let iters= args.iters;
        thread::Builder::new().name("IBBA".to_string()).spawn(move || {
            ibba(x_i, x_err, y_err, y_rel,
                 f_bestag, f_best_shared,
                 x_bestbb,
                 b1, b2, q, sync, stop, fo_c, logging, iters)
        })};

    let ea_thread =
    {
        let population = population.clone();
        let f_bestag = f_bestag.clone();
        let x_bestbb = x_bestbb.clone();
        let sync = sync.clone();
        let stop = stop.clone();
        let b1 = b1.clone();
        let b2 = b2.clone();
        let fo_c = fo.clone();
        let factor = x_e.len();
        thread::Builder::new().name("EA".to_string()).spawn(move || {
            ea(x_e, Parameters{population: 50*factor, //1000,
                               selection: 8, //4,
                               elitism: 5, //2,
                               mutation: 0.4_f64,//0.3_f64,
                               crossover: 0.0_f64, // 0.5_f64
                               seed:  seed,
            },
               population,
               f_bestag,
               x_bestbb,
               b1, b2,
               stop, sync, fo_c)
        })};

    // pending finding out how to kill threads
    //let update_thread =
    {
        let sync = sync.clone();
        let stop = stop.clone();
        let b1 = b1.clone();
        let b2 = b2.clone();
        let fo_c = fo.clone();
        let to = args.timeout.clone();
        let _ = thread::Builder::new().name("Update".to_string()).spawn(move || {
            update(stop, sync, b1, b2, fo_c, to)
        });};

    let result = ibba_thread.unwrap().join();
    let ea_result = ea_thread.unwrap().join();

    // Join EA and Update here pending stop signaling.
    if result.is_ok() {
        let (min, mut max, mut interval) = result.unwrap();
        // Go through all remaining intervals from IBBA to find the true
        // max
        let mut lq = q.write().unwrap();
        while lq.len() != 0 {
            let ref top = lq.pop().unwrap();
            let (ub, dom) = (top.fdata.upper(), &top.data);
            if ub > max {
            max = ub;
            interval = dom.clone();
        }
    }
    println!("[[{},{}], {{", min, max);
    for i in 0..args.names.len() {
        println!("'{}' : {},", args.names[i], interval[i].to_string());
    }
    println!("}}]");

}
else {println!("error")}
}
<|endoftext|>


<commit_before>
#[derive(Default, Debug)]
pub struct RegConfig {
    ep: EP,
    be: BE,
    k0: K0,
}

impl RegConfig {
    pub fn power_on_reset(&mut self) {
        self.ep = EP::D;
        self.be = BE::BigEndian;
    }
}

impl From<u32> for RegConfig {
    fn from(data: u32) -> Self {
        RegConfig {
            ep: data.into(),
            be: data.into(),
            k0: data.into(),
        }
    }
}

#[derive(Debug)]
enum EP {
    D,
    DxxDxx,
    RFU,
}

impl Default for EP {
    fn default() -> Self {
        EP::D
    }
}

impl From<u32> for EP {
    fn from(f: u32) -> Self {
        let epdata = (f >> 24) & 0b1111;
        match epdata {
            0 => EP::D,
            6 => EP::DxxDxx,
            _ => EP::RFU,
        }
    }
}

#[derive(Debug)]
enum BE {
    LittleEndian,
    BigEndian,
}

impl Default for BE {
    fn default() -> Self {
        BE::BigEndian
    }
}

impl From<u32> for BE {
    fn from(f: u32) -> Self {
        let bedata = (f >> 15) & 0b1;
        if bedata == 0 {
            BE::LittleEndian
        } else {
            BE::BigEndian
        }
    }
}

#[derive(Debug)]
enum K0 {
    NotUsed,
    Used,
}

impl Default for K0 {
    fn default() -> Self {
        K0::NotUsed
    }
}

impl From<u32> for K0 {
    fn from(f: u32) -> Self {
        let k0data = f & 0b111;
        match k0data {
            0b010 => K0::NotUsed,
            _ => K0::Used,
        }
    }
}
<commit_msg>renamed config register properies<commit_after>
#[derive(Default, Debug)]
pub struct RegConfig {
    transfer_data_pattern: TransferDataPattern,
    endianness: Endianness,
    coherency_algorithm: CoherencyAlgorithm,
}

impl RegConfig {
    pub fn power_on_reset(&mut self) {
        self.transfer_data_pattern = TransferDataPattern::D;
        self.endianness = Endianness::BigEndian;
    }
}

impl From<u32> for RegConfig {
    fn from(data: u32) -> Self {
        RegConfig {
            transfer_data_pattern: data.into(),
            endianness: data.into(),
            coherency_algorithm: data.into(),
        }
    }
}

#[derive(Debug)]
enum TransferDataPattern {
    D,
    DxxDxx,
    RFU,
}

impl Default for TransferDataPattern {
    fn default() -> Self {
        TransferDataPattern::D
    }
}

impl From<u32> for TransferDataPattern {
    fn from(f: u32) -> Self {
        let transfer_data_patterndata = (f >> 24) & 0b1111;
        match transfer_data_patterndata {
            0 => TransferDataPattern::D,
            6 => TransferDataPattern::DxxDxx,
            _ => TransferDataPattern::RFU,
        }
    }
}

#[derive(Debug)]
enum Endianness {
    LittleEndian,
    BigEndian,
}

impl Default for Endianness {
    fn default() -> Self {
        Endianness::BigEndian
    }
}

impl From<u32> for Endianness {
    fn from(f: u32) -> Self {
        let endiannessdata = (f >> 15) & 0b1;
        if endiannessdata == 0 {
            Endianness::LittleEndian
        } else {
            Endianness::BigEndian
        }
    }
}

#[derive(Debug)]
enum CoherencyAlgorithm {
    NotUsed,
    Used,
}

impl Default for CoherencyAlgorithm {
    fn default() -> Self {
        CoherencyAlgorithm::NotUsed
    }
}

impl From<u32> for CoherencyAlgorithm {
    fn from(f: u32) -> Self {
        let coherency_algorithmdata = f & 0b111;
        match coherency_algorithmdata {
            0b010 => CoherencyAlgorithm::NotUsed,
            _ => CoherencyAlgorithm::Used,
        }
    }
}
<|endoftext|>