text:
//  Copyright (c) 2011-present, Facebook, Inc.  All rights reserved.
//  This source code is licensed under both the GPLv2 (found in the
//  COPYING file in the root directory) and Apache 2.0 License
//  (found in the LICENSE.Apache file in the root directory).
//
// Copyright (c) 2011 The LevelDB Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. See the AUTHORS file for names of contributors.

#include "db/compaction/compaction_picker_universal.h"
#ifndef ROCKSDB_LITE

#include <cinttypes>
#include <limits>
#include <queue>
#include <string>
#include <utility>
#include "db/column_family.h"
#include "file/filename.h"
#include "logging/log_buffer.h"
#include "monitoring/statistics.h"
#include "test_util/sync_point.h"
#include "util/random.h"
#include "util/string_util.h"

namespace ROCKSDB_NAMESPACE {
namespace {
// A helper class that form universal compactions. The class is used by
// UniversalCompactionPicker::PickCompaction().
// The usage is to create the class, and get the compaction object by calling
// PickCompaction().
class UniversalCompactionBuilder {
 public:
  UniversalCompactionBuilder(const ImmutableCFOptions& ioptions,
                             const InternalKeyComparator* icmp,
                             const std::string& cf_name,
                             const MutableCFOptions& mutable_cf_options,
                             VersionStorageInfo* vstorage,
                             UniversalCompactionPicker* picker,
                             LogBuffer* log_buffer)
      : ioptions_(ioptions),
        icmp_(icmp),
        cf_name_(cf_name),
        mutable_cf_options_(mutable_cf_options),
        vstorage_(vstorage),
        picker_(picker),
        log_buffer_(log_buffer) {}

  // Form and return the compaction object. The caller owns return object.
  Compaction* PickCompaction();

 private:
  struct SortedRun {
    SortedRun(int _level, FileMetaData* _file, uint64_t _size,
              uint64_t _compensated_file_size, bool _being_compacted)
        : level(_level),
          file(_file),
          size(_size),
          compensated_file_size(_compensated_file_size),
          being_compacted(_being_compacted) {
      assert(compensated_file_size > 0);
      assert(level != 0 || file != nullptr);
    }

    void Dump(char* out_buf, size_t out_buf_size,
              bool print_path = false) const;

    // sorted_run_count is added into the string to print
    void DumpSizeInfo(char* out_buf, size_t out_buf_size,
                      size_t sorted_run_count) const;

    int level;
    // `file` Will be null for level > 0. For level = 0, the sorted run is
    // for this file.
    FileMetaData* file;
    // For level > 0, `size` and `compensated_file_size` are sum of sizes all
    // files in the level. `being_compacted` should be the same for all files
    // in a non-zero level. Use the value here.
    uint64_t size;
    uint64_t compensated_file_size;
    bool being_compacted;
  };

  // Pick Universal compaction to limit read amplification
  Compaction* PickCompactionToReduceSortedRuns(
      unsigned int ratio, unsigned int max_number_of_files_to_compact);

  // Pick Universal compaction to limit space amplification.
  Compaction* PickCompactionToReduceSizeAmp();

  Compaction* PickDeleteTriggeredCompaction();

  // Form a compaction from the sorted run indicated by start_index to the
  // oldest sorted run.
  // The caller is responsible for making sure that those files are not in
  // compaction.
  Compaction* PickCompactionToOldest(size_t start_index,
                                     CompactionReason compaction_reason);

  // Try to pick periodic compaction. The caller should only call it
  // if there is at least one file marked for periodic compaction.
  // null will be returned if no such a compaction can be formed
  // because some files are being compacted.
  Compaction* PickPeriodicCompaction();

  // Used in universal compaction when the enabled_trivial_move
  // option is set. Checks whether there are any overlapping files
  // in the input. Returns true if the input files are non
  // overlapping.
  bool IsInputFilesNonOverlapping(Compaction* c);

  const ImmutableCFOptions& ioptions_;
  const InternalKeyComparator* icmp_;
  double score_;
  std::vector<SortedRun> sorted_runs_;
  const std::string& cf_name_;
  const MutableCFOptions& mutable_cf_options_;
  VersionStorageInfo* vstorage_;
  UniversalCompactionPicker* picker_;
  LogBuffer* log_buffer_;

  static std::vector<SortedRun> CalculateSortedRuns(
      const VersionStorageInfo& vstorage);

  // Pick a path ID to place a newly generated file, with its estimated file
  // size.
  static uint32_t GetPathId(const ImmutableCFOptions& ioptions,
                            const MutableCFOptions& mutable_cf_options,
                            uint64_t file_size);
};

// Used in universal compaction when trivial move is enabled.
// This structure is used for the construction of min heap
// that contains the file meta data, the level of the file
// and the index of the file in that level

struct InputFileInfo {
  InputFileInfo() : f(nullptr), level(0), index(0) {}

  FileMetaData* f;
  size_t level;
  size_t index;
};

// Used in universal compaction when trivial move is enabled.
// This comparator is used for the construction of min heap
// based on the smallest key of the file.
struct SmallestKeyHeapComparator {
  explicit SmallestKeyHeapComparator(const Comparator* ucmp) { ucmp_ = ucmp; }

  bool operator()(InputFileInfo i1, InputFileInfo i2) const {
    return (ucmp_->Compare(i1.f->smallest.user_key(),
                           i2.f->smallest.user_key()) > 0);
  }

