text:
Understand personal data protection before getting Singapore company setup
In response to the rising need to keep personal information secure to counter cybercrime and data theft, Singapore passed the Personal Data Protection Act (PDPA) on 15th October 2012, based on OECD guidelines on the Protection of Privacy and Transborder Flow of Personal Data and the Asia-Pacific Economic Cooperation (APEC) Privacy Framework. The PDPA covers the rules designed to control the collection, use, disclosure, and care of personal data, allowing personal data collected to be protected against unlawful use. The balance between two sets of acknowledged rights – the rights of individuals to protect their personal data and the rights of businesses to use personal data for legitimate purposes – is a key consideration of the Act. The Act also has an extraterritorial reach and applies to organisations collecting personal data from individuals in Singapore, whether the companies are located locally or not. However, it does not apply to the public sector which is governed by other rules.
The PDPA is a necessary step toward making Singapore a leader in digital information management policies and reinforcing its status as a world-class business hub for investors interested to open new company in Singapore.
Singapore Company Setup
Personal data is data about an individual, not an organisation. Therefore, business contact information provided by an individual for business purposes, such as a job title, a business telephone number, or a business address, does not apply. Details, when gathered, that can identify a real-life person such as:
personal phone number
home phone number
NRIC or passport number
personal photograph or video image
are protected by the Act against unlawful, unauthorised use.
For business operators with Singapore company setup in mind, special attention should be paid to the Act's 9 Obligations, which are:
Consent obligation
Purpose limitation obligation
Notification obligation
Access and correction obligation
Accuracy obligation
Protection obligation
Retention limitation obligation
Transfer limitation obligation
Openness obligation
to ensure the Act is not violated while dealing with collected personal data, electronic or non-electronic. More information can be found HERE.
Deemed Consent has to be granted by an individual before the collection, usage and disclosure of personal data can proceed.
Effective November 2020, some key updates to the Act include:
Remove exclusion for agents of Government and criminalise egregious mishandling of personal data
All private sector organisations are subject to the PDPA, even when they are acting on behalf of public agencies
The new amendments also include new offences made by an individual who mishandle data such as:
Disclosure of personal data
User of personal data that results in personal gain for the offender or another person
Harm of loss to another person
Re-identification of anonymised information
Related amendments will also be made to the Public Sector (Governance) Act and Monetary Authority of Singapore Act to align the public and private sector data regimes
Increase financial penalty cap for organisations
Maximum financial penalty to be increased to 10% of an organisation's annual turnover in Singapore or S$1 million, whichever is higher
Addition to DNC provisions
The new inclusion prohibits the use of dictionary attacks and address-harvesting software when sending messages to telephone numbers
Maximum financial penalty that may be imposed on an organisation is 5% of annual turnover in Singapore or S$1 million, whichever is higher, and S$200, 000 for an individual
Expand "deemed consent" to cater for more scenarios or purposes
Contractual performance: Multiple layers of contracting and outsourcing are common in modern commercial arrangements. The amendment therefore expands deemed consent to cater for scenarios where personal data is passed from an organisation to successive layers of contractors for the organisation to fulfil the contract with its customer
By notification: Organisations may notify their customers of the new purpose and provide a reasonable period for them to opt out. Before doing so, organisations must conduct a risk assessment and conclude that the collection, use or disclosure of personal data in this manner will not likely have an adverse effect on the individual.
8. Expand "exception" for processing of personal data
Legitimate interests exception: To rely on this exception, organisations must conduct an assessment to eliminate or reduce risks associated with the collection, use or disclosure of personal data, and must be satisfied that the overall benefit of doing so outweighs any residual adverse effect on an individual. To ensure transparency, organisations must disclose when they rely on this exception.
Business improvement exception: Purposes include (a) operational efficiency and service improvements; (b) developing or enhancing products or services; and (c) knowing the organisations' customers. As a safeguard, this exception can be relied upon only for purposes that a reasonable person may consider appropriate in the circumstances, and where the purpose cannot be achieved without the use of the personal data.
This exception also applies to entities within a group as they may consolidate corporate or administrative functions or concentrate research and development expertise in a single unit. The Bill provides for additional safeguards for intra-group sharing by requiring related corporations to be bound by a contract, agreement or binding corporate rules to implement and maintain appropriate safeguards for the personal data.
Research and development exception: Current research exceptions have also been revised to support commercial research and development that is not immediately directed at productization. This could apply to research institutes carrying out scientific research and development, educational institutes embarking on social sciences research, and organisations conducting market research to identify and understand potential customer segments.
(Source: www.pwc.com)
By Admin|2021-01-19T16:20:54+08:00January 19th, 2021|Business Owner Tips, Incorporation, The VH Blog - Articles|Comments Off on Understand personal data protection before getting Singapore company setup
How Can Foreigners Start a Business and How Much to Set up a Company in Singapore?
Learn More about Start-up Tax Exemption and Singapore Company Registration Service Fee for The Right Start
The Latest Changes in Work Pass Requirements in 2021 and Company Incorporation Services Singapore Fee You Need to Know
Before You Start a Business, Understand What You Have to File Each Year and What is The Reasonable Company Incorporation Services Singapore Fee
COVID RELIEF SPECIAL!
Get 50% off when you set up your Private Limited Company with us.


text:
Contact Us Page Last Updated 18 November 2020
Goals For
Points Percentage
Win/Loss Margin
England's Record by Losses
Alb to Cze
Den to Ita
Jam to Rom
SMar to Yug
This is the full list of all 37 of England defeated opponents by the number of losses (P W D L F A Pts% W/L)
Scotland 1872-2017
P 114 W 48 D 25 L 41 F 203 A 174 - 53.1% +7
Wales 1879-2020
P 103 W 68 D 21 L 14 F 250 A 91 - 76.2% +54
Brazil 1956-2017
P 26 W 4 D 11 L 11 F 23 A 34 - 36.5% -7
P 27 W 8 D 9 L 10 F 33 A 31 - 46.3% -2
P 27 W 13 D 4 L 10 F 45 A 32 - 55.6% +3
P 31 W 17 D 5 L 9 F 71 A 39 - 62.9% +8
Germany 1930-1938, 1991-2017
P 16 W 6 D 3 L 7 F 27 A 23 - 46.9% -1 Sweden 1923-2018
P 25 W 9 D 9 L 7 F 40 A 32 - 54% +2
P 22 W 6 D 9 L 7 F 31 A 29 - 47.7% -1
Germany, West (FDR) 1954-1990
P 16 W 7 D 3 L 6 F 24 A 19 - 53.1% +1
Hungary 1908-2010
P 22 W 15 D 2 L 5 F 56 A 30 - 72.7% +10 Uruguay 1953-2014
P 11 W 3 D 3 L 5 F 11 A 15 - 41% -2
Austria 1908-2007
Belgium 1921-2020
P 25 W 16 D 5 L 4 F 72 A 32 - 74% +12
Denmark 1948-2020
P 21 W 12 D 5 L 4 F 36 A 20 - 69% +8 Ireland 1882-1953
P 61 W 48 D 9 L 4 F 239 A 54 - 86.1% +44
Yugoslavia 1939-1989
Croatia 1996-2018
P 10 W 5 D 2 L 3 F 21 A 13 - 60% +2 Ireland, Northern 1954-2005
P 37 W 27 D 7 L 3 F 84 A 27 - 82.4% +24
Portugal 1947-2016
P 23 W 10 D 10 L 3 F 46 A 25 - 65.2% +7 Romania 1939-2000
Switzerland 1933-2019
P 26 W 17 D 6 L 3 F 57 A 19 - 76.9% +14 USSR 1958-1991
Argentina 1951-2005
P 14 W 6 D 6 L 2 F 21 A 15 - 64.3% +4 Chile 1950-2013
P 6 W 2 D 2 L 2 F 4 A 5 - 50% =0
Czechoslovakia 1934-1992
P 12 W 7 D 3 L 2 F 25 A 15 - 70.8% +5 Ireland, Republic of 1946-2020
P 17 ab 1 W 6 D 9 L 2 F 23 A 13 - 61.8% +4
Mexico 1959-2010
P 9 W 6 D 1 L 2 F 23 A 4 - 72.2% +4 Norway 1937-2014
P 12 W 7 D 3 L 2 F 28 A 7 - 70.8% +5
Australia 1980-2016
P 7 W 4 D 2 L 1 F 8 A 6 - 71.4% +3 Czech Republic 1998-2019
P 4 W 2 D 1 L 1 F 10 A 4 - 62.5% +1
Iceland 1982-2020
P 5 W 3 D 1 L 1 F 13 A 4 - 70% +2 Peru 1959-2014
P 3 W 2 D 0 L 1 F 8 A 4 - 67% +1
Poland 1966-2013
P 19 W 11 D 7 L 1 F 30 A 11 - 76% +10 Russia 2007-2016
Ukraine 2000-2013
Albania 1989-2001
P 4 W 4 D 0 L 0 F 12 A 1 - 100% +4
Andorra 2006-2009
P 4 W 4 D 0 L 0 F 16 A 0 - 100% +4 Azerbaijan 2004-2005
P 2 W 2 D 0 L 0 F 3 A 0 - 100% +2
Belarus 2008-2009
P 2 W 2 D 0 L 0 F 6 A 1 - 100% +2 Bohemia 1908
Bulgaria 1962-2019
P 12 W 8 D 4 L 0 F 26 A 2 - 83.3% +8 Cameroon 1990-2002
P 4 W 3 D 1 L 0 F 9 A 4 - 87.5% +3
P 1 W 1 D 0 L 0 F 1 A 0 - 100% +1 China 1996
CIS 1992
P 1 W 0 D 1 L 0 F 2 A 2 - 50% =0 Colombia 1970-2018
P 6 W 3 D 3 L 0 F 11 A 4 - 75% +3
Costa Rica 2014-2018
P 2 W 1 D 1 L 0 F 2 A 0 - 75% +1 Cyprus 1975
Ecuador 1970-2014
P 3 W 2 D 1 L 0 F 5 A 2 - 83.3% +2 Egypt 1986-2010
Estonia 2007-2015
Finland 1937-2001
GDR (East Germany) 1963-1984
P 4 W 3 D 1 L 0 F 7 A 3 - 87.5% +3 GDR (East Germany) 1963-1984
Greece 1971-2006
P 1 W 0 D 1 L 0 F 0 A 0 - 50% =0 Jamaica 2006
Japan 1995-2010
P 3 W 2 D 1 L 0 F 5 A 3 - 83.3% +2 Israel 1986-2007
Kazakhstan 2008-2009
P 2 W 2 D 0 L 0 F 9 A 1 - 100% +2 Korean Republic (South) 2002
Kosovo 2019
P 2 W 2 D 0 L 0 F 9 A 3 - 100% +2 Kuwait 1982
P 2 W 2 D 0 L 0 F 4 A 0 - 100% +2 Lithuania 2015-2017
Luxembourg 1927-1999
P 9 W 9 D 0 L 0 F 47 A 3 - 100% +9 Macedonia FYR 2002-2006
P 1 W 1 D 0 L 0 F 4 A 2 - 100% +1 Malta 1971-2017
Moldova 1996-2013
P 4 W 4 D 0 L 0 F 16 A 0 - 100% +4 Montenegro 2010-2019
Morocco 1986-1998
P 2 W 1 D 1 L 0 F 1 A 0 - 75% +1 New Zealand 1991
Nigeria 1994-2018
P 3 W 2 D 1 L 0 F 3 A 1 - 83.3% +2 Panama 2018
Paraguay 1986-2006
P 3 W 3 D 0 L 0 F 8 A 0 - 100% +3 Rest of Europe 1938
Rest of the World 1953-1963
P 2 W 1 D 1 L 0 F 6 A 5 - 75% +1 San Marino 1993-2015
Saudi Arabia 1988-1998
P 2 W 0 D 2 L 0 F 1 A 1 - 50% =0 Serbia and Montenegro 2003
Slovakia 2002-2017
P 6 W 5 D 1 L 0 F 11 A 3 - 92% +5 Slovenia 2009-2017
South Africa 1997-2003
P 2 W 2 D 0 L 0 F 4 A 2 - 100% +2 Trinidad & Tobago 2006-2008
Tunisia 1990-2018
P 3 W 2 D 1 L 0 F 5 A 2 - 83.3% +2 Turkey 1984-2016
P 11 W 9 D 2 L 0 F 33 A 1 - 91% +9
P 1009 W 575 D 243 L 191 F 2212 A 988 - 69% +384

