text:
#include <list>
#include <memory>

#include "webrtc/modules/pacing/paced_sender.h"
#include "webrtc/system_wrappers/include/clock.h"
#include "webrtc/test/gmock.h"
#include "webrtc/test/gtest.h"

using testing::_;
using testing::Field;
using testing::Return;

namespace {
constexpr unsigned kFirstClusterBps = 900000;
constexpr unsigned kSecondClusterBps = 1800000;

// The error stems from truncating the time interval of probe packets to integer
// values. This results in probing slightly higher than the target bitrate.
// For 1.8 Mbps, this comes to be about 120 kbps with 1200 probe packets.
constexpr int kBitrateProbingError = 150000;
}  // namespace

namespace webrtc {
namespace test {

static const int kTargetBitrateBps = 800000;

class MockPacedSenderCallback : public PacedSender::PacketSender {
 public:
  MOCK_METHOD5(TimeToSendPacket,
               bool(uint32_t ssrc,
                    uint16_t sequence_number,
                    int64_t capture_time_ms,
                    bool retransmission,
                    const PacedPacketInfo& pacing_info));
  MOCK_METHOD2(TimeToSendPadding,
               size_t(size_t bytes, const PacedPacketInfo& pacing_info));
};

class PacedSenderPadding : public PacedSender::PacketSender {
 public:
  PacedSenderPadding() : padding_sent_(0) {}

  bool TimeToSendPacket(uint32_t ssrc,
                        uint16_t sequence_number,
                        int64_t capture_time_ms,
                        bool retransmission,
                        const PacedPacketInfo& pacing_info) override {
    return true;
  }

  size_t TimeToSendPadding(size_t bytes,
                           const PacedPacketInfo& pacing_info) override {
    const size_t kPaddingPacketSize = 224;
    size_t num_packets = (bytes + kPaddingPacketSize - 1) / kPaddingPacketSize;
    padding_sent_ += kPaddingPacketSize * num_packets;
    return kPaddingPacketSize * num_packets;
  }

  size_t padding_sent() { return padding_sent_; }

 private:
  size_t padding_sent_;
};

class PacedSenderProbing : public PacedSender::PacketSender {
 public:
  PacedSenderProbing() : packets_sent_(0), padding_sent_(0) {}

  bool TimeToSendPacket(uint32_t ssrc,
                        uint16_t sequence_number,
                        int64_t capture_time_ms,
                        bool retransmission,
                        const PacedPacketInfo& pacing_info) override {
    packets_sent_++;
    return true;
  }

  size_t TimeToSendPadding(size_t bytes,
                           const PacedPacketInfo& pacing_info) override {
    padding_sent_ += bytes;
    return padding_sent_;
  }

  int packets_sent() const { return packets_sent_; }

  int padding_sent() const { return padding_sent_; }

 private:
  int packets_sent_;
  int padding_sent_;
};

class PacedSenderTest : public ::testing::Test {
 protected:
  PacedSenderTest() : clock_(123456) {
    srand(0);
    // Need to initialize PacedSender after we initialize clock.
    send_bucket_.reset(new PacedSender(&clock_, &callback_, nullptr));
    send_bucket_->CreateProbeCluster(kFirstClusterBps);
    send_bucket_->CreateProbeCluster(kSecondClusterBps);
    // Default to bitrate probing disabled for testing purposes. Probing tests
    // have to enable probing, either by creating a new PacedSender instance or
    // by calling SetProbingEnabled(true).
    send_bucket_->SetProbingEnabled(false);
    send_bucket_->SetEstimatedBitrate(kTargetBitrateBps);

    clock_.AdvanceTimeMilliseconds(send_bucket_->TimeUntilNextProcess());
  }