 private:
  const Comparator* ucmp_;
};

typedef std::priority_queue<InputFileInfo, std::vector<InputFileInfo>,
                            SmallestKeyHeapComparator>
    SmallestKeyHeap;

// This function creates the heap that is used to find if the files are
// overlapping during universal compaction when the allow_trivial_move
// is set.
SmallestKeyHeap create_level_heap(Compaction* c, const Comparator* ucmp) {
  SmallestKeyHeap smallest_key_priority_q =
      SmallestKeyHeap(SmallestKeyHeapComparator(ucmp));

  InputFileInfo input_file;

  for (size_t l = 0; l < c->num_input_levels(); l++) {
    if (c->num_input_files(l) != 0) {
      if (l == 0 && c->start_level() == 0) {
        for (size_t i = 0; i < c->num_input_files(0); i++) {
          input_file.f = c->input(0, i);
          input_file.level = 0;
          input_file.index = i;
          smallest_key_priority_q.push(std::move(input_file));
        }
      } else {
        input_file.f = c->input(l, 0);
        input_file.level = l;
        input_file.index = 0;
        smallest_key_priority_q.push(std::move(input_file));
      }
    }
  }
  return smallest_key_priority_q;
}

#ifndef NDEBUG
// smallest_seqno and largest_seqno are set iff. `files` is not empty.
void GetSmallestLargestSeqno(const std::vector<FileMetaData*>& files,
                             SequenceNumber* smallest_seqno,
                             SequenceNumber* largest_seqno) {
  bool is_first = true;
  for (FileMetaData* f : files) {
    assert(f->fd.smallest_seqno <= f->fd.largest_seqno);
    if (is_first) {
      is_first = false;
      *smallest_seqno = f->fd.smallest_seqno;
      *largest_seqno = f->fd.largest_seqno;
    } else {
      if (f->fd.smallest_seqno < *smallest_seqno) {
        *smallest_seqno = f->fd.smallest_seqno;
      }
      if (f->fd.largest_seqno > *largest_seqno) {
        *largest_seqno = f->fd.largest_seqno;
      }
    }
  }
}
#endif
}  // namespace

// Algorithm that checks to see if there are any overlapping
// files in the input
bool UniversalCompactionBuilder::IsInputFilesNonOverlapping(Compaction* c) {
  auto comparator = icmp_->user_comparator();
  int first_iter = 1;

  InputFileInfo prev, curr, next;

  SmallestKeyHeap smallest_key_priority_q =
      create_level_heap(c, icmp_->user_comparator());

  while (!smallest_key_priority_q.empty()) {
    curr = smallest_key_priority_q.top();
    smallest_key_priority_q.pop();

    if (first_iter) {
      prev = curr;
      first_iter = 0;
    } else {
      if (comparator->Compare(prev.f->largest.user_key(),
                              curr.f->smallest.user_key()) >= 0) {
        // found overlapping files, return false
        return false;
      }
      assert(comparator->Compare(curr.f->largest.user_key(),
                                 prev.f->largest.user_key()) > 0);
      prev = curr;
    }

    next.f = nullptr;

    if (c->level(curr.level) != 0 &&
        curr.index < c->num_input_files(curr.level) - 1) {
      next.f = c->input(curr.level, curr.index + 1);
      next.level = curr.level;
      next.index = curr.index + 1;
    }

    if (next.f) {
      smallest_key_priority_q.push(std::move(next));
    }
  }
  return true;
}

bool UniversalCompactionPicker::NeedsCompaction(
    const VersionStorageInfo* vstorage) const {
  const int kLevel0 = 0;
  if (vstorage->CompactionScore(kLevel0) >= 1) {
    return true;
  }
  if (!vstorage->FilesMarkedForPeriodicCompaction().empty()) {
    return true;
  }
  if (!vstorage->FilesMarkedForCompaction().empty()) {
    return true;
  }
  return false;
}

Compaction* UniversalCompactionPicker::PickCompaction(
    const std::string& cf_name, const MutableCFOptions& mutable_cf_options,
    VersionStorageInfo* vstorage, LogBuffer* log_buffer,
    SequenceNumber /* earliest_memtable_seqno */) {
  UniversalCompactionBuilder builder(ioptions_, icmp_, cf_name,
                                     mutable_cf_options, vstorage, this,
                                     log_buffer);
  return builder.PickCompaction();
}

void UniversalCompactionBuilder::SortedRun::Dump(char* out_buf,
                                                 size_t out_buf_size,
                                                 bool print_path) const {
  if (level == 0) {
    assert(file != nullptr);
    if (file->fd.GetPathId() == 0 || !print_path) {
      snprintf(out_buf, out_buf_size, "file %" PRIu64, file->fd.GetNumber());
    } else {
      snprintf(out_buf, out_buf_size, "file %" PRIu64
                                      "(path "
                                      "%" PRIu32 ")",
               file->fd.GetNumber(), file->fd.GetPathId());
    }
  } else {
    snprintf(out_buf, out_buf_size, "level %d", level);
  }
}

void UniversalCompactionBuilder::SortedRun::DumpSizeInfo(
    char* out_buf, size_t out_buf_size, size_t sorted_run_count) const {
  if (level == 0) {
    assert(file != nullptr);
    snprintf(out_buf, out_buf_size,
             "file %" PRIu64 "[%" ROCKSDB_PRIszt
             "] "
             "with size %" PRIu64 " (compensated size %" PRIu64 ")",
             file->fd.GetNumber(), sorted_run_count, file->fd.GetFileSize(),
             file->compensated_file_size);
  } else {
    snprintf(out_buf, out_buf_size,
             "level %d[%" ROCKSDB_PRIszt
             "] "
             "with size %" PRIu64 " (compensated size %" PRIu64 ")",
             level, sorted_run_count, size, compensated_file_size);
  }
}

std::vector<UniversalCompactionBuilder::SortedRun>
UniversalCompactionBuilder::CalculateSortedRuns(
    const VersionStorageInfo& vstorage) {
  std::vector<UniversalCompactionBuilder::SortedRun> ret;
  for (FileMetaData* f : vstorage.LevelFiles(0)) {
    ret.emplace_back(0, f, f->fd.GetFileSize(), f->compensated_file_size,
                     f->being_compacted);
  }
  for (int level = 1; level < vstorage.num_levels(); level++) {
    uint64_t total_compensated_size = 0U;
    uint64_t total_size = 0U;
    bool being_compacted = false;
    for (FileMetaData* f : vstorage.LevelFiles(level)) {
      total_compensated_size += f->compensated_file_size;
      total_size += f->fd.GetFileSize();
      // Size amp, read amp and periodic compactions always include all files
      // for a non-zero level. However, a delete triggered compaction and
      // a trivial move might pick a subset of files in a sorted run. So
      // always check all files in a sorted run and mark the entire run as
      // being compacted if one or more files are being compacted
      if (f->being_compacted) {
        being_compacted = f->being_compacted;
      }
    }
    if (total_compensated_size > 0) {
      ret.emplace_back(level, nullptr, total_size, total_compensated_size,
                       being_compacted);
    }
  }
  return ret;
}

// Universal style of compaction. Pick files that are contiguous in
// time-range to compact.
Compaction* UniversalCompactionBuilder::PickCompaction() {
  const int kLevel0 = 0;
  score_ = vstorage_->CompactionScore(kLevel0);
  sorted_runs_ = CalculateSortedRuns(*vstorage_);

  if (sorted_runs_.size() == 0 ||
      (vstorage_->FilesMarkedForPeriodicCompaction().empty() &&
       vstorage_->FilesMarkedForCompaction().empty() &&
       sorted_runs_.size() < (unsigned int)mutable_cf_options_
                                 .level0_file_num_compaction_trigger)) {
    ROCKS_LOG_BUFFER(log_buffer_, "[%s] Universal: nothing to do\n",
                     cf_name_.c_str());
    TEST_SYNC_POINT_CALLBACK(
        "UniversalCompactionBuilder::PickCompaction:Return", nullptr);
    return nullptr;
  }
  VersionStorageInfo::LevelSummaryStorage tmp;
  ROCKS_LOG_BUFFER_MAX_SZ(
      log_buffer_, 3072,
      "[%s] Universal: sorted runs: %" ROCKSDB_PRIszt " files: %s\n",
      cf_name_.c_str(), sorted_runs_.size(), vstorage_->LevelSummary(&tmp));

  Compaction* c = nullptr;
  // Periodic compaction has higher priority than other type of compaction
  // because it's a hard requirement.
  if (!vstorage_->FilesMarkedForPeriodicCompaction().empty()) {
    // Always need to do a full compaction for periodic compaction.
    c = PickPeriodicCompaction();
  }

  // Check for size amplification.
  if (c == nullptr &&
      sorted_runs_.size() >=
          static_cast<size_t>(
              mutable_cf_options_.level0_file_num_compaction_trigger)) {
    if ((c = PickCompactionToReduceSizeAmp()) != nullptr) {
      ROCKS_LOG_BUFFER(log_buffer_, "[%s] Universal: compacting for size amp\n",
                       cf_name_.c_str());
    } else {
      // Size amplification is within limits. Try reducing read
      // amplification while maintaining file size ratios.
      unsigned int ratio =
          mutable_cf_options_.compaction_options_universal.size_ratio;

      if ((c = PickCompactionToReduceSortedRuns(ratio, UINT_MAX)) != nullptr) {
        ROCKS_LOG_BUFFER(log_buffer_,
                         "[%s] Universal: compacting for size ratio\n",
                         cf_name_.c_str());
      } else {
        // Size amplification and file size ratios are within configured limits.
        // If max read amplification is exceeding configured limits, then force
        // compaction without looking at filesize ratios and try to reduce
        // the number of files to fewer than level0_file_num_compaction_trigger.
        // This is guaranteed by NeedsCompaction()
        assert(sorted_runs_.size() >=
               static_cast<size_t>(
                   mutable_cf_options_.level0_file_num_compaction_trigger));
        // Get the total number of sorted runs that are not being compacted
        int num_sr_not_compacted = 0;
        for (size_t i = 0; i < sorted_runs_.size(); i++) {
          if (sorted_runs_[i].being_compacted == false) {
            num_sr_not_compacted++;
          }
        }

        // The number of sorted runs that are not being compacted is greater
        // than the maximum allowed number of sorted runs
        if (num_sr_not_compacted >
            mutable_cf_options_.level0_file_num_compaction_trigger) {
          unsigned int num_files =
              num_sr_not_compacted -
              mutable_cf_options_.level0_file_num_compaction_trigger + 1;
          if ((c = PickCompactionToReduceSortedRuns(UINT_MAX, num_files)) !=
              nullptr) {
            ROCKS_LOG_BUFFER(log_buffer_,
                             "[%s] Universal: compacting for file num -- %u\n",
                             cf_name_.c_str(), num_files);
          }
        }
      }
    }
  }

  if (c == nullptr) {
    if ((c = PickDeleteTriggeredCompaction()) != nullptr) {
      ROCKS_LOG_BUFFER(log_buffer_,
                       "[%s] Universal: delete triggered compaction\n",
                       cf_name_.c_str());
    }
  }

  if (c == nullptr) {
    TEST_SYNC_POINT_CALLBACK(
        "UniversalCompactionBuilder::PickCompaction:Return", nullptr);
    return nullptr;
  }

  if (mutable_cf_options_.compaction_options_universal.allow_trivial_move ==
          true &&
      c->compaction_reason() != CompactionReason::kPeriodicCompaction) {
    c->set_is_trivial_move(IsInputFilesNonOverlapping(c));
  }

// validate that all the chosen files of L0 are non overlapping in time
#ifndef NDEBUG
  SequenceNumber prev_smallest_seqno = 0U;
  bool is_first = true;

  size_t level_index = 0U;
  if (c->start_level() == 0) {
    for (auto f : *c->inputs(0)) {
      assert(f->fd.smallest_seqno <= f->fd.largest_seqno);
      if (is_first) {
        is_first = false;
      }
      prev_smallest_seqno = f->fd.smallest_seqno;
    }
    level_index = 1U;
  }
  for (; level_index < c->num_input_levels(); level_index++) {
    if (c->num_input_files(level_index) != 0) {
      SequenceNumber smallest_seqno = 0U;
      SequenceNumber largest_seqno = 0U;
      GetSmallestLargestSeqno(*(c->inputs(level_index)), &smallest_seqno,
                              &largest_seqno);
      if (is_first) {
        is_first = false;
      } else if (prev_smallest_seqno > 0) {
        // A level is considered as the bottommost level if there are
        // no files in higher levels or if files in higher levels do
        // not overlap with the files being compacted. Sequence numbers
        // of files in bottommost level can be set to 0 to help
        // compression. As a result, the following assert may not hold
        // if the prev_smallest_seqno is 0.
        assert(prev_smallest_seqno > largest_seqno);
      }
      prev_smallest_seqno = smallest_seqno;
    }
  }
#endif
  // update statistics
  RecordInHistogram(ioptions_.statistics, NUM_FILES_IN_SINGLE_COMPACTION,
                    c->inputs(0)->size());

  picker_->RegisterCompaction(c);
  vstorage_->ComputeCompactionScore(ioptions_, mutable_cf_options_);

  TEST_SYNC_POINT_CALLBACK("UniversalCompactionBuilder::PickCompaction:Return",
                           c);
  return c;
}

uint32_t UniversalCompactionBuilder::GetPathId(
    const ImmutableCFOptions& ioptions,
    const MutableCFOptions& mutable_cf_options, uint64_t file_size) {
  // Two conditions need to be satisfied:
  // (1) the target path needs to be able to hold the file's size
  // (2) Total size left in this and previous paths need to be not
  //     smaller than expected future file size before this new file is
  //     compacted, which is estimated based on size_ratio.
  // For example, if now we are compacting files of size (1, 1, 2, 4, 8),
  // we will make sure the target file, probably with size of 16, will be
  // placed in a path so that eventually when new files are generated and
  // compacted to (1, 1, 2, 4, 8, 16), all those files can be stored in or
  // before the path we chose.
  //
  // TODO(sdong): now the case of multiple column families is not
  // considered in this algorithm. So the target size can be violated in
  // that case. We need to improve it.
  uint64_t accumulated_size = 0;
  uint64_t future_size =
      file_size *
      (100 - mutable_cf_options.compaction_options_universal.size_ratio) / 100;
  uint32_t p = 0;
  assert(!ioptions.cf_paths.empty());
  for (; p < ioptions.cf_paths.size() - 1; p++) {
    uint64_t target_size = ioptions.cf_paths[p].target_size;
    if (target_size > file_size &&
        accumulated_size + (target_size - file_size) > future_size) {
      return p;
    }
    accumulated_size += target_size;
  }
  return p;
}

//
// Consider compaction files based on their size differences with
// the next file in time order.
//
Compaction* UniversalCompactionBuilder::PickCompactionToReduceSortedRuns(
    unsigned int ratio, unsigned int max_number_of_files_to_compact) {
  unsigned int min_merge_width =
      mutable_cf_options_.compaction_options_universal.min_merge_width;
  unsigned int max_merge_width =
      mutable_cf_options_.compaction_options_universal.max_merge_width;

  const SortedRun* sr = nullptr;
  bool done = false;
  size_t start_index = 0;
  unsigned int candidate_count = 0;

  unsigned int max_files_to_compact =
      std::min(max_merge_width, max_number_of_files_to_compact);
  min_merge_width = std::max(min_merge_width, 2U);

  // Caller checks the size before executing this function. This invariant is
  // important because otherwise we may have a possible integer underflow when
  // dealing with unsigned types.
  assert(sorted_runs_.size() > 0);

  // Considers a candidate file only if it is smaller than the
  // total size accumulated so far.
  for (size_t loop = 0; loop < sorted_runs_.size(); loop++) {
    candidate_count = 0;

    // Skip files that are already being compacted
    for (sr = nullptr; loop < sorted_runs_.size(); loop++) {
      sr = &sorted_runs_[loop];

      if (!sr->being_compacted) {
        candidate_count = 1;
        break;
      }
      char file_num_buf[kFormatFileNumberBufSize];
      sr->Dump(file_num_buf, sizeof(file_num_buf));
      ROCKS_LOG_BUFFER(log_buffer_,
                       "[%s] Universal: %s"
                       "[%d] being compacted, skipping",
                       cf_name_.c_str(), file_num_buf, loop);

      sr = nullptr;
    }

    // This file is not being compacted. Consider it as the
    // first candidate to be compacted.
    uint64_t candidate_size = sr != nullptr ? sr->compensated_file_size : 0;
    if (sr != nullptr) {
      char file_num_buf[kFormatFileNumberBufSize];
      sr->Dump(file_num_buf, sizeof(file_num_buf), true);
      ROCKS_LOG_BUFFER(log_buffer_,
                       "[%s] Universal: Possible candidate %s[%d].",
                       cf_name_.c_str(), file_num_buf, loop);
    }

    // Check if the succeeding files need compaction.
    for (size_t i = loop + 1;
         candidate_count < max_files_to_compact && i < sorted_runs_.size();
         i++) {
      const SortedRun* succeeding_sr = &sorted_runs_[i];
      if (succeeding_sr->being_compacted) {
        break;
      }
      // Pick files if the total/last candidate file size (increased by the
      // specified ratio) is still larger than the next candidate file.
      // candidate_size is the total size of files picked so far with the
      // default kCompactionStopStyleTotalSize; with
      // kCompactionStopStyleSimilarSize, it's simply the size of the last
      // picked file.
      double sz = candidate_size * (100.0 + ratio) / 100.0;
      if (sz < static_cast<double>(succeeding_sr->size)) {
        break;
      }
      if (mutable_cf_options_.compaction_options_universal.stop_style ==
          kCompactionStopStyleSimilarSize) {
        // Similar-size stopping rule: also check the last picked file isn't
        // far larger than the next candidate file.
        sz = (succeeding_sr->size * (100.0 + ratio)) / 100.0;
        if (sz < static_cast<double>(candidate_size)) {
          // If the small file we've encountered begins a run of similar-size
          // files, we'll pick them up on a future iteration of the outer
          // loop. If it's some lonely straggler, it'll eventually get picked
          // by the last-resort read amp strategy which disregards size ratios.
          break;
        }
        candidate_size = succeeding_sr->compensated_file_size;
      } else {  // default kCompactionStopStyleTotalSize
        candidate_size += succeeding_sr->compensated_file_size;
      }
      candidate_count++;
    }

    // Found a series of consecutive files that need compaction.
    if (candidate_count >= (unsigned int)min_merge_width) {
      start_index = loop;
      done = true;
      break;
    } else {
      for (size_t i = loop;
           i < loop + candidate_count && i < sorted_runs_.size(); i++) {
        const SortedRun* skipping_sr = &sorted_runs_[i];
        char file_num_buf[256];
        skipping_sr->DumpSizeInfo(file_num_buf, sizeof(file_num_buf), loop);
        ROCKS_LOG_BUFFER(log_buffer_, "[%s] Universal: Skipping %s",
                         cf_name_.c_str(), file_num_buf);
      }
    }
  }
  if (!done || candidate_count <= 1) {
    return nullptr;
  }
  size_t first_index_after = start_index + candidate_count;
  // Compression is enabled if files compacted earlier already reached
  // size ratio of compression.
  bool enable_compression = true;
  int ratio_to_compress =
      mutable_cf_options_.compaction_options_universal.compression_size_percent;
  if (ratio_to_compress >= 0) {
    uint64_t total_size = 0;
    for (auto& sorted_run : sorted_runs_) {
      total_size += sorted_run.compensated_file_size;
    }

    uint64_t older_file_size = 0;
    for (size_t i = sorted_runs_.size() - 1; i >= first_index_after; i--) {
      older_file_size += sorted_runs_[i].size;
      if (older_file_size * 100L >= total_size * (long)ratio_to_compress) {
        enable_compression = false;
        break;
      }
    }
  }

  uint64_t estimated_total_size = 0;
  for (unsigned int i = 0; i < first_index_after; i++) {
    estimated_total_size += sorted_runs_[i].size;
  }
  uint32_t path_id =
      GetPathId(ioptions_, mutable_cf_options_, estimated_total_size);
  int start_level = sorted_runs_[start_index].level;
  int output_level;
  if (first_index_after == sorted_runs_.size()) {
    output_level = vstorage_->num_levels() - 1;
  } else if (sorted_runs_[first_index_after].level == 0) {
    output_level = 0;
  } else {
    output_level = sorted_runs_[first_index_after].level - 1;
  }

  // last level is reserved for the files ingested behind
  if (ioptions_.allow_ingest_behind &&
      (output_level == vstorage_->num_levels() - 1)) {
    assert(output_level > 1);
    output_level--;
  }

  std::vector<CompactionInputFiles> inputs(vstorage_->num_levels());
  for (size_t i = 0; i < inputs.size(); ++i) {
    inputs[i].level = start_level + static_cast<int>(i);
  }
  for (size_t i = start_index; i < first_index_after; i++) {
    auto& picking_sr = sorted_runs_[i];
    if (picking_sr.level == 0) {
      FileMetaData* picking_file = picking_sr.file;
      inputs[0].files.push_back(picking_file);
    } else {
      auto& files = inputs[picking_sr.level - start_level].files;
      for (auto* f : vstorage_->LevelFiles(picking_sr.level)) {
        files.push_back(f);
      }
    }
    char file_num_buf[256];
    picking_sr.DumpSizeInfo(file_num_buf, sizeof(file_num_buf), i);
    ROCKS_LOG_BUFFER(log_buffer_, "[%s] Universal: Picking %s",
                     cf_name_.c_str(), file_num_buf);
  }

  CompactionReason compaction_reason;
  if (max_number_of_files_to_compact == UINT_MAX) {
    compaction_reason = CompactionReason::kUniversalSizeRatio;
  } else {
    compaction_reason = CompactionReason::kUniversalSortedRunNum;
  }
  return new Compaction(
      vstorage_, ioptions_, mutable_cf_options_, std::move(inputs),
      output_level,
      MaxFileSizeForLevel(mutable_cf_options_, output_level,
                          kCompactionStyleUniversal),
      LLONG_MAX, path_id,
      GetCompressionType(ioptions_, vstorage_, mutable_cf_options_, start_level,
                         1, enable_compression),
      GetCompressionOptions(mutable_cf_options_, vstorage_, start_level,
                            enable_compression),
      /* max_subcompactions */ 0, /* grandparents */ {}, /* is manual */ false,
      score_, false /* deletion_compaction */, compaction_reason);
}

// Look at overall size amplification. If size amplification
// exceeeds the configured value, then do a compaction
// of the candidate files all the way upto the earliest
// base file (overrides configured values of file-size ratios,
// min_merge_width and max_merge_width).
//
Compaction* UniversalCompactionBuilder::PickCompactionToReduceSizeAmp() {
  // percentage flexibility while reducing size amplification
  uint64_t ratio = mutable_cf_options_.compaction_options_universal
                       .max_size_amplification_percent;

  unsigned int candidate_count = 0;
  uint64_t candidate_size = 0;
  size_t start_index = 0;
  const SortedRun* sr = nullptr;

  assert(!sorted_runs_.empty());
  if (sorted_runs_.back().being_compacted) {
    return nullptr;
  }

  // Skip files that are already being compacted
  for (size_t loop = 0; loop < sorted_runs_.size() - 1; loop++) {
    sr = &sorted_runs_[loop];
    if (!sr->being_compacted) {
      start_index = loop;  // Consider this as the first candidate.
      break;
    }
    char file_num_buf[kFormatFileNumberBufSize];
    sr->Dump(file_num_buf, sizeof(file_num_buf), true);
    ROCKS_LOG_BUFFER(log_buffer_,
                     "[%s] Universal: skipping %s[%d] compacted %s",
                     cf_name_.c_str(), file_num_buf, loop,
                     " cannot be a candidate to reduce size amp.\n");
    sr = nullptr;
  }

  if (sr == nullptr) {
    return nullptr;  // no candidate files
  }
  {
    char file_num_buf[kFormatFileNumberBufSize];
    sr->Dump(file_num_buf, sizeof(file_num_buf), true);
    ROCKS_LOG_BUFFER(
        log_buffer_,
        "[%s] Universal: First candidate %s[%" ROCKSDB_PRIszt "] %s",
        cf_name_.c_str(), file_num_buf, start_index, " to reduce size amp.\n");
  }

  // keep adding up all the remaining files
  for (size_t loop = start_index; loop < sorted_runs_.size() - 1; loop++) {
    sr = &sorted_runs_[loop];
    if (sr->being_compacted) {
      char file_num_buf[kFormatFileNumberBufSize];
      sr->Dump(file_num_buf, sizeof(file_num_buf), true);
      ROCKS_LOG_BUFFER(
          log_buffer_, "[%s] Universal: Possible candidate %s[%d] %s",
          cf_name_.c_str(), file_num_buf, start_index,
          " is already being compacted. No size amp reduction possible.\n");
      return nullptr;
    }
    candidate_size += sr->compensated_file_size;
    candidate_count++;
  }
  if (candidate_count == 0) {
    return nullptr;
  }

  // size of earliest file
  uint64_t earliest_file_size = sorted_runs_.back().size;

  // size amplification = percentage of additional size
  if (candidate_size * 100 < ratio * earliest_file_size) {
    ROCKS_LOG_BUFFER(
        log_buffer_,
        "[%s] Universal: size amp not needed. newer-files-total-size %" PRIu64
        " earliest-file-size %" PRIu64,
        cf_name_.c_str(), candidate_size, earliest_file_size);
    return nullptr;
  } else {
    ROCKS_LOG_BUFFER(
        log_buffer_,
        "[%s] Universal: size amp needed. newer-files-total-size %" PRIu64
        " earliest-file-size %" PRIu64,
        cf_name_.c_str(), candidate_size, earliest_file_size);
  }
  return PickCompactionToOldest(start_index,
                                CompactionReason::kUniversalSizeAmplification);
}

// Pick files marked for compaction. Typically, files are marked by
// CompactOnDeleteCollector due to the presence of tombstones.
Compaction* UniversalCompactionBuilder::PickDeleteTriggeredCompaction() {
  CompactionInputFiles start_level_inputs;
  int output_level;
  std::vector<CompactionInputFiles> inputs;

  if (vstorage_->num_levels() == 1) {
#if defined(ENABLE_SINGLE_LEVEL_DTC)
    // This is single level universal. Since we're basically trying to reclaim
    // space by processing files marked for compaction due to high tombstone
    // density, let's do the same thing as compaction to reduce size amp which
    // has the same goals.
    bool compact = false;

    start_level_inputs.level = 0;
    start_level_inputs.files.clear();
    output_level = 0;
    for (FileMetaData* f : vstorage_->LevelFiles(0)) {
      if (f->marked_for_compaction) {
        compact = true;
      }
      if (compact) {
        start_level_inputs.files.push_back(f);
      }
    }
    if (start_level_inputs.size() <= 1) {
      // If only the last file in L0 is marked for compaction, ignore it
      return nullptr;
    }
    inputs.push_back(start_level_inputs);
#else
    // Disable due to a known race condition.
    // TODO: Reenable once the race condition is fixed
    return nullptr;
#endif  // ENABLE_SINGLE_LEVEL_DTC
  } else {
    int start_level;

    // For multi-level universal, the strategy is to make this look more like
    // leveled. We pick one of the files marked for compaction and compact with
    // overlapping files in the adjacent level.
    picker_->PickFilesMarkedForCompaction(cf_name_, vstorage_, &start_level,
                                          &output_level, &start_level_inputs);
    if (start_level_inputs.empty()) {
      return nullptr;
    }

    // Pick the first non-empty level after the start_level
    for (output_level = start_level + 1; output_level < vstorage_->num_levels();
         output_level++) {
      if (vstorage_->NumLevelFiles(output_level) != 0) {
        break;
      }
    }

    // If all higher levels are empty, pick the highest level as output level
    if (output_level == vstorage_->num_levels()) {
      if (start_level == 0) {
        output_level = vstorage_->num_levels() - 1;
      } else {
        // If start level is non-zero and all higher levels are empty, this
        // compaction will translate into a trivial move. Since the idea is
        // to reclaim space and trivial move doesn't help with that, we
        // skip compaction in this case and return nullptr
        return nullptr;
      }
    }
    if (ioptions_.allow_ingest_behind &&
        output_level == vstorage_->num_levels() - 1) {
      assert(output_level > 1);
      output_level--;
    }

    if (output_level != 0) {
      if (start_level == 0) {
        if (!picker_->GetOverlappingL0Files(vstorage_, &start_level_inputs,
                                            output_level, nullptr)) {
          return nullptr;
        }
      }

      CompactionInputFiles output_level_inputs;
      int parent_index = -1;

      output_level_inputs.level = output_level;
      if (!picker_->SetupOtherInputs(cf_name_, mutable_cf_options_, vstorage_,
                                     &start_level_inputs, &output_level_inputs,
                                     &parent_index, -1)) {
        return nullptr;
      }
      inputs.push_back(start_level_inputs);
      if (!output_level_inputs.empty()) {
        inputs.push_back(output_level_inputs);
      }
      if (picker_->FilesRangeOverlapWithCompaction(inputs, output_level)) {
        return nullptr;
      }
    } else {
      inputs.push_back(start_level_inputs);
    }
  }

  uint64_t estimated_total_size = 0;
  // Use size of the output level as estimated file size
  for (FileMetaData* f : vstorage_->LevelFiles(output_level)) {
    estimated_total_size += f->fd.GetFileSize();
  }
  uint32_t path_id =
      GetPathId(ioptions_, mutable_cf_options_, estimated_total_size);
  return new Compaction(
      vstorage_, ioptions_, mutable_cf_options_, std::move(inputs),
      output_level,
      MaxFileSizeForLevel(mutable_cf_options_, output_level,
                          kCompactionStyleUniversal),
      /* max_grandparent_overlap_bytes */ LLONG_MAX, path_id,
      GetCompressionType(ioptions_, vstorage_, mutable_cf_options_,
                         output_level, 1),
      GetCompressionOptions(mutable_cf_options_, vstorage_, output_level),
      /* max_subcompactions */ 0, /* grandparents */ {}, /* is manual */ false,
      score_, false /* deletion_compaction */,
      CompactionReason::kFilesMarkedForCompaction);
}

Compaction* UniversalCompactionBuilder::PickCompactionToOldest(
    size_t start_index, CompactionReason compaction_reason) {
  assert(start_index < sorted_runs_.size());

  // Estimate total file size
  uint64_t estimated_total_size = 0;
  for (size_t loop = start_index; loop < sorted_runs_.size(); loop++) {
    estimated_total_size += sorted_runs_[loop].size;
  }
  uint32_t path_id =
      GetPathId(ioptions_, mutable_cf_options_, estimated_total_size);
  int start_level = sorted_runs_[start_index].level;

  std::vector<CompactionInputFiles> inputs(vstorage_->num_levels());
  for (size_t i = 0; i < inputs.size(); ++i) {
    inputs[i].level = start_level + static_cast<int>(i);
  }
  for (size_t loop = start_index; loop < sorted_runs_.size(); loop++) {
    auto& picking_sr = sorted_runs_[loop];
    if (picking_sr.level == 0) {
      FileMetaData* f = picking_sr.file;
      inputs[0].files.push_back(f);
    } else {
      auto& files = inputs[picking_sr.level - start_level].files;
      for (auto* f : vstorage_->LevelFiles(picking_sr.level)) {
        files.push_back(f);
      }
    }
    std::string comp_reason_print_string;
    if (compaction_reason == CompactionReason::kPeriodicCompaction) {
      comp_reason_print_string = "periodic compaction";
    } else if (compaction_reason ==
               CompactionReason::kUniversalSizeAmplification) {
      comp_reason_print_string = "size amp";
    } else {
      assert(false);
    }

    char file_num_buf[256];
    picking_sr.DumpSizeInfo(file_num_buf, sizeof(file_num_buf), loop);
    ROCKS_LOG_BUFFER(log_buffer_, "[%s] Universal: %s picking %s",
                     cf_name_.c_str(), comp_reason_print_string.c_str(),
                     file_num_buf);
  }

  // output files at the bottom most level, unless it's reserved
  int output_level = vstorage_->num_levels() - 1;
  // last level is reserved for the files ingested behind
  if (ioptions_.allow_ingest_behind) {
    assert(output_level > 1);
    output_level--;
  }

  // We never check size for
  // compaction_options_universal.compression_size_percent,
  // because we always compact all the files, so always compress.
  return new Compaction(
      vstorage_, ioptions_, mutable_cf_options_, std::move(inputs),
      output_level,
      MaxFileSizeForLevel(mutable_cf_options_, output_level,
                          kCompactionStyleUniversal),
      LLONG_MAX, path_id,
      GetCompressionType(ioptions_, vstorage_, mutable_cf_options_, start_level,
                         1, true /* enable_compression */),
      GetCompressionOptions(mutable_cf_options_, vstorage_, start_level,
                            true /* enable_compression */),
      /* max_subcompactions */ 0, /* grandparents */ {}, /* is manual */ false,
      score_, false /* deletion_compaction */, compaction_reason);
}

Compaction* UniversalCompactionBuilder::PickPeriodicCompaction() {
  ROCKS_LOG_BUFFER(log_buffer_, "[%s] Universal: Periodic Compaction",
                   cf_name_.c_str());

  // In universal compaction, sorted runs contain older data are almost always
  // generated earlier too. To simplify the problem, we just try to trigger
  // a full compaction. We start from the oldest sorted run and include
  // all sorted runs, until we hit a sorted already being compacted.
  // Since usually the largest (which is usually the oldest) sorted run is
  // included anyway, doing a full compaction won't increase write
  // amplification much.

  // Get some information from marked files to check whether a file is
  // included in the compaction.

  size_t start_index = sorted_runs_.size();
  while (start_index > 0 && !sorted_runs_[start_index - 1].being_compacted) {
    start_index--;
  }
  if (start_index == sorted_runs_.size()) {
    return nullptr;
  }

  // There is a rare corner case where we can't pick up all the files
  // because some files are being compacted and we end up with picking files
  // but none of them need periodic compaction. Unless we simply recompact
  // the last sorted run (either the last level or last L0 file), we would just
  // execute the compaction, in order to simplify  the logic.
  if (start_index == sorted_runs_.size() - 1) {
    bool included_file_marked = false;
    int start_level = sorted_runs_[start_index].level;
    FileMetaData* start_file = sorted_runs_[start_index].file;
    for (const std::pair<int, FileMetaData*>& level_file_pair :
         vstorage_->FilesMarkedForPeriodicCompaction()) {
      if (start_level != 0) {
        // Last sorted run is a level
        if (start_level == level_file_pair.first) {
          included_file_marked = true;
          break;
        }
      } else {
        // Last sorted run is a L0 file.
        if (start_file == level_file_pair.second) {
          included_file_marked = true;
          break;
        }
      }
    }
    if (!included_file_marked) {
      ROCKS_LOG_BUFFER(log_buffer_,
                       "[%s] Universal: Cannot form a compaction covering file "
                       "marked for periodic compaction",
                       cf_name_.c_str());
      return nullptr;
    }
  }

  Compaction* c = PickCompactionToOldest(start_index,
                                         CompactionReason::kPeriodicCompaction);

  TEST_SYNC_POINT_CALLBACK(
      "UniversalCompactionPicker::PickPeriodicCompaction:Return", c);

  return c;
}
}  // namespace ROCKSDB_NAMESPACE