redpajama_set_name: RedPajamaCommonCrawl


Showstopper! The Improvised Musical extends and transfers…..
Posted byFairyPoweredProductions 28th November 2015 Posted inUncategorizedLeave a comment on Showstopper! The Improvised Musical extends and transfers…..


Some articles I've written about setting up and configuring Linux systems. Hardly comprehensive, a lot of the stuff is basic and/or covered well enough elsewhere. Most of it's centered around the Debian distribution, but the principles should be applicable elsewhere. My own servers are hosted at Linode, but very little's specific to that environment.


text:
Jankowiak wins third Gamblers Classic
The Arkansas Razorbacks have hired Dan Enos as their new offensive coordinator. This is a familiars place for the veteran coach.
He previously worked for the Razorbacks for three seasons. Enos previously was their offensive coordinator and quarterbacks coach from 2015 through 2017 under former head coach Brett Bielema.
Football (Photo by Pixabay)
Now, he will be working with current head coach Sam Pittman. This opportunity became available when Kendal Briles left to become the TCU Horned Frogs offensive coordinator.
Briles filled the role in Fort Worth, Texas after Garrett Riley left the role. Riley accepted the Clemson Tigers offensive coordinator position.
Enos departs after Terrapins quarterback Taulia Tagovailoa announced that he would return for the 2023 season. The veteran quarterback will now have to work with a new offensive coordinator after declining an opportunity to depart for the 2023 NFL Draft.
The longtime coach is credited with Tagovailoa's development. Now, he will be working with quarterback K.J. Jefferson, who announced that he will return in 2023.
The Razorbacks under Briles averaged 32.5 points per game.
Since initially leaving Fayetteville, Arkansas, Enos has bounced around. He spent the 2018 season as the Alabama Crimson Tide assistant head coach and quarterbacks coach.
The following season, he was the Miami (Florida) Hurricanes offensive coordinator and quarterbacks coach. Then in 2020, he was the Cincinnati Bearcats assistant head coach and running backs coach.
See also 76ers' Embiid says he doesn't care about Simmons
Spotlight: Boxer Ed Sanders
Anthony Caruso III - August 11, 2020 0
Boosted GT and Chuck Seitsinger fight in Maryland
Anthony Caruso III - May 4, 2019 0


What does it take to win a Governor's Award in the Arts? Funding a music scholarship? Donating your priceless collection of original paintings? Or attending the high school band concert?
This year, Arts South Dakota and the South Dakota Arts Council, along with Governor Noem, are presenting the biennial Governor's Awards in the Arts. I hope you'll get the chance to see the winners' names and congratulate those outstanding individuals and organizations. But I'm not writing today to only congratulate them. I also want to congratulate so many of YOU who, like our Governor's Award winners, are major participants in the arts in our state.
The fact is that we could give out dozens of awards every year, to people who make a difference for the arts in their towns, their schools and their state. The panel of judges for the Governor's Awards looks through so many nominations—and all of those nominated deserve an award. Every day, people are changing their communities for the better through the arts.
Some are donating time, talent and resources to programs that will transform an at-risk young person from a troubled youth to a creative artist—and good citizen. Others are working to save a historic building by baking cookies, buying an auction item or sanding wooden floors. Still others are creating art of their own and serving as an inspiration for a new generation of painters, dancers, actors and musicians.
These participants, for the most part, do not receive awards. But that doesn't mean they don't receive rewards. They are rewarded with a more active, vital, dynamic community in which to live, by students who love school and have an enhanced education through the arts, and by a feeling that they've achieved something lasting for South Dakota. Making our state a place where the arts flourish is a great long-term strategy for development—and for attracting new families to live and work here.
As you look around your community in this new year and plan for an exciting and vibrant 2019, think about the award-winning arts efforts of your friends and neighbors, teachers and business people, students and citizens. And think about what you'll do to make this year a reward-winning year for your community and South Dakota!
For more about the arts in South Dakota—and ways to participate in the arts in YOUR community, visit www.ArtsSouthDakota.org.


text:
use std::collections::{BTreeMap, HashMap};
use std::mem::drop;
use std::path::PathBuf;
use std::sync::Arc;
use std::time::{Duration, Instant};

use async_trait::async_trait;
use bazel_protos::{self, call_option};
use boxfuture::{try_future, BoxFuture, Boxable};
use bytes::Bytes;
use concrete_time::TimeSpan;
use digest::{Digest as DigestTrait, FixedOutput};
use fs::{self, File, PathStat};
use futures::compat::Future01CompatExt;
use futures::future::{self as future03, TryFutureExt};
use futures01::{future, Future, Stream};
use grpcio;
use hashing::{Digest, Fingerprint};
use libc;
use log::{debug, trace, warn};
use protobuf::{self, Message, ProtobufEnum};
use sha2::Sha256;
use store::{Snapshot, Store, StoreFileByDigest};
use tokio::time::delay_for;

use crate::{
  Context, ExecutionStats, FallibleProcessResultWithPlatform, MultiPlatformProcess, Platform,
  PlatformConstraint, Process, ProcessMetadata,
};
use std;
use std::cmp::min;
use workunit_store::WorkUnitStore;

// Environment variable which is exclusively used for cache key invalidation.
// This may be not specified in an Process, and may be populated only by the
// CommandRunner.
pub const CACHE_KEY_GEN_VERSION_ENV_VAR_NAME: &str = "PANTS_CACHE_KEY_GEN_VERSION";

#[derive(Derivative)]
#[derivative(Debug)]
struct CancelRemoteExecutionToken {
  // CancelRemoteExecutionToken is used to cancel remote execution process
  // if we no longer care about the result, but we think it's still running.
  // Remote execution process can be cancelled by sending CancelOperationRequest.
  #[derivative(Debug = "ignore")]
  operations_client: Arc<bazel_protos::operations_grpc::OperationsClient>,
  operation_name: ::std::string::String,
  #[derivative(Debug = "ignore")]
  executor: task_executor::Executor,
  send_cancellation_on_drop: bool,
}

impl CancelRemoteExecutionToken {
  fn new(
    operations_client: Arc<bazel_protos::operations_grpc::OperationsClient>,
    operation_name: ::std::string::String,
    executor: task_executor::Executor,
  ) -> CancelRemoteExecutionToken {
    CancelRemoteExecutionToken {
      operations_client,
      operation_name,
      executor,
      send_cancellation_on_drop: true,
    }
  }

  fn do_not_send_cancellation_on_drop(&mut self) {
    self.send_cancellation_on_drop = false;
  }
}

impl Drop for CancelRemoteExecutionToken {
  fn drop(&mut self) {
    if self.send_cancellation_on_drop {
      let mut cancel_op_req = bazel_protos::operations::CancelOperationRequest::new();
      cancel_op_req.set_name(self.operation_name.clone());
      let operation_name = self.operation_name.clone();
      match self
        .operations_client
        .cancel_operation_async(&cancel_op_req)
      {
        Ok(receiver) => {
          self.executor.spawn_and_ignore(async move {
            match receiver.compat().await {
              Ok(_) => debug!("Canceled operation {} successfully", operation_name),
              Err(err) => debug!("Failed to cancel operation {}, err {}", operation_name, err),
            }
          });
        }
        Err(err) => debug!(
          "Failed to schedule cancel operation: {}, err {}",
          self.operation_name, err
        ),
      };
    }
  }
}

#[derive(Debug)]
pub enum OperationOrStatus {
  Operation(bazel_protos::operations::Operation),
  Status(bazel_protos::status::Status),
}

#[derive(Clone)]
pub struct CommandRunner {
  metadata: ProcessMetadata,
  headers: BTreeMap<String, String>,
  channel: grpcio::Channel,
  env: Arc<grpcio::Environment>,
  execution_client: Arc<bazel_protos::remote_execution_grpc::ExecutionClient>,
  operations_client: Arc<bazel_protos::operations_grpc::OperationsClient>,
  store: Store,
  platform: Platform,
  executor: task_executor::Executor,
  // We use a buffer time for queuing of process requests so that the process's requested timeout more
  // accurately reflects how long the caller intended the process to last.
  queue_buffer_time: Duration,
  backoff_incremental_wait: Duration,
  backoff_max_wait: Duration,
}

#[derive(Debug, PartialEq)]
pub enum ExecutionError {
  // String is the error message.
  Fatal(String),
  // Digests are Files and Directories which have been reported to be missing. May be incomplete.
  MissingDigests(Vec<Digest>),
  // String is the operation name which can be used to poll the GetOperation gRPC API.
  NotFinished(String),
  // String is the error message.
  Retryable(String),
}

#[derive(Default)]
pub struct ExecutionHistory {
  attempts: Vec<ExecutionStats>,
  current_attempt: ExecutionStats,
}

impl ExecutionHistory {
  fn total_attempt_count(&self) -> usize {
    self.attempts.len() + 1
  }

  /// Completes the current attempt and places it in the attempts list.
  fn complete_attempt(&mut self) {
    let current_attempt = std::mem::take(&mut self.current_attempt);
    self.attempts.push(current_attempt);
  }
}

impl CommandRunner {
  // The Execute API used to be unary, and became streaming. The contract of the streaming API is
  // that if the client closes the stream after one request, it should continue to function exactly
  // like the unary API.
  // For maximal compatibility with servers, we fall back to this unary-like behavior, and control
  // our own polling rates.
  // In the future, we may want to remove this behavior if servers reliably support the full stream
  // behavior.

  fn platform(&self) -> Platform {
    self.platform
  }

  async fn oneshot_execute(
    &self,
    execute_request: &bazel_protos::remote_execution::ExecuteRequest,
    build_id: String,
  ) -> Result<OperationOrStatus, String> {
    let stream = self
      .execution_client
      .execute_opt(
        &execute_request,
        call_option(&self.headers, Some(build_id))?,
      )
      .map_err(rpcerror_to_string)?;

    let maybe_operation_result = stream
      .take(1)
      .into_future()
      // If there was a response, drop the _stream to disconnect so that the server doesn't keep
      // the connection alive and continue sending on it.
      .map(|(maybe_operation, stream)| {
        drop(stream);
        maybe_operation
      })
      // If there was an error, drop the _stream to disconnect so that the server doesn't keep the
      // connection alive and continue sending on it.
      .map_err(|(error, stream)| {
        drop(stream);
        error
      })
      .compat()
      .await;

    match maybe_operation_result {
      Ok(Some(operation)) => Ok(OperationOrStatus::Operation(operation)),
      Ok(None) => {
        Err("Didn't get proper stream response from server during remote execution".to_owned())
      }
      Err(err) => rpcerror_to_status_or_string(err).map(OperationOrStatus::Status),
    }
  }
}

