<commit_before>#include "../include/cxx.h"
#include <cstring>
#include <exception>
#include <iostream>
#include <memory>
#include <stdexcept>
#include <vector>

extern "C" {
const char *cxxbridge05$cxx_string$data(const std::string &s) noexcept {
  return s.data();
}

size_t cxxbridge05$cxx_string$length(const std::string &s) noexcept {
  return s.length();
}

// rust::String
void cxxbridge05$string$new(rust::String *self) noexcept;
void cxxbridge05$string$clone(rust::String *self,
                              const rust::String &other) noexcept;
bool cxxbridge05$string$from(rust::String *self, const char *ptr,
                             size_t len) noexcept;
void cxxbridge05$string$drop(rust::String *self) noexcept;
const char *cxxbridge05$string$ptr(const rust::String *self) noexcept;
size_t cxxbridge05$string$len(const rust::String *self) noexcept;

// rust::Str
bool cxxbridge05$str$valid(const char *ptr, size_t len) noexcept;
} // extern "C"

namespace rust {
inline namespace cxxbridge05 {

template <typename Exception>
void panic [[noreturn]] (const char *msg) {
#if defined(RUST_CXX_NO_EXCEPTIONS)
  std::cerr << "Error: " << msg << ". Aborting." << std::endl;
  std::terminate();
#else
  throw Exception(msg);
#endif
}

template void panic<std::out_of_range>[[noreturn]] (const char *msg);

String::String() noexcept { cxxbridge05$string$new(this); }

String::String(const String &other) noexcept {
  cxxbridge05$string$clone(this, other);
}

String::String(String &&other) noexcept {
  this->repr = other.repr;
  cxxbridge05$string$new(&other);
}

String::~String() noexcept { cxxbridge05$string$drop(this); }

String::String(const std::string &s) : String(s.data(), s.length()) {}

String::String(const char *s) : String(s, std::strlen(s)) {}

String::String(const char *s, size_t len) {
  if (!cxxbridge05$string$from(this, s, len)) {
    panic<std::invalid_argument>("data for rust::String is not utf-8");
  }
}

String &String::operator=(const String &other) noexcept {
  if (this != &other) {
    cxxbridge05$string$drop(this);
    cxxbridge05$string$clone(this, other);
  }
  return *this;
}

String &String::operator=(String &&other) noexcept {
  if (this != &other) {
    cxxbridge05$string$drop(this);
    this->repr = other.repr;
    cxxbridge05$string$new(&other);
  }
  return *this;
}

String::operator std::string() const {
  return std::string(this->data(), this->size());
}

const char *String::data() const noexcept {
  return cxxbridge05$string$ptr(this);
}

size_t String::size() const noexcept { return cxxbridge05$string$len(this); }

size_t String::length() const noexcept { return cxxbridge05$string$len(this); }

String::String(unsafe_bitcopy_t, const String &bits) noexcept
    : repr(bits.repr) {}

std::ostream &operator<<(std::ostream &os, const String &s) {
  os.write(s.data(), s.size());
  return os;
}

Str::Str() noexcept : repr(Repr{reinterpret_cast<const char *>(this), 0}) {}

Str::Str(const Str &) noexcept = default;

Str::Str(const std::string &s) : Str(s.data(), s.length()) {}

Str::Str(const char *s) : Str(s, std::strlen(s)) {}

Str::Str(const char *s, size_t len) : repr(Repr{s, len}) {
  if (!cxxbridge05$str$valid(this->repr.ptr, this->repr.len)) {
    panic<std::invalid_argument>("data for rust::Str is not utf-8");
  }
}

Str &Str::operator=(Str other) noexcept {
  this->repr = other.repr;
  return *this;
}

Str::operator std::string() const {
  return std::string(this->data(), this->size());
}

const char *Str::data() const noexcept { return this->repr.ptr; }

size_t Str::size() const noexcept { return this->repr.len; }

size_t Str::length() const noexcept { return this->repr.len; }

Str::Str(Repr repr_) noexcept : repr(repr_) {}

Str::operator Repr() noexcept { return this->repr; }

std::ostream &operator<<(std::ostream &os, const Str &s) {
  os.write(s.data(), s.size());
  return os;
}

extern "C" {
const char *cxxbridge05$error(const char *ptr, size_t len) {
  char *copy = new char[len];
  strncpy(copy, ptr, len);
  return copy;
}
} // extern "C"

Error::Error(Str::Repr msg) noexcept : msg(msg) {}

Error::Error(const Error &other) {
  this->msg.ptr = cxxbridge05$error(other.msg.ptr, other.msg.len);
  this->msg.len = other.msg.len;
}

Error::Error(Error &&other) noexcept {
  delete[] this->msg.ptr;
  this->msg = other.msg;
  other.msg.ptr = nullptr;
  other.msg.len = 0;
}

Error::~Error() noexcept { delete[] this->msg.ptr; }

const char *Error::what() const noexcept { return this->msg.ptr; }

} // namespace cxxbridge05
} // namespace rust

extern "C" {
void cxxbridge05$unique_ptr$std$string$null(
    std::unique_ptr<std::string> *ptr) noexcept {
  new (ptr) std::unique_ptr<std::string>();
}
void cxxbridge05$unique_ptr$std$string$raw(std::unique_ptr<std::string> *ptr,
                                           std::string *raw) noexcept {
  new (ptr) std::unique_ptr<std::string>(raw);
}
const std::string *cxxbridge05$unique_ptr$std$string$get(
    const std::unique_ptr<std::string> &ptr) noexcept {
  return ptr.get();
}
std::string *cxxbridge05$unique_ptr$std$string$release(
    std::unique_ptr<std::string> &ptr) noexcept {
  return ptr.release();
}
void cxxbridge05$unique_ptr$std$string$drop(
    std::unique_ptr<std::string> *ptr) noexcept {
  ptr->~unique_ptr();
}
} // extern "C"

#define STD_VECTOR_OPS(RUST_TYPE, CXX_TYPE)                                    \
  size_t cxxbridge05$std$vector$##RUST_TYPE##$size(                            \
      const std::vector<CXX_TYPE> &s) noexcept {                               \
    return s.size();                                                           \
  }                                                                            \
  const CXX_TYPE *cxxbridge05$std$vector$##RUST_TYPE##$get_unchecked(          \
      const std::vector<CXX_TYPE> &s, size_t pos) noexcept {                   \
    return &s[pos];                                                            \
  }                                                                            \
  void cxxbridge05$unique_ptr$std$vector$##RUST_TYPE##$null(                   \
      std::unique_ptr<std::vector<CXX_TYPE>> *ptr) noexcept {                  \
    new (ptr) std::unique_ptr<std::vector<CXX_TYPE>>();                        \
  }                                                                            \
  void cxxbridge05$unique_ptr$std$vector$##RUST_TYPE##$raw(                    \
      std::unique_ptr<std::vector<CXX_TYPE>> *ptr,                             \
      std::vector<CXX_TYPE> *raw) noexcept {                                   \
    new (ptr) std::unique_ptr<std::vector<CXX_TYPE>>(raw);                     \
  }                                                                            \
  const std::vector<CXX_TYPE>                                                  \
      *cxxbridge05$unique_ptr$std$vector$##RUST_TYPE##$get(                    \
          const std::unique_ptr<std::vector<CXX_TYPE>> &ptr) noexcept {        \
    return ptr.get();                                                          \
  }                                                                            \
  std::vector<CXX_TYPE>                                                        \
      *cxxbridge05$unique_ptr$std$vector$##RUST_TYPE##$release(                \
          std::unique_ptr<std::vector<CXX_TYPE>> &ptr) noexcept {              \
    return ptr.release();                                                      \
  }                                                                            \
  void cxxbridge05$unique_ptr$std$vector$##RUST_TYPE##$drop(                   \
      std::unique_ptr<std::vector<CXX_TYPE>> *ptr) noexcept {                  \
    ptr->~unique_ptr();                                                        \
  }

#define RUST_VEC_EXTERNS(RUST_TYPE, CXX_TYPE)                                  \
  void cxxbridge05$rust_vec$##RUST_TYPE##$new(                                 \
      rust::Vec<CXX_TYPE> *ptr) noexcept;                                      \
  void cxxbridge05$rust_vec$##RUST_TYPE##$drop(                                \
      rust::Vec<CXX_TYPE> *ptr) noexcept;                                      \
  size_t cxxbridge05$rust_vec$##RUST_TYPE##$len(                               \
      const rust::Vec<CXX_TYPE> *ptr) noexcept;                                \
  const CXX_TYPE *cxxbridge05$rust_vec$##RUST_TYPE##$data(                     \
      const rust::Vec<CXX_TYPE> *ptr) noexcept;                                \
  size_t cxxbridge05$rust_vec$##RUST_TYPE##$stride() noexcept;

#define RUST_VEC_OPS(RUST_TYPE, CXX_TYPE)                                      \
  template <>                                                                  \
  Vec<CXX_TYPE>::Vec() noexcept {                                              \
    cxxbridge05$rust_vec$##RUST_TYPE##$new(this);                              \
  }                                                                            \
  template <>                                                                  \
  void Vec<CXX_TYPE>::drop() noexcept {                                        \
    return cxxbridge05$rust_vec$##RUST_TYPE##$drop(this);                      \
  }                                                                            \
  template <>                                                                  \
  size_t Vec<CXX_TYPE>::size() const noexcept {                                \
    return cxxbridge05$rust_vec$##RUST_TYPE##$len(this);                       \
  }                                                                            \
  template <>                                                                  \
  const CXX_TYPE *Vec<CXX_TYPE>::data() const noexcept {                       \
    return cxxbridge05$rust_vec$##RUST_TYPE##$data(this);                      \
  }                                                                            \
  template <>                                                                  \
  size_t Vec<CXX_TYPE>::stride() noexcept {                                    \
    return cxxbridge05$rust_vec$##RUST_TYPE##$stride();                        \
  }

// Usize and isize are the same type as one of the below.
#define FOR_EACH_NUMERIC(MACRO)                                                \
  MACRO(u8, uint8_t)                                                           \
  MACRO(u16, uint16_t)                                                         \
  MACRO(u32, uint32_t)                                                         \
  MACRO(u64, uint64_t)                                                         \
  MACRO(i8, int8_t)                                                            \
  MACRO(i16, int16_t)                                                          \
  MACRO(i32, int32_t)                                                          \
  MACRO(i64, int64_t)                                                          \
  MACRO(f32, float)                                                            \
  MACRO(f64, double)