#endif  // !ROCKSDB_LITE

redpajama_set_name: RedPajamaGithub


text:
See the future of travel
Travel technology is one of the fastest growing sectors in the world, and The Travel Tech Show at WTM Africa provides the perfect platform for suppliers to meet with key decision makers across the world looking to source technology systems.
Following a hugely successful event in 2019, there will once again be a number of dedicated travel technology seminars taking place in the Travel Technology Theatre in 2020. The seminar content will be delivered by experts covering topics such as blogging, social media, mobile, tech and hospitality technology.
Increase your business with the help of new technologies, the travel trade community that visits WTM Africa will find top quality exhibitors with the latest trends in technology for tourism, while watching dedicated technology sessions in the Travel Tech Theatre.
The Travel Tech Show sessions focus on topics pertinent to technology and its influence on the industry.
Acknowledged for its high calibre of speakers, the Travel Tech Show at WTM Africa features an impressive programme of events in a dedicated area which will cover the latest trends and innovations in the travel technology and digital space.
Highlights across the three days include programmes in Blogging.
Mobile, Social Media Technology and Hospitality Technology.
Travel Technology is the fastest growing region on record.
Are you a technology supplier?
WTM Africa witnessed a 15% increase in visitors last year, and this dedicated area on the showfloor brought a new experience for visitors and gave exhibitors a great opportunity to promote their technology products.
How can technology help you?
The travel trade community that visits WTM Africa will find the latest trends in technology for tourism, while watching dedicated technology sessions in the Travel Tech Theatre.
Find new technologies