#[async_trait]
impl super::CommandRunner for CommandRunner {
  fn extract_compatible_request(&self, req: &MultiPlatformProcess) -> Option<Process> {
    for compatible_constraint in vec![
      &(PlatformConstraint::None, PlatformConstraint::None),
      &(self.platform.into(), PlatformConstraint::None),
      &(
        self.platform.into(),
        PlatformConstraint::current_platform_constraint().unwrap(),
      ),
    ]
    .iter()
    {
      if let Some(compatible_req) = req.0.get(compatible_constraint) {
        return Some(compatible_req.clone());
      }
    }
    None
  }

  ///
  /// Runs a command via a gRPC service implementing the Bazel Remote Execution API
  /// (https://docs.google.com/document/d/1AaGk7fOPByEvpAbqeXIyE8HX_A3_axxNnvroblTZ_6s/edit).
  ///
  /// If the CommandRunner has a Store, files will be uploaded to the remote CAS as needed.
  /// Note that it does not proactively upload files to a remote CAS. This is because if we will
  /// get a cache hit, uploading the files was wasted time and bandwidth, and if the remote CAS
  /// already has some files, uploading them all is a waste. Instead, we look at the responses we
  /// get back from the server, and upload the files it says it's missing.
  ///
  /// In the future, we may want to do some clever things like proactively upload files which the
  /// user has changed, or files which aren't known to the local git repository, but these are
  /// optimizations to shave off a round-trip in the future.
  ///
  /// Loops until the server gives a response, either successful or error. Does not have any
  /// timeout: polls in a tight loop.
  ///
  async fn run(
    &self,
    req: MultiPlatformProcess,
    context: Context,
  ) -> Result<FallibleProcessResultWithPlatform, String> {
    let platform = self.platform();
    let compatible_underlying_request = self.extract_compatible_request(&req).unwrap();
    let store = self.store.clone();
    let (action, command, execute_request) =
      make_execute_request(&compatible_underlying_request, self.metadata.clone())?;

    let Process {
      description,
      timeout,
      input_files,
      ..
    } = compatible_underlying_request;

    let mut history = ExecutionHistory::default();

    // Upload inputs.
    {
      let (command_digest, action_digest) = future03::try_join(
        self.store_proto_locally(&command),
        self.store_proto_locally(&action),
      )
      .await?;

      let summary = store
        .ensure_remote_has_recursive(vec![command_digest, action_digest, input_files])
        .compat()
        .await?;
      history.current_attempt += summary;
    }

    trace!(
      "Executing request remotely: {:?} (command: {:?})",
      execute_request,
      command
    );
    let start_time = Instant::now();
    let mut operation = self
      .oneshot_execute(&execute_request, context.build_id.clone())
      .await?;
    let mut iter_num = 0;
    let mut maybe_cancel_remote_exec_token = match operation {
      OperationOrStatus::Operation(ref operation) => Some(CancelRemoteExecutionToken::new(
        self.operations_client.clone(),
        operation.name.clone(),
        self.executor.clone(),
      )),
      _ => None,
    };

    let response = loop {
      match self
        .extract_execute_response(operation, &mut history)
        .compat()
        .await
      {
        Ok(result) => {
          if let Some(mut cancel_remote_exec_token) = maybe_cancel_remote_exec_token {
            cancel_remote_exec_token.do_not_send_cancellation_on_drop();
          }
          break result;
        }
        Err(err) => {
          match err {
            ExecutionError::Fatal(err) => {
              // In case of receiving Fatal error from the server it is assumed that remote
              // execution is no longer running.
              if let Some(mut cancel_remote_exec_token) = maybe_cancel_remote_exec_token {
                cancel_remote_exec_token.do_not_send_cancellation_on_drop();
              }
              return Err(err);
            }
            ExecutionError::Retryable(message) => {
              if history.total_attempt_count() >= 5 {
                if let Some(mut cancel_remote_exec_token) = maybe_cancel_remote_exec_token {
                  cancel_remote_exec_token.do_not_send_cancellation_on_drop();
                }
                return Err(format!(
                  "Gave up retrying remote execution after {} retriable attempts; last failure: {}",
                  history.total_attempt_count(),
                  message
                ));
              } else {
                trace!(
                  "Got retryable error from server; retrying. Error: {}",
                  message
                );
              }

              // Kick off a new operation to retry.
              operation = self
                .retry_execution(
                  &execute_request,
                  context.build_id.clone(),
                  &mut history,
                  &mut maybe_cancel_remote_exec_token,
                  &mut iter_num,
                )
                .await?;
            }
            ExecutionError::MissingDigests(missing_digests) => {
              trace!(
                "Server reported missing digests ({:?}); trying to upload: {:?}",
                history.current_attempt,
                missing_digests,
              );
              let summary = store
                .ensure_remote_has_recursive(missing_digests)
                .compat()
                .await?;
              operation = self
                .retry_execution(
                  &execute_request,
                  context.build_id.clone(),
                  &mut history,
                  &mut maybe_cancel_remote_exec_token,
                  &mut iter_num,
                )
                .await?;
              history.current_attempt += summary;
            }
            ExecutionError::NotFinished(operation_name) => {
              let mut operation_request = bazel_protos::operations::GetOperationRequest::new();
              operation_request.set_name(operation_name.clone());

              let backoff_period = min(
                self.backoff_max_wait,
                (1 + iter_num) * self.backoff_incremental_wait,
              );

              // Take the grpc result and cancel the op if too much time has passed.
              // This timeout is here to make sure that if something goes wrong, e.g.
              // the connection hangs, we don't poll forever.
              let elapsed = start_time.elapsed();
              let total_timeout = timeout.map(|t| t + self.queue_buffer_time);
              if total_timeout.map(|t| elapsed > t).unwrap_or(false) {
                history.current_attempt.remote_execution = Some(elapsed);
                history.complete_attempt();

                break FallibleProcessResultWithPlatform {
                  stdout: Bytes::from(format!(
                    "Exceeded timeout of {:?} ({:?} for the process and {:?} for remoting buffer time) with {:?} for operation {}, {}",
                    total_timeout, timeout, self.queue_buffer_time, elapsed, operation_name, description
                  )),
                  stderr: Bytes::new(),
                  exit_code: -libc::SIGTERM,
                  output_directory: hashing::EMPTY_DIGEST,
                  execution_attempts: history.attempts,
                  platform,
                };
              }

              // Wait before retrying, and then create a new operation.
              // TODO: maybe the delay here should be the min of remaining time and the backoff period
              delay_for(backoff_period).await;
              iter_num += 1;
              operation = self
                .operations_client
                .get_operation_opt(
                  &operation_request,
                  call_option(&self.headers, Some(context.build_id.clone()))?,
                )
                .or_else(move |err| rpcerror_recover_cancelled(operation_request.take_name(), err))
                .map_err(rpcerror_to_string)
                .map(OperationOrStatus::Operation)?;
            }
          }
        }
      }
    };

    let mut attempts = String::new();
    for (i, attempt) in response.execution_attempts.iter().enumerate() {
      attempts += &format!("\nAttempt {}: {:?}", i, attempt);
    }
    debug!(
      "Finished remote exceution of {} after {} attempts: Stats: {}",
      description,
      response.execution_attempts.len(),
      attempts
    );
    Ok(response)
  }
}

impl CommandRunner {
  pub fn new(
    address: &str,
    metadata: ProcessMetadata,
    root_ca_certs: Option<Vec<u8>>,
    oauth_bearer_token: Option<String>,
    headers: BTreeMap<String, String>,
    store: Store,
    platform: Platform,
    executor: task_executor::Executor,
    queue_buffer_time: Duration,
    backoff_incremental_wait: Duration,
    backoff_max_wait: Duration,
  ) -> Result<CommandRunner, String> {
    let env = Arc::new(grpcio::EnvBuilder::new().build());
    let channel = {
      let builder = grpcio::ChannelBuilder::new(env.clone());
      if let Some(root_ca_certs) = root_ca_certs {
        let creds = grpcio::ChannelCredentialsBuilder::new()
          .root_cert(root_ca_certs)
          .build();
        builder.secure_connect(address, creds)
      } else {
        builder.connect(address)
      }
    };
    let execution_client = Arc::new(bazel_protos::remote_execution_grpc::ExecutionClient::new(
      channel.clone(),
    ));
    let operations_client = Arc::new(bazel_protos::operations_grpc::OperationsClient::new(
      channel.clone(),
    ));

    let mut headers = headers;
    if let Some(oauth_bearer_token) = oauth_bearer_token {
      headers.insert(
        String::from("authorization"),
        format!("Bearer {}", oauth_bearer_token),
      );
    }

    // Validate that any configured static headers are valid.
    call_option(&headers, None)?;

    let command_runner = CommandRunner {
      metadata,
      headers,
      channel,
      env,
      execution_client,
      operations_client,
      store,
      platform,
      executor,
      queue_buffer_time,
      backoff_incremental_wait,
      backoff_max_wait,
    };

    Ok(command_runner)
  }

  async fn store_proto_locally<P: protobuf::Message>(&self, proto: &P) -> Result<Digest, String> {
    let command_bytes = proto
      .write_to_bytes()
      .map_err(|e| format!("Error serializing proto {:?}", e))?;
    self
      .store
      .store_file_bytes(Bytes::from(command_bytes), true)
      .await
      .map_err(|e| format!("Error saving proto to local store: {:?}", e))
  }