#define FOR_EACH_STD_VECTOR(MACRO)                                             \
  FOR_EACH_NUMERIC(MACRO)                                                      \
  MACRO(usize, size_t)                                                         \
  MACRO(isize, rust::isize)                                                    \
  MACRO(string, std::string)

#define FOR_EACH_RUST_VEC(MACRO)                                               \
  FOR_EACH_NUMERIC(MACRO)                                                      \
  MACRO(bool, bool)                                                            \
  MACRO(string, rust::String)

extern "C" {
FOR_EACH_STD_VECTOR(STD_VECTOR_OPS)
FOR_EACH_RUST_VEC(RUST_VEC_EXTERNS)
} // extern "C"

namespace rust {
inline namespace cxxbridge05 {
FOR_EACH_RUST_VEC(RUST_VEC_OPS)
} // namespace cxxbridge05
} // namespace rust
<commit_msg>Match std::string's behavior on (nullptr, 0) construction<commit_after>#include "../include/cxx.h"
#include <cstring>
#include <exception>
#include <iostream>
#include <memory>
#include <stdexcept>
#include <vector>

extern "C" {
const char *cxxbridge05$cxx_string$data(const std::string &s) noexcept {
  return s.data();
}

size_t cxxbridge05$cxx_string$length(const std::string &s) noexcept {
  return s.length();
}

// rust::String
void cxxbridge05$string$new(rust::String *self) noexcept;
void cxxbridge05$string$clone(rust::String *self,
                              const rust::String &other) noexcept;
bool cxxbridge05$string$from(rust::String *self, const char *ptr,
                             size_t len) noexcept;
void cxxbridge05$string$drop(rust::String *self) noexcept;
const char *cxxbridge05$string$ptr(const rust::String *self) noexcept;
size_t cxxbridge05$string$len(const rust::String *self) noexcept;

// rust::Str
bool cxxbridge05$str$valid(const char *ptr, size_t len) noexcept;
} // extern "C"

namespace rust {
inline namespace cxxbridge05 {

template <typename Exception>
void panic [[noreturn]] (const char *msg) {
#if defined(RUST_CXX_NO_EXCEPTIONS)
  std::cerr << "Error: " << msg << ". Aborting." << std::endl;
  std::terminate();
#else
  throw Exception(msg);
#endif
}

template void panic<std::out_of_range>[[noreturn]] (const char *msg);

String::String() noexcept { cxxbridge05$string$new(this); }

String::String(const String &other) noexcept {
  cxxbridge05$string$clone(this, other);
}

String::String(String &&other) noexcept {
  this->repr = other.repr;
  cxxbridge05$string$new(&other);
}

String::~String() noexcept { cxxbridge05$string$drop(this); }

String::String(const std::string &s) {
  if (!cxxbridge05$string$from(this, s.data(), s.length())) {
    panic<std::invalid_argument>("data for rust::String is not utf-8");
  }
}

String::String(const char *s) {
  if (!cxxbridge05$string$from(this, s, std::strlen(s))) {
    panic<std::invalid_argument>("data for rust::String is not utf-8");
  }
}

String::String(const char *s, size_t len) {
  if (!cxxbridge05$string$from(
          this,
          s == nullptr && len == 0 ? reinterpret_cast<const char *>(1) : s,
          len)) {
    panic<std::invalid_argument>("data for rust::String is not utf-8");
  }
}

String &String::operator=(const String &other) noexcept {
  if (this != &other) {
    cxxbridge05$string$drop(this);
    cxxbridge05$string$clone(this, other);
  }
  return *this;
}

String &String::operator=(String &&other) noexcept {
  if (this != &other) {
    cxxbridge05$string$drop(this);
    this->repr = other.repr;
    cxxbridge05$string$new(&other);
  }
  return *this;
}

String::operator std::string() const {
  return std::string(this->data(), this->size());
}

const char *String::data() const noexcept {
  return cxxbridge05$string$ptr(this);
}

size_t String::size() const noexcept { return cxxbridge05$string$len(this); }

size_t String::length() const noexcept { return cxxbridge05$string$len(this); }

String::String(unsafe_bitcopy_t, const String &bits) noexcept
    : repr(bits.repr) {}

std::ostream &operator<<(std::ostream &os, const String &s) {
  os.write(s.data(), s.size());
  return os;
}

Str::Str() noexcept : repr(Repr{reinterpret_cast<const char *>(1), 0}) {}

Str::Str(const Str &) noexcept = default;

Str::Str(const std::string &s) : repr(Repr{s.data(), s.length()}) {
  if (!cxxbridge05$str$valid(this->repr.ptr, this->repr.len)) {
    panic<std::invalid_argument>("data for rust::Str is not utf-8");
  }
}

Str::Str(const char *s) : repr(Repr{s, std::strlen(s)}) {
  if (!cxxbridge05$str$valid(this->repr.ptr, this->repr.len)) {
    panic<std::invalid_argument>("data for rust::Str is not utf-8");
  }
}

Str::Str(const char *s, size_t len)
    : repr(
          Repr{s == nullptr && len == 0 ? reinterpret_cast<const char *>(1) : s,
               len}) {
  if (!cxxbridge05$str$valid(this->repr.ptr, this->repr.len)) {
    panic<std::invalid_argument>("data for rust::Str is not utf-8");
  }
}

Str &Str::operator=(Str other) noexcept {
  this->repr = other.repr;
  return *this;
}

Str::operator std::string() const {
  return std::string(this->data(), this->size());
}

const char *Str::data() const noexcept { return this->repr.ptr; }

size_t Str::size() const noexcept { return this->repr.len; }

size_t Str::length() const noexcept { return this->repr.len; }

Str::Str(Repr repr_) noexcept : repr(repr_) {}

Str::operator Repr() noexcept { return this->repr; }

std::ostream &operator<<(std::ostream &os, const Str &s) {
  os.write(s.data(), s.size());
  return os;
}

extern "C" {
const char *cxxbridge05$error(const char *ptr, size_t len) {
  char *copy = new char[len];
  strncpy(copy, ptr, len);
  return copy;
}
} // extern "C"

Error::Error(Str::Repr msg) noexcept : msg(msg) {}

Error::Error(const Error &other) {
  this->msg.ptr = cxxbridge05$error(other.msg.ptr, other.msg.len);
  this->msg.len = other.msg.len;
}

Error::Error(Error &&other) noexcept {
  delete[] this->msg.ptr;
  this->msg = other.msg;
  other.msg.ptr = nullptr;
  other.msg.len = 0;
}

Error::~Error() noexcept { delete[] this->msg.ptr; }

const char *Error::what() const noexcept { return this->msg.ptr; }

} // namespace cxxbridge05
} // namespace rust

extern "C" {
void cxxbridge05$unique_ptr$std$string$null(
    std::unique_ptr<std::string> *ptr) noexcept {
  new (ptr) std::unique_ptr<std::string>();
}
void cxxbridge05$unique_ptr$std$string$raw(std::unique_ptr<std::string> *ptr,
                                           std::string *raw) noexcept {
  new (ptr) std::unique_ptr<std::string>(raw);
}
const std::string *cxxbridge05$unique_ptr$std$string$get(
    const std::unique_ptr<std::string> &ptr) noexcept {
  return ptr.get();
}
std::string *cxxbridge05$unique_ptr$std$string$release(
    std::unique_ptr<std::string> &ptr) noexcept {
  return ptr.release();
}
void cxxbridge05$unique_ptr$std$string$drop(
    std::unique_ptr<std::string> *ptr) noexcept {
  ptr->~unique_ptr();
}
} // extern "C"

#define STD_VECTOR_OPS(RUST_TYPE, CXX_TYPE)                                    \
  size_t cxxbridge05$std$vector$##RUST_TYPE##$size(                            \
      const std::vector<CXX_TYPE> &s) noexcept {                               \
    return s.size();                                                           \
  }                                                                            \
  const CXX_TYPE *cxxbridge05$std$vector$##RUST_TYPE##$get_unchecked(          \
      const std::vector<CXX_TYPE> &s, size_t pos) noexcept {                   \
    return &s[pos];                                                            \
  }                                                                            \
  void cxxbridge05$unique_ptr$std$vector$##RUST_TYPE##$null(                   \
      std::unique_ptr<std::vector<CXX_TYPE>> *ptr) noexcept {                  \
    new (ptr) std::unique_ptr<std::vector<CXX_TYPE>>();                        \
  }                                                                            \
  void cxxbridge05$unique_ptr$std$vector$##RUST_TYPE##$raw(                    \
      std::unique_ptr<std::vector<CXX_TYPE>> *ptr,                             \
      std::vector<CXX_TYPE> *raw) noexcept {                                   \
    new (ptr) std::unique_ptr<std::vector<CXX_TYPE>>(raw);                     \
  }                                                                            \
  const std::vector<CXX_TYPE>                                                  \
      *cxxbridge05$unique_ptr$std$vector$##RUST_TYPE##$get(                    \
          const std::unique_ptr<std::vector<CXX_TYPE>> &ptr) noexcept {        \
    return ptr.get();                                                          \
  }                                                                            \
  std::vector<CXX_TYPE>                                                        \
      *cxxbridge05$unique_ptr$std$vector$##RUST_TYPE##$release(                \
          std::unique_ptr<std::vector<CXX_TYPE>> &ptr) noexcept {              \
    return ptr.release();                                                      \
  }                                                                            \
  void cxxbridge05$unique_ptr$std$vector$##RUST_TYPE##$drop(                   \
      std::unique_ptr<std::vector<CXX_TYPE>> *ptr) noexcept {                  \
    ptr->~unique_ptr();                                                        \
  }