  void SendAndExpectPacket(PacedSender::Priority priority,
                           uint32_t ssrc,
                           uint16_t sequence_number,
                           int64_t capture_time_ms,
                           size_t size,
                           bool retransmission) {
    send_bucket_->InsertPacket(priority, ssrc, sequence_number, capture_time_ms,
                               size, retransmission);
    EXPECT_CALL(callback_, TimeToSendPacket(ssrc, sequence_number,
                                            capture_time_ms, retransmission, _))
        .Times(1)
        .WillRepeatedly(Return(true));
  }
  SimulatedClock clock_;
  MockPacedSenderCallback callback_;
  std::unique_ptr<PacedSender> send_bucket_;
};

TEST_F(PacedSenderTest, QueuePacket) {
  uint32_t ssrc = 12345;
  uint16_t sequence_number = 1234;
  // Due to the multiplicative factor we can send 5 packets during a send
  // interval. (network capacity * multiplier / (8 bits per byte *
  // (packet size * #send intervals per second)
  const size_t packets_to_send =
      kTargetBitrateBps * PacedSender::kDefaultPaceMultiplier / (8 * 250 * 200);
  for (size_t i = 0; i < packets_to_send; ++i) {
    SendAndExpectPacket(PacedSender::kNormalPriority, ssrc, sequence_number++,
                        clock_.TimeInMilliseconds(), 250, false);
  }

  int64_t queued_packet_timestamp = clock_.TimeInMilliseconds();
  send_bucket_->InsertPacket(PacedSender::kNormalPriority, ssrc,
                             sequence_number, queued_packet_timestamp, 250,
                             false);
  EXPECT_EQ(packets_to_send + 1, send_bucket_->QueueSizePackets());
  send_bucket_->Process();
  EXPECT_EQ(5, send_bucket_->TimeUntilNextProcess());
  EXPECT_CALL(callback_, TimeToSendPadding(_, _)).Times(0);
  clock_.AdvanceTimeMilliseconds(4);
  EXPECT_EQ(1, send_bucket_->TimeUntilNextProcess());
  clock_.AdvanceTimeMilliseconds(1);
  EXPECT_EQ(0, send_bucket_->TimeUntilNextProcess());
  EXPECT_EQ(1u, send_bucket_->QueueSizePackets());
  EXPECT_CALL(callback_, TimeToSendPacket(ssrc, sequence_number++,
                                          queued_packet_timestamp, false, _))
      .Times(1)
      .WillRepeatedly(Return(true));
  send_bucket_->Process();
  sequence_number++;
  EXPECT_EQ(0u, send_bucket_->QueueSizePackets());

  // We can send packets_to_send -1 packets of size 250 during the current
  // interval since one packet has already been sent.
  for (size_t i = 0; i < packets_to_send - 1; ++i) {
    SendAndExpectPacket(PacedSender::kNormalPriority, ssrc, sequence_number++,
                        clock_.TimeInMilliseconds(), 250, false);
  }
  send_bucket_->InsertPacket(PacedSender::kNormalPriority, ssrc,
                             sequence_number++, clock_.TimeInMilliseconds(),
                             250, false);
  EXPECT_EQ(packets_to_send, send_bucket_->QueueSizePackets());
  send_bucket_->Process();
  EXPECT_EQ(1u, send_bucket_->QueueSizePackets());
}

TEST_F(PacedSenderTest, PaceQueuedPackets) {
  uint32_t ssrc = 12345;
  uint16_t sequence_number = 1234;

  // Due to the multiplicative factor we can send 5 packets during a send
  // interval. (network capacity * multiplier / (8 bits per byte *
  // (packet size * #send intervals per second)
  const size_t packets_to_send_per_interval =
      kTargetBitrateBps * PacedSender::kDefaultPaceMultiplier / (8 * 250 * 200);
  for (size_t i = 0; i < packets_to_send_per_interval; ++i) {
    SendAndExpectPacket(PacedSender::kNormalPriority, ssrc, sequence_number++,
                        clock_.TimeInMilliseconds(), 250, false);
  }

  for (size_t j = 0; j < packets_to_send_per_interval * 10; ++j) {
    send_bucket_->InsertPacket(PacedSender::kNormalPriority, ssrc,
                               sequence_number++, clock_.TimeInMilliseconds(),
                               250, false);
  }
  EXPECT_EQ(packets_to_send_per_interval + packets_to_send_per_interval * 10,
            send_bucket_->QueueSizePackets());
  send_bucket_->Process();
  EXPECT_EQ(packets_to_send_per_interval * 10,
            send_bucket_->QueueSizePackets());
  EXPECT_CALL(callback_, TimeToSendPadding(_, _)).Times(0);
  for (int k = 0; k < 10; ++k) {
    EXPECT_EQ(5, send_bucket_->TimeUntilNextProcess());
    clock_.AdvanceTimeMilliseconds(5);
    EXPECT_CALL(callback_, TimeToSendPacket(ssrc, _, _, false, _))
        .Times(packets_to_send_per_interval)
        .WillRepeatedly(Return(true));
    EXPECT_EQ(0, send_bucket_->TimeUntilNextProcess());
    send_bucket_->Process();
  }
  EXPECT_EQ(0u, send_bucket_->QueueSizePackets());
  EXPECT_EQ(5, send_bucket_->TimeUntilNextProcess());
  clock_.AdvanceTimeMilliseconds(5);
  EXPECT_EQ(0, send_bucket_->TimeUntilNextProcess());
  EXPECT_EQ(0u, send_bucket_->QueueSizePackets());
  send_bucket_->Process();

  for (size_t i = 0; i < packets_to_send_per_interval; ++i) {
    SendAndExpectPacket(PacedSender::kNormalPriority, ssrc, sequence_number++,
                        clock_.TimeInMilliseconds(), 250, false);
  }
  send_bucket_->InsertPacket(PacedSender::kNormalPriority, ssrc,
                             sequence_number, clock_.TimeInMilliseconds(), 250,
                             false);
  send_bucket_->Process();
  EXPECT_EQ(1u, send_bucket_->QueueSizePackets());
}

TEST_F(PacedSenderTest, PaceQueuedPacketsWithDuplicates) {
  uint32_t ssrc = 12345;
  uint16_t sequence_number = 1234;
  uint16_t queued_sequence_number;

  // Due to the multiplicative factor we can send 5 packets during a send
  // interval. (network capacity * multiplier / (8 bits per byte *
  // (packet size * #send intervals per second)
  const size_t packets_to_send_per_interval =
      kTargetBitrateBps * PacedSender::kDefaultPaceMultiplier / (8 * 250 * 200);
  for (size_t i = 0; i < packets_to_send_per_interval; ++i) {
    SendAndExpectPacket(PacedSender::kNormalPriority, ssrc, sequence_number++,
                        clock_.TimeInMilliseconds(), 250, false);
  }
  queued_sequence_number = sequence_number;

  for (size_t j = 0; j < packets_to_send_per_interval * 10; ++j) {
    // Send in duplicate packets.
    send_bucket_->InsertPacket(PacedSender::kNormalPriority, ssrc,
                               sequence_number, clock_.TimeInMilliseconds(),
                               250, false);
    send_bucket_->InsertPacket(PacedSender::kNormalPriority, ssrc,
                               sequence_number++, clock_.TimeInMilliseconds(),
                               250, false);
  }
  EXPECT_CALL(callback_, TimeToSendPadding(_, _)).Times(0);
  send_bucket_->Process();
  for (int k = 0; k < 10; ++k) {
    EXPECT_EQ(5, send_bucket_->TimeUntilNextProcess());
    clock_.AdvanceTimeMilliseconds(5);

    for (size_t i = 0; i < packets_to_send_per_interval; ++i) {
      EXPECT_CALL(callback_,
                  TimeToSendPacket(ssrc, queued_sequence_number++, _, false, _))
          .Times(1)
          .WillRepeatedly(Return(true));
    }
    EXPECT_EQ(0, send_bucket_->TimeUntilNextProcess());
    send_bucket_->Process();
  }
  EXPECT_EQ(5, send_bucket_->TimeUntilNextProcess());
  clock_.AdvanceTimeMilliseconds(5);
  EXPECT_EQ(0, send_bucket_->TimeUntilNextProcess());
  send_bucket_->Process();

  for (size_t i = 0; i < packets_to_send_per_interval; ++i) {
    SendAndExpectPacket(PacedSender::kNormalPriority, ssrc, sequence_number++,
                        clock_.TimeInMilliseconds(), 250, false);
  }
  send_bucket_->InsertPacket(PacedSender::kNormalPriority, ssrc,
                             sequence_number++, clock_.TimeInMilliseconds(),
                             250, false);
  send_bucket_->Process();
  EXPECT_EQ(1u, send_bucket_->QueueSizePackets());
}

TEST_F(PacedSenderTest, CanQueuePacketsWithSameSequenceNumberOnDifferentSsrcs) {
  uint32_t ssrc = 12345;
  uint16_t sequence_number = 1234;

  SendAndExpectPacket(PacedSender::kNormalPriority,
                      ssrc,
                      sequence_number,
                      clock_.TimeInMilliseconds(),
                      250,
                      false);

  // Expect packet on second ssrc to be queued and sent as well.
  SendAndExpectPacket(PacedSender::kNormalPriority,
                      ssrc + 1,
                      sequence_number,
                      clock_.TimeInMilliseconds(),
                      250,
                      false);

  clock_.AdvanceTimeMilliseconds(1000);
  send_bucket_->Process();
}

TEST_F(PacedSenderTest, Padding) {
  uint32_t ssrc = 12345;
  uint16_t sequence_number = 1234;

  send_bucket_->SetEstimatedBitrate(kTargetBitrateBps);
  send_bucket_->SetSendBitrateLimits(kTargetBitrateBps, kTargetBitrateBps);

  // Due to the multiplicative factor we can send 5 packets during a send
  // interval. (network capacity * multiplier / (8 bits per byte *
  // (packet size * #send intervals per second)
  const size_t packets_to_send_per_interval =
      kTargetBitrateBps * PacedSender::kDefaultPaceMultiplier / (8 * 250 * 200);
  for (size_t i = 0; i < packets_to_send_per_interval; ++i) {
    SendAndExpectPacket(PacedSender::kNormalPriority, ssrc, sequence_number++,
                        clock_.TimeInMilliseconds(), 250, false);
  }
  // No padding is expected since we have sent too much already.
  EXPECT_CALL(callback_, TimeToSendPadding(_, _)).Times(0);
  EXPECT_EQ(0, send_bucket_->TimeUntilNextProcess());
  send_bucket_->Process();
  EXPECT_EQ(0u, send_bucket_->QueueSizePackets());

  // 5 milliseconds later should not send padding since we filled the buffers
  // initially.
  EXPECT_CALL(callback_, TimeToSendPadding(250, _)).Times(0);
  EXPECT_EQ(5, send_bucket_->TimeUntilNextProcess());
  clock_.AdvanceTimeMilliseconds(5);
  EXPECT_EQ(0, send_bucket_->TimeUntilNextProcess());
  send_bucket_->Process();

  // 5 milliseconds later we have enough budget to send some padding.
  EXPECT_CALL(callback_, TimeToSendPadding(250, _))
      .Times(1)
      .WillOnce(Return(250));
  EXPECT_EQ(5, send_bucket_->TimeUntilNextProcess());
  clock_.AdvanceTimeMilliseconds(5);
  EXPECT_EQ(0, send_bucket_->TimeUntilNextProcess());
  send_bucket_->Process();
}

TEST_F(PacedSenderTest, NoPaddingBeforeNormalPacket) {
  send_bucket_->SetEstimatedBitrate(kTargetBitrateBps);
  send_bucket_->SetSendBitrateLimits(kTargetBitrateBps, kTargetBitrateBps);

  EXPECT_CALL(callback_, TimeToSendPadding(_, _)).Times(0);
  send_bucket_->Process();
  clock_.AdvanceTimeMilliseconds(send_bucket_->TimeUntilNextProcess());

  send_bucket_->Process();
  clock_.AdvanceTimeMilliseconds(send_bucket_->TimeUntilNextProcess());

  uint32_t ssrc = 12345;
  uint16_t sequence_number = 1234;
  int64_t capture_time_ms = 56789;

  SendAndExpectPacket(PacedSender::kNormalPriority, ssrc, sequence_number++,
                      capture_time_ms, 250, false);
  EXPECT_CALL(callback_, TimeToSendPadding(250, _))
      .Times(1)
      .WillOnce(Return(250));
  send_bucket_->Process();
}

TEST_F(PacedSenderTest, VerifyPaddingUpToBitrate) {
  uint32_t ssrc = 12345;
  uint16_t sequence_number = 1234;
  int64_t capture_time_ms = 56789;
  const int kTimeStep = 5;
  const int64_t kBitrateWindow = 100;
  send_bucket_->SetEstimatedBitrate(kTargetBitrateBps);
  send_bucket_->SetSendBitrateLimits(kTargetBitrateBps, kTargetBitrateBps);

  int64_t start_time = clock_.TimeInMilliseconds();
  while (clock_.TimeInMilliseconds() - start_time < kBitrateWindow) {
    SendAndExpectPacket(PacedSender::kNormalPriority,
                        ssrc,
                        sequence_number++,
                        capture_time_ms,
                        250,
                        false);
    EXPECT_CALL(callback_, TimeToSendPadding(250, _))
        .Times(1)
        .WillOnce(Return(250));
    send_bucket_->Process();
    clock_.AdvanceTimeMilliseconds(kTimeStep);
  }
}

TEST_F(PacedSenderTest, VerifyAverageBitrateVaryingMediaPayload) {
  uint32_t ssrc = 12345;
  uint16_t sequence_number = 1234;
  int64_t capture_time_ms = 56789;
  const int kTimeStep = 5;
  const int64_t kBitrateWindow = 10000;
  PacedSenderPadding callback;
  send_bucket_.reset(new PacedSender(&clock_, &callback, nullptr));
  send_bucket_->SetProbingEnabled(false);
  send_bucket_->SetEstimatedBitrate(kTargetBitrateBps);

  send_bucket_->SetSendBitrateLimits(
      0 /*allocated_bitrate_bps*/,
      kTargetBitrateBps * 2 /* max_padding_bitrate_bps */);

  int64_t start_time = clock_.TimeInMilliseconds();
  size_t media_bytes = 0;
  while (clock_.TimeInMilliseconds() - start_time < kBitrateWindow) {
    int rand_value = rand();  // NOLINT (rand_r instead of rand)
    size_t media_payload = rand_value % 100 + 200;  // [200, 300] bytes.
    send_bucket_->InsertPacket(PacedSender::kNormalPriority, ssrc,
                               sequence_number++, capture_time_ms,
                               media_payload, false);
    media_bytes += media_payload;
    clock_.AdvanceTimeMilliseconds(kTimeStep);
    send_bucket_->Process();
  }
  EXPECT_NEAR(kTargetBitrateBps / 1000,
              static_cast<int>(8 * (media_bytes + callback.padding_sent()) /
                               kBitrateWindow),
              1);
}

TEST_F(PacedSenderTest, Priority) {
  uint32_t ssrc_low_priority = 12345;
  uint32_t ssrc = 12346;
  uint16_t sequence_number = 1234;
  int64_t capture_time_ms = 56789;
  int64_t capture_time_ms_low_priority = 1234567;

  // Due to the multiplicative factor we can send 5 packets during a send
  // interval. (network capacity * multiplier / (8 bits per byte *
  // (packet size * #send intervals per second)
  const size_t packets_to_send_per_interval =
      kTargetBitrateBps * PacedSender::kDefaultPaceMultiplier / (8 * 250 * 200);
  for (size_t i = 0; i < packets_to_send_per_interval; ++i) {
    SendAndExpectPacket(PacedSender::kNormalPriority, ssrc, sequence_number++,
                        clock_.TimeInMilliseconds(), 250, false);
  }
  send_bucket_->Process();
  EXPECT_EQ(0u, send_bucket_->QueueSizePackets());

  // Expect normal and low priority to be queued and high to pass through.
  send_bucket_->InsertPacket(PacedSender::kLowPriority, ssrc_low_priority,
                             sequence_number++, capture_time_ms_low_priority,
                             250, false);

  for (size_t i = 0; i < packets_to_send_per_interval; ++i) {
    send_bucket_->InsertPacket(PacedSender::kNormalPriority, ssrc,
                               sequence_number++, capture_time_ms, 250, false);
  }
  send_bucket_->InsertPacket(PacedSender::kHighPriority, ssrc,
                             sequence_number++, capture_time_ms, 250, false);

  // Expect all high and normal priority to be sent out first.
  EXPECT_CALL(callback_, TimeToSendPadding(_, _)).Times(0);
  EXPECT_CALL(callback_, TimeToSendPacket(ssrc, _, capture_time_ms, false, _))
      .Times(packets_to_send_per_interval + 1)
      .WillRepeatedly(Return(true));

  EXPECT_EQ(5, send_bucket_->TimeUntilNextProcess());
  clock_.AdvanceTimeMilliseconds(5);
  EXPECT_EQ(0, send_bucket_->TimeUntilNextProcess());
  send_bucket_->Process();
  EXPECT_EQ(1u, send_bucket_->QueueSizePackets());

  EXPECT_CALL(callback_,
              TimeToSendPacket(ssrc_low_priority, _,
                               capture_time_ms_low_priority, false, _))
      .Times(1)
      .WillRepeatedly(Return(true));

  EXPECT_EQ(5, send_bucket_->TimeUntilNextProcess());
  clock_.AdvanceTimeMilliseconds(5);
  EXPECT_EQ(0, send_bucket_->TimeUntilNextProcess());
  send_bucket_->Process();
}

TEST_F(PacedSenderTest, RetransmissionPriority) {
  uint32_t ssrc = 12345;
  uint16_t sequence_number = 1234;
  int64_t capture_time_ms = 45678;
  int64_t capture_time_ms_retransmission = 56789;

  // Due to the multiplicative factor we can send 5 packets during a send
  // interval. (network capacity * multiplier / (8 bits per byte *
  // (packet size * #send intervals per second)
  const size_t packets_to_send_per_interval =
      kTargetBitrateBps * PacedSender::kDefaultPaceMultiplier / (8 * 250 * 200);
  send_bucket_->Process();
  EXPECT_EQ(0u, send_bucket_->QueueSizePackets());

  // Alternate retransmissions and normal packets.
  for (size_t i = 0; i < packets_to_send_per_interval; ++i) {
    send_bucket_->InsertPacket(PacedSender::kNormalPriority, ssrc,
                               sequence_number++,
                               capture_time_ms_retransmission, 250, true);
    send_bucket_->InsertPacket(PacedSender::kNormalPriority, ssrc,
                               sequence_number++, capture_time_ms, 250, false);
  }
  EXPECT_EQ(2 * packets_to_send_per_interval, send_bucket_->QueueSizePackets());

  // Expect all retransmissions to be sent out first despite having a later
  // capture time.
  EXPECT_CALL(callback_, TimeToSendPadding(_, _)).Times(0);
  EXPECT_CALL(callback_, TimeToSendPacket(_, _, _, false, _)).Times(0);
  EXPECT_CALL(callback_, TimeToSendPacket(
                             ssrc, _, capture_time_ms_retransmission, true, _))
      .Times(packets_to_send_per_interval)
      .WillRepeatedly(Return(true));

  EXPECT_EQ(5, send_bucket_->TimeUntilNextProcess());
  clock_.AdvanceTimeMilliseconds(5);
  EXPECT_EQ(0, send_bucket_->TimeUntilNextProcess());
  send_bucket_->Process();
  EXPECT_EQ(packets_to_send_per_interval, send_bucket_->QueueSizePackets());

  // Expect the remaining (non-retransmission) packets to be sent.
  EXPECT_CALL(callback_, TimeToSendPadding(_, _)).Times(0);
  EXPECT_CALL(callback_, TimeToSendPacket(_, _, _, true, _)).Times(0);
  EXPECT_CALL(callback_, TimeToSendPacket(ssrc, _, capture_time_ms, false, _))
      .Times(packets_to_send_per_interval)
      .WillRepeatedly(Return(true));

  EXPECT_EQ(5, send_bucket_->TimeUntilNextProcess());
  clock_.AdvanceTimeMilliseconds(5);
  EXPECT_EQ(0, send_bucket_->TimeUntilNextProcess());
  send_bucket_->Process();

  EXPECT_EQ(0u, send_bucket_->QueueSizePackets());
}

TEST_F(PacedSenderTest, HighPrioDoesntAffectBudget) {
  uint32_t ssrc = 12346;
  uint16_t sequence_number = 1234;
  int64_t capture_time_ms = 56789;

  // As high prio packets doesn't affect the budget, we should be able to send
  // a high number of them at once.
  for (int i = 0; i < 25; ++i) {
    SendAndExpectPacket(PacedSender::kHighPriority, ssrc, sequence_number++,
                        capture_time_ms, 250, false);
  }
  send_bucket_->Process();
  // Low prio packets does affect the budget.
  // Due to the multiplicative factor we can send 5 packets during a send
  // interval. (network capacity * multiplier / (8 bits per byte *
  // (packet size * #send intervals per second)
  const size_t packets_to_send_per_interval =
      kTargetBitrateBps * PacedSender::kDefaultPaceMultiplier / (8 * 250 * 200);
  for (size_t i = 0; i < packets_to_send_per_interval; ++i) {
    SendAndExpectPacket(PacedSender::kLowPriority, ssrc, sequence_number++,
                        clock_.TimeInMilliseconds(), 250, false);
  }
  send_bucket_->InsertPacket(PacedSender::kLowPriority, ssrc, sequence_number,
                             capture_time_ms, 250, false);
  EXPECT_EQ(5, send_bucket_->TimeUntilNextProcess());
  clock_.AdvanceTimeMilliseconds(5);
  send_bucket_->Process();
  EXPECT_EQ(1u, send_bucket_->QueueSizePackets());
  EXPECT_CALL(callback_, TimeToSendPacket(ssrc, sequence_number++,
                                          capture_time_ms, false, _))
      .Times(1)
      .WillRepeatedly(Return(true));
  EXPECT_EQ(5, send_bucket_->TimeUntilNextProcess());
  clock_.AdvanceTimeMilliseconds(5);
  send_bucket_->Process();
  EXPECT_EQ(0u, send_bucket_->QueueSizePackets());
}

TEST_F(PacedSenderTest, Pause) {
  uint32_t ssrc_low_priority = 12345;
  uint32_t ssrc = 12346;
  uint32_t ssrc_high_priority = 12347;
  uint16_t sequence_number = 1234;
  int64_t capture_time_ms = clock_.TimeInMilliseconds();

  EXPECT_EQ(0, send_bucket_->QueueInMs());

  // Due to the multiplicative factor we can send 5 packets during a send
  // interval. (network capacity * multiplier / (8 bits per byte *
  // (packet size * #send intervals per second)
  const size_t packets_to_send_per_interval =
      kTargetBitrateBps * PacedSender::kDefaultPaceMultiplier / (8 * 250 * 200);
  for (size_t i = 0; i < packets_to_send_per_interval; ++i) {
    SendAndExpectPacket(PacedSender::kNormalPriority, ssrc, sequence_number++,
                        clock_.TimeInMilliseconds(), 250, false);
  }

  send_bucket_->Process();

  send_bucket_->Pause();

  for (size_t i = 0; i < packets_to_send_per_interval; ++i) {
    send_bucket_->InsertPacket(PacedSender::kLowPriority, ssrc_low_priority,
                               sequence_number++, capture_time_ms, 250, false);
    send_bucket_->InsertPacket(PacedSender::kNormalPriority, ssrc,
                               sequence_number++, capture_time_ms, 250, false);
    send_bucket_->InsertPacket(PacedSender::kHighPriority, ssrc_high_priority,
                               sequence_number++, capture_time_ms, 250, false);
  }
  clock_.AdvanceTimeMilliseconds(10000);
  int64_t second_capture_time_ms = clock_.TimeInMilliseconds();
  for (size_t i = 0; i < packets_to_send_per_interval; ++i) {
    send_bucket_->InsertPacket(PacedSender::kLowPriority, ssrc_low_priority,
                               sequence_number++, second_capture_time_ms, 250,
                               false);
    send_bucket_->InsertPacket(PacedSender::kNormalPriority, ssrc,
                               sequence_number++, second_capture_time_ms, 250,
                               false);
    send_bucket_->InsertPacket(PacedSender::kHighPriority, ssrc_high_priority,
                               sequence_number++, second_capture_time_ms, 250,
                               false);
  }

  // Expect everything to be queued.
  EXPECT_EQ(second_capture_time_ms - capture_time_ms,
            send_bucket_->QueueInMs());

  for (int i = 0; i < 10; ++i) {
    clock_.AdvanceTimeMilliseconds(5);
    // TimeUntilNextProcess must not return 0 when paused.  If it does,
    // we risk running a busy loop, so ideally it should return a large value.
    EXPECT_GE(send_bucket_->TimeUntilNextProcess(), 1000);
    send_bucket_->Process();
  }

  // Expect high prio packets to come out first followed by normal
  // prio packets and low prio packets (all in capture order).
  {
    ::testing::InSequence sequence;
    EXPECT_CALL(callback_,
                TimeToSendPacket(ssrc_high_priority, _, capture_time_ms, _, _))
        .Times(packets_to_send_per_interval)
        .WillRepeatedly(Return(true));
    EXPECT_CALL(callback_, TimeToSendPacket(ssrc_high_priority, _,
                                            second_capture_time_ms, _, _))
        .Times(packets_to_send_per_interval)
        .WillRepeatedly(Return(true));

    for (size_t i = 0; i < packets_to_send_per_interval; ++i) {
      EXPECT_CALL(callback_, TimeToSendPacket(ssrc, _, capture_time_ms, _, _))
          .Times(1)
          .WillRepeatedly(Return(true));
    }
    for (size_t i = 0; i < packets_to_send_per_interval; ++i) {
      EXPECT_CALL(callback_,
                  TimeToSendPacket(ssrc, _, second_capture_time_ms, _, _))
          .Times(1)
          .WillRepeatedly(Return(true));
    }
    for (size_t i = 0; i < packets_to_send_per_interval; ++i) {
      EXPECT_CALL(callback_,
                  TimeToSendPacket(ssrc_low_priority, _, capture_time_ms, _, _))
          .Times(1)
          .WillRepeatedly(Return(true));
    }
    for (size_t i = 0; i < packets_to_send_per_interval; ++i) {
      EXPECT_CALL(callback_, TimeToSendPacket(ssrc_low_priority, _,
                                              second_capture_time_ms, _, _))
          .Times(1)
          .WillRepeatedly(Return(true));
    }
  }
  send_bucket_->Resume();

  for (size_t i = 0; i < 4; i++) {
    EXPECT_EQ(5, send_bucket_->TimeUntilNextProcess());
    clock_.AdvanceTimeMilliseconds(5);
    EXPECT_EQ(0, send_bucket_->TimeUntilNextProcess());
    send_bucket_->Process();
  }

  EXPECT_EQ(0, send_bucket_->QueueInMs());
}

TEST_F(PacedSenderTest, ResendPacket) {
  uint32_t ssrc = 12346;
  uint16_t sequence_number = 1234;
  int64_t capture_time_ms = clock_.TimeInMilliseconds();
  EXPECT_EQ(0, send_bucket_->QueueInMs());

  send_bucket_->InsertPacket(PacedSender::kNormalPriority, ssrc,
                             sequence_number, capture_time_ms, 250, false);
  clock_.AdvanceTimeMilliseconds(1);
  send_bucket_->InsertPacket(PacedSender::kNormalPriority, ssrc,
                             sequence_number + 1, capture_time_ms + 1, 250,
                             false);
  clock_.AdvanceTimeMilliseconds(9999);
  EXPECT_EQ(clock_.TimeInMilliseconds() - capture_time_ms,
            send_bucket_->QueueInMs());
  // Fails to send first packet so only one call.
  EXPECT_CALL(callback_, TimeToSendPacket(ssrc, sequence_number,
                                          capture_time_ms, false, _))
      .Times(1)
      .WillOnce(Return(false));
  clock_.AdvanceTimeMilliseconds(10000);
  send_bucket_->Process();

  // Queue remains unchanged.
  EXPECT_EQ(clock_.TimeInMilliseconds() - capture_time_ms,
            send_bucket_->QueueInMs());

  // Fails to send second packet.
  EXPECT_CALL(callback_, TimeToSendPacket(ssrc, sequence_number,
                                          capture_time_ms, false, _))
      .Times(1)
      .WillOnce(Return(true));
  EXPECT_CALL(callback_, TimeToSendPacket(ssrc, sequence_number + 1,
                                          capture_time_ms + 1, false, _))
      .Times(1)
      .WillOnce(Return(false));
  clock_.AdvanceTimeMilliseconds(10000);
  send_bucket_->Process();

  // Queue is reduced by 1 packet.
  EXPECT_EQ(clock_.TimeInMilliseconds() - capture_time_ms - 1,
            send_bucket_->QueueInMs());

  // Send second packet and queue becomes empty.
  EXPECT_CALL(callback_, TimeToSendPacket(ssrc, sequence_number + 1,
                                          capture_time_ms + 1, false, _))
      .Times(1)
      .WillOnce(Return(true));
  clock_.AdvanceTimeMilliseconds(10000);
  send_bucket_->Process();
  EXPECT_EQ(0, send_bucket_->QueueInMs());
}

TEST_F(PacedSenderTest, ExpectedQueueTimeMs) {
  uint32_t ssrc = 12346;
  uint16_t sequence_number = 1234;
  const size_t kNumPackets = 60;
  const size_t kPacketSize = 1200;
  const int32_t kMaxBitrate = PacedSender::kDefaultPaceMultiplier * 30000;
  EXPECT_EQ(0, send_bucket_->ExpectedQueueTimeMs());

  send_bucket_->SetEstimatedBitrate(30000);
  for (size_t i = 0; i < kNumPackets; ++i) {
    SendAndExpectPacket(PacedSender::kNormalPriority, ssrc, sequence_number++,
                        clock_.TimeInMilliseconds(), kPacketSize, false);
  }

  // Queue in ms = 1000 * (bytes in queue) *8 / (bits per second)
  int64_t queue_in_ms =
      static_cast<int64_t>(1000 * kNumPackets * kPacketSize * 8 / kMaxBitrate);
  EXPECT_EQ(queue_in_ms, send_bucket_->ExpectedQueueTimeMs());

  int64_t time_start = clock_.TimeInMilliseconds();
  while (send_bucket_->QueueSizePackets() > 0) {
    int time_until_process = send_bucket_->TimeUntilNextProcess();
    if (time_until_process <= 0) {
      send_bucket_->Process();
    } else {
      clock_.AdvanceTimeMilliseconds(time_until_process);
    }
  }
  int64_t duration = clock_.TimeInMilliseconds() - time_start;

  EXPECT_EQ(0, send_bucket_->ExpectedQueueTimeMs());

  // Allow for aliasing, duration should be within one pack of max time limit.
  EXPECT_NEAR(duration, PacedSender::kMaxQueueLengthMs,
              static_cast<int64_t>(1000 * kPacketSize * 8 / kMaxBitrate));
}

TEST_F(PacedSenderTest, QueueTimeGrowsOverTime) {
  uint32_t ssrc = 12346;
  uint16_t sequence_number = 1234;
  EXPECT_EQ(0, send_bucket_->QueueInMs());

  send_bucket_->SetEstimatedBitrate(30000);
  SendAndExpectPacket(PacedSender::kNormalPriority,
                      ssrc,
                      sequence_number,
                      clock_.TimeInMilliseconds(),
                      1200,
                      false);

  clock_.AdvanceTimeMilliseconds(500);
  EXPECT_EQ(500, send_bucket_->QueueInMs());
  send_bucket_->Process();
  EXPECT_EQ(0, send_bucket_->QueueInMs());
}

TEST_F(PacedSenderTest, ProbingWithInsertedPackets) {
  const size_t kPacketSize = 1200;
  const int kInitialBitrateBps = 300000;
  uint32_t ssrc = 12346;
  uint16_t sequence_number = 1234;

  PacedSenderProbing packet_sender;
  send_bucket_.reset(new PacedSender(&clock_, &packet_sender, nullptr));
  send_bucket_->CreateProbeCluster(kFirstClusterBps);
  send_bucket_->CreateProbeCluster(kSecondClusterBps);
  send_bucket_->SetEstimatedBitrate(kInitialBitrateBps);

  for (int i = 0; i < 10; ++i) {
    send_bucket_->InsertPacket(PacedSender::kNormalPriority, ssrc,
                               sequence_number++, clock_.TimeInMilliseconds(),
                               kPacketSize, false);
  }

  int64_t start = clock_.TimeInMilliseconds();
  while (packet_sender.packets_sent() < 5) {
    int time_until_process = send_bucket_->TimeUntilNextProcess();
    clock_.AdvanceTimeMilliseconds(time_until_process);
    send_bucket_->Process();
  }
  int packets_sent = packet_sender.packets_sent();
  // Validate first cluster bitrate. Note that we have to account for number
  // of intervals and hence (packets_sent - 1) on the first cluster.
  EXPECT_NEAR((packets_sent - 1) * kPacketSize * 8000 /
                  (clock_.TimeInMilliseconds() - start),
              kFirstClusterBps, kBitrateProbingError);
  EXPECT_EQ(0, packet_sender.padding_sent());

  clock_.AdvanceTimeMilliseconds(send_bucket_->TimeUntilNextProcess());
  start = clock_.TimeInMilliseconds();
  while (packet_sender.packets_sent() < 10) {
    int time_until_process = send_bucket_->TimeUntilNextProcess();
    clock_.AdvanceTimeMilliseconds(time_until_process);
    send_bucket_->Process();
  }
  packets_sent = packet_sender.packets_sent() - packets_sent;
  // Validate second cluster bitrate.
  EXPECT_NEAR((packets_sent - 1) * kPacketSize * 8000 /
                  (clock_.TimeInMilliseconds() - start),
              kSecondClusterBps, kBitrateProbingError);
}

TEST_F(PacedSenderTest, ProbingWithPaddingSupport) {
  const size_t kPacketSize = 1200;
  const int kInitialBitrateBps = 300000;
  uint32_t ssrc = 12346;
  uint16_t sequence_number = 1234;

  PacedSenderProbing packet_sender;
  send_bucket_.reset(new PacedSender(&clock_, &packet_sender, nullptr));
  send_bucket_->CreateProbeCluster(kFirstClusterBps);
  send_bucket_->SetEstimatedBitrate(kInitialBitrateBps);

  for (int i = 0; i < 3; ++i) {
    send_bucket_->InsertPacket(PacedSender::kNormalPriority, ssrc,
                               sequence_number++, clock_.TimeInMilliseconds(),
                               kPacketSize, false);
  }

  int64_t start = clock_.TimeInMilliseconds();
  int process_count = 0;
  while (process_count < 5) {
    int time_until_process = send_bucket_->TimeUntilNextProcess();
    clock_.AdvanceTimeMilliseconds(time_until_process);
    send_bucket_->Process();
    ++process_count;
  }
  int packets_sent = packet_sender.packets_sent();
  int padding_sent = packet_sender.padding_sent();
  EXPECT_GT(packets_sent, 0);
  EXPECT_GT(padding_sent, 0);
  // Note that the number of intervals here for kPacketSize is
  // packets_sent due to padding in the same cluster.
  EXPECT_NEAR((packets_sent * kPacketSize * 8000 + padding_sent) /
                  (clock_.TimeInMilliseconds() - start),
              kFirstClusterBps, kBitrateProbingError);
}

TEST_F(PacedSenderTest, PriorityInversion) {
  uint32_t ssrc = 12346;
  uint16_t sequence_number = 1234;
  const size_t kPacketSize = 1200;

  send_bucket_->InsertPacket(
      PacedSender::kHighPriority, ssrc, sequence_number + 3,
      clock_.TimeInMilliseconds() + 33, kPacketSize, true);

  send_bucket_->InsertPacket(
      PacedSender::kHighPriority, ssrc, sequence_number + 2,
      clock_.TimeInMilliseconds() + 33, kPacketSize, true);

  send_bucket_->InsertPacket(PacedSender::kHighPriority, ssrc, sequence_number,
                             clock_.TimeInMilliseconds(), kPacketSize, true);

  send_bucket_->InsertPacket(PacedSender::kHighPriority, ssrc,
                             sequence_number + 1, clock_.TimeInMilliseconds(),
                             kPacketSize, true);

  // Packets from earlier frames should be sent first.
  {
    ::testing::InSequence sequence;
    EXPECT_CALL(callback_,
                TimeToSendPacket(ssrc, sequence_number,
                                 clock_.TimeInMilliseconds(), true, _))
        .WillOnce(Return(true));
    EXPECT_CALL(callback_,
                TimeToSendPacket(ssrc, sequence_number + 1,
                                 clock_.TimeInMilliseconds(), true, _))
        .WillOnce(Return(true));
    EXPECT_CALL(callback_,
                TimeToSendPacket(ssrc, sequence_number + 3,
                                 clock_.TimeInMilliseconds() + 33, true, _))
        .WillOnce(Return(true));
    EXPECT_CALL(callback_,
                TimeToSendPacket(ssrc, sequence_number + 2,
                                 clock_.TimeInMilliseconds() + 33, true, _))
        .WillOnce(Return(true));

    while (send_bucket_->QueueSizePackets() > 0) {
      int time_until_process = send_bucket_->TimeUntilNextProcess();
      if (time_until_process <= 0) {
        send_bucket_->Process();
      } else {
        clock_.AdvanceTimeMilliseconds(time_until_process);
      }
    }
  }
}

TEST_F(PacedSenderTest, PaddingOveruse) {
  uint32_t ssrc = 12346;
  uint16_t sequence_number = 1234;
  const size_t kPacketSize = 1200;

  send_bucket_->Process();
  send_bucket_->SetEstimatedBitrate(60000);
  send_bucket_->SetSendBitrateLimits(60000, 0);

  SendAndExpectPacket(PacedSender::kNormalPriority, ssrc, sequence_number++,
                      clock_.TimeInMilliseconds(), kPacketSize, false);
  send_bucket_->Process();

  // Add 30kbit padding. When increasing budget, media budget will increase from
  // negative (overuse) while padding budget will increase from 0.
  clock_.AdvanceTimeMilliseconds(5);
  send_bucket_->SetSendBitrateLimits(60000, 30000);

  SendAndExpectPacket(PacedSender::kNormalPriority, ssrc, sequence_number++,
                      clock_.TimeInMilliseconds(), kPacketSize, false);
  EXPECT_LT(5u, send_bucket_->ExpectedQueueTimeMs());
  // Don't send padding if queue is non-empty, even if padding budget > 0.
  EXPECT_CALL(callback_, TimeToSendPadding(_, _)).Times(0);
  send_bucket_->Process();
}

TEST_F(PacedSenderTest, AverageQueueTime) {
  uint32_t ssrc = 12346;
  uint16_t sequence_number = 1234;
  const size_t kPacketSize = 1200;
  const int kBitrateBps = 10 * kPacketSize * 8;  // 10 packets per second.

  send_bucket_->SetEstimatedBitrate(kBitrateBps);

  EXPECT_EQ(0, send_bucket_->AverageQueueTimeMs());

  int64_t first_capture_time = clock_.TimeInMilliseconds();
  send_bucket_->InsertPacket(PacedSender::kNormalPriority, ssrc,
                             sequence_number, first_capture_time, kPacketSize,
                             false);
  clock_.AdvanceTimeMilliseconds(10);
  send_bucket_->InsertPacket(PacedSender::kNormalPriority, ssrc,
                             sequence_number + 1, clock_.TimeInMilliseconds(),
                             kPacketSize, false);
  clock_.AdvanceTimeMilliseconds(10);

  EXPECT_EQ((20 + 10) / 2, send_bucket_->AverageQueueTimeMs());

  // Only first packet (queued for 20ms) should be removed, leave the second
  // packet (queued for 10ms) alone in the queue.
  EXPECT_CALL(callback_, TimeToSendPacket(ssrc, sequence_number,
                                          first_capture_time, false, _))
      .Times(1)
      .WillRepeatedly(Return(true));
  send_bucket_->Process();

  EXPECT_EQ(10, send_bucket_->AverageQueueTimeMs());

  clock_.AdvanceTimeMilliseconds(10);
  EXPECT_CALL(callback_, TimeToSendPacket(ssrc, sequence_number + 1,
                                          first_capture_time + 10, false, _))
      .Times(1)
      .WillRepeatedly(Return(true));
  for (int i = 0; i < 3; ++i) {
    clock_.AdvanceTimeMilliseconds(30);  // Max delta.
    send_bucket_->Process();
  }

  EXPECT_EQ(0, send_bucket_->AverageQueueTimeMs());
}

TEST_F(PacedSenderTest, ProbeClusterId) {
  uint32_t ssrc = 12346;
  uint16_t sequence_number = 1234;
  const size_t kPacketSize = 1200;

  send_bucket_->SetSendBitrateLimits(kTargetBitrateBps, kTargetBitrateBps);
  send_bucket_->SetProbingEnabled(true);
  for (int i = 0; i < 10; ++i) {
    send_bucket_->InsertPacket(PacedSender::kNormalPriority, ssrc,
                               sequence_number + i, clock_.TimeInMilliseconds(),
                               kPacketSize, false);
  }

  // First probing cluster.
  EXPECT_CALL(callback_,
              TimeToSendPacket(_, _, _, _,
                               Field(&PacedPacketInfo::probe_cluster_id, 0)))
      .Times(5)
      .WillRepeatedly(Return(true));
  for (int i = 0; i < 5; ++i) {
    clock_.AdvanceTimeMilliseconds(20);
    send_bucket_->Process();
  }

  // Second probing cluster.
  EXPECT_CALL(callback_,
              TimeToSendPacket(_, _, _, _,
                               Field(&PacedPacketInfo::probe_cluster_id, 1)))
      .Times(5)
      .WillRepeatedly(Return(true));
  for (int i = 0; i < 5; ++i) {
    clock_.AdvanceTimeMilliseconds(20);
    send_bucket_->Process();
  }

  // Needed for the Field comparer below.
  const int kNotAProbe = PacedPacketInfo::kNotAProbe;
  // No more probing packets.
  EXPECT_CALL(callback_,
              TimeToSendPadding(
                  _, Field(&PacedPacketInfo::probe_cluster_id, kNotAProbe)))
      .Times(1)
      .WillRepeatedly(Return(500));
  send_bucket_->Process();
}

TEST_F(PacedSenderTest, AvoidBusyLoopOnSendFailure) {
  uint32_t ssrc = 12346;
  uint16_t sequence_number = 1234;
  const size_t kPacketSize = kFirstClusterBps / (8000 / 10);

  send_bucket_->SetSendBitrateLimits(kTargetBitrateBps, kTargetBitrateBps);
  send_bucket_->SetProbingEnabled(true);
  send_bucket_->InsertPacket(PacedSender::kNormalPriority, ssrc,
                             sequence_number, clock_.TimeInMilliseconds(),
                             kPacketSize, false);

  EXPECT_CALL(callback_, TimeToSendPacket(_, _, _, _, _))
      .WillOnce(Return(true));
  send_bucket_->Process();
  EXPECT_EQ(10, send_bucket_->TimeUntilNextProcess());
  clock_.AdvanceTimeMilliseconds(9);

  EXPECT_CALL(callback_, TimeToSendPadding(_, _))
      .Times(2)
      .WillRepeatedly(Return(0));
  send_bucket_->Process();
  EXPECT_EQ(1, send_bucket_->TimeUntilNextProcess());
  clock_.AdvanceTimeMilliseconds(1);
  send_bucket_->Process();
  EXPECT_EQ(5, send_bucket_->TimeUntilNextProcess());
}

}  // namespace test
}  // namespace webrtc