  // Only public for tests
  pub(crate) fn extract_execute_response(
    &self,
    operation_or_status: OperationOrStatus,
    attempts: &mut ExecutionHistory,
  ) -> BoxFuture<FallibleProcessResultWithPlatform, ExecutionError> {
    trace!("Got operation response: {:?}", operation_or_status);

    let status = match operation_or_status {
      OperationOrStatus::Operation(mut operation) => {
        if !operation.get_done() {
          return future::err(ExecutionError::NotFinished(operation.take_name())).to_boxed();
        }
        if operation.has_error() {
          return future::err(ExecutionError::Fatal(format_error(&operation.get_error())))
            .to_boxed();
        }
        if !operation.has_response() {
          return future::err(ExecutionError::Fatal(
            "Operation finished but no response supplied".to_string(),
          ))
          .to_boxed();
        }

        let mut execute_response = bazel_protos::remote_execution::ExecuteResponse::new();
        try_future!(execute_response
          .merge_from_bytes(operation.get_response().get_value())
          .map_err(|e| ExecutionError::Fatal(format!("Invalid ExecuteResponse: {:?}", e))));
        trace!("Got (nested) execute response: {:?}", execute_response);
        if execute_response.get_result().has_execution_metadata() {
          let metadata = execute_response.get_result().get_execution_metadata();
          let workunit_state = workunit_store::expect_workunit_state();
          let workunit_store = workunit_state.store;
          let parent_id = workunit_state.parent_id;
          let result_cached = execute_response.get_cached_result();

          match TimeSpan::from_start_and_end(
            metadata.get_queued_timestamp(),
            metadata.get_worker_start_timestamp(),
            "remote queue",
          ) {
            Ok(time_span) => {
              attempts.current_attempt.remote_queue = Some(time_span.duration.into());
              maybe_add_workunit(
                result_cached,
                "remote execution action scheduling",
                time_span,
                parent_id.clone(),
                &workunit_store,
              );
            }
            Err(s) => warn!("{}", s),
          };

          match TimeSpan::from_start_and_end(
            metadata.get_input_fetch_start_timestamp(),
            metadata.get_input_fetch_completed_timestamp(),
            "remote input fetch",
          ) {
            Ok(time_span) => {
              attempts.current_attempt.remote_input_fetch = Some(time_span.duration.into());
              maybe_add_workunit(
                result_cached,
                "remote execution worker input fetching",
                time_span,
                parent_id.clone(),
                &workunit_store,
              );
            }
            Err(s) => warn!("{}", s),
          }

          match TimeSpan::from_start_and_end(
            metadata.get_execution_start_timestamp(),
            metadata.get_execution_completed_timestamp(),
            "remote execution",
          ) {
            Ok(time_span) => {
              attempts.current_attempt.remote_execution = Some(time_span.duration.into());
              maybe_add_workunit(
                result_cached,
                "remote execution worker command executing",
                time_span,
                parent_id.clone(),
                &workunit_store,
              );
            }
            Err(s) => warn!("{}", s),
          }

          match TimeSpan::from_start_and_end(
            metadata.get_output_upload_start_timestamp(),
            metadata.get_output_upload_completed_timestamp(),
            "remote output store",
          ) {
            Ok(time_span) => {
              attempts.current_attempt.remote_output_store = Some(time_span.duration.into());
              maybe_add_workunit(
                result_cached,
                "remote execution worker output uploading",
                time_span,
                parent_id,
                &workunit_store,
              );
            }
            Err(s) => warn!("{}", s),
          }
          attempts.current_attempt.was_cache_hit = execute_response.cached_result;
        }

        let status = execute_response.take_status();
        if grpcio::RpcStatusCode::from(status.get_code()) == grpcio::RpcStatusCode::OK {
          let mut execution_attempts = std::mem::take(&mut attempts.attempts);
          execution_attempts.push(attempts.current_attempt);
          return populate_fallible_execution_result(
            self.store.clone(),
            execute_response,
            execution_attempts,
            self.platform,
          )
          .map_err(ExecutionError::Fatal)
          .to_boxed();
        }
        status
      }
      OperationOrStatus::Status(status) => status,
    };

    match grpcio::RpcStatusCode::from(status.get_code()) {
      grpcio::RpcStatusCode::OK => unreachable!(),
      grpcio::RpcStatusCode::FAILED_PRECONDITION => {
        if status.get_details().len() != 1 {
          return future::err(ExecutionError::Fatal(format!(
            "Received multiple details in FailedPrecondition ExecuteResponse's status field: {:?}",
            status.get_details()
          )))
          .to_boxed();
        }
        let details = status.get_details().get(0).unwrap();
        let mut precondition_failure = bazel_protos::error_details::PreconditionFailure::new();
        if details.get_type_url()
          != format!(
            "type.googleapis.com/{}",
            precondition_failure.descriptor().full_name()
          )
        {
          return future::err(ExecutionError::Fatal(format!(
            "Received FailedPrecondition, but didn't know how to resolve it: {},\
             protobuf type {}",
            status.get_message(),
            details.get_type_url()
          )))
          .to_boxed();
        }
        try_future!(precondition_failure
          .merge_from_bytes(details.get_value())
          .map_err(|e| ExecutionError::Fatal(format!(
            "Error deserializing FailedPrecondition proto: {:?}",
            e
          ))));

        let mut missing_digests = Vec::with_capacity(precondition_failure.get_violations().len());

        for violation in precondition_failure.get_violations() {
          if violation.get_field_type() != "MISSING" {
            return future::err(ExecutionError::Fatal(format!(
              "Didn't know how to process PreconditionFailure violation: {:?}",
              violation
            )))
            .to_boxed();
          }
          let parts: Vec<_> = violation.get_subject().split('/').collect();
          if parts.len() != 3 || parts[0] != "blobs" {
            return future::err(ExecutionError::Fatal(format!(
              "Received FailedPrecondition MISSING but didn't recognize subject {}",
              violation.get_subject()
            )))
            .to_boxed();
          }
          let digest = Digest(
            try_future!(Fingerprint::from_hex_string(parts[1]).map_err(|e| {
              ExecutionError::Fatal(format!("Bad digest in missing blob: {}: {}", parts[1], e))
            })),
            try_future!(parts[2]
              .parse::<usize>()
              .map_err(|e| ExecutionError::Fatal(format!(
                "Missing blob had bad size: {}: {}",
                parts[2], e
              )))),
          );
          missing_digests.push(digest);
        }
        if missing_digests.is_empty() {
          return future::err(ExecutionError::Fatal(
            "Error from remote execution: FailedPrecondition, but no details".to_owned(),
          ))
          .to_boxed();
        }
        future::err(ExecutionError::MissingDigests(missing_digests)).to_boxed()
      }
      code => match code {
        grpcio::RpcStatusCode::ABORTED
        | grpcio::RpcStatusCode::INTERNAL
        | grpcio::RpcStatusCode::RESOURCE_EXHAUSTED
        | grpcio::RpcStatusCode::UNAVAILABLE
        | grpcio::RpcStatusCode::UNKNOWN => {
          future::err(ExecutionError::Retryable(status.get_message().to_owned())).to_boxed()
        }
        _ => future::err(ExecutionError::Fatal(format!(
          "Error from remote execution: {:?}: {:?}",
          code,
          status.get_message()
        )))
        .to_boxed(),
      },
    }
    .to_boxed()
  }

  async fn retry_execution(
    &self,
    execute_request: &bazel_protos::remote_execution::ExecuteRequest,
    build_id: String,
    history: &mut ExecutionHistory,
    maybe_cancel_remote_exec_token: &mut Option<CancelRemoteExecutionToken>,
    iter_num: &mut u32,
  ) -> Result<OperationOrStatus, String> {
    if let Some(ref mut cancel_remote_exec_token) = maybe_cancel_remote_exec_token {
      // This request already failed: no need to cancel it.
      cancel_remote_exec_token.do_not_send_cancellation_on_drop();
    }

    history.complete_attempt();

    let operation = self.oneshot_execute(&execute_request, build_id).await?;
    *maybe_cancel_remote_exec_token = match operation {
      OperationOrStatus::Operation(ref operation) => Some(CancelRemoteExecutionToken::new(
        self.operations_client.clone(),
        operation.name.clone(),
        self.executor.clone(),
      )),
      _ => None,
    };
    // NB: Reset `iter_num` for a new Execute attempt.
    *iter_num = 0;

    Ok(operation)
  }
}

fn maybe_add_workunit(
  result_cached: bool,
  name: &str,
  time_span: concrete_time::TimeSpan,
  parent_id: Option<String>,
  workunit_store: &WorkUnitStore,
) {
  //  TODO: workunits for scheduling, fetching, executing and uploading should be recorded
  //   only if '--reporting-zipkin-trace-v2' is set
  if !result_cached {
    let metadata = workunit_store::WorkunitMetadata::new();
    workunit_store.add_completed_workunit(name.to_string(), time_span, parent_id, metadata);
  }
}

pub fn make_execute_request(
  req: &Process,
  metadata: ProcessMetadata,
) -> Result<
  (
    bazel_protos::remote_execution::Action,
    bazel_protos::remote_execution::Command,
    bazel_protos::remote_execution::ExecuteRequest,
  ),
  String,
> {
  let mut command = bazel_protos::remote_execution::Command::new();
  command.set_arguments(protobuf::RepeatedField::from_vec(req.argv.clone()));
  for (name, value) in &req.env {
    if name.as_str() == CACHE_KEY_GEN_VERSION_ENV_VAR_NAME {
      return Err(format!(
        "Cannot set env var with name {} as that is reserved for internal use by pants",
        CACHE_KEY_GEN_VERSION_ENV_VAR_NAME
      ));
    }
    let mut env = bazel_protos::remote_execution::Command_EnvironmentVariable::new();
    env.set_name(name.to_string());
    env.set_value(value.to_string());
    command.mut_environment_variables().push(env);
  }

  let ProcessMetadata {
    instance_name,
    cache_key_gen_version,
    mut platform_properties,
  } = metadata;

  if let Some(cache_key_gen_version) = cache_key_gen_version {
    let mut env = bazel_protos::remote_execution::Command_EnvironmentVariable::new();
    env.set_name(CACHE_KEY_GEN_VERSION_ENV_VAR_NAME.to_string());
    env.set_value(cache_key_gen_version);
    command.mut_environment_variables().push(env);
  }
  let mut output_files = req
    .output_files
    .iter()
    .map(|p| {
      p.to_str()
        .map(str::to_owned)
        .ok_or_else(|| format!("Non-UTF8 output file path: {:?}", p))
    })
    .collect::<Result<Vec<String>, String>>()?;
  output_files.sort();
  command.set_output_files(protobuf::RepeatedField::from_vec(output_files));

  let mut output_directories = req
    .output_directories
    .iter()
    .map(|p| {
      p.to_str()
        .map(str::to_owned)
        .ok_or_else(|| format!("Non-UTF8 output directory path: {:?}", p))
    })
    .collect::<Result<Vec<String>, String>>()?;
  output_directories.sort();
  command.set_output_directories(protobuf::RepeatedField::from_vec(output_directories));

  if let Some(working_directory) = &req.working_directory {
    command.set_working_directory(
      working_directory
        .to_str()
        .map(str::to_owned)
        .unwrap_or_else(|| panic!("Non-UTF8 working directory path: {:?}", working_directory)),
    )
  }

  if req.jdk_home.is_some() {
    // Ideally, the JDK would be brought along as part of the input directory, but we don't
    // currently have support for that. Scoot supports this property, and will symlink .jdk to a
    // system-installed JDK https://github.com/twitter/scoot/pull/391 - we should probably come to
    // some kind of consensus across tools as to how this should work; RBE appears to work by
    // allowing you to specify a jdk-version platform property, and it will put a JDK at a
    // well-known path in the docker container you specify in which to run.
    platform_properties.push(("JDK_SYMLINK".to_owned(), ".jdk".to_owned()));
  }
  platform_properties.push(("target_platform".to_owned(), req.target_platform.into()));

  for (name, value) in platform_properties {
    command.mut_platform().mut_properties().push({
      let mut property = bazel_protos::remote_execution::Platform_Property::new();
      property.set_name(name.clone());
      property.set_value(value.clone());
      property
    });
  }

  let mut action = bazel_protos::remote_execution::Action::new();
  action.set_command_digest((&digest(&command)?).into());
  action.set_input_root_digest((&req.input_files).into());

  let mut execute_request = bazel_protos::remote_execution::ExecuteRequest::new();
  if let Some(instance_name) = instance_name {
    execute_request.set_instance_name(instance_name);
  }
  execute_request.set_action_digest((&digest(&action)?).into());

  Ok((action, command, execute_request))
}

pub fn populate_fallible_execution_result(
  store: Store,
  execute_response: bazel_protos::remote_execution::ExecuteResponse,
  execution_attempts: Vec<ExecutionStats>,
  platform: Platform,
) -> impl Future<Item = FallibleProcessResultWithPlatform, Error = String> {
  extract_stdout(&store, &execute_response)
    .join(extract_stderr(&store, &execute_response))
    .join(extract_output_files(store, &execute_response))
    .and_then(move |((stdout, stderr), output_directory)| {
      Ok(FallibleProcessResultWithPlatform {
        stdout: stdout,
        stderr: stderr,
        exit_code: execute_response.get_result().get_exit_code(),
        output_directory: output_directory,
        execution_attempts: execution_attempts,
        platform,
      })
    })
}