#define RUST_VEC_EXTERNS(RUST_TYPE, CXX_TYPE)                                  \
  void cxxbridge05$rust_vec$##RUST_TYPE##$new(                                 \
      rust::Vec<CXX_TYPE> *ptr) noexcept;                                      \
  void cxxbridge05$rust_vec$##RUST_TYPE##$drop(                                \
      rust::Vec<CXX_TYPE> *ptr) noexcept;                                      \
  size_t cxxbridge05$rust_vec$##RUST_TYPE##$len(                               \
      const rust::Vec<CXX_TYPE> *ptr) noexcept;                                \
  const CXX_TYPE *cxxbridge05$rust_vec$##RUST_TYPE##$data(                     \
      const rust::Vec<CXX_TYPE> *ptr) noexcept;                                \
  size_t cxxbridge05$rust_vec$##RUST_TYPE##$stride() noexcept;

#define RUST_VEC_OPS(RUST_TYPE, CXX_TYPE)                                      \
  template <>                                                                  \
  Vec<CXX_TYPE>::Vec() noexcept {                                              \
    cxxbridge05$rust_vec$##RUST_TYPE##$new(this);                              \
  }                                                                            \
  template <>                                                                  \
  void Vec<CXX_TYPE>::drop() noexcept {                                        \
    return cxxbridge05$rust_vec$##RUST_TYPE##$drop(this);                      \
  }                                                                            \
  template <>                                                                  \
  size_t Vec<CXX_TYPE>::size() const noexcept {                                \
    return cxxbridge05$rust_vec$##RUST_TYPE##$len(this);                       \
  }                                                                            \
  template <>                                                                  \
  const CXX_TYPE *Vec<CXX_TYPE>::data() const noexcept {                       \
    return cxxbridge05$rust_vec$##RUST_TYPE##$data(this);                      \
  }                                                                            \
  template <>                                                                  \
  size_t Vec<CXX_TYPE>::stride() noexcept {                                    \
    return cxxbridge05$rust_vec$##RUST_TYPE##$stride();                        \
  }

// Usize and isize are the same type as one of the below.
#define FOR_EACH_NUMERIC(MACRO)                                                \
  MACRO(u8, uint8_t)                                                           \
  MACRO(u16, uint16_t)                                                         \
  MACRO(u32, uint32_t)                                                         \
  MACRO(u64, uint64_t)                                                         \
  MACRO(i8, int8_t)                                                            \
  MACRO(i16, int16_t)                                                          \
  MACRO(i32, int32_t)                                                          \
  MACRO(i64, int64_t)                                                          \
  MACRO(f32, float)                                                            \
  MACRO(f64, double)

#define FOR_EACH_STD_VECTOR(MACRO)                                             \
  FOR_EACH_NUMERIC(MACRO)                                                      \
  MACRO(usize, size_t)                                                         \
  MACRO(isize, rust::isize)                                                    \
  MACRO(string, std::string)

#define FOR_EACH_RUST_VEC(MACRO)                                               \
  FOR_EACH_NUMERIC(MACRO)                                                      \
  MACRO(bool, bool)                                                            \
  MACRO(string, rust::String)

extern "C" {
FOR_EACH_STD_VECTOR(STD_VECTOR_OPS)
FOR_EACH_RUST_VEC(RUST_VEC_EXTERNS)
} // extern "C"

namespace rust {
inline namespace cxxbridge05 {
FOR_EACH_RUST_VEC(RUST_VEC_OPS)
} // namespace cxxbridge05
} // namespace rust
<|endoftext|>


<commit_before>// Copyright (c) 2009-2010 Satoshi Nakamoto
// Copyright (c) 2009-2014 The Bitcoin developers
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#include "db.h"

#include "addrman.h"
#include "hash.h"
#include "protocol.h"
#include "util.h"
#include "utilstrencodings.h"

#include <stdint.h>

#ifndef WIN32
#include <sys/stat.h>
#endif

#include <boost/filesystem.hpp>
#include <boost/thread.hpp>
#include <boost/version.hpp>

#include <openssl/rand.h>

using namespace std;
using namespace boost;

unsigned int nWalletDBUpdated;

//
// CDB
//

CDBEnv bitdb;

void CDBEnv::EnvShutdown()
{
    if (!fDbEnvInit)
        return;

    fDbEnvInit = false;
    int ret = dbenv.close(0);
    if (ret != 0)
        LogPrintf("CDBEnv::EnvShutdown : Error %d shutting down database environment: %s\n", ret, DbEnv::strerror(ret));
    if (!fMockDb)
        DbEnv(0).remove(path.string().c_str(), 0);
}

CDBEnv::CDBEnv() : dbenv(DB_CXX_NO_EXCEPTIONS)
{
    fDbEnvInit = false;
    fMockDb = false;
}

CDBEnv::~CDBEnv()
{
    EnvShutdown();
}

void CDBEnv::Close()
{
    EnvShutdown();
}

bool CDBEnv::Open(const boost::filesystem::path& pathIn)
{
    if (fDbEnvInit)
        return true;

    boost::this_thread::interruption_point();

    path = pathIn;
    filesystem::path pathLogDir = path / "database";
    TryCreateDirectory(pathLogDir);
    filesystem::path pathErrorFile = path / "db.log";
    LogPrintf("CDBEnv::Open : LogDir=%s ErrorFile=%s\n", pathLogDir.string(), pathErrorFile.string());

    unsigned int nEnvFlags = 0;
    if (GetBoolArg("-privdb", true))
        nEnvFlags |= DB_PRIVATE;

    dbenv.set_lg_dir(pathLogDir.string().c_str());
    dbenv.set_cachesize(0, 0x100000, 1); // 1 MiB should be enough for just the wallet
    dbenv.set_lg_bsize(0x10000);
    dbenv.set_lg_max(1048576);
    dbenv.set_lk_max_locks(40000);
    dbenv.set_lk_max_objects(40000);
    dbenv.set_errfile(fopen(pathErrorFile.string().c_str(), "a")); /// debug
    dbenv.set_flags(DB_AUTO_COMMIT, 1);
    dbenv.set_flags(DB_TXN_WRITE_NOSYNC, 1);
    dbenv.log_set_config(DB_LOG_AUTO_REMOVE, 1);
    int ret = dbenv.open(path.string().c_str(),
                         DB_CREATE |
                             DB_INIT_LOCK |
                             DB_INIT_LOG |
                             DB_INIT_MPOOL |
                             DB_INIT_TXN |
                             DB_THREAD |
                             DB_RECOVER |
                             nEnvFlags,
                         S_IRUSR | S_IWUSR);
    if (ret != 0)
        return error("CDBEnv::Open : Error %d opening database environment: %s\n", ret, DbEnv::strerror(ret));

    fDbEnvInit = true;
    fMockDb = false;
    return true;
}

void CDBEnv::MakeMock()
{
    if (fDbEnvInit)
        throw runtime_error("CDBEnv::MakeMock : Already initialized");

    boost::this_thread::interruption_point();

    LogPrint("db", "CDBEnv::MakeMock\n");

    dbenv.set_cachesize(1, 0, 1);
    dbenv.set_lg_bsize(10485760 * 4);
    dbenv.set_lg_max(10485760);
    dbenv.set_lk_max_locks(10000);
    dbenv.set_lk_max_objects(10000);
    dbenv.set_flags(DB_AUTO_COMMIT, 1);
    dbenv.log_set_config(DB_LOG_IN_MEMORY, 1);
    int ret = dbenv.open(NULL,
                         DB_CREATE |
                             DB_INIT_LOCK |
                             DB_INIT_LOG |
                             DB_INIT_MPOOL |
                             DB_INIT_TXN |
                             DB_THREAD |
                             DB_PRIVATE,
                         S_IRUSR | S_IWUSR);
    if (ret > 0)
        throw runtime_error(strprintf("CDBEnv::MakeMock : Error %d opening database environment.", ret));

    fDbEnvInit = true;
    fMockDb = true;
}

CDBEnv::VerifyResult CDBEnv::Verify(std::string strFile, bool (*recoverFunc)(CDBEnv& dbenv, std::string strFile))
{
    LOCK(cs_db);
    assert(mapFileUseCount.count(strFile) == 0);

    Db db(&dbenv, 0);
    int result = db.verify(strFile.c_str(), NULL, NULL, 0);
    if (result == 0)
        return VERIFY_OK;
    else if (recoverFunc == NULL)
        return RECOVER_FAIL;

    // Try to recover:
    bool fRecovered = (*recoverFunc)(*this, strFile);
    return (fRecovered ? RECOVER_OK : RECOVER_FAIL);
}

bool CDBEnv::Salvage(std::string strFile, bool fAggressive, std::vector<CDBEnv::KeyValPair>& vResult)
{
    LOCK(cs_db);
    assert(mapFileUseCount.count(strFile) == 0);

    u_int32_t flags = DB_SALVAGE;
    if (fAggressive)
        flags |= DB_AGGRESSIVE;

    stringstream strDump;

    Db db(&dbenv, 0);
    int result = db.verify(strFile.c_str(), NULL, &strDump, flags);
    if (result == DB_VERIFY_BAD) {
        LogPrintf("CDBEnv::Salvage : Database salvage found errors, all data may not be recoverable.\n");
        if (!fAggressive) {
            LogPrintf("CDBEnv::Salvage : Rerun with aggressive mode to ignore errors and continue.\n");
            return false;
        }
    }
    if (result != 0 && result != DB_VERIFY_BAD) {
        LogPrintf("CDBEnv::Salvage : Database salvage failed with result %d.\n", result);
        return false;
    }

    // Format of bdb dump is ascii lines:
    // header lines...
    // HEADER=END
    // hexadecimal key
    // hexadecimal value
    // ... repeated
    // DATA=END

    string strLine;
    while (!strDump.eof() && strLine != "HEADER=END")
        getline(strDump, strLine); // Skip past header

    std::string keyHex, valueHex;
    while (!strDump.eof() && keyHex != "DATA=END") {
        getline(strDump, keyHex);
        if (keyHex != "DATA_END") {
            getline(strDump, valueHex);
            vResult.push_back(make_pair(ParseHex(keyHex), ParseHex(valueHex)));
        }
    }

    return (result == 0);
}

void CDBEnv::CheckpointLSN(const std::string& strFile)
{
    dbenv.txn_checkpoint(0, 0, 0);
    if (fMockDb)
        return;
    dbenv.lsn_reset(strFile.c_str(), 0);
}