redpajama_set_name: RedPajamaCommonCrawl


Deb created her famous carrot cake in 1984, baked out of her garage (turned into a kitchen) until opening Carrot Tree Kitchen in 1995.
They converted an old motel into a restaurant and bakery.
They offer a creative menu for both breakfast and lunch.
Debbie and I stopped for lunch. Debbie had the (L'Hermione) their famous honey pecan chicken salad with mixed greens in a tortilla. I enjoyed the (Debi's Turkey Club Summer Salad) a combination of diced turkey, crisp bacon, Swiss cheese, grape tomatoes, cucumbers, carrots, on tender mixed greens with a delicious deviled egg. The make a Honey Cider dressing that is outstanding.
Their bakery is another story, what a great job they do with it. Check out Bread Crumbs to hear and see more about the bakery.


Boston Insurance Brokerage, Inc. (BIB) is a premier national wholesale commercial brokerage firm. With offices in Boston and Denver, our production base includes hundreds of producers with the access and expertise to write business nationwide. Divisions are broken down into four specialized areas: Property/Casualty & Environmental, Healthcare & Professional Liability, Workers Compensation and Executive & Professional Liability.
Revenue Architects provides embedded fractional inbound and integrated marketing services for BIB. We develop strategies, manage systems – including marketing automation and CRM and we design and run campaigns and programs for lead generation.