redpajama_set_name: RedPajamaGithub


Registration is closed. Please call MAR customer service for registration options.
Garlic-herb crusted roast strip loin of beef with Merlot demi glace.
Mediterranean style grilled chicken breast, with herbs, artichokes, bacon and roasted red peppers.
Cheese tortellini, braised greens and tomato with a Parmesan cream sauce.
There will be a $25 cancellation before November 28th.
There will be no refunds after November 28th.
A block of rooms has been reserved for Monday, December 3rd and Tuesday, December 4th, at a rate of $110 plus tax.
This special room rate will be available until November 12th, based on availability.
Attendees may contact the hotel directly 413-458-9371 between the hours of 9:00am - 6:00pm and ask to speak with the reservations department.
Please make sure to reference your group name (The Mass Assoc of Realtors) when making your reservations.


Click on a "Linked to" name to go to the individual.
Click on the Cemetery Name to go to the cemetery.
Rhoad's Burying Ground is probably one of the oldest in the area.
Cemetery photograph by C. Wilson Gerhart.


Show your love for NVIDIA.
Cooler Master and GeForce® GTX have teamed up to give you the brightest green LED backlighting combined with the best responsive feeling that gamers have come to love. Get multiple LED lighting modes, on-the-fly macros, profile support, and Cherry MX switches -all in a classic, minimalistic design. Show your love for GeForce® GTX with custom keycaps and bright green LEDs on the MasterKeys Pro L GeForce® GTX Edition.
The MasterKeys Pro L GeForce® GTX Edition implements rich, bright green LEDs for direct solutions to some of pro gaming's biggest annoyances. A reflective metal plate built into the keyboard amplifies the brightness of the greens, allowing for more visibility of your keys during dim sessions. Multiple lighting modes include Light Wave, Breathing and unique responsive effects.
Refined symmetry and a heavy-weight quality build help keep things clean and simple.
Trying to get familiar with a new game's controls? Light the relevant keys up to help you learn the in-game keybinds faster. With four profile keys, you can set up your backlighting and record macros without hassle. Program multiple keystrokes to a single key or change per-key backlighting with intuitive keyboard commands.
When you have a good thing going, the last thing you want to do is exit your game to adjust your keyboard settings. The MasterKeys Pro L GeForce® GTX Edition keyboards use an innovative On-the-Fly system. Change your settings all from the convenience of your keyboard, without the need to download any software or exit your game.
The MasterKeys Pro L GeForce® GTX Edition is outfitted with a 32-bit ARM Cortex processor that powers the keyboard's independent functions. Make this power your weapon. Save and execute commands and macros instantly. Thanks to the MasterKeys On-the-fly system, you'll have an instant advantage on your opponents.
The MasterKeys Pro L GeForce® GTX Edition employs an exclusive combination of rollover technologies for the most efficient, accurate anti-ghosting technology yet. N-key rollover works in tandem with 6-key rollover to ensure that every single keypress is correctly detected, no matter how many are pressed. Rest easy knowing no matter how fast and furious it gets, your keyboard can handle it.