CDB::CDB(const std::string& strFilename, const char* pszMode) : pdb(NULL), activeTxn(NULL)
{
    int ret;
    fReadOnly = (!strchr(pszMode, '+') && !strchr(pszMode, 'w'));
    if (strFilename.empty())
        return;

    bool fCreate = strchr(pszMode, 'c') != NULL;
    unsigned int nFlags = DB_THREAD;
    if (fCreate)
        nFlags |= DB_CREATE;

    {
        LOCK(bitdb.cs_db);
        if (!bitdb.Open(GetDataDir()))
            throw runtime_error("CDB : Failed to open database environment.");

        strFile = strFilename;
        ++bitdb.mapFileUseCount[strFile];
        pdb = bitdb.mapDb[strFile];
        if (pdb == NULL) {
            pdb = new Db(&bitdb.dbenv, 0);

            bool fMockDb = bitdb.IsMock();
            if (fMockDb) {
                DbMpoolFile* mpf = pdb->get_mpf();
                ret = mpf->set_flags(DB_MPOOL_NOFILE, 1);
                if (ret != 0)
                    throw runtime_error(strprintf("CDB : Failed to configure for no temp file backing for database %s", strFile));
            }

            ret = pdb->open(NULL,                               // Txn pointer
                            fMockDb ? NULL : strFile.c_str(),   // Filename
                            fMockDb ? strFile.c_str() : "main", // Logical db name
                            DB_BTREE,                           // Database type
                            nFlags,                             // Flags
                            0);

            if (ret != 0) {
                delete pdb;
                pdb = NULL;
                --bitdb.mapFileUseCount[strFile];
                strFile = "";
                throw runtime_error(strprintf("CDB : Error %d, can't open database %s", ret, strFile));
            }

            if (fCreate && !Exists(string("version"))) {
                bool fTmp = fReadOnly;
                fReadOnly = false;
                WriteVersion(CLIENT_VERSION);
                fReadOnly = fTmp;
            }

            bitdb.mapDb[strFile] = pdb;
        }
    }
}

void CDB::Flush()
{
    if (activeTxn)
        return;

    // Flush database activity from memory pool to disk log
    unsigned int nMinutes = 0;
    if (fReadOnly)
        nMinutes = 1;

    bitdb.dbenv.txn_checkpoint(nMinutes ? GetArg("-dblogsize", 100) * 1024 : 0, nMinutes, 0);
}

void CDB::Close()
{
    if (!pdb)
        return;
    if (activeTxn)
        activeTxn->abort();
    activeTxn = NULL;
    pdb = NULL;

    Flush();

    {
        LOCK(bitdb.cs_db);
        --bitdb.mapFileUseCount[strFile];
    }
}

void CDBEnv::CloseDb(const string& strFile)
{
    {
        LOCK(cs_db);
        if (mapDb[strFile] != NULL) {
            // Close the database handle
            Db* pdb = mapDb[strFile];
            pdb->close(0);
            delete pdb;
            mapDb[strFile] = NULL;
        }
    }
}

bool CDBEnv::RemoveDb(const string& strFile)
{
    this->CloseDb(strFile);

    LOCK(cs_db);
    int rc = dbenv.dbremove(NULL, strFile.c_str(), NULL, DB_AUTO_COMMIT);
    return (rc == 0);
}

bool CDB::Rewrite(const string& strFile, const char* pszSkip)
{
    while (true) {
        {
            LOCK(bitdb.cs_db);
            if (!bitdb.mapFileUseCount.count(strFile) || bitdb.mapFileUseCount[strFile] == 0) {
                // Flush log data to the dat file
                bitdb.CloseDb(strFile);
                bitdb.CheckpointLSN(strFile);
                bitdb.mapFileUseCount.erase(strFile);

                bool fSuccess = true;
                LogPrintf("CDB::Rewrite : Rewriting %s...\n", strFile);
                string strFileRes = strFile + ".rewrite";
                { // surround usage of db with extra {}
                    CDB db(strFile.c_str(), "r");
                    Db* pdbCopy = new Db(&bitdb.dbenv, 0);

                    int ret = pdbCopy->open(NULL,               // Txn pointer
                                            strFileRes.c_str(), // Filename
                                            "main",             // Logical db name
                                            DB_BTREE,           // Database type
                                            DB_CREATE,          // Flags
                                            0);
                    if (ret > 0) {
                        LogPrintf("CDB::Rewrite : Can't create database file %s\n", strFileRes);
                        fSuccess = false;
                    }

                    Dbc* pcursor = db.GetCursor();
                    if (pcursor)
                        while (fSuccess) {
                            CDataStream ssKey(SER_DISK, CLIENT_VERSION);
                            CDataStream ssValue(SER_DISK, CLIENT_VERSION);
                            int ret = db.ReadAtCursor(pcursor, ssKey, ssValue, DB_NEXT);
                            if (ret == DB_NOTFOUND) {
                                pcursor->close();
                                break;
                            } else if (ret != 0) {
                                pcursor->close();
                                fSuccess = false;
                                break;
                            }
                            if (pszSkip &&
                                strncmp(&ssKey[0], pszSkip, std::min(ssKey.size(), strlen(pszSkip))) == 0)
                                continue;
                            if (strncmp(&ssKey[0], "\x07version", 8) == 0) {
                                // Update version:
                                ssValue.clear();
                                ssValue << CLIENT_VERSION;
                            }
                            Dbt datKey(&ssKey[0], ssKey.size());
                            Dbt datValue(&ssValue[0], ssValue.size());
                            int ret2 = pdbCopy->put(NULL, &datKey, &datValue, DB_NOOVERWRITE);
                            if (ret2 > 0)
                                fSuccess = false;
                        }
                    if (fSuccess) {
                        db.Close();
                        bitdb.CloseDb(strFile);
                        if (pdbCopy->close(0))
                            fSuccess = false;
                        delete pdbCopy;
                    }
                }
                if (fSuccess) {
                    Db dbA(&bitdb.dbenv, 0);
                    if (dbA.remove(strFile.c_str(), NULL, 0))
                        fSuccess = false;
                    Db dbB(&bitdb.dbenv, 0);
                    if (dbB.rename(strFileRes.c_str(), NULL, strFile.c_str(), 0))
                        fSuccess = false;
                }
                if (!fSuccess)
                    LogPrintf("CDB::Rewrite : Failed to rewrite database file %s\n", strFileRes);
                return fSuccess;
            }
        }
        MilliSleep(100);
    }
    return false;
}

void CDBEnv::Flush(bool fShutdown)
{
    int64_t nStart = GetTimeMillis();
    // Flush log data to the actual data file on all files that are not in use
    LogPrint("db", "CDBEnv::Flush : Flush(%s)%s\n", fShutdown ? "true" : "false", fDbEnvInit ? "" : " database not started");
    if (!fDbEnvInit)
        return;
    {
        LOCK(cs_db);
        map<string, int>::iterator mi = mapFileUseCount.begin();
        while (mi != mapFileUseCount.end()) {
            string strFile = (*mi).first;
            int nRefCount = (*mi).second;
            LogPrint("db", "CDBEnv::Flush : Flushing %s (refcount = %d)...\n", strFile, nRefCount);
            if (nRefCount == 0) {
                // Move log data to the dat file
                CloseDb(strFile);
                LogPrint("db", "CDBEnv::Flush : %s checkpoint\n", strFile);
                dbenv.txn_checkpoint(0, 0, 0);
                LogPrint("db", "CDBEnv::Flush : %s detach\n", strFile);
                if (!fMockDb)
                    dbenv.lsn_reset(strFile.c_str(), 0);
                LogPrint("db", "CDBEnv::Flush : %s closed\n", strFile);
                mapFileUseCount.erase(mi++);
            } else
                mi++;
        }
        LogPrint("db", "CDBEnv::Flush : Flush(%s)%s took %15dms\n", fShutdown ? "true" : "false", fDbEnvInit ? "" : " database not started", GetTimeMillis() - nStart);
        if (fShutdown) {
            char** listp;
            if (mapFileUseCount.empty()) {
                dbenv.log_archive(&listp, DB_ARCH_REMOVE);
                Close();
                if (!fMockDb)
                    boost::filesystem::remove_all(path / "database");
            }
        }
    }
}
<commit_msg>[walletdb] Fix syntax error in key parser<commit_after>// Copyright (c) 2009-2010 Satoshi Nakamoto
// Copyright (c) 2009-2014 The Bitcoin developers
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#include "db.h"

#include "addrman.h"
#include "hash.h"
#include "protocol.h"
#include "util.h"
#include "utilstrencodings.h"

#include <stdint.h>

#ifndef WIN32
#include <sys/stat.h>
#endif

#include <boost/filesystem.hpp>
#include <boost/thread.hpp>
#include <boost/version.hpp>

#include <openssl/rand.h>

using namespace std;
using namespace boost;

unsigned int nWalletDBUpdated;

//
// CDB
//

CDBEnv bitdb;

void CDBEnv::EnvShutdown()
{
    if (!fDbEnvInit)
        return;

    fDbEnvInit = false;
    int ret = dbenv.close(0);
    if (ret != 0)
        LogPrintf("CDBEnv::EnvShutdown : Error %d shutting down database environment: %s\n", ret, DbEnv::strerror(ret));
    if (!fMockDb)
        DbEnv(0).remove(path.string().c_str(), 0);
}

CDBEnv::CDBEnv() : dbenv(DB_CXX_NO_EXCEPTIONS)
{
    fDbEnvInit = false;
    fMockDb = false;
}

CDBEnv::~CDBEnv()
{
    EnvShutdown();
}

void CDBEnv::Close()
{
    EnvShutdown();
}