fn extract_stdout(
  store: &Store,
  execute_response: &bazel_protos::remote_execution::ExecuteResponse,
) -> BoxFuture<Bytes, String> {
  if execute_response.get_result().has_stdout_digest() {
    let store = store.clone();
    let stdout_digest_result: Result<Digest, String> =
      execute_response.get_result().get_stdout_digest().into();
    let stdout_digest =
      try_future!(stdout_digest_result.map_err(|err| format!("Error extracting stdout: {}", err)));
    Box::pin(async move {
      let (bytes, _metadata) = store
        .load_file_bytes_with(stdout_digest, |v| v)
        .map_err(move |error| {
          format!(
            "Error fetching stdout digest ({:?}): {:?}",
            stdout_digest, error
          )
        })
        .await?
        .ok_or_else(|| {
          format!(
            "Couldn't find stdout digest ({:?}), when fetching.",
            stdout_digest
          )
        })?;
      Ok(bytes)
    })
    .compat()
    .to_boxed()
  } else {
    let store = store.clone();
    let stdout_raw = Bytes::from(execute_response.get_result().get_stdout_raw());
    let stdout_copy = stdout_raw.clone();
    Box::pin(async move {
      store
        .store_file_bytes(stdout_raw, true)
        .map_err(move |error| format!("Error storing raw stdout: {:?}", error))
        .await?;
      Ok(stdout_copy)
    })
    .compat()
    .to_boxed()
  }
}

fn extract_stderr(
  store: &Store,
  execute_response: &bazel_protos::remote_execution::ExecuteResponse,
) -> BoxFuture<Bytes, String> {
  if execute_response.get_result().has_stderr_digest() {
    let store = store.clone();
    let stderr_digest_result: Result<Digest, String> =
      execute_response.get_result().get_stderr_digest().into();
    let stderr_digest =
      try_future!(stderr_digest_result.map_err(|err| format!("Error extracting stderr: {}", err)));

    Box::pin(async move {
      let (bytes, _metadata) = store
        .load_file_bytes_with(stderr_digest, |v| v)
        .map_err(move |error| {
          format!(
            "Error fetching stderr digest ({:?}): {:?}",
            stderr_digest, error
          )
        })
        .await?
        .ok_or_else(|| {
          format!(
            "Couldn't find stderr digest ({:?}), when fetching.",
            stderr_digest
          )
        })?;
      Ok(bytes)
    })
    .compat()
    .to_boxed()
  } else {
    let store = store.clone();
    let stderr_raw = Bytes::from(execute_response.get_result().get_stderr_raw());
    let stderr_copy = stderr_raw.clone();
    Box::pin(async move {
      store
        .store_file_bytes(stderr_raw, true)
        .map_err(move |error| format!("Error storing raw stderr: {:?}", error))
        .await?;
      Ok(stderr_copy)
    })
    .compat()
    .to_boxed()
  }
}

pub fn extract_output_files(
  store: Store,
  execute_response: &bazel_protos::remote_execution::ExecuteResponse,
) -> BoxFuture<Digest, String> {
  // Get Digests of output Directories.
  // Then we'll make a Directory for the output files, and merge them.
  let mut directory_digests =
    Vec::with_capacity(execute_response.get_result().get_output_directories().len() + 1);
  // TODO: Maybe take rather than clone
  let output_directories = execute_response
    .get_result()
    .get_output_directories()
    .to_owned();
  for dir in output_directories {
    let store = store.clone();
    directory_digests.push(
      (async move {
        let digest_result: Result<Digest, String> = dir.get_tree_digest().into();
        let mut digest = digest_result?;
        if !dir.get_path().is_empty() {
          for component in dir.get_path().rsplit('/') {
            let component = component.to_owned();
            let mut directory = bazel_protos::remote_execution::Directory::new();
            directory.mut_directories().push({
              let mut node = bazel_protos::remote_execution::DirectoryNode::new();
              node.set_name(component);
              node.set_digest((&digest).into());
              node
            });
            digest = store.record_directory(&directory, true).await?;
          }
        }
        let res: Result<_, String> = Ok(digest);
        res
      })
      .map_err(|err| format!("Error saving remote output directory: {}", err)),
    );
  }

  // Make a directory for the files
  let mut path_map = HashMap::new();
  let path_stats_result: Result<Vec<PathStat>, String> = execute_response
    .get_result()
    .get_output_files()
    .iter()
    .map(|output_file| {
      let output_file_path_buf = PathBuf::from(output_file.get_path());
      let digest: Result<Digest, String> = output_file.get_digest().into();
      path_map.insert(output_file_path_buf.clone(), digest?);
      Ok(PathStat::file(
        output_file_path_buf.clone(),
        File {
          path: output_file_path_buf,
          is_executable: output_file.get_is_executable(),
        },
      ))
    })
    .collect();

  let path_stats = try_future!(path_stats_result);

  #[derive(Clone)]
  struct StoreOneOffRemoteDigest {
    map_of_paths_to_digests: HashMap<PathBuf, Digest>,
  }

  impl StoreOneOffRemoteDigest {
    fn new(map: HashMap<PathBuf, Digest>) -> StoreOneOffRemoteDigest {
      StoreOneOffRemoteDigest {
        map_of_paths_to_digests: map,
      }
    }
  }

  impl StoreFileByDigest<String> for StoreOneOffRemoteDigest {
    fn store_by_digest(&self, file: File) -> BoxFuture<Digest, String> {
      match self.map_of_paths_to_digests.get(&file.path) {
        Some(digest) => future::ok(*digest),
        None => future::err(format!(
          "Didn't know digest for path in remote execution response: {:?}",
          file.path
        )),
      }
      .to_boxed()
    }
  }

  Box::pin(async move {
    let files_digest = Snapshot::digest_from_path_stats(
      store.clone(),
      StoreOneOffRemoteDigest::new(path_map),
      &path_stats,
    )
    .map_err(move |error| {
      format!(
        "Error when storing the output file directory info in the remote CAS: {:?}",
        error
      )
    });

    let (files_digest, mut directory_digests) =
      future03::try_join(files_digest, future03::try_join_all(directory_digests)).await?;

    directory_digests.push(files_digest);
    Snapshot::merge_directories(store, directory_digests)
      .map_err(|err| format!("Error when merging output files and directories: {}", err))
      .await
  })
  .compat()
  .to_boxed()
}

pub fn format_error(error: &bazel_protos::status::Status) -> String {
  let error_code_enum = bazel_protos::code::Code::from_i32(error.get_code());
  let error_code = match error_code_enum {
    Some(x) => format!("{:?}", x),
    None => format!("{:?}", error.get_code()),
  };
  format!("{}: {}", error_code, error.get_message())
}

///
/// If the given operation represents a cancelled request, recover it into
/// ExecutionError::NotFinished.
///
fn rpcerror_recover_cancelled(
  operation_name: String,
  err: grpcio::Error,
) -> Result<bazel_protos::operations::Operation, grpcio::Error> {
  // If the error represented cancellation, return an Operation for the given Operation name.
  match &err {
    &grpcio::Error::RpcFailure(ref rs) if rs.status == grpcio::RpcStatusCode::CANCELLED => {
      let mut next_operation = bazel_protos::operations::Operation::new();
      next_operation.set_name(operation_name);
      return Ok(next_operation);
    }
    _ => {}
  }
  // Did not represent cancellation.
  Err(err)
}

fn rpcerror_to_status_or_string(
  error: grpcio::Error,
) -> Result<bazel_protos::status::Status, String> {
  match error {
    grpcio::Error::RpcFailure(grpcio::RpcStatus {
      status_proto_bytes: Some(status_proto_bytes),
      ..
    }) => {
      let mut status_proto = bazel_protos::status::Status::new();
      status_proto.merge_from_bytes(&status_proto_bytes).unwrap();
      Ok(status_proto)
    }
    grpcio::Error::RpcFailure(grpcio::RpcStatus {
      status, details, ..
    }) => Err(format!(
      "{:?}: {:?}",
      status,
      details.unwrap_or_else(|| "[no message]".to_string())
    )),
    err => Err(format!("{:?}", err)),
  }
}

fn rpcerror_to_string(error: grpcio::Error) -> String {
  match error {
    grpcio::Error::RpcFailure(status) => format!(
      "{:?}: {:?}",
      status.status,
      status.details.unwrap_or_else(|| "[no message]".to_string())
    ),
    err => format!("{:?}", err),
  }
}

pub fn digest(message: &dyn Message) -> Result<Digest, String> {
  let bytes = message.write_to_bytes().map_err(|e| format!("{:?}", e))?;

  let mut hasher = Sha256::default();
  hasher.input(&bytes);

  Ok(Digest(
    Fingerprint::from_bytes_unsafe(&hasher.fixed_result()),
    bytes.len(),
  ))
}

redpajama_set_name: RedPajamaGithub


text:
Our Top 5 Broadway Backstory Moments
April 6, 2018 by Natalie Grillo
Broadway Backstory is a documentary-style podcast from TodayTix and Theater People that explores the stories behind our favorite shows and how they develop from an idea to a full Broadway production. We get the behind-the-scenes story directly from the people who lived it – the conceivers, actors, directors, and producers.
We are so honored to announce that Broadway Backstory has been nominated for a Webby Award! You can vote here for Broadway Backstory in the Best Branded Podcast or Segment section.
In honor of the nomination, we decided to look back on some of our favorite moments from the series:
1. When Lucas Steele got emotional discussing his experience on "Natasha, Pierre, and the Great Comet of 1812"
Photographed by Chad Batka
"It's somehow become everything I never knew I always wanted to be working on." – Lucas Steele
2. When Billy Porter described what winning a Tony Award for "Kinky Boots" meant to him
Photographed by Monica Simoes
"To hear my name was the kind of validation that was useful in healing, the very healing for my soul and for my spirit." – Billy Porter
3. When Adrienne Warren described making her Broadway debut in "Bring it On: The Musical"
Photographed by Joan Marcus
"I just remember all of us being so short of breath and just all smiling and just being way too extra onstage and hitting the choreography way to hard." – Adrienne Warren
4. When Captain Beverley Bass described her admiration for "Come From Away"
Photographed by Matthew Murphy
"I'm so honored by the way that she [Jenn Colella] portrays me because it is so perfectly done. It makes me so proud to watch the show every single time I see it." – Captain Beverley Bass
5. When Lin-Manuel Miranda did a Big Pun rap
"I wanted Hamilton to not hide his light under a bushel and I wanted him to dazzle. I wanted every other character to be like who the f*** is this? What is he talking about? It's really intricate, it's as intricate as the Big Pun raps I used to listen to in college. I just wanted someone who is just dazzling with syllables." – Lin-Manuel Miranda
We would love for you to take the time for vote for Broadway Backstory for a Webby award here. Thank you for your continued support!
Billy Porter
Broadway Backstory
Captain Beverley Bass
Great Comet
Lucas Steele


Our busy lifestyles are often filled with stress brought on by work, family and other obligations. This essential oil diffuser can help create a serene sensation in your surroundings. The result is an aromatic paradise, helping you create a relaxing and comforting spa-like atmosphere right in your own home. Pull up a chair, it's time to unplug.
The lights and color changing worked, but I was only able to get the diffuser to work only one time and after that it didnt put out anymore mist. I tried everything replacing the water, cleaning it again, and still nothing worked. Sent back.