text:
Unsworth LaPlante, PLLC
Vermont Estate Planning Attorneys
Vermont: (802) 879-7133
Attend A Free Webinar
White River Junction
Free Estate Planning Worksheet
FAQs for Families Without an Estate Plan
Medicaid Resources
Medicaid Analysis Worksheet
Medicaid Guide
Vermont Medicaid
Advanced Estate Planning
Basic Estate Planning
Estate Planning for Niches
Home » Law in the U.S. can be Participatory
Law in the U.S. can be Participatory
November 7, 2017 by Stephen Hartnett
Blog Author: Stephen C. Hartnett, J.D., LL.M. (Tax), Director of Education,
American Academy of Estate Planning Attorneys, Inc.
In some countries, like a dictatorship or a true monarchy (not a constitutional monarchy such as the United Kingdom), people do not really participate in making the law. The law is handed down by fiat. In the United States, our laws are enacted by our elected representatives. Sometimes, those laws may be viewed as violating the fundamental rights guaranteed to all of us by our Constitution. That's when the judiciary may be asked to step in to make an impartial determination as to whether the law violates the fundamental rights embodied by our Constitution. In our system, anyone who is truly harmed by a law may challenge its constitutionality. They can do this by challenging the application of the law in court. Here's a quick story of how one person participated in changing the law in the United States.
Edith Windsor married her longtime partner, Dr. Thea Spyer, in 2007. Later, when Dr. Spyer died in 2009, the estate filed a federal estate tax return, claiming a marital deduction for the assets going to Ms. Windsor, her spouse under New York law. The IRS denied the deduction based on the Defense of Marriage Act (DOMA), which prohibited the federal government from recognizing same-sex marriages, even those recognized by a state. The IRS disallowed the marital deduction for assets going to Windsor and claimed, as a result, the estate owed more than $363,000 in federal estate taxes. The estate paid the amount owed and sued for a refund in federal district court, challenging the IRS' denial of the marital deduction. (Often taxpayers pay a disputed tax and then file suit in federal district court rather than not paying and challenging the amount due in the U.S. Tax Court, which is often viewed as a less favorable venue.) She won at the federal district court. The case was appealed to the U.S. Court of Appeals, which affirmed the decision of the district court. Finally, the case ended up at the U.S. Supreme Court, which affirmed the decision of the lower courts.
The U.S. Supreme Court held DOMA was unconstitutional insofar as it denied a benefit (a deduction) to same-sex married couples while granting the same benefit to similarly situated heterosexual couples. Based on the decision in U.S. v. Windsor, same-sex married couples gained equality of treatment under the law by the federal government. The Court did not determine whether same-sex couples had a constitutional right to marry, though they would reach that determination two years later in another case, Obergefell v. Hodges, which built on the Windsor decision.
Ms. Windsor, who demonstrated how an individual in our country can participate in making and shaping the law, died recently. Here is a link to an article in the New York Times about her life and death.
Stephen Hartnett
Stephen is a member of the American Academy of Estate Planning Attorneys (AAEPA), a national organization serving the needs of legal professionals concentrating on estate planning. He was on the national Board of Governors for the AAEPA and is the only AAEPA member in Vermont.
His mission is to provide quality estate planning services, including assistance with Living Trusts, Wills, Medicaid Planning, Probate, Trust Administration, Powers of Attorney, Special Needs Planning, and Family Limited Partnerships.
Latest posts by Stephen Hartnett (see all)
2021 Estate Planning Survey Yields Interesting Results - April 16, 2021
Biden Would Like to Reform Social Security - April 9, 2021
Dynasty Trusts - March 26, 2021
Filed Under: Estate Planning, Legal Education
It's Better to Give Than to Receive
Five Important Facts About IRA Estate Planning
Tax Planning for 2022
It Can Be Scary to Die Without an Estate Plan…the HORRORS of Intestacy
Neither Age Nor Health Determines Whether You Need an Estate Plan
IRS Announces Adjusted 2022 Estate Tax Exclusion
Elder Law and Medicaid Planning Attorneys
Unsworth LaPlante, PLC
DOWNLOAD OUR FREE ESTATE PLANNING WORKSHEET
26 Railroad Ave
Essex Junction, VT 05452
The information on this Vermont Attorneys & Lawyers / Law Firm website is for general information purposes only. Nothing on this or associated pages, documents, comments, answers, emails, or other communications should be taken as legal advice for any individual case or situation. This information on this website is not intended to create, and receipt or viewing of this information does not constitute, an attorney-client relationship.
American Academy of Estate Planning Attorneys, Inc. Privacy Policy | Contact Us | Disclaimer | Site Map | Powered by American Academy of Estate Planning Attorneys
© 2022 American Academy of Estate Planning Attorneys, Inc.


I was born in Colombia, educated in Barcelona and fine-tuned in London. It's given me international perspective with a European eye for aesthetic, mixed with the eccentricity and wit and all that's exceptional about creativity in the U.K. After finishing studies at Idep Barcelona, I set up my own agency, La Casa de Carlota, that pioneered in engaging designers with Downs Syndrome to work with clients like The Barcelona Council, La Caixa and Nestlé. La Casa now continues working from their original studio in Barcelona with satellite studios across South America.
My journey took me to London, where I could continue to elevate my craft. Working at The Partners for just over three years, on clients as diverse as Ferrari to Nespresso and UBS to Scarosso, has given me the precision and confidence in executing work which delivers on a strategic and visual level.
Experiencing the world from so many places and perspectives gives me the freedom and confidence to express this sensitively through my work. Seeing the world differently means I design differently.


Throughout this series of I'm a Celebrity... Get Me Out Of Here! I have been obsessed with soapstar Sair Khan's incredibly expressive face.
Despite being one of the quieter ones, her face always seems to have something to say. And whatever the task is, there's one particular expression she always seems to find time to pull.
I don't blame her - this is the look I have when navigating my whole life. Which one of these will I be today?
This has been made with respect, not malice.
To tell everyone how much you hated this, or maybe start a race-war, why not leave a comment?


I'm marching for science, are you? | Judy Keen, Ph.D.
The March for Science is this Saturday. Are you marching? I am, and here are my reasons.
Blog piece posted in Global Health Now Newsletter from the Johns Hopkins Bloomberg School of Public Health.


Being a doctor requires you intensive skills to keep a patient. It is indeed a crucial work, where you have to carefully watch, listen, and observe whatever your patient is going through to cure the disease, or lessen the pain, or to keep it simple, keeping your patient healthy.
Analysing one's health always starts with proper diagnosis. Be it on the skin, the muscle, or the whole physical body itself. To know what's going on with your patient requires you to take a deep view of what is going on your patient's body. Auscultation is just a part.
Auscultation, like any other kind of diagnosis, is critical. As a doctor, you should be able to perform accurate and precise auscultation to deliver better results. Proper equipment is essential with accurate auscultation. A good stethoscope will deliver you better performance. ADC Adscope 609ST stethoscope is one of the best stethoscopes in the market. Read more to know more about ADC Adscope 609ST stethoscope.
The ADC Adscope 609ST stethoscope is one of the most affordable and durable stethoscope available in the market. This stethoscope is ultra lightweight, and is designed to provide accurate response among patients.
ADC Adscope 609ST stethoscope features a dual head, a combination diaphragm and bell adult chestpiece, an extra 1.38 inch bell, a highly sensitive 1.75 inch diaphragm, a non-chill bell and diaphragm retaining ring, a clinical headset with reinforcing yoke moulded to tubing, a flexible 22 inch PVC tubing, a lightweight aluminium binaurals with satin finish, an Adsoft Plus snap on silicone ear tips, and a spare of Adsoft ear tips. This stethoscope is considered 100% latex free. Its total weight is 3.5 oz and its length is about 31 inches. This stethoscope is inspected, and packaged in United States of America. As per purchase, you will be given a five (5) year warranty.
This product is perfect for doctors and nurses who wanted to have a light stethoscope to use, while able to perform accurate auscultation. Also, to doctors and nurses who wanted to have the comfort upon auscultation.
In every product, there is always the good side, from which, customers came to appreciate. In this article, let there be an unbiased delivery of what this product can do and what to expect about this product. Let yourself have an insight of the plus you get upon purchasing ADC Adscope 609ST stethoscope.
ADC Adscope 609ST stethoscope is affordable. That's a big plus-plus to every doctors and nurses who wanted to purchase a stethoscope. Most sellers online sell ADC Adscope 609ST stethoscope for only $21.82 completed with freebies.
Also, this stethoscope is lightweight, so you can bring it anywhere. Having it so light can lessen the stress of bringing your stethoscope to literally, anywhere you go. You can keep this equipment for emergencies and rainy days.
This stethoscope is pretty sturdy and durable for its price, it is like a cheaper Littman's, as stated by Freddy Pacheco (2012), who had made a purchased in year 2012 on Amazon.
Most of the customers who bought this product claimed that the sound quality is audible – some even stated that this stethoscope provided better heart sounds. Karen Bribriesca (2014) had made a purchase of this stethoscope as well, on Amazon. She claimed that the sound quality is good, after giving this stethoscope to one of her students who came running into her telling her that he/she can hear so well. Karen even stated that ADC have good quality stethoscopes.
Medic (2014) even compared the quality of ADC Adscope 609ST stethoscope to Littman's. He happened to purchase quite expensive stethoscopes throughout his practice, believing that, expensive stethoscopes will provide him accurate auscultations. But, due to some instances, he came to purchase ADC Adscope 609ST Stethoscope and put it into use. To his surprise, this stethoscope delivered him high quality heart sounds, as to what he claim, almost similar to the quality of sounds delivered by Littman's.
Cly (2014), is another satisfied customer upon purchase of ADC Adscope 609ST stethoscope. He was in need of a replacement for his Littman classic 2 SE, so he came to decide to purchase a stethoscope from ADC, as it only requires a small amount of money to purchase one. Upon using the stethoscope, he was very astounded to hear good quality heart sounds. And from that, he considered this stethoscope as good replacement for Littman's.
Nicole Heinz (2014) came to appreciate ADC Adscope 609ST stethoscope a lot. She was always complimented of how sleek it looks, and of course, of the quality of her auscultations. She was a very proud user of this stethoscope. She can hear clear and loud heart sounds.
After all this sunshine reviews, let's get into the downside of this product. You might now be expecting too much, so let's discuss what others think of this stethoscope as well.
Some commented that the ADC Adscope 609ST stethoscope is too short for them to use. They claim that it is not too lengthy, and that they are sometimes having a hard time in performing auscultations due to its length.
Junior 5 (2011), who happened to make a purchase of this stethoscope, was not that all giddy upon setting this stethoscope in the field. He claimed that ADC Adscope 609ST stethoscope does not deliver clear heart sounds. From that experience, he stated, this stethoscope is not good for beginners; beginners should opt to buy a more sensitive stethoscope.
Richard Arms (2011) was not that satisfied with this stethoscope and had given it a rating of three (3) stars. He claimed that this stethoscope definitely looks good, and does well in auscultations indoor. But, when used in emergency situations, like using it on an ambulance, he claimed that this stethoscope is pretty much a junk. He does recommend this stethoscope to students, but not to his fellow EMT.
Jannet (2014), bought this stethoscope for veterinary use. She claimed that ADC Adscope 609ST stethoscope does deliver good heart sounds when she uses it to listen to her heart. But when she uses it to perform auscultations on dogs and cats, the stethoscope cannot deliver better sounds. She then came up with not recommending this stethoscope to her fellow veterinarians.
The ADC Adscope 609ST stethoscope is a great choice if you happen to be an experienced nurse or physician who wanted to save money and do not want to invest too much in purchasing a stethoscope. Yes, experienced nurse or physician. Also, this is a great deal to nurses and physicians who wanted to have a lightweight stethoscope.
The ADC Adscope 609ST stethoscope was recommended for human auscultations. So if you happen to be a veterinarian, this stethoscope is not a good one for you. The ADC Adscope 609ST stethoscope performs better when performing auscultations in humans.
In making a purchase, the deal is always up to you. You can try ADC Adscope 609ST stethoscope to experience the stethoscope first hand. Yes, you can still rely on other people's review upon deciding what to buy. But, the experience of using the stethoscope weights up technically everything.