bool CDBEnv::Open(const boost::filesystem::path& pathIn)
{
    if (fDbEnvInit)
        return true;

    boost::this_thread::interruption_point();

    path = pathIn;
    filesystem::path pathLogDir = path / "database";
    TryCreateDirectory(pathLogDir);
    filesystem::path pathErrorFile = path / "db.log";
    LogPrintf("CDBEnv::Open : LogDir=%s ErrorFile=%s\n", pathLogDir.string(), pathErrorFile.string());

    unsigned int nEnvFlags = 0;
    if (GetBoolArg("-privdb", true))
        nEnvFlags |= DB_PRIVATE;

    dbenv.set_lg_dir(pathLogDir.string().c_str());
    dbenv.set_cachesize(0, 0x100000, 1); // 1 MiB should be enough for just the wallet
    dbenv.set_lg_bsize(0x10000);
    dbenv.set_lg_max(1048576);
    dbenv.set_lk_max_locks(40000);
    dbenv.set_lk_max_objects(40000);
    dbenv.set_errfile(fopen(pathErrorFile.string().c_str(), "a")); /// debug
    dbenv.set_flags(DB_AUTO_COMMIT, 1);
    dbenv.set_flags(DB_TXN_WRITE_NOSYNC, 1);
    dbenv.log_set_config(DB_LOG_AUTO_REMOVE, 1);
    int ret = dbenv.open(path.string().c_str(),
                         DB_CREATE |
                             DB_INIT_LOCK |
                             DB_INIT_LOG |
                             DB_INIT_MPOOL |
                             DB_INIT_TXN |
                             DB_THREAD |
                             DB_RECOVER |
                             nEnvFlags,
                         S_IRUSR | S_IWUSR);
    if (ret != 0)
        return error("CDBEnv::Open : Error %d opening database environment: %s\n", ret, DbEnv::strerror(ret));

    fDbEnvInit = true;
    fMockDb = false;
    return true;
}

void CDBEnv::MakeMock()
{
    if (fDbEnvInit)
        throw runtime_error("CDBEnv::MakeMock : Already initialized");

    boost::this_thread::interruption_point();

    LogPrint("db", "CDBEnv::MakeMock\n");

    dbenv.set_cachesize(1, 0, 1);
    dbenv.set_lg_bsize(10485760 * 4);
    dbenv.set_lg_max(10485760);
    dbenv.set_lk_max_locks(10000);
    dbenv.set_lk_max_objects(10000);
    dbenv.set_flags(DB_AUTO_COMMIT, 1);
    dbenv.log_set_config(DB_LOG_IN_MEMORY, 1);
    int ret = dbenv.open(NULL,
                         DB_CREATE |
                             DB_INIT_LOCK |
                             DB_INIT_LOG |
                             DB_INIT_MPOOL |
                             DB_INIT_TXN |
                             DB_THREAD |
                             DB_PRIVATE,
                         S_IRUSR | S_IWUSR);
    if (ret > 0)
        throw runtime_error(strprintf("CDBEnv::MakeMock : Error %d opening database environment.", ret));

    fDbEnvInit = true;
    fMockDb = true;
}

CDBEnv::VerifyResult CDBEnv::Verify(std::string strFile, bool (*recoverFunc)(CDBEnv& dbenv, std::string strFile))
{
    LOCK(cs_db);
    assert(mapFileUseCount.count(strFile) == 0);

    Db db(&dbenv, 0);
    int result = db.verify(strFile.c_str(), NULL, NULL, 0);
    if (result == 0)
        return VERIFY_OK;
    else if (recoverFunc == NULL)
        return RECOVER_FAIL;

    // Try to recover:
    bool fRecovered = (*recoverFunc)(*this, strFile);
    return (fRecovered ? RECOVER_OK : RECOVER_FAIL);
}

bool CDBEnv::Salvage(std::string strFile, bool fAggressive, std::vector<CDBEnv::KeyValPair>& vResult)
{
    LOCK(cs_db);
    assert(mapFileUseCount.count(strFile) == 0);

    u_int32_t flags = DB_SALVAGE;
    if (fAggressive)
        flags |= DB_AGGRESSIVE;

    stringstream strDump;

    Db db(&dbenv, 0);
    int result = db.verify(strFile.c_str(), NULL, &strDump, flags);
    if (result == DB_VERIFY_BAD) {
        LogPrintf("CDBEnv::Salvage : Database salvage found errors, all data may not be recoverable.\n");
        if (!fAggressive) {
            LogPrintf("CDBEnv::Salvage : Rerun with aggressive mode to ignore errors and continue.\n");
            return false;
        }
    }
    if (result != 0 && result != DB_VERIFY_BAD) {
        LogPrintf("CDBEnv::Salvage : Database salvage failed with result %d.\n", result);
        return false;
    }

    // Format of bdb dump is ascii lines:
    // header lines...
    // HEADER=END
    // hexadecimal key
    // hexadecimal value
    // ... repeated
    // DATA=END

    string strLine;
    while (!strDump.eof() && strLine != "HEADER=END")
        getline(strDump, strLine); // Skip past header

    std::string keyHex, valueHex;
    while (!strDump.eof() && keyHex != "DATA=END") {
        getline(strDump, keyHex);
        if (keyHex != "DATA=END") {
            getline(strDump, valueHex);
            vResult.push_back(make_pair(ParseHex(keyHex), ParseHex(valueHex)));
        }
    }

    return (result == 0);
}

void CDBEnv::CheckpointLSN(const std::string& strFile)
{
    dbenv.txn_checkpoint(0, 0, 0);
    if (fMockDb)
        return;
    dbenv.lsn_reset(strFile.c_str(), 0);
}

CDB::CDB(const std::string& strFilename, const char* pszMode) : pdb(NULL), activeTxn(NULL)
{
    int ret;
    fReadOnly = (!strchr(pszMode, '+') && !strchr(pszMode, 'w'));
    if (strFilename.empty())
        return;

    bool fCreate = strchr(pszMode, 'c') != NULL;
    unsigned int nFlags = DB_THREAD;
    if (fCreate)
        nFlags |= DB_CREATE;

    {
        LOCK(bitdb.cs_db);
        if (!bitdb.Open(GetDataDir()))
            throw runtime_error("CDB : Failed to open database environment.");

        strFile = strFilename;
        ++bitdb.mapFileUseCount[strFile];
        pdb = bitdb.mapDb[strFile];
        if (pdb == NULL) {
            pdb = new Db(&bitdb.dbenv, 0);

            bool fMockDb = bitdb.IsMock();
            if (fMockDb) {
                DbMpoolFile* mpf = pdb->get_mpf();
                ret = mpf->set_flags(DB_MPOOL_NOFILE, 1);
                if (ret != 0)
                    throw runtime_error(strprintf("CDB : Failed to configure for no temp file backing for database %s", strFile));
            }

            ret = pdb->open(NULL,                               // Txn pointer
                            fMockDb ? NULL : strFile.c_str(),   // Filename
                            fMockDb ? strFile.c_str() : "main", // Logical db name
                            DB_BTREE,                           // Database type
                            nFlags,                             // Flags
                            0);

            if (ret != 0) {
                delete pdb;
                pdb = NULL;
                --bitdb.mapFileUseCount[strFile];
                strFile = "";
                throw runtime_error(strprintf("CDB : Error %d, can't open database %s", ret, strFile));
            }

            if (fCreate && !Exists(string("version"))) {
                bool fTmp = fReadOnly;
                fReadOnly = false;
                WriteVersion(CLIENT_VERSION);
                fReadOnly = fTmp;
            }

            bitdb.mapDb[strFile] = pdb;
        }
    }
}

void CDB::Flush()
{
    if (activeTxn)
        return;

    // Flush database activity from memory pool to disk log
    unsigned int nMinutes = 0;
    if (fReadOnly)
        nMinutes = 1;

    bitdb.dbenv.txn_checkpoint(nMinutes ? GetArg("-dblogsize", 100) * 1024 : 0, nMinutes, 0);
}

void CDB::Close()
{
    if (!pdb)
        return;
    if (activeTxn)
        activeTxn->abort();
    activeTxn = NULL;
    pdb = NULL;

    Flush();

    {
        LOCK(bitdb.cs_db);
        --bitdb.mapFileUseCount[strFile];
    }
}

void CDBEnv::CloseDb(const string& strFile)
{
    {
        LOCK(cs_db);
        if (mapDb[strFile] != NULL) {
            // Close the database handle
            Db* pdb = mapDb[strFile];
            pdb->close(0);
            delete pdb;
            mapDb[strFile] = NULL;
        }
    }
}

bool CDBEnv::RemoveDb(const string& strFile)
{
    this->CloseDb(strFile);

    LOCK(cs_db);
    int rc = dbenv.dbremove(NULL, strFile.c_str(), NULL, DB_AUTO_COMMIT);
    return (rc == 0);
}

bool CDB::Rewrite(const string& strFile, const char* pszSkip)
{
    while (true) {
        {
            LOCK(bitdb.cs_db);
            if (!bitdb.mapFileUseCount.count(strFile) || bitdb.mapFileUseCount[strFile] == 0) {
                // Flush log data to the dat file
                bitdb.CloseDb(strFile);
                bitdb.CheckpointLSN(strFile);
                bitdb.mapFileUseCount.erase(strFile);

                bool fSuccess = true;
                LogPrintf("CDB::Rewrite : Rewriting %s...\n", strFile);
                string strFileRes = strFile + ".rewrite";
                { // surround usage of db with extra {}
                    CDB db(strFile.c_str(), "r");
                    Db* pdbCopy = new Db(&bitdb.dbenv, 0);

                    int ret = pdbCopy->open(NULL,               // Txn pointer
                                            strFileRes.c_str(), // Filename
                                            "main",             // Logical db name
                                            DB_BTREE,           // Database type
                                            DB_CREATE,          // Flags
                                            0);
                    if (ret > 0) {
                        LogPrintf("CDB::Rewrite : Can't create database file %s\n", strFileRes);
                        fSuccess = false;
                    }

                    Dbc* pcursor = db.GetCursor();
                    if (pcursor)
                        while (fSuccess) {
                            CDataStream ssKey(SER_DISK, CLIENT_VERSION);
                            CDataStream ssValue(SER_DISK, CLIENT_VERSION);
                            int ret = db.ReadAtCursor(pcursor, ssKey, ssValue, DB_NEXT);
                            if (ret == DB_NOTFOUND) {
                                pcursor->close();
                                break;
                            } else if (ret != 0) {
                                pcursor->close();
                                fSuccess = false;
                                break;
                            }
                            if (pszSkip &&
                                strncmp(&ssKey[0], pszSkip, std::min(ssKey.size(), strlen(pszSkip))) == 0)
                                continue;
                            if (strncmp(&ssKey[0], "\x07version", 8) == 0) {
                                // Update version:
                                ssValue.clear();
                                ssValue << CLIENT_VERSION;
                            }
                            Dbt datKey(&ssKey[0], ssKey.size());
                            Dbt datValue(&ssValue[0], ssValue.size());
                            int ret2 = pdbCopy->put(NULL, &datKey, &datValue, DB_NOOVERWRITE);
                            if (ret2 > 0)
                                fSuccess = false;
                        }
                    if (fSuccess) {
                        db.Close();
                        bitdb.CloseDb(strFile);
                        if (pdbCopy->close(0))
                            fSuccess = false;
                        delete pdbCopy;
                    }
                }
                if (fSuccess) {
                    Db dbA(&bitdb.dbenv, 0);
                    if (dbA.remove(strFile.c_str(), NULL, 0))
                        fSuccess = false;
                    Db dbB(&bitdb.dbenv, 0);
                    if (dbB.rename(strFileRes.c_str(), NULL, strFile.c_str(), 0))
                        fSuccess = false;
                }
                if (!fSuccess)
                    LogPrintf("CDB::Rewrite : Failed to rewrite database file %s\n", strFileRes);
                return fSuccess;
            }
        }
        MilliSleep(100);
    }
    return false;
}