text:
On Brains, Minds, And Their Possible Uses
Elementary Infra-Bayesianism
universalprior.substack.com
TL;DR: I got nerd-sniped into working through some rather technical work in AI Safety. Here's my best guess of what is going on. Imprecise probabilities for handling catastrophic downside risk.
Jan Hendrik Kirchner
Short summary: I apply the updating equation from Infra-Bayesianism to a concrete example of an Infradistribution and illustrate the process. When we "care" a lot for things that are unlikely given what we've observed before, we get updates that are extremely sensitive to outliers.
I've written previously on how to act when confronted with something smarter than yourself. When in such a precarious situation, it is difficult to trust "the other"; they might dispense their wisdom in a way that steers you to their benefit. In general, we're screwed.
But there are ideas for a constrained set-up that forces "the other" to explain itself and point out potential flaws in its arguments. We might thus leverage "the other"'s ingenuity against itself by slowing down its reasoning to our pace. "The other" would no longer be an oracle with prophecies that might or might not kill us but instead a teacher who lets us see things we otherwise couldn't.
While that idea is nice, there is a severe flaw at its core: obfuscation. By making the argument sufficiently long and complicated, "the other" can sneak a false conclusion past our defenses. Forcing "the other" to lay out its reasoning, thus, is not a foolproof solution. But (as some have argued), it's unclear whether this will be a problem in practice.
Why am I bringing this up? No reason in particular.
Why Infra-Bayesianism?
Engaging with the work of Vanessa Kosoy is a rite of passage in the AI Safety space. Why is that?
The pessimist answer is that alignment is really, really difficult, and if you can't understand complicated math, you can't contribute.
The optimist take is that math is fun, and (a certain type of) person gets nerd sniped by this kind of thing.
The realist take naturally falls somewhere in between. Complicated math can be important and enjoyable. It's okay to have fun with it.
But being complicated is (in itself) not a mark of quality. If you can't explain it, you don't understand it. So here goes my attempt at "Elementary Infrabayesianism", where I motivate a portion of Infrabayesianism using pretty pictures and high school mathematic
Uncertain updates
Imagine it's late in the night, the lights are off, and you are trying to find your smartphone. You cannot turn on the lights, and you are having a bit of trouble seeing properly
. You have a vague sense about where your smartphone should be (your prior, panel a). Then you see a red blinking light from your smartphone (sensory evidence, panel b). Since your brain is really good at this type of thing, you integrate the sensory evidence with your prior optimally
to obtain an improved sense of where your smartphone might be (posterior, panel c).
That's boring old Bayes, nothing to see here; move along.
Now let's say you are even more uncertain about where you put your smartphone.
It might be one end of the room or the other (bimodal prior, panel a). You see a blinking light further to the right (sensory evidence, panel b), so your overall belief shifts to the right (bimodal posterior, panel c). Importantly, by conserving probability mass, your belief that the phone might be on the left end of the room is reduced. The absence of evidence is evidence of absence.
This is still only boring old Bayes. To go Infra, we have to go weird.
Fundamentally uncertain updates
Let's say you are really, fundamentally unsure about where you put your phone. If someone were to put a gun to your head threaten to sign you up for sweaters for kittens unless you give them your best guess, you could not
This is the situation Vanessa Kosoy finds herself in
. With Infra-Bayesianism, she proposes a theoretical framework for thinking in situations where you can't (or don't want to) specify a prior over your hypotheses.
Because she is a mathematician, she is using the proper terminology while I'm using the handwavy language of Bayesian sensory integration:
a signed measure is a generalization of probability distributions,
an indicator function for a fuzzy set is a generalization of your observation/sensory evidence,
a continuous function g∈C(X,[0,1]) is... wait, what is g?
g tells you how much you care about stuff that happens in regions that become very unlikely/impossible given the sensory evidence you obtain. Why should you care about that, you ask? Great question; let's not care about it for now. Let's set it equal to zero, g=0.
When g=0, the updating equation for our two priors, P1 and P2, becomes very familiar indeed:
This is basically Bayes' theorem applied to each prior separately. Still, the evidence term (the denominator) is computed in a wonky way
, but this doesn't make much difference since it's a shared scaling factor. Consistently, things also look very normal when using this updating rule to integrate sensory information. We shift our two priors towards the evidence and scale them proportional to how unlikely they said the evidence is.
While this picture looks almost identical to the previous section, notice that the posterior is still split in two! Thus, we can still tell which one of our initial guesses turned out to be "more accurate".
Fundamentally dangerous updates
Alright, you know where this is going. We will have to start caring about things that become less likely after observing the evidence. Why we have to care is a bit hard to motivate; Vanessa Kossoy and Diffractor motivate in three parts where I don't even get the first part
Instead, I will motivate why you might care about things that seem very unlikely given your evidence by revealing more information about the thought experiment:
It's not so much that you can't give your best guess estimate about where you put your smartphone. Rather, you dare not. Getting this wrong would be, like, really bad. You might be unsure whether it's even your phone that's blinking or if it's the phone of the other person sleeping in the room
. Or perhaps the bright red light you see is the bulbous red nose of somebody else sleeping in the room. Getting the location of your smartphone wrong would be messy. Better not risk it. We'll set g=1.
The update rule doesn't change too much at first glance
Again, the denominator changes from one wonky thing (P+) to another (P−); but that still doesn't matter since it's the same for both equations.
But there is a ϰ that showed up out of nowhere! ϰ is a variable that tells us how good our distribution is at explaining things we did not get any evidence for
. Intuitively, you can tell that this will favor the prior distribution that was previously punished for not explaining the observation. And indeed, when we run the simulation:
One of the two "distributions"
is taking off! Even though the corresponding prior was bad at explaining the observation, the updating still strongly increases the mass associated with that hypothesis.
Intuitively this translates into something like:
You are unsure about the location of your smartphone (and mortally afraid to get it wrong). You follow the red blinking light, but you never discard your alternative hypothesis that the smartphone might be at the other end of the room. At the slightest indication that something is off you'll discard all the information you have collected and start the search from scratch.
This is a very cautious strategy, and it might be appropriate when you're in dangerous domains with the potential for catastrophic outliers, basically what Nassim Taleb calls Black Swan events. I'm not sure how productive this strategy is, though; noise might dramatically mess up your updates at some point.
This concludes the introduction to Elementary Infrabayesianism. I realize that I have only scratched the surface of what's in the sequence, and there is more coming out every other month, but letting yourself get nerd-sniped is just about as important as being able to stop working on something and publish. I hope what I wrote here is helpful to some, particularly in conjunction with the other explanations on the topic (1 2 3), which also go beyond the introduction.
I'm afraid at this point I'm obliged to add a hot take on what all of this means for AI Safety. I'm not sure. I can tell myself a story about how being very careful about how quickly you discard alternative hypotheses/narrow down the hypothesis space is important. I can also see the outline of how this framework ties in with fancy decision theory. But I still feel like I only scratched the surface of what's there. I'd really like to get a better grasp of that Nirvana trick, but timelines are short and there is a lot out there to explore.
French high school, though, not American high school.
If there's been alcohol involved, I want to know nothing of it.
despite your alledged disinhibited state
The idea that alcohol might have been involved in navigating you into this situation is harder to deny.
Is this ever a reasonable assumption? I don't know. It seems to me you can always pick an uninformative prior. But perhaps the point is that sometimes you should acknowledge your cluelessness. Otherwise, you expose yourself to severe downside risks? But I'm not convinced.
Not the coming home drunk situation, only the fundamental confusing part. Oh no, that came out wrong. What I mean is that she is trying to become less fundamentally confused. Urgh. I'll stop digging now.
A proper infradistribution would have to be a convex set of distributions and upper complete and everything. Also, the support of the Gaussians would have to be compact. But for the example I'm constructing, this won't become relevant. The edge points (the two Gaussians) of the convex set fully characterize how the entire convex set changes.
caption...
rather than
for an uninformative prior.
Despite having read it at least twice!
A more "natural" way to motivate it might be to talk about possible worlds and updateless decision theory, but this is something that you apparently get out of Infrabayesianism, so we don't want to use it to motivate it.
The story is coming together. This is why you can't turn on the light, btw.
Actually, in this particular example, it turns out that
, since we've got two normalized probability distributions.
You can't find any ϰ in Vanessa Kosoy's paper because she is thinking more generally about Banach spaces and a situation where there is no Radon-Nikodyn derivative. But if we have a density for our measures, we can write ϰ as
for an inframeasure (m,b).
I'm still calling them distributions, although we've left that territory already in the last section. More appropriate would be something like "density function of the signed measure" or "Radon-Nikodym derivative".
© 2023 Jan Hendrik Kirchner


A site that's as stripped back as the tshirts they're selling.
Paper thin 3D rotation and sleek serif typography characterise this new site for the boutique culture publication: Tank Magazine.
It's rare to see a really novel spin on a grid layout, but the masked grid of work on d/B's website does a great job of encouraging exploration.
Interesting new project from Future Corp with some nice UI touches and a lovely animated logo.
Ordinarily speed and responsiveness is a key factor when interacting with large images in a slideshow, but the use of slower, more sedate transitions on this site for boat makers Ringle 39 is spot on.


Well, my photo clicker is broken, so I'm rocking the 10 second iPhone timer or mirror selfies until my new one comes in! Who knew a little gadget would be so appreciated! Here are some outfits from this past week! It's been SUPER hot some days, so my hair updo has been on repeat.
I love the pieces the Rocksbox stylist picked for me so they could be layered!
And, that's a wrap! Hope you're staying cool!