Storyteller, i think we have another promising poet here. The picture of the poet walking on the street and the bikers shooting off etc. are quite good.
However, there is still something tentative, something loose with the expressions. They should improve with more practice.
Yes, I agree we very definitely have a promising poet here who writes good, strong poetry. I especially like Amongst the Velvet with its imagery drawn from "this little town in the hills" that's both so evocative of Aizawl and yet so universal.


text:
Here's how the major college cheating scheme actually worked
in: Finance
Federal prosecutors charged dozens of people on Tuesday in a giant college entrance scandal in which wealthy parents, including some high-profile actresses and a slew of business executives, paid bribes and worked with cooperating witnesses to get their children into top colleges across the U.S.
The sprawling investigation made airwaves across the country, as people reacted with shock to the news of some of the countries wealthiest citizens were allegedly buying positions for their kids and consequently cheating other qualified students out of the running.
Justice Department officials said at a news conference in Boston on Tuesday that it's the biggest college entrance scandal it has ever prosecuted.
Among those charged with fraud are actresses Felicity Huffman, who starred in ABC's "Desperate Housewives," and Lori Loughlin, who appeared in ABC's "Full House," as well as business executives like Douglas Hodge, a former CEO of Pimco investment management company, and Manuel Henriquez, chairman and CEO of Hercules Technology Growth Capital, whose stock price fell more than 9 percent Tuesday afternoon.
The indictment said that in most instances, students and children were unaware of the bribes and fraudulent activity of their parents, such as doctoring exam scores and creating fake resumes and profiles to up their chances of getting into school. Prosecutors did not charge any students or colleges.
Here's some key points to how it all went down.
Funneling bribe money into a 'charitable' account
The so-called ringleader of the scandal was William Singer, founder of a college preparatory business called the Edge College & Career Network, who was arrested for running the scheme using a fraudulent charity.
His business, also known as The Key, based in California, allegedly helped students cheat on SAT and ACT exams and helped parents bribe coaches at colleges and universities to take their kids without any athletic background.
Singer pleaded guilty Tuesday to four charges: racketeering conspiracy, money laundering conspiracy, conspiracy to defraud the U.S. and obstruction of justice.
According to court documents, those charged used the "facade of the charitable organization" to hide the nature and source of bribe payments. Since Singer's business The Key is a nonprofit, parents could allegedly wire money into a charitable account while avoiding federal taxes.
Between approximately 2011 and 2018, parents averaged $25 million in bribes to college administrators and coaches, the documents note, to designate their children as pretend recruited athletes or as members of other favored admissions categories, thus "facilitating the children's admission to those universities."
Photoshop to make nonathletic kids look athletic
Singer also helped parents submit false and manipulated information about their kids' athletic abilities, going so far as to Photoshop students' faces onto athletes' bodies found on the internet.
One parent submitted both her daughter's fake SAT score and a profile that falsely said she was a "3-year Varsity Letter winner" in water polo, along with an altered picture, according to the indictment. In another instance, parents paid Singer over $1 million to get their child into Yale with a lie that she was a captain of a soccer team.
In an email recorded in the court documents, Singer wrote: "This girl will be a midfielder and attending Yale so she has to be very good," requesting he get "a soccer pic probably Asian girl."
Parents also bribed athletic recruits. Loughlin allegedly "agreed to pay bribes totaling $500,000 in exchange for having their two daughters designated as recruits" to the University of Southern California's crew team.
Cheating on the SATs
Also part of the widespread scandal was indicted parents who helped their children do better on SAT and ACT standardized exams through several means.
These parents paid between $15,000 and $75,000 per test to exam administrators who gave students answers, corrected their work or let others pose for them, according to the indictment.
Huffman used the phrase "Ruh Ro!" after finding out that her daughter's school would be proctoring the SAT exam. Another parent, William McGlashan Jr., was instructed by Singer to claim his child had a learning disability in order to win him more time to take the exam alone.
According to the indictment, Singer told Gordon Caplan, a co-chairman of international law firm Willkie Farr, on the phone that he's essentially created a "side door" for wealthy families to get their kids into college, often without the kids ever knowing.
"There is a front door which means you get in on your own," Singer said. "The back door is through institutional advancement, which is 10 times as much money. And I've created this side door in."
"Nobody knows what happens," Singer said. "She feels great about herself. She got a test a score, and now you're actually capable for help getting into a school. Because the test score's no longer an issue. Does that make sense?"
Tags:actuallycheatingcollegemajorschemeworked
Previous : Principal reads kids bedtime stories on Facebook Live
Next : All-female Argentina tango festival calls for end to machismo | Argentina News
The Apollo 11 Mission Was Also a Global Media Sensation


text:
History: Russian
Causes of 5 Day War in 2008
Submitted by: arpone1960
Category: History: Russian
Date Submitted: 03/07/2014 01:05 PM
Causes of Five Day War in 2008 History Essay
In August of 2008, Georgia launched a full-scale military attack against South Ossetian region in an attempt to recover the lost territory. Georgia claimed they were responding to attacks on its peacekeepers in the villages of South Ossetia, and that Russia was advancing non-peacekeeping units in the territory. Russia Retaliated with an army and Airborne troops.
Russian side claims that these actions were necessary humanitarian intervention for peace enforcement. Russian, Ossetian and Abkhazian forces launched full scale assault on Georgian forces. After five days of heavy fighting, Georgian forces withdrew which allowed Russians to occupy the major Georgian cities. After the ceasefire, Russia pulled out its troops from Georgia while establishing major buffer zones around Abkhazia and South Ossetia. Russian forces remain posted in Abkhazia and South Ossetia under bilateral arrangements with the breakaway regions. The five day war was a true test for Georgia. This showed the country that taking back the breakaway regions and returning the thousands of internally displaced Georgians to their homes had become almost impossible. This war has long term effects on Georgia-Russia relations.
In this paper I look into the enduring ethnic divisions within Georgia; not only with Abkhazia and South Ossetia but the historical divisions between the regions and how these divisions have contributed into a divided mentality in the country. The age old ethnic and territorial divisions, the fall of the Soviet Union and Russia's constant interference in Georgia, will be researched as possible causes if continuous conflict between these groups. Russia's interference before and during the Soviet Union will be mentioned, for it holds great influence when it comes down to the relationship these ethnic groups have, and the territorial disputes that came from it. The war during 1991-1992 between Georgia and South Ossetia will be...
The Causes Of...
Causes Of World War One
Causes Of World War 2
Causes Of Civil War


Home / Development / The Big Question: What do game developers do on holiday, and how do they unwind?
The Big Question: What do game developers do on holiday, and how do they unwind?
It's July already, the days are long, occasionally sunny and Develop hits Brighton again – summertime is well and truly here. In the busy world of games development, how do studios kick back and unwind? We spoke to them to find out.
"As a game dev it's often frustrating not to be able to play all the games you want when they come out, so inevitably Easter and Christmas end up being a great time to catch up on games you missed.
Last year I managed to get to a conference somewhere new so we added on a few days holiday before the event. Not only was it an amazing opportunity to explore a new country and culture in advance but by the time everyone else arrived I already knew my way around, was relaxed and was ready to go!"
"As Snap Finger Click is still in its early days, I'm currently wearing a lot of hats! This means I haven't been able to get on holiday as much as I would like to. I haven't had a proper holiday for a couple of years now, but I do manage to get the odd weekend break. I'm originally from the Netherlands so I try to visit my family for a couple of days two or three times a year. I just got back from a recent trip, but I admit that the laptop came with me! Our new game,f It's Quiz Time, is out soon and I had a few things I needed to get done.
"The life of a game developer is a cycle of long hours and product launches, with not much room in the middle for relaxing. When you get a moment to disconnect you should do just that! I like to go to the countryside and coast, anywhere that gets me away from the office and stretching those tense muscles. My best ideas and clearest thoughts on where to take my business next have come from being removed from my usual surroundings, bring pen and paper with you for those lightbulb moments!"