void CDBEnv::Flush(bool fShutdown)
{
    int64_t nStart = GetTimeMillis();
    // Flush log data to the actual data file on all files that are not in use
    LogPrint("db", "CDBEnv::Flush : Flush(%s)%s\n", fShutdown ? "true" : "false", fDbEnvInit ? "" : " database not started");
    if (!fDbEnvInit)
        return;
    {
        LOCK(cs_db);
        map<string, int>::iterator mi = mapFileUseCount.begin();
        while (mi != mapFileUseCount.end()) {
            string strFile = (*mi).first;
            int nRefCount = (*mi).second;
            LogPrint("db", "CDBEnv::Flush : Flushing %s (refcount = %d)...\n", strFile, nRefCount);
            if (nRefCount == 0) {
                // Move log data to the dat file
                CloseDb(strFile);
                LogPrint("db", "CDBEnv::Flush : %s checkpoint\n", strFile);
                dbenv.txn_checkpoint(0, 0, 0);
                LogPrint("db", "CDBEnv::Flush : %s detach\n", strFile);
                if (!fMockDb)
                    dbenv.lsn_reset(strFile.c_str(), 0);
                LogPrint("db", "CDBEnv::Flush : %s closed\n", strFile);
                mapFileUseCount.erase(mi++);
            } else
                mi++;
        }
        LogPrint("db", "CDBEnv::Flush : Flush(%s)%s took %15dms\n", fShutdown ? "true" : "false", fDbEnvInit ? "" : " database not started", GetTimeMillis() - nStart);
        if (fShutdown) {
            char** listp;
            if (mapFileUseCount.empty()) {
                dbenv.log_archive(&listp, DB_ARCH_REMOVE);
                Close();
                if (!fMockDb)
                    boost::filesystem::remove_all(path / "database");
            }
        }
    }
}
<|endoftext|>


<commit_before>
#include <stdio.h>

#include "charset.h"
#include "str.h"
#include "contain.h"
#include "except.h"
#include "source.h"
#include "baseobj.h"

// ------------------------------------------------------------------------ //
// --- TOKEN EXTRACTOR ---------------------------------------------------- //
// ------------------------------------------------------------------------ //

class EParser: public EMessage
{
protected:
    string filename;
    int linenum;
public:
    EParser(const string& ifilename, int ilinenum, const string& msg)
        : EMessage(msg), filename(ifilename), linenum(ilinenum)  { }
    virtual ~EParser() throw();
    virtual string what() const throw();
};

enum Token
{
    tokUndefined = -1,
    tokBlockBegin, tokBlockEnd, tokEnd, // these depend on C-style vs. Python-style mode
    tokEof,
    tokIdent, tokIntValue, tokStrValue,
    tokComma, tokPeriod, tokDiv
};

enum SyntaxMode { syntaxIndent, syntaxCurly };

class Parser
{
protected:
    InText* input;
    Stack<int> indentStack;

    void parseStringLiteral();
    void skipMultilineComment();

public:
    SyntaxMode mode;
    bool singleLineBlock; // only for syntaxIndent, e.g. if a: b = c
    Token token;
    string strValue;
    ularge intValue;

    Parser(const string& filename);
    ~Parser();

    Token next() throw(EParser, ESysError);

    void error(const string& msg) throw(EParser);
    void syntax(const string& msg) throw(EParser);

    int indentLevel()  { return indentStack.top(); }
};

// ------------------------------------------------------------------------ //

EParser::~EParser() throw() { }

string EParser::what() const throw()
{
    string s;
    if (!filename.empty())
        s = filename + '(' + itostring(linenum) + "): ";
    return s + EMessage::what();
}

const charset wsChars = "\t ";
const charset identFirst = "A-Za-z_";
const charset identRest = "0-9A-Za-z_";
const charset digits = "0-9";
const charset hexDigits = "0-9A-Fa-f";
const charset printableChars = "~20-~FF";

static string mkPrintable(char c)
{
    if (c == '\\')
        return string("\\\\");
    else if (c == '\'')
        return string("\\\'");
    else if (printableChars[c])
        return string(c);
    else
        return "\\x" + itostring(unsigned(c), 16);
}

Parser::Parser(const string& filename)
    : input(new InFile(filename)),
      indentStack(), mode(syntaxIndent), singleLineBlock(false),
      token(tokUndefined), strValue(), intValue(0)
{
    indentStack.push(0);
}

Parser::~Parser()
{
    delete input;
}

void Parser::error(const string& msg) throw(EParser)
{
    throw EParser(input->getFileName(), input->getLinenum(), msg);
}

void Parser::syntax(const string& msg) throw(EParser)
{
    error("Syntax error: " + msg);
}

void Parser::parseStringLiteral()
{
    static const charset stringChars = printableChars - charset("'\\");
    strValue.clear();
    while (true)
    {
        strValue += input->token(stringChars);
        if (input->getEof())
            syntax("Unexpected end of file in string literal");
        char c = input->get();
        if (input->isEolChar(c))
            syntax("Unexpected end of line in string literal");
        if (c == '\'')
            return;
        else if (c == '\\')
        {
            c = input->get();
            if (c == 't')
                strValue += '\t';
            else if (c == 'r')
                strValue += '\r';
            else if (c == 'n')
                strValue += '\n';
            else if (c == 'x')
            {
                string s;
                if (hexDigits[input->preview()])
                {
                    s += input->get();
                    if (hexDigits[input->preview()])
                        s += input->get();
                    bool e, o;
                    ularge value = stringtou(s.c_str(), &e, &o, 16);
                    strValue += char(value);
                }
                else
                    syntax("Malformed hex sequence");
            }
            else
                strValue += c;
        }
        else
            syntax("Illegal character in string literal '" + mkPrintable(c) + "'");
    }
}

void Parser::skipMultilineComment()
{
    static const charset commentChars = (printableChars - '}') + wsChars;
    while (true)
    {
        input->skip(commentChars);
        if (input->getEol())
        {
            if (input->getEof())
                error("Unexpected end of file in comments");
            input->skipEol();
            continue;
        }
        char e = input->get();
        if (e == '}')
        {
            if (input->preview() == '#')
            {
                input->get();
                break;
            }
        }
        else
            syntax("Illegal character in comments '" + mkPrintable(e) + "'");
    }
    input->skip(wsChars);
    if (!input->getEol())
        syntax("Multiline comments must end with a new line");
    input->skipEol();
}

Token Parser::next() throw(EParser, ESysError)
{
restart:
    strValue.clear();

    input->skip(wsChars);

    char c = input->preview();

    // --- Handle EOF and EOL ---
    if (input->getEof())
    {
        // finalize all indents at end of file
        if (mode == syntaxIndent && indentStack.size() > 1)
        {
            strValue = "<END>";
            indentStack.pop();
            return token = tokBlockEnd;
        }
        strValue = "<EOF>";
        return token = tokEof;
    }

    else if (input->getEol())
    {
        input->skipEol();
        if (mode == syntaxIndent)
        {
            if (singleLineBlock)
            {
                strValue = "<END>";
                singleLineBlock = false;
                return token = tokBlockEnd;
            }
            else
            {
                strValue = "<SEP>";
                return token = tokEnd;
            }
        }
        else
            goto restart;
    }

    else if (c == '#')
    {
        input->get();
        if (input->preview() == '{')
            skipMultilineComment();
        else
            input->skipLine();
        goto restart;
    }

    else if (mode == syntaxIndent && input->getNewLine())
    {
        // this is a new line, blanks are skipped, so we are at the first
        // non-blank char:
        int newIndent = input->getIndent();
        int oldIndent = indentStack.top();
        if (newIndent > oldIndent)
        {
            strValue = "<BEGIN>";
            indentStack.push(newIndent);
            input->resetNewLine();
            return token = tokBlockBegin;
        }
        else if (newIndent < oldIndent)
        {
            strValue = "<END>";
            indentStack.pop();
            oldIndent = indentStack.top();
            if (newIndent > oldIndent)
                syntax("Unmatched un-indent");
            else if (newIndent == oldIndent)
            {
                input->resetNewLine();
                return token = tokBlockEnd;
            }
            else
                return token = tokBlockEnd;
        }
        // else: pass through to token analysis
    }

    // --- Handle ordinary tokens ---
    if (identFirst[c])  // identifier or keyword
    {
        strValue = input->get();
        strValue += input->token(identRest);
        return token = tokIdent;
    }

    else if (digits[c])  // numeric
    {
        strValue = input->token(digits);
        bool e, o;
        intValue = stringtou(strValue.c_str(), &e, &o, 10);
        if (e)
            error("'" + strValue + "' is not a valid number");
        if (o)
            error("Numeric overflow (" + strValue + ")");
        return token = tokIntValue;
    }

    else  // special chars
    {
        strValue = input->get();
        switch (c)
        {
        case ',': return token = tokComma;
        case '.': return token = tokPeriod;
        case '\'': parseStringLiteral(); return token = tokStrValue;
        case ';': strValue = "<SEP>"; return token = tokEnd;
        case ':':
            mode = syntaxIndent;
            input->skip(wsChars);
            singleLineBlock = !input->getEol();
            return token = tokBlockBegin;
        case '/': return token = tokDiv;
        }
    }

    syntax("Illegal character '" + mkPrintable(c) + "'");

    return tokUndefined;
}