About 130 cubic meters of oil spilled over an area of about 1,000 square meters at the Trebs field in the Yamal-Nenets autonomous district, the local branch of the Emergency Situations Ministry reported on its website, as cited by Interfax.
The field is being developed by oil company Bashneft.
No fire broke out following the spill, and no one was injured. Cleanup work is now under way.
This was the second accident at the Trebs field during well re-entry by oil-field services company Burs.
In April, an unsealed well head spewed a mixture of oil and gas into the surrounding area. The Federal Service for Environmental, Technological and Atomic Inspection said the accident occurred in part because of Burs personnel's lack of experience.
In the wake of the spill, Bashneft fired Alexander Dashevsky, senior vice president for oil and gas production, and Rinat Nagayev, head of the oil and gas department.
Bashneft said it is already implementing a program aimed at preventing similar accidents in the future.


Published at Friday, April 19th, 2019 - 1:16 PM. expensive Kitchen Design. By Robert C. Battaglia.
Here you are at [blog]. Many people have used on line to find facts, tips, posts or any other reference for their purposes. Like you are. Do you come here to have new unique idea about expensive kitchen appliances? How many webpages have you read to get more detail about expensive kitchen appliances?
Expensive kitchen appliances is one of raised niche at this moment. We know it from search engine records like google adwords or google trends. In an effort to carry valuable information to our readers, weve tried to locate the closest relevance photo about expensive kitchen appliances. And here you can view now, this image have already been extracted from reputable source.
We think this expensive kitchen appliances pic will give you certain additional point for your need and that we hope you like it. We understand, we might have different view concerning this but at least weve tried our best.
This image has been uploaded by Robert C. Battaglia. You are able to explore additional valuable articles in [cat] group. We thank you for your visit to our website. Make sure you get the information you are looking for. Do not forget to share and love our reference to help further develop our website.