text:
After Orlando, Why Didn't We Unite As One?
By Tom Hoopes, June 22, 2016
On January 7, 2015, terrorists shot and killed 12 people in Paris. The response in France was immediate and overwhelming. "Charlie Hebdo vigils: Across France, hundreds of thousands gather in a show of defiant solidarity," said a UK newspaper headline that very night.
On June 12, a shooter pledging allegiance to ISIS shot and killed 49 people in Orlando. "Thousands Attend Vigils Around US for Orlando Victims," reported ABC News on June 14.
France's hundreds of thousands vs. America's thousands. A worldwide rallying cry of "Je Suis Charlie" ("I am Charlie") in support of cartoonists vs. a heartfelt but fractured show of support for victims in an American city.
Don't get me wrong. There were beautiful examples of people reaching out to comfort and serve the victims and their families after Orlando. There were the lines of people giving blood. There was the JetBlue plane where strangers reached out to a grandma. There were worldwide vigils.
But our numbers were uninspiring: Thousands in New York and Los Angeles. Hundreds in Vermont. "More than two dozen" in Georgia. In Hawaii, "nearly 200."
Why didn't we unite as one? Why didn't we hang up signs that say "God bless America"? I don't mean "why didn't the bad people do this?" I mean why didn't you, and why didn't I?
Ironically, at the very moment when America most needs tolerance, non-judgmentalism and unity we are at our most intolerant, most judgmental, least united.
Some of us couldn't mourn these people because we were too busy thinking and talking about guns. There should have been more guns, so people could fight back! Or, there should have been fewer guns — it's too easy for killers to stock up!
Some of us could only think about what the killer represented: He represented immigration, or Islam, or ISIS, or homophobia, or, strangely, Christian opposition to gay marriage.
Some of us could only see the victims as categories: They were not just human beings; they were homosexuals, or night-clubbers; they were privileged or under-privileged; they were white or Latino.
Some of us felt we had to pretend that we know nothing about the killer's motivation: We had to pretend he hadn't made that relatively clear. Some of us had to pretend that we knew everything about the killer's motivation: It was Islam, pure and simple.
Why are we like this?
To say we are too political is silly: Man is a political animal. It's the way we are political that matters.
Some of us are ideologues.
Ideologues have a fanatical attachment to one piece of the truth such that this one truth comes to shape every issue. When something like Orlando happens, our ideological blinders become very clear. We didn't see human beings, we see pawns: We don't say, "These poor people died," we say, "These deaths prove I'm right!"
Others of us are partisan pragmatists.
We don't really see "truth" as a thing. When you confront us with an idea, we don't ask, "Is it true?" We ask, "Does it help me?" Does it further my ambition, or my wealth, or the win-loss record of the team? When we looked at the shooting at Orlando we were too busy asking "How does this help my party?"
You can see how these two political tendencies played out at the cross.
The Sanhedrin were ideologues. Jesus was a threat to their worldview. "If we leave him alone, all will believe in him," they said. So they killed him.
Pilate was a partisan pragmatist. Jesus threatened his power. When Jesus appealed to the truth, Pilate said "What is truth?" and killed him.
Both of these ways of looking at the world kill people, because both make human beings a means to some other end: their ideology or their party.
Sexual ideologies kill. Economic ideologies (of all kinds) kill. Partisan blindness (of all kinds) kills.
The only way out of both traps is love. Not romantic love that focuses on feelings. Not permissive love that dismisses the truth. Real love.
Love means being able to see the truth with clarity and yourself with honesty, like the Good Thief.
It means loving God above all things; more than your worldview; more than your partisan group.
It means loving my neighbor as myself, despite his flaws, because I, too, am flawed.
The world is waiting for someone who can do that. It should be Christians. It should be us.
This article also appeared at Aleteia.
Photo: Wikimedia commons.
The Gregorian Institute is Benedictine College's initiative to promote Catholic identity in public life by equipping leaders (the Gregorian speech digest), training leaders (the Gregorian Fellows), defending the faith (the Memorare Army for Religious Freedom), and celebrating Catholic identity (the Catholic Hall of Fame).
Tags: Orlando


text:
Boko Haram Ramps up Use of Children for Suicide Attacks: U.N.
By Lucy Westcott On 4/12/17 at 10:30 AM EDT
Members of the #BringBackOurGirls campaign rally in Nigeria's capital Abuja to mark 1,000 days since more than 200 schoolgirls were kidnapped from their secondary school in Chibok by Boko Haram, January 8, 2017. Afolabi Sotunde/Reuters
World Boko Haram Child Soldiers ISIS Nigeria
Boko Haram has dramatically increased its recruitment and use of children in suicide attacks, according to the United Nations children's agency.
Boko Haram, the Islamist group that has waged a campaign of violence and terror across parts of west and central Africa since 2009, used 27 children in the first quarter of 2017, compared to nine during the same period last year. That's a 200 percent increase and nearly as many children that were used in the whole of last year—30—said Marie-Pierre Poirier, Unicef's regional director for West and Central Africa.
Related: How Boko Haram spreads hunger beyond Nigeria's borders
One recent example in northern Cameroon saw a boy believed to be around 12 detonate a bomb in the district of Kolofata. The February attack killed two people.
Since 2014, 117 children have been used in to carry out bomb attacks in public places in Nigeria, Cameroon, Chad and Niger, the four countries affected by Boko Haram. In the "vast majority" of cases, says Unicef, girls were used by the group. An untold number of them have also been victims of sexual violence. In 2014, four children were used by the group, rising to 56 in 2015. Since the beginning of 2017, there have been 27 suicide attacks in northeastern Nigeria, which Unicef calls a "sharp increase."
"These children are victims, not perpetrators," Poirier said in a statement on Wednesday. "Forcing or deceiving them into committing such horrific acts is reprehensible."
Unicef's report is released ahead of the three year anniversary of the abduction of more than 200 schoolgirls from the northeastern Nigerian village of Chibok. The majority of those girls are still missing.
Boko Haram is not the only armed group to use children in its attack. The Islamic State militant group has long used children to not only carry out suicide attacks, but to hunt down and execute hostages on camera.
Trump to Sell Planes to Nigeria for Boko Haram Fight
Goodluck Jonathan Denies Rejecting Chibok Rescue Offer
Nigeria Admits Boko Haram Leader Is Actually Alive


Ocean Spray® Craisins® Brand Original Dried Cranberries. Gluten free. Sweetened dried cranberries. Refined sunflower oil is used as a processing agent. 1-800-662-3263. Made in the USA with North American Cranberries.


After a 273 mile journey from Beverley we caught the overnight ferry from Portsmouth to St Malo, Brittany. We arrived in loads of time and took our place behind two suspect dudes in a clapped out van, watching as everyone else was called onto the ship. Last but 2 we were. By the time we boarded the restaurant was full and we had to eat in the buffet - to be fair, it did us a favour. The buffet was excellent and saved us a few quid. Disembarking the two dudes were pulled over by the gendarmerie and held us up again, but only for a minute. Their van consisted of compartments of surf boards, skateboards,wetsuits and almost nothing else.
Arrived just after 8.30am and drove the 220 miles to our first port of call - Surgères.
Selected a pitch at the local campsite and eyed up the pool. 27degrees C and sunny. Unfortunately Graham forgot his swimming trunks! He cycled off off in search of a suitable shop whilst Carol chilled some beer and enjoyed the sun.
Will have an early night after a van prepared dinner as we have an appointment with the bank manager to open a french bank account tomorrow am. ooo errr!
Just managed to get up and out for our 10am appointment at the bank.
Geraldine our advisor welcomed us into her office and so began a hour and a half of banking french style. Graham was sure that she would be able to speak English but alas not and he valiantly managed to converse well enough for us to open an account - after agreeing the terms and conditions and multiple signing of several pieces of paper. In France you pay a nominal sum per month for the privilege of having a carte bancaire and an annual fee for insurance - obligatoire. Bienvenue à France! So yes, the banking is free but the mandatory insurance for loss and theft is not. However we did get a complimentary Michelin guide to Charente Maritime- in french of course!
After lunch we visit estate agents. Apparently of course what we want is rare indeed!
We did visit a lovely town house with Cristelle a local agent - however it had no parking, only 1 shower room for 5 bedrooms, no pool (but room to build), and on a busy through road so some traffic noise (and we know what Graham thinks about that!) On the plus side it had been beautifully restored with exposed stone walls and marble flooring downstairs - very chic!
Met Ingrid the estate agent 10 am start again which is early for us! Apparently the modern hous we were to view has been sold!
So we viewed a large town house(too large) with 6 bedrooms - characterful - large garden with large trees, nice terrace and plenty room for a pool but would need a far more extensive budget than ours to refurbish.
We then viewed a stone house on a relatively quiet road just a few minutes pleasant walk from the town centre via the Chateau. Unassuming on the outside but surprisingly lovely inside, with a manageable garden with just room for a pool. A well loved home full of quirky features, 4 bedrooms all good sizes - 1 downstairs with a walk in wardrobe and ensuite. A small kitchen with room to knock through to make a good sized kitchen /diner. Also under the top end of our budget so affordable to build pool and rebuild kitchen. A definate contender! Hurrah!
Rear view of what we have nicknamed "The Garden House"
Also good to compare with our next viewing (house name removed) and top favourite on paper.
So 2 properties to compare and contrast - spent time over dinner chez Rex discussing pros and cons - at the moment we to our surprise are leaning towards " The Garden House". And so to bed.
Craaack! What was that? Attempted to get out of the passenger door but blocked - as we scrambled out of the drivers door into the darkness of night we were met with concerned voices and saw the remnents of large branches of a tree completly covering Rex! The campsite owner was called and the Sapeurs Pompiers (Fire brigade). A crowd of interested on lookers had now developed and a lovely couple opposite us made coffee for us as we looked on to the scene. A few minutes later 2 young muscular pompiers were cutting branches and clearing the way for us to move Rex to a safer plot!
Une echappé belle - lucky escape - and could have been much worse! Apparently it had been extremely dry the last few months and the extremely heavy rain through last night must have contributed to the Tree's demise -- Ha Ha! We will inspect for any damage tomorrow but it appears we may have survived with minor scratches to Rex and possibly damage to the TV ariel.
Tomorrow we head off to St Jean D'Angely and a viewing booked for Monday at 9am-What? This means getting up at 7h!!
A leisurely drive through possible contender villages - all appeared to have little commerce so crossed off the list. Arrived in St Jean D'Angely in sunshine but soon changed to rain and the usual heaviest and noisiest showers occured aprox 4 am!
Up early to walk in to the town centre to meet Marc the estate agent in St Jean at 9am.
He showed us a very grand pavillon in the centre with a fantastic pool. Very grand, old school with a prestigious feel. However it was above budget which we prepared to stretch to if if was perfect. It wasn't. It needed a lot of work to update and repair. The elderly owner had just gone to a retirement home. The decor was very grand and floral but probably not changed since the 60s! There was a enormous underground garage with a lounge off it - an enormous man cave! And also a shower/wc and twin bedroom at the back of the garage as well as numerous workrooms - like a bunker. We'd already decided No when Marc dealt the killer blow: the terrace was leaking into the basement and needed repairing - that wasn't in the brochure! En parfait état it said. Someone with a much larger budget than ours will create a beautiful home we're sure - but as in Dragon's Den we had to tell Marc we were "out".
We arranged to view 2 more smaller and cheaper properties on Wednesday and then went on to our next estate agency to meet Carolyn, an English expat working as an agent. She showed us round a beautiful large modernised townhouse with a lovely large garden. It had a sluice in the basement with a canal of swiftly flowing water running through the basement (right through the middle of the house) and into a canal alongside the garden! Apparently this was the remnants of an old mill. You altered the level of the sluice dependent on how high the river was opposite. Although the house was lovely and just on budget we felt it was perhaps too large a garden and we would have to put in a pool. The thought of fast flowing water running through the basement in the winter months when it was not occupied was also a concern - so again we were " out".
Carolyn gave us some good advice re life in the area for expats . She agreed with us that the unamed house was currently overpriced by the owners and was to feedback to them - not sure if the owner would agree to sell it if not priced more sensibly. She also gave us her home telephone number if we should need any further help which was very kind.
We were by this point exhausted and couldn't face another round of estate agent visiting so wandered back to the campsite for a very late lunch. During the evening we pondered on "The Garden House". We prefer Surgères to St. Jean, it's in a good location, it's the right size and price, it has an ensuite (quite rare in France), and an opportunity for us to add value by improvements. What were we doing messing about searching out others? We decide that, as it's due to keep raining for the next few days, why not go back for a second look and then holiday when it's sunny. So that's what we plan. Graham will phone Marc tomorrow and cancel the two viewings and then ring Ingrid, the agent in Surgères to request another viewing.
Had a lie in. Graham rings Marc and achieves a small milestone: a conversation on the phone tout en francais - albeit a small one, a personal first. We travel the long way back to Surgères, through Saint Prochaire and Pont L'Abbe d'Arnoult - larger villages with shops and restaurants with shortlisted properties situated within, and have a good walk round. However we are underwhelmed and feel that Surgères town is still our preferred location. Graham rings Ingrid to arrange another viewing of "the Garden House" as this appears to tick all the boxes for us.
So back to Surgères - requesting a tree free pitch at the campsite! We will re-view the house tomorrow am- we hope it will still feel as nice on a second viewing.
Just managed to get to our appointment with Ingrid the estate agent at 10.30am!
The weather is horrid - torrential rain!
We revisited the house now named La Maison Pierre (the stone house - not quite, but near enough -ed.). It was even better than we first thought! We met the owners M and Mme Drapeau who were delightful. Spent lots of time measuring and taking photos, asking about insulation, electrics, etc., then back to the office to make an offer. Ingid advised us to make a lower offer than we thought we should. So we left Ingrid to negotiate on our behalf - and left to have a lovely lunch in a local Italian restaurant.
On not hearing from Ingrid we decided to visit the nearest seaside resort Chataleillon Plage - however as it was raining heavily we decided to move inland to Rochefort. As we arrived at the municipal campsite Ingrid rang - another couple viewed the house 2 weeks before with another agency and are seeking finance. The only way to definitely secure the sale is to offer the asking price and sign the sale document today! Be the first! If you offer the asking price in France the vendor HAS to accept and he is it bound by it. No gazumping - good system!
So we drove back to Surgères as quickly as Rex allowed and signed the document.
We returned to Rochefort and on arrival at the site recieved a call from Ingrid to say the owners have signed agreeing our purchase and it is ours! They are happy, we are happy. They will be leaving all the beds upstairs and some other items of furniture as they are downsizing to an apartment by the sea. We think they felt sorry for us paying the top price! Nothing wrong with emotional blackmail! And part of us felt we should pay a premium as we are foreigners, and the other interested party are local. A bit like a second home tax but it cuts out the middleman and goes straight to the owner.
No Champagne available so we celebrated with a strong beer! Let the adventure begin! Soit commencer l'aventure!