class _AtExit
{
public:
    ~_AtExit()
    {
        if (Base::objCount != 0)
            fprintf(stderr, "Internal: objCount = %d\n", Base::objCount);
        if (stralloc != 0)
            fprintf(stderr, "Internal: stralloc = %d\n", stralloc);
        if (FifoChunk::chunkCount != 0)
            fprintf(stderr, "Internal: chunkCount = %d\n", FifoChunk::chunkCount);
    }
} _atexit;

int main()
{
    Parser parser("tests/parser.txt");
    try
    {
        while (parser.next() != tokEof)
        {
            printf("%s ", parser.strValue.c_str());
            if (parser.token == tokBlockBegin || parser.token == tokBlockEnd || parser.token == tokEnd)
                printf("\n");
        }
    }
    catch (Exception& e)
    {
        fprintf(stderr, "%s\n", e.what().c_str());
    }
    return 0;
}

<commit_msg>Will not support C-style blocks yet, too complicated. Later maybe.<commit_after>
#include <stdio.h>

#include "charset.h"
#include "str.h"
#include "contain.h"
#include "except.h"
#include "source.h"
#include "baseobj.h"

// ------------------------------------------------------------------------ //
// --- TOKEN EXTRACTOR ---------------------------------------------------- //
// ------------------------------------------------------------------------ //

class EParser: public EMessage
{
protected:
    string filename;
    int linenum;
public:
    EParser(const string& ifilename, int ilinenum, const string& msg)
        : EMessage(msg), filename(ifilename), linenum(ilinenum)  { }
    virtual ~EParser() throw();
    virtual string what() const throw();
};

enum Token
{
    tokUndefined = -1,
    tokBlockBegin, tokBlockEnd, tokEnd, // these will depend on C-style vs. Python-style modes in the future
    tokEof,
    tokIdent, tokIntValue, tokStrValue,
    tokComma, tokPeriod, tokDiv
};

enum SyntaxMode { syntaxIndent, syntaxCurly };

class Parser
{
protected:
    InText* input;
    Stack<int> indentStack;

    void parseStringLiteral();
    void skipMultilineComment();

public:
    bool singleLineBlock; // if a: b = c
    Token token;
    string strValue;
    ularge intValue;

    Parser(const string& filename);
    ~Parser();

    Token next(bool expectBlock = false) throw(EParser, ESysError);

    void error(const string& msg) throw(EParser);
    void syntax(const string& msg) throw(EParser);

    int indentLevel()  { return indentStack.top(); }
};

// ------------------------------------------------------------------------ //

EParser::~EParser() throw() { }

string EParser::what() const throw()
{
    string s;
    if (!filename.empty())
        s = filename + '(' + itostring(linenum) + "): ";
    return s + EMessage::what();
}

const charset wsChars = "\t ";
const charset identFirst = "A-Za-z_";
const charset identRest = "0-9A-Za-z_";
const charset digits = "0-9";
const charset hexDigits = "0-9A-Fa-f";
const charset printableChars = "~20-~FF";

static string mkPrintable(char c)
{
    if (c == '\\')
        return string("\\\\");
    else if (c == '\'')
        return string("\\\'");
    else if (printableChars[c])
        return string(c);
    else
        return "\\x" + itostring(unsigned(c), 16);
}

Parser::Parser(const string& filename)
    : input(new InFile(filename)),
      indentStack(), singleLineBlock(false),
      token(tokUndefined), strValue(), intValue(0)
{
    indentStack.push(0);
}

Parser::~Parser()
{
    delete input;
}

void Parser::error(const string& msg) throw(EParser)
{
    throw EParser(input->getFileName(), input->getLinenum(), msg);
}

void Parser::syntax(const string& msg) throw(EParser)
{
    error("Syntax error: " + msg);
}

void Parser::parseStringLiteral()
{
    static const charset stringChars = printableChars - charset("'\\");
    strValue.clear();
    while (true)
    {
        strValue += input->token(stringChars);
        if (input->getEof())
            syntax("Unexpected end of file in string literal");
        char c = input->get();
        if (input->isEolChar(c))
            syntax("Unexpected end of line in string literal");
        if (c == '\'')
            return;
        else if (c == '\\')
        {
            c = input->get();
            if (c == 't')
                strValue += '\t';
            else if (c == 'r')
                strValue += '\r';
            else if (c == 'n')
                strValue += '\n';
            else if (c == 'x')
            {
                string s;
                if (hexDigits[input->preview()])
                {
                    s += input->get();
                    if (hexDigits[input->preview()])
                        s += input->get();
                    bool e, o;
                    ularge value = stringtou(s.c_str(), &e, &o, 16);
                    strValue += char(value);
                }
                else
                    syntax("Malformed hex sequence");
            }
            else
                strValue += c;
        }
        else
            syntax("Illegal character in string literal '" + mkPrintable(c) + "'");
    }
}

void Parser::skipMultilineComment()
{
    static const charset commentChars = (printableChars - '}') + wsChars;
    while (true)
    {
        input->skip(commentChars);
        if (input->getEol())
        {
            if (input->getEof())
                error("Unexpected end of file in comments");
            input->skipEol();
            continue;
        }
        char e = input->get();
        if (e == '}')
        {
            if (input->preview() == '#')
            {
                input->get();
                break;
            }
        }
        else
            syntax("Illegal character in comments '" + mkPrintable(e) + "'");
    }
    input->skip(wsChars);
    if (!input->getEol())
        syntax("Multiline comments must end with a new line");
    input->skipEol();
}

Token Parser::next(bool expectBlock) throw(EParser, ESysError)
{
restart:
    strValue.clear();

    input->skip(wsChars);

    char c = input->preview();

    // --- Handle EOF and EOL ---
    if (input->getEof())
    {
        // finalize all indents at end of file
        if (indentStack.size() > 1)
        {
            strValue = "<END>";
            indentStack.pop();
            return token = tokBlockEnd;
        }
        strValue = "<EOF>";
        return token = tokEof;
    }

    else if (input->getEol())
    {
        input->skipEol();
        if (singleLineBlock)
        {
            strValue = "<END>";
            singleLineBlock = false;
            return token = tokBlockEnd;
        }
        else
        {
            strValue = "<SEP>";
            return token = tokEnd;
        }
    }

    else if (c == '#')
    {
        input->get();
        if (input->preview() == '{')
            skipMultilineComment();
        else
            input->skipLine();
        goto restart;
    }

    else if (input->getNewLine())
    {
        // this is a new line, blanks are skipped, so we are at the first
        // non-blank char:
        int newIndent = input->getIndent();
        int oldIndent = indentStack.top();
        if (newIndent > oldIndent)
        {
            strValue = "<BEGIN>";
            indentStack.push(newIndent);
            input->resetNewLine();
            return token = tokBlockBegin;
        }
        else if (newIndent < oldIndent)
        {
            strValue = "<END>";
            indentStack.pop();
            oldIndent = indentStack.top();
            if (newIndent > oldIndent)
                syntax("Unmatched un-indent");
            else if (newIndent == oldIndent)
            {
                input->resetNewLine();
                return token = tokBlockEnd;
            }
            else
                return token = tokBlockEnd;
        }
        // else: pass through to token analysis
    }

    // --- Handle ordinary tokens ---
    if (identFirst[c])  // identifier or keyword
    {
        strValue = input->get();
        strValue += input->token(identRest);
        return token = tokIdent;
    }

    else if (digits[c])  // numeric
    {
        strValue = input->token(digits);
        bool e, o;
        intValue = stringtou(strValue.c_str(), &e, &o, 10);
        if (e)
            error("'" + strValue + "' is not a valid number");
        if (o)
            error("Numeric overflow (" + strValue + ")");
        return token = tokIntValue;
    }

    else  // special chars
    {
        strValue = input->get();
        switch (c)
        {
        case ',': return token = tokComma;
        case '.': return token = tokPeriod;
        case '\'': parseStringLiteral(); return token = tokStrValue;
        case ';': strValue = "<SEP>"; return token = tokEnd;
        case ':':
            if (!expectBlock)
                syntax("Nested block expected");
            input->skip(wsChars);
            singleLineBlock = !input->getEol();
            return token = tokBlockBegin;
        case '/': return token = tokDiv;
        }
    }

    syntax("Illegal character '" + mkPrintable(c) + "'");

    return tokUndefined;
}

class _AtExit
{
public:
    ~_AtExit()
    {
        if (Base::objCount != 0)
            fprintf(stderr, "Internal: objCount = %d\n", Base::objCount);
        if (stralloc != 0)
            fprintf(stderr, "Internal: stralloc = %d\n", stralloc);
        if (FifoChunk::chunkCount != 0)
            fprintf(stderr, "Internal: chunkCount = %d\n", FifoChunk::chunkCount);
    }
} _atexit;

int main()
{
    Parser parser("tests/parser.txt");
    try
    {
        while (parser.next() != tokEof)
        {
            printf("%s ", parser.strValue.c_str());
            if (parser.token == tokBlockBegin || parser.token == tokBlockEnd || parser.token == tokEnd)
                printf("\n");
        }
    }
    catch (Exception& e)
    {
        fprintf(stderr, "%s\n", e.what().c_str());
    }
    return 0;
}

<|endoftext|>


<commit_before>#include <iostream>
#include <oauth.h>
#include <opencv2/opencv.hpp>

#include <opencv2/opencv.hpp>
#include <opencv2/superres/optical_flow.hpp>

#include "tweet.h"
#include "webclient.h"
// #include "mykey.h"
#include "jphacks_key.h"

int main(void)
{
    // buffering off for debug on pty
    setvbuf( stdout, NULL, _IONBF, BUFSIZ );

    WebClient::initialize();
    TwitterClient tc(c_key, c_sec, t_key, t_sec);
    std::string filename("../../skeleton.png");
    cv::Mat src = cv::imread(filename);

    //return ( tc.tweet(message, src) ) ? 0 : 1;
    return 0;
}
<commit_msg>optical flow から動体を検出する処理を追加<commit_after>/* main.cpp */
//-----------------------------------------------------------------------
//include files
//-----------------------------------------------------------------------
#include <iostream>
#include <oauth.h>
#include <thread>
#include <mutex>
#include <unistd.h>