text:
Die Liste der Naturdenkmale im Kreis Soest nennt die Listen der in den Städten und Gemeinden im Kreis Soest in Nordrhein-Westfalen gelegenen Naturdenkmale

Siehe auch
 Liste der geschützten Landschaftsbestandteile im Kreis Soest
 Liste der Landschaftsschutzgebiete im Kreis Soest
 Liste der Naturschutzgebiete im Kreis Soest

Weblinks

!Soest,Kreis

redpajama_set_name: RedPajamaWikipedia


As the population becomes diverse internationally, Religious Discrimination becomes important as an area of law around the world. This book helps readers understand the issue of religion and inequality and aims to increase the likelihood of achieving equality at both national and international levels for those suffering religious discrimination.
Anne-Marie Mooney Cotter is an Attorney, The Social Security Disability Law Firm, USA.


text:
Dr. Jo Boaler
DR. JO BOALER is a Professor of Mathematics Education at Stanford University. She was also the chair of the Curriculum and Teacher Education area group. Professor Boaler is a former secondary school teacher of mathematics and has taught in diverse, inner London comprehensive schools, across the 11-18 age range. Her PhD won the national award for educational research in the UK, and she is the author of numerous articles and seven books. Professor Boaler specializes in the impact of different mathematics teaching approaches upon student understanding, achievement and equity. Her book: Experiencing School Mathematics won the 'Outstanding Book of the Year' award for education in Britain. She is an elected fellow of the Royal Society of Arts (Great Britain), a former president of the International Organisation for Women and Mathematics Education (IOWME) and a recipient of an 'Early Career Award' from the National Science Foundation in the US.
Her book What's Math Got to Do With It? (Viking/Penguin 2008) aims to increase public understanding of the importance of mathematics, and the nature of teaching and learning. She is currently working with members of the British Government and with the Specialist Schools and Academies Trust to bring effective research based approaches into schools. Please visit her website at http://ed.stanford.edu/faculty/joboaler.

redpajama_set_name: RedPajamaCommonCrawl


text:
Amitav Ghosh to Visit Burma
Press Council Releases Draft Code of Ethics
Suu Kyi Stresses Burma-India Ties in New Delhi
Burmese Workers Return after Clash with Thais
What Message Will Obama Bring?
Cheap Cooking Oil Imports Hit Burmese Producers
Earthquake Toll Raised to 26; Aftershock Hits Naypyidaw
Landmines Killing, Maiming More in Burma
PepsiCo to Sign Bottling Deal in Burma
Thai Govt Approves Plan for Rice Partnership
Rangoon's Tourism Boom Risks Heritage
Obama Urged to Denounce Rights Abuses in Cambodia
China's Communist Party Conclave Nears End
Rohingya Refuse to Register as 'Bengali'
Three Burmese Soldiers Abducted by Border
Seismologist Warns of Future Devastating Quakes
Trouble Brewing for China
Arakan Strife Could Spread Across Burma: ICG
ILO Says Burma Acting to Cut Forced Labor
Norway Pledges Aid to Update Burma's Electricity Law
Karen Refugees Shot and Killed near Camp
Clinton Arrives in Australia for Defense Meetings
Australia Troops Eyed to Join US-Philippine Drills
Two Indonesians Arrested in Failed Bomb Attack
China Slams Dalai Lama as Tibetans Self-immolate
Burmese Shrug at Obama Visit, as Beijing Shudders
Workers Barred from Factory despite Strike End
Obama Visit to Firm up US Policy on Asia
Ancient Buddhist Relics Returned by Locals
Suu Kyi Makes First India Visit for 40 Years
OIC to Hold Talks on Rohingya Issue
Japanese Companies Eye Burma's Woodlands
Burma Seeks More Border Trade with Bangladesh
Number of Japanese Tourists to Burma Doubles
25 Dead, 100 Injured in Burma Train Blast
Upper Burma Earthquake Death Toll Rises
Cautious Enforcer to be China's Next Premier
Japan's Economy Shrinks 3.5 Percent in Third Quarter
Terry Hurt as Liverpool and Chelsea Draw
Strong Quake Strikes Burma; at Least 5 Killed
25 Dead in Petrol Fire after Tankers on Train Overturn
Clinton to Join Obama for Burma Trip
A Woman's (Political) Work is Never Done
Burma Business Roundup (Saturday, Nov. 10)
President Obama is Coming to Burma
Border Trade Cards to Boost Business, Cut Graft
Rohingyas Arrested in Dawei Sent Back to Arakan
Skilled Burmese Have Duty to Return: 88 Gen
The acclaimed author of the "The Glass Palace" will give readings and attend public discussions of his work in Rangoon and Mandalay this week.
By Kyaw Phyo Tha 14 November 2012
RANGOON — During his last visit to Burma, he had a chance to interview Aung San Suu Kyi. As a result, he was followed everywhere by secret police.
But now in 2012, fifteen years later, Amitav Ghosh, the international award-winning author, will have a chance to see someone else when he is in town this month—his readers. No more chases this time, hopefully.
Organized by The American Center Baldwin Library Book Club in Rangoon, a discussion between the 56-year-old Bengali Indian writer and the club members will take place on Nov. 16, according to the library's director.
"After we learned about his trip, we arranged to read his book 'The Hungry Tide' for this month because we read 'The Glass Palace' a few months ago. We've announced to the club members that the writer will be at the discussion. They are excited to see him," said the director.
Burmese writer and editor Ma Thida (San Chaung), who is also a book club member, is the person who broke the news about the novelist's Burmese visit to the director.
"As a member myself, I'm aware that other members want to see him in person. For a long time I wished I could arrange a discussion between him and the members. When I learn about his trip, I tipped the information to the library director," said the writer-cum-editor, who has personally known Ghosh since 2009.
Internationally, Amitav Ghosh is famous for his work in the English language. His 2011 novel "River of Smoke" was short-listed for the Man Asian Literary Prize 2011. In 1997, he won the Arthur C. Clarke Award for "The Calcutta Chromosome," published in 1995.
But in Burma, he is well known for his 2000 novel "The Glass Palace," which set in Burma over a span of 115 years and tells the tale of a family and how historical events influenced their lives. A Burmese translation of the novel won the country's highest literary award, the Burmese National Literature Award, in 2010.
Nay Win Myint, the Burmse translator of "The Glass Palace," told The Irrawaddy that he "heartily welcomes" Ghosh's visit.
"It's great to have a visit from a great writer like Amitav Ghosh," he said. "He is our guest. If he's curious about Burma, we have to explain everything to him when we see him at the Indian consulate in Mandalay on Nov. 18."
Amitav Ghosh told The Irrawaddy via email that it is wonderful that "The Glass Palace" has been well-received in Burma, and he is very excited about joining the book club discussion.
"I am very much looking forward to talking to my readers there," said the Calcutta native.
He added that during his trip he will be doing readings from "The Glass Palace" at the Indian embassy in Rangoon and at the Indian consulate in Mandalay, and will see his friends in the writing community in Burma.
Aye Say, a 39-year old freelance translator, has been a book club member since it started in 2008. He has read "The Glass Palace," and said he likes it because "it successfully portrayed the hardship the last Burmese King Thibaw faced in exile."
"I wonder how he knew this? I will surely ask him when we meet on Nov. 16 how he did his research for this book," he said.
The American Center Baldwin Library Book Club discussion on "The Hungry Tide" will take place on Nov. 16 from 3:30 -5:00 pm at the Myanmar Institute of Theology (MIT), American Corner, Insein Road, Gyogone, Insein Township. Call 642040, 09420107885 for more information.
Kyaw Phyo Tha The Irrawaddy Kyaw Phyo Tha is the News Editor of the English edition of The Irrawaddy.