text:
Very Fun Getaway
Take a (spring) break from the ordinary at Choctaw Casino
Return of Alt-Rock
Smashing Pumpkins founders reunite for new tour, including Dallas stop
Black Panther an early contender for best movie of 2018
Chadwick Boseman in Black Panther. Photo courtesy of Marvel Studios
Lupita Nyong'o and Letitia Wright in Black Panther. Photo courtesy of Marvel Studios
Danai Gurira in Black Panther. Photo courtesy of Marvel Studios
Movies in the Marvel Cinematic Universe have been enormously successful, if not universally beloved, because they tend to follow a certain formula. Introduce a particular hero, add in a certain level of snark, pair him with one or more other heroes, challenge him with the villain of the month, and repeat.
The problem with this style is that it's repetitive and there's very little at stake. While most of the previous 17 MCU films are fun, few of them have anything remotely comparable to real emotion. They merely contain cartoon figures whose job is to entertain us, and nothing more.
Black Panther changes all that. No longer does a hero have to be a loner who joins up with others only when necessary. Instead, T'Challa/Black Panther (Chadwick Boseman) relies on a whole host of people from his home country of Wakanda to be the leader and hero he is.
Notably, that group is composed mostly of women, including his stoic mother, Ramonda (Angela Bassett); spy and ex-girlfriend, Nakia (Lupita Nyong'o); tech wizard and little sister, Shuri (Letitia Wright); and leader of the Dora Milaje, an all-female warrior group, Okoye (Danai Gurira).
The plot of the film is also very personal. Following the death of his father in Captain America: Civil War, T'Challa is on the hunt for Ulysses Klaue (Andy Serkis). Klaue has a long history of running afoul of Wakanda, constantly trying to steal the ultra-valuable vibranium from them. Klaue is now being helped by the mysterious Erik Killmonger (Michael B. Jordan), whose link to Wakanda has him on a unique mission.
Writer/director Ryan Coogler (Fruitvale Station, Creed) and co-writer Joe Robert Cole have crafted about as perfect a superhero movie as one could imagine. They refuse to cut any corners, fleshing out the story of every significant character so that it's clear this is not a one-man show for Black Panther. The action scenes are not just an excuse for random mayhem; they serve a clear narrative purpose each and every time.
The filmmakers also don't shy away in the slightest from making this a truly African film. From the costumes to the hairstyles to the tribal customs, every detail is designed to immerse the audience in the world of Wakanda, and to pay homage to African people in general.
Most importantly, the film actually has something to say about the real, non-movie world. Yes, it's a work of fiction, but it's very much grounded in the realities of the world we live in. The plight of Africans, African-Americans, and people of color around the world is at the heart of the plot. To not only acknowledge racial inequities but to make them the driving force sets Black Panther apart from other superhero films in an astonishing way.
Despite having played a trio of real-life African-American heroes, T'Challa might be Boseman's best role to date. There's no legacy to uphold, so he's free to play the character however he wants, and he makes it one of Marvel's most relatable heroes to date.
He's helped immensely by the main quartet of women, especially Nyong'o, Wright, and Gurira. Nyong'o and Gurira demonstrate just as much strength and skill as Boseman despite their characters not being artificially enhanced. And Wright steals the movie every time she's on screen with her effervescent spirit.
Black Panther feels altogether different from anything Marvel has ever made, and that's a great thing. It's deserving not only of high praise, but of being put into early consideration for best movie of the year.


BOWLING GREEN — South Warren's Faith Martin wasn't going to be left off the leader board at the state championship this go around.
A year ago, Martin would've finished in the top-5 but her tournament ended early due to a disqualification.
Fast forward to 2018, Martin found her name in the top-10.
Behind Martin's sixth place finish, the South Warren girls' golf team placed seventh overall.
McKenna Stahl ended her two-day tournament appearance with a 91, carding 19-over in the second round after going 11-over the opening round. Lauren Holeman ended 37-over while Abigail Cline concluded with a score of 46-over.
Martin shot the first two rounds smooth and precisely, carding 2-over for the opening day and setting her up in third place as she entered the final day. But six bogeys, along with one double-bogey on the back nine holes, put Martin behind on the leaderboard.
Despite being slightly off on the second day, Martin was proud to cap off the 2018 season representing South Warren in the top-10 once again.
"I had some tough rounds, but that's golf and it happens. Overall it's a good year," Martin said.
Martin wasn't the only Spartan to have a successful weekend at the top of a leaderboard, however.
CM Mixon, a commit to the University of Louisville, capped off his high school career just four shots away from winning a state championship, finishing in second place with a two-under score of 142.
Mixon's front nine put himself in a position to put pressure on John Marshall Butler, putting down birdies on holes 2, 4 and 8. But the back nine was a bit of struggle for Mixon, as he concluded with one bogey and a double-bogey.
Butler would go on to take the trophy with a 3-under score of 139.
Bowling Green's Collier Curd also put himself in a position to compete for the crown, finishing with a two-over 146 over his two days. The junior ended round one at even par, but it was the second round that he would like to have a do over with. Collier's final 18 holes included three bogies, including two on the back nine.
"It was a pretty good year overall," Curd added.


Hyderabad, Feb 15: In a bizarre incident, two people were killed while 10 others injured after the DCM they were travelling in hit by a lorry from the rear on Friday morning at Shamirpet.
The accident occurred at Thurkapally village when the DCM driver carrying around 40 is returning from a wedding reception in Gajwel people to Suraram.
The departed were identified as E Srinivas from Sangareddy and Raju from Suraram.
Commuters informed the police and shifted them to a hospital for treatment. Meanwhile, the police registered a case and arrested the lorry driver M Srinivas and seized the vehicle.


text:
package router

import (
	wt "github.com/zettio/weave/testing"
	"testing"
	"time"
)

// TODO test gossip unicast and broadcast; atm we only test topology
// gossip, which does not employ unicast or broadcast.

type mockChannelConnection struct {
	RemoteConnection
	dest *Router
}

// Construct a "passive" Router, i.e. without any goroutines.
//
// We need to create some dummy channels otherwise tests hang on nil
// channels when Router.OnGossip() calls async methods.
func NewTestRouter(name PeerName) *Router {
	router := NewRouter(nil, name, nil, 10, 1024, nil)
	router.ConnectionMaker.queryChan = make(chan *ConnectionMakerInteraction, ChannelSize)
	router.Routes.queryChan = make(chan *Interaction, ChannelSize)
	return router
}

func (conn *mockChannelConnection) SendProtocolMsg(protocolMsg ProtocolMsg) {
	if err := conn.dest.handleGossip(protocolMsg.msg, deliverGossip); err != nil {
		panic(err)
	}
}

func (router *Router) AddTestChannelConnection(r *Router) {
	fromName := router.Ourself.Peer.Name
	toName := r.Ourself.Peer.Name

	fromPeer := NewPeer(fromName, router.Ourself.Peer.UID, 0)
	toPeer := NewPeer(toName, r.Ourself.Peer.UID, 0)

	r.Peers.FetchWithDefault(fromPeer)    // Has side-effect of incrementing refcount
	router.Peers.FetchWithDefault(toPeer) //

	conn := &mockChannelConnection{RemoteConnection{router.Ourself.Peer, toPeer, "", false}, r}
	router.Ourself.handleAddConnection(conn)
	router.Ourself.handleConnectionEstablished(conn)
}

func (router *Router) DeleteTestChannelConnection(r *Router) {
	fromName := router.Ourself.Peer.Name
	toName := r.Ourself.Peer.Name

	fromPeer, _ := r.Peers.Fetch(fromName)
	toPeer, _ := router.Peers.Fetch(toName)

	fromPeer.DecrementLocalRefCount()
	toPeer.DecrementLocalRefCount()

	conn, _ := router.Ourself.ConnectionTo(toName)
	router.Ourself.handleDeleteConnection(conn)
}

func TestGossipTopology(t *testing.T) {
	wt.RunWithTimeout(t, 1*time.Second, func() {
		implTestGossipTopology(t)
	})
}

// Create a Peer representing the receiver router, with connections to
// the routers supplied as arguments, carrying across all UID and
// version information.
func (router *Router) tp(routers ...*Router) *Peer {
	peer := NewPeer(router.Ourself.Peer.Name, router.Ourself.Peer.UID, 0)
	connections := make(map[PeerName]Connection)
	for _, r := range routers {
		p := NewPeer(r.Ourself.Peer.Name, r.Ourself.Peer.UID, r.Ourself.Peer.version)
		connections[r.Ourself.Peer.Name] = newMockConnection(peer, p)
	}
	peer.SetVersionAndConnections(router.Ourself.Peer.version, connections)
	return peer
}

// Check that the topology of router matches the peers and all of their connections
func checkTopology(t *testing.T, router *Router, wantedPeers ...*Peer) {
	checkTopologyPeers(t, true, router.Peers.allPeers(), wantedPeers...)
}

func implTestGossipTopology(t *testing.T) {
	// Create some peers that will talk to each other
	peer1Name, _ := PeerNameFromString("01:00:00:01:00:00")
	peer2Name, _ := PeerNameFromString("02:00:00:02:00:00")
	peer3Name, _ := PeerNameFromString("03:00:00:03:00:00")
	r1 := NewTestRouter(peer1Name)
	r2 := NewTestRouter(peer2Name)
	r3 := NewTestRouter(peer3Name)

	// Check state when they have no connections
	checkTopology(t, r1, r1.tp())
	checkTopology(t, r2, r2.tp())

	// Now try adding some connections
	r1.AddTestChannelConnection(r2)
	checkTopology(t, r1, r1.tp(r2), r2.tp())
	checkTopology(t, r2, r1.tp(r2), r2.tp())
	r2.AddTestChannelConnection(r1)
	checkTopology(t, r1, r1.tp(r2), r2.tp(r1))
	checkTopology(t, r2, r1.tp(r2), r2.tp(r1))

	// Currently, the connection from 2 to 3 is one-way only
	r2.AddTestChannelConnection(r3)
	checkTopology(t, r1, r1.tp(r2), r2.tp(r1, r3), r3.tp())
	checkTopology(t, r2, r1.tp(r2), r2.tp(r1, r3), r3.tp())
	// When r2 gossiped to r3, 1 was unreachable from r3 so it got removed from the
	// list of peers, but remains referenced in the connection from 1 to 3.
	checkTopology(t, r3, r2.tp(r1, r3), r3.tp())

	// Add a connection from 3 to 1 and now r1 is reachable.
	r3.AddTestChannelConnection(r1)
	checkTopology(t, r1, r1.tp(r2), r2.tp(r1, r3), r3.tp(r1))
	checkTopology(t, r2, r1.tp(r2), r2.tp(r1, r3), r3.tp(r1))
	checkTopology(t, r3, r1.tp(), r2.tp(r1, r3), r3.tp(r1))

	r1.AddTestChannelConnection(r3)
	checkTopology(t, r1, r1.tp(r2, r3), r2.tp(r1, r3), r3.tp(r1))
	checkTopology(t, r2, r1.tp(r2, r3), r2.tp(r1, r3), r3.tp(r1))
	checkTopology(t, r3, r1.tp(r2, r3), r2.tp(r1, r3), r3.tp(r1))

	// Drop the connection from 2 to 3
	r2.DeleteTestChannelConnection(r3)
	checkTopology(t, r1, r1.tp(r2, r3), r2.tp(r1), r3.tp(r1))
	checkTopology(t, r2, r1.tp(r2, r3), r2.tp(r1))
	checkTopology(t, r3, r1.tp(r2, r3), r2.tp(r1), r3.tp(r1))

	// Drop the connection from 1 to 3
	r1.DeleteTestChannelConnection(r3)
	checkTopology(t, r1, r1.tp(r2), r2.tp(r1), r3.tp(r1))

	checkTopology(t, r1, r1.tp(r2), r2.tp(r1), r3.tp(r1))
	checkTopology(t, r2, r1.tp(r2), r2.tp(r1))
	// r3 still thinks r1 has a connection to it
	checkTopology(t, r3, r1.tp(r2, r3), r2.tp(r1), r3.tp(r1))

	// On a timer, r3 will gossip to r1
	r3.SendAllGossip()
	checkTopology(t, r1, r1.tp(r2), r2.tp(r1), r3.tp(r1))
}


The Entrepreneurs' Roundtable is an intentionally intimate monthly members-only issue-based breakfast conversation created to connect local independent businesses, elected officials and other key decision makers in the city, region, and state.
For July's Entrepreneurs' Roundtable, SBN is excited to welcome co-sponsors of HB 2132 and SB 1140. State Representative Chris Rabb, State Representative Donna Bullock, State Representative Brian Sims, and State Representative Leanne Krueger-Braneky will be present to discuss the bills. Kelly Flanigan from PennEnvironment will moderate the conversation. This bipartisan legislation proposes Pennsylvania's transition to 100% renewables by 2050 and will establish a Clean Energy Transition Task Force, a Clean Energy Center of Excellence, and a Council for Clean Energy Workforce Development.
This policy breakfast is a members-only event with limited seating.
10:30 AM – 11:00 AM – Tour of clean energy research center with Kevin Wright of Protogen Energy, lead construction and design firm.


Subjects: Putting Australian Workers First – abolition of 457 Visas.
Peter Dutton, what's wrong with the current scheme as far as you're concerned?
Good morning Steve. Look, a number of problems. We saw rorting. We saw difficulties around the application of the scheme. There was no prior work experience required. There were all sorts of problems around labour market testing where most occupations were exempt from advertising to try and get a local worker into that job. So it was really racked with difficulties and we've decided to abolish the 457 Programme.
To address some of the concerns raised earlier, I think we're pretty much on the same page. That is that we believe very strongly that the first principle is that we should be putting Australians into Australian jobs and if the worker or the employer can demonstrate that there's not somebody to fill that job then we can look at a short term stream for two years and a medium term stream for four years where a higher level of skill is required.
So many of the health departments, including in Queensland, bring people in under a medium term stream now under the new arrangements, particularly where they can't have those skills held here in Brisbane.
But the other aspect to it Steve is that we want to make sure that the training is taking place locally so that we can train up, whether they're younger workers or mature age workers, people that have been made redundant, people that are looking to change perhaps towards retirement or maybe phase down to one or two days a week leading into retirement. So there are a number of aspects of the new arrangement which I think will serve us well, but the 457 Programme had been discredited and we took a decision to abolish it.
I'm talking with Immigration Minister Peter Dutton. I think I called you Education Minister, my apologies.
But I wanted to ask you about education, because Brisbane is an education town and it does rely on a combination of both overseas students who apply for specific sorts of visas to come and study here - many of them try and work here at the same time - as well as specific sorts of lecturers who have skillsets or qualifications in certain skillsets. What are the implications for Brisbane's entertainment sector? We have major universities in this city that really rely on our getting the right sort of people with the right sort of skills to teach in our education institutions.
Well Steve, what we're saying is first and foremost the default position has to be to test the local labour market, to advertise, to try and get an Australian worker into that job. If the company can demonstrate that that's not possible, then there's an option under a two year visa for a short term stream. There is no permanent residency outcome at the end of that, so it's only a temporary arrangement. The person goes back to their country of origin after they've completed that work.
If it is for a university lecturer, for example, or a neurosurgeon or somebody that brings a specialist set of skills, there is a more defined list in the medium term stream which is for four years and they do have the prospect of staying as a permanent resident and then becoming an Australian citizen after that.
So to go to your earlier conversation, the whole idea is to try and target those people with the skills where there is a shortage to try and enhance the local market. Hopefully that lecturer then provides a passage of those skills to people under the lecturer and we train up and provide more support around training a local workforce so that when the position is next advertised or when we need to expand that business or that employment arrangement at the university, we can have those people that have been locally trained.
So there is still a prospect of bringing in people on a short term basis or on a medium term basis, but not under the old 457 arrangement where essentially whilst it was for a four year term, it provided a permanent residency outcome, passage onto citizenship and many people I think were more concerned about that than actually the work they were engaged to do. So lots of rorts that I think we've now brought to an end and I think people can have greater faith in the new arrangement that we've introduced.
I'm speaking with Immigration Minister Peter Dutton. The person I was speaking with Minister was Steve Baxter who's an entrepreneur and investor, founder of PIPE Works. I'm not sure – are you still with me, Steve Baxter? Are you still there?
Your question was specifically about how it affects the high tech sector I think, wasn't it? What this will mean for getting the right sort of skills to train people in the digital economy, the new economy?
Yeah look, I'm obviously keen – the feedstock for the industry, the tech start-up sector is young people, young, skilled, highly skilled, talented people. So my thing is provided we're going to actually redirect more of that skilled immigration into that I'm stoked. We should go hard into that and less in the KFC 457's and waitresses and waiters.
Can you speak to that at all Peter Dutton?
Well Steve, I think that's exactly what we've done. I mean, we should be encouraging businesses like Steve's, particularly in start-ups, to firstly engage the local talent and if that needs to be supplemented or they can't find the right skillset locally then absolutely. Search internationally for the best talent, bring them in and that's a great boost to that business offering and the products are better, the business is more successful. They end up employing more local people. That's a great thing.
But as Steve points out, there are now about 200, more than 200 employment classifications that we've knocked out from the old 457 Visa arrangement because we do believe there was rorting going on and we do believe that Australians were being displaced by the employment of foreign workers. And there is a place, as Steve rightly points out, but it's about getting the balance right and I think that's what we've tried to achieve here.
Yeah. Why don't we go harder? If tech start-ups and high tech is the way of the future - and it is, I think, there's no denying that - why don't we actually proactively go out there and get those people into this country so they actually - instead of being reactionary here, be proactive and sort of say well, if you've got these skills, we actually want you, because we don't have enough of those skills in Australia it's a given. So why not get on the front foot of this and actually put a plan out there we can all get behind?
Well Steve, I think it's a fair point, but if you look at - I mean, you know your sector better than me or the listeners to Steve's programme, but there is a lot of money that we've invested as a Government into this very space. It's one of Malcolm Turnbull's main passions, is to try and create that industry.
But I don't want to be employing the people into your business. I want you to be selecting the talent and deciding who comes into your business. The only thing that I'm saying from a Government perspective is where it's possible, I want that person to be an Australian to fill the Australian job and if you need to go to whatever part of the US or Europe or Asia it is to bring in that talent, to supplement your business and to make it more successful, that's great, but that is an issue for business to identify that talent.
We're providing the framework where it can be brought in and we just want to make sure that you've tested the local market, that there is work experience, that it is a legitimate arrangement and if hopefully through the training it's also required to be provided by the employers under this programme, hopefully we can then provide training opportunities for more Australians so that we can supplement your workforce into the future.
So I think we provide the framework, but I don't think the Government wants to get into selecting people for particular businesses or sectors. I think we've tried to provide the framework around start-ups, investment in start-ups and hopefully generating more capital around that space because it is an exciting and innovative space and it is a big employer in Brisbane and Queensland and will continue to be. So we're just going to try and get that balance right between the local workforce and what talent you need from overseas.


text:
Mayor Lovely Warren, 2 others plead not guilty to campaign finance charges
By [email protected]_84 on October 5, 2020
Dozens of people showed up, hoping to attend this court hearing to show the mayor, her finance director and the treasurer of her campaign committee their support, but with COVID-19 rules, only a handful of people were allowed inside.
News10NBC Investigative Reporter Jennifer Lewke was one of them. She sat just a few rows behind the mayor.
The only time the mayor spoke was to say "yes, sir" when the judge reminded her she needed to return to court after releasing her in her own recognizance.
Mayor Warren arrived about 20 minutes before the hearing.
She is charged with scheme to defraud and violation of election law for allegedly using an illegal PAC to bolster her campaign fundraising.
Her attorney entered a not guilty plea on her behalf.
The other defendants in this case, facing the same charges are the city's current finance director, Rosalind Brooks-Harris, who was the treasurer of the PAC at the time and Albert Jones Jr. who was the treasurer of the campaign committee at the time.
They too pleaded not guilty to the charges against them.
They all had a lot of supporters outside the courtroom, who cheered when they came out and encouraged them to keep their heads up.
"She's a very good friend and a close friend of mine and I just don't believe that she would intentionally do anything to hurt the people of Rochester," Minister Joyce Pettway said.
"[I] just feel like they haven't given her a fair chance from the beginning of her run and it just seems like they pick on her for every little thing that she may do or may not do and I just think that she did a lot of good for us," Carrie Fuqua said.
The mayor and the two other defendants are due back in court on Jan. 12.
An out-of-county judge has been assigned to the case.
Monday in court he said his schedule is pretty full and if this goes to trial, it wouldn't likely be until May.
IMF Urges Infrastructure Investment to Boost Post-COVID Growth | Investing News
States Overpaid Covid Claims, Now They Want the Money Back


The Roku SD player is the entry level model media streamer. The system features Wi-Fi 802.11 b/g and an Ethernet port for broadband internet access. The Roku SD player connects to your TV and offer up to DVD picture quality.
The Roku HD and HD-XR are of a higher specification. IT offer high definition streaming capability using its HDMI or Component Video connector. According to Roku the Roku HD-XR is the first Netflix – streaming device to embed next generation 802.11n dual-band wireless connectivity. The Roku HD-XR is backward compatible with older model routers and has a USB port for future use.


Sen. John McCain (R-Arizona) hasn't made any appearances in Indian Country during his presidential campaign but he's got two key tribal advocates on his side.
Rep. Tom Cole (R-Oklahoma), the only Native American in Congress, and former Sen. Ben Nighthorse Campbell (R-Colorado), who retired in 2004, say McCain's record on tribal issues is well-known. They cite his work on the Native American Graves Protection and Repatriation Act, the Indian Gaming Regulatory Act, the Native American Languages Act, tribal college reauthorization and Indian water rights among his achievements.
"He will know these issues better than any president ever has in my lifetime," Cole, a member of the Chickasaw Nation of Oklahoma, told Indian Country Today. "He knows them more than his advisers do."
Campbell has been campaigning for McCain in Indian Country and says the candidate supports increased funding for the Indian Health Service, a resolution to apologize to Native people for their treatment by the federal government and reform of the federal recognition process.


text:
Further developments of filmwise condensation of steam on horizontal integral finned tubes
furtherdevelopme00gutt.pdf (8.362Mb)
Guttendorf, Mark Brady
Marto, P.J.
Memory, S.B.
Heat transfer measurements have been made for filmwise condensation of steam on three families of horizontal integral finned copper tubes. The families differ from each other in their tube root diameter (12.7mm, 19.05mm, 25.00mm). The tubes making up each family differ from each other only in the fin spacing. Similar measurements have been carried out on three smooth horizontal copper tubes of outside diameters equal to the root diameters of each family, allowing the heat transfer enhancements due to the fins to be measured directly. Results carried out under vacuum and atmospheric conditions indicate that there is a optimum fin spacing which is independent of tube root diameter and operating pressure. This optimum fin spacing is 1.5mm. Heat transfer measurements were carried out on all tubes with and without the use of a spiral insert (used to enhance the internal heat transfer). It was found that with the current processing technique used, the heat transfer enhancement for a finned tube (which is based on the outside heat transfer coefficient) varies depending on whether or not an insert is used, the enhancement being lower when no insert is used. However, it was found that when testing a smooth tube there was no difierence when an insert was or was not used. There is a need to develop a more accurate correlation for the inside heat-transfer coefficient. Further tests have been repeated using a finned tube geometrically similar to one being tested at the University of London. Discrepancies that existed between the two sets of data have been eliminated.
Further studies in filmwise condensation of steam on horizontal finned tubes
Swensen, Keith Andrew (Monterey, California. Naval Postgraduate School, 1992-03);
Over the years, there has been significant variation in the filmwise steam condensation data at NOS on horizontal low0integral finned tubes. With a view to increasing the accuracy of the data, inserts were used inside the ...
Nucleate pool boiling characteristics of R-124
Bertsch, George M. (Monterey, California: Naval Postgraduate School, 1993-03);
This thesis examines the pool boiling heat transfer characteristics of HCFC-124 and HCFC-124/oil mixtures with up to 10% (by weight) miscible alkylbenzene oil. One smooth and 4 enhanced tubes were tested: a 19 and 26 low ...
Effect of vapor velocity during condensation on horizontal finned tubes
Hopkins, Charles Louis III (Monterey, California. Naval Postgraduate School, 1988-12);
Heat-transfer measurements were made for condensation of R-113 and steam on a smooth tube and on three finned tubes with rectangular shape fins. These tubes had a fin height and width of 1.0 mm and spacings of 0.25, ...


IMMACULATE MINT CONDITION HOME, PRIDE OF OWNERSHIP EVIDENT INSIDE AND OUT OF THIS RENOVATED AND METICULOUSLY MAINTAINED HOME. COMFORTABLE AND CONVENIENT LAYOUT. NEWER ROF,WINDOWS, DOORS, ELECTRICAL, HEATING AND COOLING. ALL APPLIANCES ARE STAYING. FRESHLY PAINTED AND SHINING HARDWOOD FLOORS. MANY EXTRAS, INCLUDING CUSTOM WINDOW TREATMENTS, CEDAR CLOSET AND CALIFORNIA STYLE CLOSETS. SPARKLING CLEAN READY FOR YOU TO ENJOY. LOVELY BRICK WALKWAY AND BLUESTONE STEPS. PROFESSIONALY LANDSCAPED, PRIVATE BACKYARD WITH STUNNING VIEWS. HOUSE SIZE, LOT SIZE AND TAXES ARE APPROXIMATE.
I was searching for a Property and found this listing (MLS® #4910616). Please send me more information regarding 87 Cherry Lane, Airmont, NY, 10952. Thank you!
I'd like to request a showing of 87 Cherry Lane, Airmont, NY, 10952 (MLS® #4910616). Thank you!