#include <opencv2/opencv.hpp>
#include <opencv2/superres/optical_flow.hpp>

#include "sequentialCalcOptFlow.h"
#include "sequentialCaptCurrBuffer.h"

#include "tweet.h"
#include "webclient.h"
// #include "mykey.h"
#include "jphacks_key.h"

//-----------------------------------------------------------------------
// using namespace
//-----------------------------------------------------------------------
using namespace std;

//-----------------------------------------------------------------------

//***********************************************************************
// Function : main |
//***********************************************************************
int main(void)
{
    // buffering off for debug on pty
    setvbuf( stdout, NULL, _IONBF, BUFSIZ );

    WebClient::initialize();
    TwitterClient tc(c_key, c_sec, t_key, t_sec);
    std::string filename("../../skeleton.png");
    cv::Mat src = cv::imread(filename);

    // current frame の連続取得(別スレッド)
    cv::Mat curr_tmp;
    bool break_flag = false;
    thread cap_th( sequentialCaptCurrBuffer, ref(curr_tmp), ref(break_flag));
    while( curr_tmp.empty() ){
        sleep(0);
    }

    // optical flow の連続算出(別スレッド)
    cv::Mat flow_tmp;
    thread optflow_th( sequentialCalcOptFlow, ref(curr_tmp), ref(flow_tmp), ref(break_flag));
    while( flow_tmp.empty() ){
        sleep(0);
    }

    while( cv::waitKey(1) != '\x1b' ) {
        cap_mtx.lock();
        cv::Mat curr = curr_tmp.clone();
        cap_mtx.unlock();

        opt_flow_mtx.lock();
        cv::Mat flow = flow_tmp.clone();
        opt_flow_mtx.unlock();

        cv::Mat flowXY[2];
        split(flow, flowXY);

        // オプティカルフローの可視化（色符号化）
        //  オプティカルフローを極座標に変換（角度は[deg]）
        cv::Mat magnitude, angle;
        cv::cartToPolar(flowXY[0], flowXY[1], magnitude, angle, true);

        double maxVal;
        cv::minMaxLoc(magnitude, NULL, &maxVal, NULL, NULL);
        // std::cout << maxVal << "\n";
        //  色相（H）はオプティカルフローの角度
        //  彩度（S）は0～1に正規化したオプティカルフローの大きさ
        //  明度（V）は1
        cv::Mat hsvPlanes[3];
        hsvPlanes[0] = angle;
        if(maxVal > 10){
            cv::normalize(magnitude, hsvPlanes[2], 0, 1, cv::NORM_MINMAX); // 正規化
        } else {
            hsvPlanes[2] = cv::Mat::zeros(magnitude.size(), CV_32F);
        }

        hsvPlanes[1] = cv::Mat::ones(magnitude.size(), CV_32F);

        //  HSVを合成して一枚の画像にする
        cv::Mat hsv;
        merge(hsvPlanes, 3, hsv);

        //  HSVからBGRに変換
        cv::Mat flowBgr;
        cvtColor(hsv, flowBgr, cv::COLOR_HSV2BGR);

        // 表示
        cv::imshow("optical flow", flowBgr);

        // グレースケール
        cv::Mat gray, bin;
        cv::cvtColor( flowBgr, gray, CV_BGR2GRAY);
        cv::minMaxLoc(flowBgr, NULL, &maxVal, NULL, NULL);

        // 平滑化
        blur( gray, gray, cv::Size(3,3) );
        cv::imshow("gray", gray);

        // cv::threshold(cv::Mat1b(gray*255), bin, 0.0, 255.0, CV_THRESH_BINARY | CV_THRESH_OTSU);
        cv::threshold(cv::Mat1b(gray*255), bin, 10, 255.0, CV_THRESH_BINARY);
        cv::imshow("bin", bin);

        //輪郭の座標リスト
        std::vector< std::vector< cv::Point > > contours;

        //輪郭取得
        cv::findContours(bin, contours, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_NONE);
        //cv::findContours(bin, contours, CV_RETR_LIST, CV_CHAIN_APPROX_NONE);

        // 検出された輪郭線を緑で描画
        for (auto contour = contours.begin(); contour != contours.end(); contour++){
            // cv::polylines(prev, *contour, true, cv::Scalar(0, 255, 0), 2);

            //輪郭を直線近似する
            std::vector< cv::Point > approx;
            cv::approxPolyDP(cv::Mat(*contour), approx, 0.01 * cv::arcLength(*contour, true), true);
            // 近似の面積が一定以上なら取得
            double area = cv::contourArea(approx);

            if (area > 1000.0){
                cv::Rect brect = cv::boundingRect(cv::Mat(approx).reshape(2));

                // 外接矩形を描画
                cv::rectangle(curr, brect.tl(), brect.br(), cv::Scalar(255, 0, 0), 2, CV_AA);
                // cv::polylines(curr, *contour, true, cv::Scalar(0, 255, 0), 2);
            }
        }

        //全体を表示する場合
        cv::imshow("coun", curr);
    }

    // スレッドの終了
    break_flag = true;
    cap_th.join();
    optflow_th.join();

    //return ( tc.tweet(message, src) ) ? 0 : 1;
    return 0;
}
<|endoftext|>


<commit_before>#include "ipc.h"

ObjHandle::ObjHandle(SegmentId segmentid, size_t size, IpcPointer ipcpointer)
  : segmentid_(segmentid), size_(size), ipcpointer_(ipcpointer)
{}

MemorySegmentPool::MemorySegmentPool(bool create) : create_mode_(create) { }

// creates a memory segment if it is not already there; if the pool is in create mode,
// space is allocated, if it is in open mode, the shared memory is mapped into the process
void MemorySegmentPool::open_segment(SegmentId segmentid, size_t size) {
  if (segmentid < segments_.size()) {
    return;
  }
  segment_names_.resize(segmentid + 1);
  segments_.resize(segmentid + 1);
  std::string segment_name = std::string("segment:") + std::to_string(segmentid);
  if (create_mode_) {
    assert(size > 0);
    shared_memory_object::remove(segment_name.c_str()); // remove segment if it has not been properly removed from last run
    size_t new_size = (size / page_size_ + 2) * page_size_; // additional room for boost's bookkeeping
    segments_[segmentid] = std::unique_ptr<managed_shared_memory>(new managed_shared_memory(create_only, segment_name.c_str(), new_size));
  } else {
    segments_[segmentid] = std::unique_ptr<managed_shared_memory>(new managed_shared_memory(open_only, segment_name.c_str()));
  }
  segment_names_[segmentid] = segment_name;
}

ObjHandle MemorySegmentPool::allocate(size_t size) {
  // TODO(pcm): at the moment, this always creates a new segment, this will be changed
  SegmentId segmentid = segment_names_.size();
  open_segment(segmentid, size);
  void* ptr = segments_[segmentid]->allocate(size);
  auto handle = segments_[segmentid]->get_handle_from_address(ptr);
  return ObjHandle(segmentid, size, handle);
}

// returns address of the object refered to by the handle, needs to be called on
// the process that will use the address
char* MemorySegmentPool::get_address(ObjHandle pointer) {
  if (pointer.segmentid() >= segments_.size()) {
    open_segment(pointer.segmentid());
  }
  return static_cast<char*>(segments_[pointer.segmentid()]->get_address_from_handle(pointer.ipcpointer()));
}

MemorySegmentPool::~MemorySegmentPool() {
  assert(segment_names_.size() == segments_.size());
  for (size_t i = 0; i < segment_names_.size(); ++i) {
    segments_[i].reset();
    shared_memory_object::remove(segment_names_[i].c_str());
  }
}
<commit_msg>opening all memory segments now<commit_after>#include "ipc.h"

ObjHandle::ObjHandle(SegmentId segmentid, size_t size, IpcPointer ipcpointer)
  : segmentid_(segmentid), size_(size), ipcpointer_(ipcpointer)
{}

MemorySegmentPool::MemorySegmentPool(bool create) : create_mode_(create) { }

// creates a memory segment if it is not already there; if the pool is in create mode,
// space is allocated, if it is in open mode, the shared memory is mapped into the process
void MemorySegmentPool::open_segment(SegmentId segmentid, size_t size) {
  if (segmentid < segments_.size()) {
    return;
  }
  segment_names_.resize(segmentid + 1);
  segments_.resize(segmentid + 1);
  std::string segment_name = std::string("segment:") + std::to_string(segmentid);
  if (create_mode_) {
    assert(size > 0);
    shared_memory_object::remove(segment_name.c_str()); // remove segment if it has not been properly removed from last run
    size_t new_size = (size / page_size_ + 2) * page_size_; // additional room for boost's bookkeeping
    segments_[segmentid] = std::unique_ptr<managed_shared_memory>(new managed_shared_memory(create_only, segment_name.c_str(), new_size));
  } else {
    segments_[segmentid] = std::unique_ptr<managed_shared_memory>(new managed_shared_memory(open_only, segment_name.c_str()));
  }
  segment_names_[segmentid] = segment_name;
}

ObjHandle MemorySegmentPool::allocate(size_t size) {
  // TODO(pcm): at the moment, this always creates a new segment, this will be changed
  SegmentId segmentid = segment_names_.size();
  open_segment(segmentid, size);
  void* ptr = segments_[segmentid]->allocate(size);
  auto handle = segments_[segmentid]->get_handle_from_address(ptr);
  return ObjHandle(segmentid, size, handle);
}

// returns address of the object refered to by the handle, needs to be called on
// the process that will use the address
char* MemorySegmentPool::get_address(ObjHandle pointer) {
  if (pointer.segmentid() >= segments_.size()) {
    for (int i = segments_.size(); i <= pointer.segmentid(); ++i) {
      open_segment(i);
    }
  }
  managed_shared_memory* segment = segments_[pointer.segmentid()].get();
  return static_cast<char*>(segment->get_address_from_handle(pointer.ipcpointer()));
}

MemorySegmentPool::~MemorySegmentPool() {
  assert(segment_names_.size() == segments_.size());
  for (size_t i = 0; i < segment_names_.size(); ++i) {
    segments_[i].reset();
    shared_memory_object::remove(segment_names_[i].c_str());
  }
}
<|endoftext|>