Well friends, I've finally done it. Done that simple thing that nearly all the adults in the world can do, that, well, most teenagers can do. That thing that I have been avoiding like the plague for over a decade. I learnt to drive.
I spent the money, took the classes, practiced in our manual car, nearly broke up my pending nuptuals, but in some small miracle, I learnt how to drive. I'm feeling pretty pleased with myself.
Jordan however decided to celebrating by getting a vicious flu. The kind that makes his workaholic self completely stop. He has probably slept for 20 of the last 24 hours. I on the other hand, am currently spending most of my days mind-over-matter-ing it, in an attempt not to get what he's getting. And to aid in my attempt to refuse to allow bacteria into my body, I'm also eating kind of insane amounts of vitamin C.
Not just vitamin C though, the internet has led me to believe that I need not only citrus in IV form, but also garlic, ginger, and spicy food. So here is the garlick-iest, ginger-iest, spiciest, and citrus-y salad you'll ever need. It's all the immune boosters in one so that we all don't end up curled up in a ball watching terrible TV. I for one like to be in fine form when I watch bad TV.
2 stalks Celery, sliced on a bias.
Bring a large pot of water to a boil. Season liberally with salt.
Cook soba noodles according to package instructions, or until al dente.
Strain, and immediately pout cold water over top and woosh it around with your hands or a spoon to cool it all down. Set aside.
Meanwhile, take your minced garlic put it near the edge of your cutting board. Sprinkle a small mount of salt on top. With the side of your knife, crush the garlic until it is pureed. Put it in a large bowl.
Add in the ginger, lime juice, soy sauce, and chili sauce.
Whisk to combine, then slowly add in the sesame oil. Taste, and add more citrus, oil, or soy as needed.
Add in all the remaining ingredients. Toss to fully combine and serve immediately, or cover and keep in the fridge for up to 2 days.
I mentioned this in my last post, and I feel a bit weird about announcing it over the internet, but here goes: Over the holidays Jordan proposed, and I said yes. It has been a magnificent couple of weeks, full of celebrating with friends and family. Jordan told me that the wedding is off if I go on a "wedding diet" and I assured him that it wouldn't happen, because it can't happen. Because everywhere I turn these days someone is pouring me a glass of bubbly, and then refilling it, and then refilling it again. Let me tell you friends, it is hard to stay sober when you're recently engaged.
So this post is against all the new years resolutions, and against the very principle of a wedding diet, because it is hang-over food.
Spaghetti Carbonara, or "bacon and egg bascetti" as I used to call it when I was wee, it basically just that- bacon, eggs, parmesan, and loads of black pepper. You don't need to cook the sauce, it cooks as the it's tossed with the hot pasta. You can easily make this without the poached egg of course, but there is something about adding that makes the pasta feel like breakfast. Which is sometimes just the ticket.
Cut the bacon into ½ inch pieces and cook them in a small frying pan over medium heat for about 15 minutes, or until they are crunchy, but not burning.
Strain the fat off into a jar of can. Put the bacon aside.
Fill a large and a medium sized pot with water and bring to a boil.
Meanwhile grate the parmesan and mix it in a large bowl with 3 of the eggs and healthy cracking of black pepper.
When the large pot of water comes to a boil, season it liberally with salt and cook the pasta to the directions on the package.
Just as the pasta is done and you're about to strain it, crack the eggs into the remaining medium sized pot.
Strain the pasta and add it, and the bacon to the egg and parm mixture. Stir vigorously until it has completely combined, making sure it doesn't curdle.
Using a slotted spoon remove the eggs from the water- testing to make sure they are done by gently poking at the yolk and white with your finger, ensuring that the white is hard but the yolk is soft.
Put the eggs on top of the pasta and enjoy immediately!
I love polenta. I love it a lot.
It is, for me, the ultimate comfort food. It's smooth and creamy and, perhaps most importantly is super cheap. I pretty well lived off of polenta for a couple years. Breakfast? Put an egg on it. Lunch? Some tomato sauce. Dinner? My favourite is with sautéed mushrooms and onions. You can serve it with steak, or Bolognese sauce, or darn near anything.
But when I was young and ever so broke, mostly I ate it with straight up tomato sauce. When I was feeling rich I would buy some parm and add some in, but most days it wasn't so fancy. I could make a big batch and feed myself for a few meals for under $3.00. Mega cheap.
And, even in my intense poverty, it was a deeply satisfying meal. It takes only a few minutes to make and it is rich and as comforting as any dish could be.
And it is almost ridiculously easy to make. It is a no fuss sort of a dish. You simply bring some liquid to a boil (stock, milk, or a combination of both) whisk in the polenta and let it simmer for half and hour or so. That's it. Unless you're trying to keep your costing at a minimum, you should add in cheese and a little nub of butter for a bit of flavour.
Once it's cooked it becomes a creamy porridge, but your left over's will harden up in the fridge and become something that you can bake or fry and give it some crispy texture. But I like it best hot out of the pot, eaten with a spoon, feeling like a kid again.
In a medium pot over medium heat bring a pinch of salt, the stock/water and the milk up to a boil.
Pour the polenta into a fine sieve and shake it over the pot whisking the whole time- this will prevent lumps from forming.
Keep whisking until the polenta starts to thicken, about 2 minutes.
Switch from a whisk to a spatula or wooden spoon and stir on occasion for 25-35 more minutes, adding a bit of water if it starts to look too thick.
Add in the cheese and butter and stir until it is totally incorporated. Check for seasoning and add more salt if you need it.
I love pasta. I used to think I would be happy eating pasta every day. It is my ultimate comfort food. When I'm sick I want pasta, when it's cold I want pasta, when I'm celebrating I want pasta, when it's hot out I want pasta. I love pasta.
Then I worked at a high end Italian restaurant here in town, that shall remain nameless, where we had pasta every day for staff meal. It was always spaghetti with whatever we had kicking around left over. Except that there was never anything left over, so it was always spaghetti with butter and parm. We also had a salad of leftovers alongside it, except there was never any leftovers, so he ordered in iceberg lettuce for us. It was a sad sad meal, and everyone who worked there was significantly plumper when they left than when they had arrived.
It was a restaurant full of flaws, full of some extraodinarily cruel people, and full of beautiful food for the guests, and iceberg lettuce for the staff. I felt really crappy about myself when I worked there. And for quite a while I stopped eating pasta. I had just gotten my fill.
Slowly though, it came back, and it ought to. I'm a tiny bit Italian and it manifested itself into my diet when I was very small and it never left. I love, passionately, food that uncomplicated, unfussy, that used very few ingredients, but uses the best ones possibly, to make simple beautiful food. That's what Italian food is all about.
Which brings us back to pasta. Pasta for me is the epitimy of simple food. The combination of essentially just flour, salt and eggs makes the most gorgeous textured noodle that, at it's best, is just graced with a sauce made of only a very few things. It is simplicity done right.
In a large bowl mix together the flour and salt. Create a well in the centre of it and add in the yolks, oil and milk. Mix together until it combines. Now put the dough onto a clean surface and knead it- push the dough out flat, fold it over and push it again with the base of your hand, pushing and folding over and over again. When the dough is ready you will be able to do the window test- Pull a small piece of dough and gently stretch it with your fingertips. If it is ready you will be able to get the dough to become so thin it is slightly translucent. If not and the dough rips, keep kneading. If you doubt at all whether or not it is done, keep kneading.
When it is done, wrap it up in plastic wrap and let it cool rest for at least half an hour, or up to overnight.
Once it's rested set up your pasta roller. Cut the dough into quarters and cover the others carefully. On a very well floured surface roll out the dough by hand with a rolling pin to about 1/2 cm thick.
On the pasta machine on the thickest setting roll out the dough.
Now on the second thickest roll out the dough again. Keep going until the pasta machine is on setting number 3.
Flour the dough again and fold it into thirds and cut into strips for linguine. Either coat them heavily with more flour and wrap them up to use within a couple days or while they are still soft hang them up. I used my towel rack, but you can also hang them up (clean) hangers and dry them that way.
I wish that I had a cuter story about gnocchi. I wish my Nona had taught me to rice the potatoes, that she had shown me just how much flour you need to bring the dough together. I wish, to be honest, I could even remember her gnocchi, but I don't. Although I've heard my mom and cousin talking about how incredible they were, the only time I remember her serving us gnocchi I also remember her apologizing for not making them from scratch.
But such is memory I guess, flawed.
So instead I learnt how to make gnocchi from reading the French Laundry Cookbook, where Thomas Keller goes to great length to explain how to make them. There are many ways to make gnocchi, and many debates on how to do it best, should you use starchy russets potatoes, or waxier Yukon golds? Should there be cheese added, or just on the top? If you use another starch, a squash, or a sweet potato, is it still gnocchi?
Over the years since I first forayed into the world of homemade pastas I have tried just about every possible method and every possible ingredient, and this is the recipe I always come back to. I use Yukon golds- waxier, so that you get more control over the starch content, no cheese in the gnocchi, it's an unnescessary flavour, and it detracts from what is darn close to perfection to begin with. And you can call it a squash gnocchi, or a sweet potatoe gnocchi, but again- if it ain't broke, don't fix it.
Gnocchi are surprisingly simple to make, you roast the potatoes, push them through a potato ricer or through a seive, to get very fluffy potatoes, and then you add in a few eggs and a touch of flour and knead it together until it barely forms, and then roll it, cut it, and boil it. It's also wonderful because it freezes brilliantly, so if you make a bigger batch you can keep some for later.
While it is simple, and just about anyone can do it, I should note that it takes a quick hand, and the first time you do it you should stick to a small batch and just practise the technique. Gluten, the protein in wheat, forms at 55C and you want the dough to come together before it cools down past that temperature, so you must work quickly and keep a cloth over your dough as you go. And always have a pot of water boiling so you can test the little pastas, and make sure the consistently is just right.
Poke some small holes in the potatoes with a fork on every side, and then lay them on a baking sheet and bake until an inserted knife goes in and out without any resistance, about 45 minutes to an hour.
As soon as the potatoes have cooled just enough to touch, put a towel over the rest of the potatoes, take one and cut it in half. Without peeling it, put it flesh side down in the ricer and press it in until no more potato comes out. Repeat with the rest. If you don't have a potato ricer you can take a sieve and press it the potatoes through with the back of a large spoon, this is a bit more time consuming, but totally effective- I have done it many times.
When the potatoes are all riced make a well in the middle of the bowl.
Add in the eggs and a bit of the flour, and the salt. Mix until it has barely come together. If the dough is sticking to your hangs you need some more flour.
Again add in a bit more and check again, making sure your hands are clean.
One the dough is supple, but not sticky your in business.
Take about a cup of the dough out. Put a tea towel over the rest.
Flour the surface of your counter generously and roll out the reserved dough. I roll mine with both hands, and when it starts to feel a bit too long, I just cut it in half and do each hald seperately, the dough will break if you are too rough with it.
With a pastry cutter or a knife cut the dough ito small logs. You can at this point roll them to get ridges on a gnocchi board or the back of a fork but I find this to be not too important. Now put them on a ery well floured tray and shake the tray a bit so that each piece is totally covered in flour. They will stick together if you are not diligent about thi.
Now put a couple in your boiling water to test. If you haven't added enough flour they may break apart. If they do just mix in another small handful. If they don't keep going!
Repeat with the rest of the dough until you have lots of lovely little gnocchis all ready to go.
If you are planning on freezing some/all your gnocchi put them in the freezer as they are on the tray covered in flour. After a couple hours take them apart and put them in a freezer bag and put them back.
Bring a very large pot of water to a boil. If you are using frozen gnocchi use the biggest pot you have and do it in batches, otherwise they will bring down the water temperature too much and won't cook properly.
Salt the water generously and put your gnocchi in!
When they rise to the top they are ready to be put in your favourite sauce and eaten with abandon.
Here I have sauteed some garlic and shallots in some olive oil, added in some pancetta, and topped it off with toasted pine nuts. The simplest and most delicious dinner!
For the wonderful people over at Edible Vancouver I did a little writing about swiss chard, pasta, and my over embellished Italian roots. Check it out here if your so inclined!
Which is especially nice right now because we're getting that first bout of bone chilling weather here in Van, and I do not want to be leaving my house for food. I want to hibernate. I want to drink hot chocolate, and apple cider, and read books and swaddle myself in knitted blankets. That's what I want. What I also want it barley risotto.
Risotto that warms you up form the inside out on a cold night but is healthy enough that I don't feel to guilty about eating a cookie for breakfast the next day. Risotto that's rich and soothing and is delicious with both grilled sausages and with sauteed salmon. Risotto that is good heated up the next day because it's not made of rice that gets soggy. Risotto that has that nuttiness and bit of chew that characterized whole grains. Risotto that is just plain really good.
Bring the stock up to a boil with 2 cups of water.
Add a pinch of salt and then add in the barley and cook them to their package instructions, about 25 minutes.
Meanwhile in a medium pan on medium-low heat warm up a good glug of olive oil. Add in your onions and fennel and saute until they become translucent and very fragrant.
Add in your garlic and the herbs and cook just until you can start to smell the garlic but not so that it gets any colour.
Add in the barley, the cheese and the knob of butter and stir to combine it all and check your seasoning.
And then eat this wonderful mix by itself, or serve it as a side!
They say that scent is the sense most linked to memory and I think, despite not knowing who they are, that they're right. I think about it occasionally, if a man walks by wearing Jordan's old cologne and I get a flash in my head of his old apartment, or the way freshly cut rhubarb makes me think of my mom making pie, but never is it more obvious to me then when I smell bacon.
Bacon, which I have eaten literally hundreds of times in at least dozens of ways.
But every time I smell bacon cooking all I can think of is a pale pale yellow bowl with thin red and blue stripes around the top of the inside. I can see it vividly, sitting on top of the glass tabletop from my childhood backyard, with our neighbours overgrown shrubs turning into trees in the background. I can feel the warmth of the hot Toronto summers, but mostly what I see is the Spaghetti carbonara inside that striped bowl, and what I smell is bacon.
It was the ultimate summer meal, it took minutes to throw together, cook bacon, cook pasta, toss with eggs and pepper and parmesan, put on table. The speed of it was important not only because my Mom was a busy woman, but also so the burners wouldn't be on and heat up the house.
Good eggs are also crucial, and maybe most important is the parm. Try to get grana padano, or real parmesanno reggiano.
And also, don't skip on the pepper. The name Carbonara means black, like coals, and though I don't like quite that much pepper in mine it should have a fair bit.
10 thick slices of the best bacon you can get. Pancetta is a lovely subsistute as well.
Cut the bacon into thick pieces.
Fry them on medium heat until wonderful and crispy, but with a little chew to them still.
Get a big pot of water on high heat.
Meanwhile mix your eggs, parm and a healthy cracking of pepper.
I was a little crazy this time and added a bit of parsley. You could do that too if you wanted.
Now put that strange eggy sauce in the bottom of a large bowl.
Now, perhaps you have a good stove and your water is boiling already. In that case, throw your pasta in, give it a good stir and cook it depending on the package instructions, but basically if until it is cooked throw with a bit of bite to it yet. If you don't have a good stove, throw on some Aretha and dance around a bit, and then add your pasta, stir it a bit and cook it by the package instructions. Whatever works for you.
Once it's cooked strain it and then quickly put it into that big bowl with the sauce in the bottom and give it a good toss. You want to move quickly now. If you take to long the eggs with curdle, but if you move just fast enough you'll have a wonderful silky sauce that wraps around each noodle. And it will be glorious.