text:
Hurricane Iota makes landfall as Category 4 storm along Nicaraguan coast, forecast to bring life-threatening storm surge
Hurricane Iota makes landfall as Category 4 storm along Nicaraguan coast, forecast to bring extreme rain and life-threatening storm surge
Hurricane Iota made landfall Monday evening as a Category 4 storm along the northeastern coast of Nicaragua.
According to the National Hurricane Center, Iota's landfall is 15 miles south of Category 4 Hurricane Eta's landfall on Nov. 3.
Life-threatening storm surge, catastrophic winds, flash flooding and landslides are expected across parts of Central America already battered by Hurricane Eta less than two weeks ago.
Throughout Monday, Hurricane Iota rapidly strengthened into a Category 5 storm before landfall as a Category 4.
As of the 11 p.m. update, the U.S. National Hurricane Center said the storm had maximum sustained winds of 155 mph and is moving westward at 9 mph.
Authorities warned that Iota would probably come ashore over areas where Eta's torrential rains saturated the soil, leaving it prone to new landslides and floods, and that the storm surge could reach a shocking 15 to 20 feet above normal tides.
That storm surge was on the mind of Yasmina Wriedt on Monday in Bilwi's El Muelle neighborhood, sitting tight against the sea.
"The situation doesn't look good at all," Wriedt said. "We woke up without electricity, with rain and the surf is getting really high."
Wriedt, who works for a small-scale fishing organization called Piquinera, said that the roof of her house was blown off in Eta less than two weeks ago. "We repaired it as best we could, now I think the wind will take it again because they say (Iota) is even stronger," Wriedt said, the sound of hammering echoing around her as neighbors boarded windows and reinforced roofs.
During Eta the surf came up to just behind her house, where she lives with eight other members of her family. "Today I'm afraid again about losing my house and I'm frightened for all of us who live in this neighborhood."
Wriedt said some neighbors went to stay with relatives elsewhere, but most have stayed. "We're almost all here," she said. "Neither the army nor the government came to move us."
Cairo Jarquin, Nicaragua emergency response project manager for Catholic Relief Services, had just visited Bilwi and smaller coastal communities Friday.
In Wawa Bar, Jarquin said he found "total destruction." People had been working furiously to put roofs back over their families' heads, but now Iota threatened to take what was left.
"The little that remained standing could be razed," Jarquin said. There were other communities farther inland that he was not even able to reach due to the condition of roads. He said he heard that Wawa bar was evacuated again Saturday.
Evacuations were being conducted from low-lying areas in Nicaragua and Honduras near their shared border through the weekend.
Nicaraguan Vice President Rosario Murillo, who is also the first lady, said Monday the government had done everything necessary to protect lives, including the evacuation of thousands. She added that Taiwan had donated 800 tons of rice to help those affected by the storms.
Limborth Bucardo, of the Miskito Indigenous ethnic group, said many people had moved to churches in Bilwi. He rode out Eta with his wife and two children at home, but this time decided to move in with relatives in a safer neighborhood.
"We hadn't finished repairing our houses and settling in when another hurricane comes," Bucardo said. "The shelters in Bilwi are already full, packed with people from (surrounding) communities."
Iota is the record 30th named storm of this year's extraordinarily busy Atlantic hurricane season. It's also the ninth storm to rapidly intensify this season, a dangerous phenomenon that is happening increasingly more often. Such activity has focused attention on climate change, which scientists say is causing wetter, stronger and more destructive storms.
Iota is stronger, based on central pressure, than 2005s Hurricane Katrina and is the first storm with a Greek alphabet name to hit Category 5, Colorado State University hurricane researcher Phil Klotzbach said. It also sets the record for the latest Category 5 hurricane on record, beating the record set by the Nov. 8, 1932, Cuba Hurricane.
Eta had hit Nicaragua as a Category 4 hurricane, killing more than 130 people as torrential rains caused flash floods and mudslides in parts of Central America and Mexico. Then it meandered across Cuba, the Florida Keys and around the Gulf of Mexico before slogging ashore again near Cedar Key, Florida, and dashing across Florida and the Carolinas.
Iota was forecast to drop 10 to 20 inches of rain in northern Nicaragua, Honduras, Guatemala and southern Belize, with as much as 30 inches (750 millimeters) in isolated spots. Costa Rica and Panama could also experience heavy rain and possible flooding, the hurricane center said.
The prospect of more rain was raising the anxiety of those still homeless after Eta.
On Monday, Carmen Isabel Rodríguez Ortez, 48, was still living inside a government shelter with more than 250 people in La Lima, Honduras, just outside San Pedro Sula. Devastated by Eta's destruction, she quickly broke into sobs as she contemplated the torrential rains of another storm.
"We're living a real nightmare," Rodríguez said. The Chamelecon river flooded her Reformada neighborhood as Eta passed, submerging their homes. "Now they announce more rain and we don't know what's going to happen, because our homes are completely flooded."
Eta was this year's 28th named storm, tying the 2005 record. Remnants of Theta, the 29th, dissipated Sunday in the eastern Atlantic Ocean.
Over the past couple of decades, meteorologists have been more worried about storms like Iota that power up much faster than normal. They created an official threshold for this rapid intensification -- a storm gaining 35 mph (56 kph) in wind speed in just 24 hours. Iota doubled it.
Earlier this year, Hannah, Laura, Sally, Teddy, Gamma, Delta, Zeta and Iota all rapidly intensified. Laura and Delta tied or set records for rapid intensification.
The official end of the hurricane season is Nov. 30.
WEATHER HURRICANE
Montco couple describes being on a cruise as Hurricane Nicole neared
Nicole becomes Category 1 hurricane, heads toward Florida coast
Tropical Storm Nicole expected to hit Florida as Cat 1 hurricane
10 years since Sandy: Nora Muchanic recalls night of storm


text:
Magic Girl
Since ancient times, the people of the Planet Alah have passed down stories of god-like creatures with outrageous powers and abilities. These tales have served as forms of entertainment, presented lessons to the children and helped preserve the old ways of the culture. Each and every citizen of Alah is familiar with the fairy tales, which have become more like a religion than simple lore.
Some people find themselves so inspired by the descriptions and deeds of the valiant "super beings" presented in these fables, that they push themselves to the ultimate limit, hoping to acquire mystical powers of their own. Ling Ling, a bright and precocious child, excels in her study of witchcraft, a skill passed down from her grandmother. In particular, her affinity with spell casting has surpassed even that of her beloved instructor.
Little did anyone know that one day that prowess would be put to the ultimate test…
One day, a great earthquake shook the planet. Soon after, lightning began to rain from the sky in all directions. The people, stunned by the mysterious disasters, could have never in their wildest dreams imagined the source of such unparalleled destruction.
For suddenly in the sky appeared remarkable beings matching the very descriptions of those in the ancient stories!! Though unlike in the fables, these creatures were just the opposite of benevolent: there was naught but evil in their eyes, and when they began to attack the people, their methods were absolutely merciless.
"We have angered the gods!" lamented the faithful, while the skeptics cried, "Everything we've been told is a lie!"
Whatever the reason for their actions, the cruel invaders were relentless in their assault, laying waste to everything in sight both natural and manmade, and slaying anyone and everyone they encountered. Ling Ling's small village was quickly and easily overcome before anyone, including her maternal grandmother, could escape.
Only because she had been exploring the neighboring forest at the time of the attack, Ling Ling was the sole survivor of the chaos. Once a joyous child, her heart filled with bitter hatred and a burning need for revenge.
Now she stands alone against the entire fleet of otherworldy monsters. Will her power and ability be enough to overcome the very beings that inspired her to study the dark arts in the first place?
Copyright © 2022 · All Rights Reserved · Magic Girl


Info on Stucco and Plastering-- January 2013 - thirty-fifth big issue !
Although the use of asbestos dates back for centuries,United States Gypsum, the largest manufacturer of plaster did not use asbestos in it's materials until the 1920's.
Acoustic plaster was a lightweight, soft plaster for ceilings that was mainly used for noise reduction in areas where people converged, for example in a church narthex and hallways in schools.
Note how the flashing is angled back toward the wall, driving water into the wall.
I guess they didn't read my column on flashing windows.
wet and mushy like oatmeal.
What is the difference between stucco and parging ?
Painting stucco, will the rain mess up my new stucco ?
Backwards flashing causes severe rot near Leesburg, Virginia.
6 year old house has a cement basecoat and a synthetic (fake) finish. Please click here to see what I said about backwards flashing.