This slide is made from brass which aged by hand for a completely unique finish with a warm but clear sound. Tonally the aged slide is identical to the standard polished brass version: warm with a brassy boldness.
A word from the Rock Slide - "If you are into tweed and worn out looking gear these are for you. Tonally they sound similar to a standard brass balltip Rock Slide, but they resemble something from the bottom of the Bayou. We individually hand age these using a multi-step recipe of destruction. They have a smooth finish for playability. Each slide is aged by hand. Appearance will vary from slide to slide."


At MaxDumpster, we strive to bring you the best service at the best price available. We have a wide selection of dumpster sizes in stock in Saint James, MD, with flexible & timley pickup and delivery. Give us a call today for all your dumpster rental and roll off needs.
At this point, how to approach hiring a expert 6 Yard Dumpster in Saint James, MD service provider? Before heading hire among the professional agencies, one should possess transparent picture about the volume of the throw away that is proceeding to be got rid of and regardless of if the 6 Yard Dumpster in Saint James, MD service provider can hold your requirements. you need to go through the agreement agreement in the Dumpster rental service provider and also familiarize yourself with the terms and conditions in the agreement with there being limits for certain companies on the quantity throw away as well as objects disposed from the waste just be sure you fit into the requirements. It is always wise to have a prior check with supplier on all of these issues before your going hire a single.
You can order the bin as well as dumpster according to your own need. They are available in different sizes and also shapes. According to the quantity of the trash, you can place the necessity for the same.
Speedy service for example next day 6 Yard Dumpster in Saint James, MD is an additional fantastic object to look for. If you are in a hurry to have the project began and accomplished, this is a have to have option.
You will need time and do the job to take out the lavatory, vanity, split out the floor of your lavatory and consider the baseboards down. Once you have accomplished this it is possible to throw the particles into the following day 6 Yard Dumpster in Saint James, MD you have being placed in your property. Quickly chuck the ball debris apart and simply eliminate the mess when the dumpster is gone from a yard.
But 6 Yard Dumpster in Saint James, MDs aren't one size fits all. To make it easier to keep your costs in check, you have to pay only for the receptacle dimension that suits your own amount of waste. So whether you rent the 10-, 20-, or 30-yard capacity dumpster, you'll have exactly the expanse connected with space you may need to jettison all of your rubbish. Contact your community junk trucking service currently for a no cost, no-obligation estimate on the different sizes connected with dumpsters.
If you are a enterprise you are probably considering having the garbage 6 Yard Dumpster in Saint James, MD forever. But if you are doing a project with a home, then you're looking at a set fee of time to hold the unit. Normally for these kinds of projects, you will want the discretion unit with regard to anywhere from a couple of days to a few weeks. Whilst businesses may have to enter into a legal contract that will in the end save these money, home users might not exactly. This is where watchful research comes into play. While an organization can possibly make a deal a lower pace if they can assure usage for any set length of time, smaller tasks might not be able to do so. Take your search on the internet to help you be sure to locate the best deal for which you are tapering to do.
You can certainly get rid of the garbage as well as waste of which builds up everyday when you rent the dumpster. By renting the dumpster you have made your health that much less complicated versus striving to get rid of each of the garbage with a few tons via pickup truck. A dumpster will let you speed up particles the house getting built. You'll not have to permit time and petrol money transporting the throw away of empty packaging and also boxes back to the employers.
There are various sort of Maryland dumpster renting available together with a medium sized dumpster with wheels on it. A dumpster with wheels on it is moving and can be used to complete numerous cleanup tasks at one time. More substantial dumpsters can be placed inside the location that you pick on your residence. Next day shipping options create cleanup simple and easy , efficient. Rapid pickup of the full dumpster is usually an asset to development dumpster. You can easily as well as quickly get your property cleaned up and looking it is very best.
If you have a large venture you are trying to full in McLean, Vienna, or even Tyson's Corner throughout Arlington County, Veterans administration you will need to rent the dumpster.
The old flooring can be wasted into the hired dumpster. The flooring may have acquired to of been cut to have it off of the floorboards. You know what chaos this can lead to. Renting the dumpster can make your daily life as well as the development crew's life less complicated by simply having the ability to toss it into the dumpster.
Community cleanup is very important and often needed to keep our-self away from numerous irritating issues such as health problems, unclean as well as untidy atmosphere and so on. Trash disposal locally becomes inescapable in the occasions of natural disasters like fulfills and world quakes. When the location is strike by such natural disasters, it'll be filled with trash piled by means of left out ruins of the houses, worn out home furniture and many more.
Kitchen appliances that are throughout pretty good form and not beat up and ugly or very dirty, may be donated, as some cabinets can. Direct out trash has to move to the garbage dump, and eco friendly materials including copper as well as aluminum may either be taken care of at the development site or merely taken to the proper recycle center. You can save money by organizing it by yourself. Some dumpster renting enable organizing at your internet site because they are available divided into areas. Parts of a few recycled supplies will get you back a couple of bucks and this could offset the cost of the 6 Yard Dumpster in Saint James, at times by a great deal.
If you are inside the mood to eradicate all the useless that has absorbed your garage and surface buildings, you should call a company that can bring you a dumpster to rent in the morning.
There is a pretty good chance that the to-trash number will be a many more extensive when compared to a few bags worth. Find a good local 6 Yard Dumpster in Saint James business to rent a dumpster via. This way you have the convenience of having a person else go on it away for you, and you will not even require to worry about going above weekly trash pickup boundaries. If you do pursuit, there are some businesses that will even choose what is eco friendly or used and recycle/donate to charities those items for you. That's including killing several birds with one jewel, not just a couple! When companies are involved in such a huge activity of renovating your trash into reused items, have you thought to share under your control in shielding the sustainability of the planet? You can delight yourself regarding helping the companies to reach their goal i actually.e. being enviromentally friendly. All you have to do is build your trash achieve the right industrialist that may recycle it in the environmental friendly manner and concealed them directly into reusable solutions.
Once your condo in Baltimore, Virginia or maybe Washington DC is carried out, the builder can slowly move the dumpster out of your property and your condo building is gorgeous and thoroughly clean. Your new tenants or preceding renters can happily appreciate their brand new surroundings.
While you are reducing, be sure you reuse as well as recycle. Precious metals like water piping can be distributed at save shops should you have scrap available. Old bare cans enables you to store fingernails or toenails or anchoring screws. You could perhaps try offering old gym equipment you no longer experience the internet (or maybe give it to an associate). Or, should you have way more versus the occasional object that you not want or need, use the newfound room to have a yard sale. If you're in a big hurry to get rid of almost everything, though, do put it inside your rented dumpster. Several 6 Yard Dumpster in Saint James, MD companies goes the extra mile to lower their environmental affect by checking the dumpster's contents to seek out reusable as well as recyclable supplies that they can both recycle or maybe donate for you to charity.
The particular caution that have to fallowed when you are choosing a 6 Yard Dumpster in Saint James, MD company with the city without the need of landfill, you have to choose a nearby service provider to enable you to be assured involving prompt shipping and low support charges as the distance travelled to pick your trash is going to be less.
Dumpster going may have several negative facets, but it is truly an art. Not only can you find trendy stuff at no cost, but you are able to do it while having a fun journey. If you don't thoughts a little dirt, try a dumpster dive at least once. Allow me to share five easy methods to properly plan a successful evening of dumpster going.
Dumpsters are usually priced based on the sizing and period of the 6 Yard Dumpster in Saint James, MD, comprehending the rental period of this service provider will assist you to take a selection on time forced to have the dumpster for your job site, keeping trash ready with the disposal can reduce the period of the 6 Yard Dumpster in Saint James, MD thus price of this 6 Yard Dumpster in Saint James, MD.
For your safeguard and basic safety, find a crap removal business with vehicles and personnel that are insured and licensed. Confirm that this hauler is insured and licensed. The hauler should be fully included in workman's compensation, general liability, as well as auto insurance.
Leftover loyal to a single rental company is the best selection made. It is because by being an everyday customer, you are more likely to receive discounts as well as special remedies. When shopping for a single, make sure that it's a reputable business that offers unrestricted services. It therefore has to be specialist enough by using a logo. A brand logo is needed to differentiate among good and bad firms. It should supply timely providers without waiting hence needs to have created a great reputation. How customers are treated is what is needed to judge send out name. Simply no 6 Yard Dumpster in Saint James, MD company incorporates a right to take advantage of the clientele. The prices are extremely competitive and may be cost effective to anyone. If you need to find the most affordable price, it is better to choose a community possessed rental rather than a privately owned rental. Community primarily based ones will forever provide the best for the community and also give back to the same society. Almost always there is pride throughout seeing your fee being used for the benefit for your community.


Here's two clips showing why you need to visit Nelson over summer. First up is the helmet cam highlights from our trip down last weekend. It's a bit long, but I'm sure you can deal with that. Second are highlights from Jeff Carter and Dodzy's property empire expansion expedition to the now infamous Peaking Ridge.
Jeff it's spelt Peaking not Peeking... Just to clarify.
The mythical Wairoa Gorge trails were built between 2010 and 2013 by four trail crews. Watch as we get an insight into how and why it all came about from the men who built them.
Spoke 54 - Out NOW!


I had a problem with my Windows Defender giving me the following error code: 0X80240022 when it tried to update. I was also unable to download updates for XP, and office through the browser.
To solve it I went to start> programs > administrative tools > services.
Then restarted both automatic updates and background intelligent transfer service. (right click them and choose restart).
Most other sites try to sell a registry cleaner.
It worked for me too. Even after countless hours dealing with Microsoft tech support and being scammed by all the "regfix" software programs. Much appreciated!!
Event Type mptelemetry, P1 80240022, P2 processdownloadresults, P3 download, P4 1.5.1972.0, P5 mpsigdwn.dll, P6 1.5.1.1972.0 P7 microsoft forefront client security, P8 NIL, p9 Nil, P10 NIL.
Having tried all suggestions without success I Installed .NET framework 1.1 and now all is fine.
I have been trying everything and this information fixed the problem!
what is the last part "services"????
I use Chinese…..does anyone know that?
I had the same error with the Microsoft Security Essentials antivirus.
Hey Thanks. Worked for me and my XP PC. Cheers!
I have same problem, i using window vista, how can i get rid of this plz?
YO, Thanks worked for me too!!!!
Worked for me too. Under Vista64 the service 'automatic updates' is named 'windows update' though!
windows update refuses to install even with the firewall down.
sorry man, i did exactly what you said but im still getting the same problems, i see it worked for everyone else so would it be possible that there is a special case of sorts?
Only thing to add is that this fix may not work until you also restart your computer after restarting both of the services.
Thanks for posting this easy solution!
This procedure worked for me also. I was originally getting a 0x80080005 error trying to download Microsoft security updates. The log file referenced error 0x80240022. I rebooted and the fix worked. Thanks for the help!!!
This is one of many fixes I have tried in order to clear this error which is driving me crazy!
Damn. It did not work for me.
I have Windows 7 and can't find automatic updates or background intelligent transfer service. I'm a novice at computers.
Took me a minute or 2 to find Administrative tools. I right clicked start & chose to customise the start menu. Found admin tools & added it to the program list, then followed your instructions. Windows 7 is the same as Vista & you need to look for Windows update.
Tried this 5 or 6 times & still get the same error..
i use windows xp but i couldn't find the administrative tools n services. anyone can explain it to me what should i do to find this administrative tools n services?
Great job! Thanks for that.
type services.msc and hit enter on your keyboard.
Rinse and repeat for Automatic Updates, if it's not there, look for Windows Updates and try that.
i have problem with the antivirus Microsoft forefront client security it does not update the antivirus definition and anti spyware and if i going to update manually something appear "error found code 0x80240022".
anyone can help this issue?
i am also having problems with the 80240022 windows updates, but when i go to admin tools, there is nothing in my folder? I had to go through the control panel, maybe I am not in the right place but can anyone help please!


`A journalist who saw videotape of the Monday hangings of Saddam Hussein's half-brother and the dictator's former chief judge has described how one of the men was decapitated.
New York Times reporter John F. Burns told CNN's Wolf Blitzer Monday evening that Barzan Hassan's head "just snapped off," because he was apparently given too much rope and fell too far — about eight feet — for a man of his medium build and weight.
This entry was posted on Tuesday, January 16th, 2007 at 8:42 pm and is tagged as: death, iraq, unlucky. You can follow any responses to this entry through the RSS 2.0 feed. You can leave a response, or trackback from your own site.
Entries (RSS) and Comments (RSS). 35 queries. 0.713 seconds.


Answer: All of your general ledger account numbers, names of the general ledger accounts and the balance for each general ledger account will translate into General Ledger 8.0. You update after you have closed out the month, so these balances are your current balances and your year-to-date amounts.
If you keep all individual entries on line (closed entries), they will not be imported into General Ledger 8.0. Most firms clear the entries when they close each month, and, thus, would not have individual entries on line. And we do not disturb your old General Ledger when we import the data into General Ledger 8.0. Therefore, you can still refer to data in the old General Ledger.
If you have the DOS version 2.1d of General Ledger, you will need our free Utility Disk for General Ledger. Each step takes less than a minute. The Utility Disk translates General Ledger 2.1d to 7.0 data. Then General Ledger 8.0 translates the 7.0 data to the new version.


text:
You are here: Home \ About us \ Affiliations
SCIE has been an accredited centre for delivery of Cambridge International Examinations IGCSE and A Level courses since 2003.
SCIE is an Approved Centre for delivery of Edexcel examinations.
SCIE is a centre for UK university applications through UCAS.
SCIE is a member of the College Board.
SCIE is a fully accredited member of the Council of International Schools.
SCIE is a member of East Asia Regional Council of Schools.
SCIE is a fully accredited member of FOBISIA.
SCIE is an independent operator of the International Award.
SCIE is an official Intenational Private Centre for the admistration of Trinity College examinations.
SCIE is a member of the the Royal Geographical Society (RGS).
SCIE is an ASDAN education Network Partner.
SCIE is a member of SISAC (Shenzhen International School Athletic Conference).
SCIE is an examination center of DELE Spanish Test.
中博的彩舒适
体彩官网首页下载
澳门银河官网地址
www.yf5599www.vwin
舞帝彩票平台
彩七天乐
腾博会诚信


The KAELIA Bandage Dress features a halter-neck style complemented with an attached off shoulder cuffs. Don't forget the thigh slit making it truly fit for a LX Queen. Adorn the KAELIA from your next girl's brunch to the date night.


The item Diary of a real Payne: : true story, Annie Tipton represents a specific, individual, material embodiment of a distinct intellectual or artistic creation found in Adams Public Library.
When EJ's mom and dad expect her to star in the role of angel in this year's Christmas pageant wearing a full-on angel costume (halo and all!), EJ objects. But Mom and Dad aren't buying any of her excuses. Will EJ become part of the adventure of the real Christmas story-- and discover that her little role in the Christmas pageant in little old Spooner, Wisconsin, really isn't so little after all?


Feel the luxury of Green Thread's beautiful bamboo socks. They are cashmere-soft for incredible comfort with no rubbing seams – not even across the toe.
Bamboo is a wonderful fabric for socks. It is anti-bacterial and draws moisture away from the skin. Bamboo is also breathable and odour eliminating for super cool, dry feet. Perfect for the Australian climate.
Green Thread socks are calf length and they fit. The soft, stretchy fabric will contour perfectly to your feet.
A box of 5 pairs in a variety of colours, perfect for business and casual wear.
Made from healthy, breathable bamboo - an environmental wonder-plant.
Cashmere soft, but incredibly hard wearing.
Contrasting heel and toe colours along with the size printed on the sole of the sock makes them easy to pair up after washing.
These socks are so soft and comfy and the only ones my son wants to wear!
Great product!! Highly recommend these socks.
The softest socks I have ever put on my feet.
Great colours and silky feel.
Socks are great but you need to review your delivery service with Australia Post as it would appear that they either lost the article for a bit or are just very slow delivering.
Socks are soft and comfortable.
Great socks, what can I say?


text:
Cyberattacks
June 30, 2011 Cybersecurity
Federalist Society Explores Legal Issues Surrounding Cyber Conflict
WASHINGTON, June 30, 2011 – The Federalist Society convened Tuesday to discuss the complex and interconnected legal and policy issues of cyber security in relation to the law of armed conflict, privacy and legislative action. Morning and afternoon panels comprised of national security and economic security experts presented to the legal society the difficulties of applying the law of armed conflict towards cyber threats. The new threat conditions introduced by cyber intrusions and attacks do not fit the old paradigm of doing warfare. Panelists agreed, however, that the new rules should not be determined before major cyber conflicts have taken place. Keep Reading
June 17, 2011 Cybersecurity/House of Representatives/International
Foreign Policy Research Institute Holds Cybersecurity Talk
WASHINGTON, June 17, 2011 –,The Philadelphia-based Foreign Policy Research Institute presented expertise on the emerging threat in cyberspace Thursday to journalists, private sector industry leaders, government officials and strategists in Washington. Lawrence Husick, Senior Fellow at Foreign Policy Research Institute's (FPRI) Center on Terrorism and Counter-Terrorism, offered his expertise on leveraging technology as a defining characteristic of the modern terrorist. His presentation centered on the rapidly evolving nature of cyber attacks, and the lack of a comprehensive private sector cybersecurity initiative. Keep Reading