<commit_before>#include "p11engine.h"

#include <openssl/evp.h>
#include <openssl/pem.h>
#include <boost/scoped_array.hpp>

#include "utils.h"

#ifdef TEST_PKCS11_ENGINE_PATH
#define kPkcs11Path TEST_PKCS11_ENGINE_PATH
#else
#define kPkcs11Path "/usr/lib/engines/libpkcs11.so"
#endif

P11Engine* P11EngineGuard::instance = NULL;
int P11EngineGuard::ref_counter = 0;

P11Engine::P11Engine(const P11Config& config) : config_(config), ctx_(config_.module), slots_(ctx_.get()) {
  if (config_.module.empty()) return;

  PKCS11_SLOT* slot = PKCS11_find_token(ctx_.get(), slots_.get_slots(), slots_.get_nslots());
  if (!slot || !slot->token) throw std::runtime_error("Couldn't find pkcs11 token");

  LOG_DEBUG << "Slot manufacturer......: " << slot->manufacturer;
  LOG_DEBUG << "Slot description.......: " << slot->description;
  LOG_DEBUG << "Slot token label.......: " << slot->token->label;
  LOG_DEBUG << "Slot token manufacturer: " << slot->token->manufacturer;
  LOG_DEBUG << "Slot token model.......: " << slot->token->model;
  LOG_DEBUG << "Slot token serialnr....: " << slot->token->serialnr;

  uri_prefix_ = std::string("pkcs11:serial=") + slot->token->serialnr + ";pin-value=" + config_.pass + ";id=%";

  ENGINE_load_builtin_engines();
  ssl_engine_ = ENGINE_by_id("dynamic");
  if (!ssl_engine_) throw std::runtime_error("SSL pkcs11 engine initialization failed");

  if (!ENGINE_ctrl_cmd_string(ssl_engine_, "SO_PATH", kPkcs11Path, 0))
    throw std::runtime_error(std::string("Engine command failed: SO_PATH ") + kPkcs11Path);

  if (!ENGINE_ctrl_cmd_string(ssl_engine_, "ID", "pkcs11", 0))
    throw std::runtime_error("Engine command failed: ID pksc11");

  if (!ENGINE_ctrl_cmd_string(ssl_engine_, "LIST_ADD", "1", 0))
    throw std::runtime_error("Engine command failed: LIST_ADD 1");

  if (!ENGINE_ctrl_cmd_string(ssl_engine_, "LOAD", NULL, 0)) throw std::runtime_error("Engine command failed: LOAD");

  if (!ENGINE_ctrl_cmd_string(ssl_engine_, "MODULE_PATH", config_.module.c_str(), 0))
    throw std::runtime_error(std::string("Engine command failed: MODULE_PATH ") + config_.module.string());

  if (!ENGINE_ctrl_cmd_string(ssl_engine_, "PIN", config_.pass.c_str(), 0))
    throw std::runtime_error(std::string("Engine command failed: PIN ") + config_.pass);

  if (!ENGINE_init(ssl_engine_)) throw std::runtime_error("Engine initialization failed");
}

P11Engine::~P11Engine() {
  if (!config_.module.empty()) {
    ENGINE_finish(ssl_engine_);
    ENGINE_cleanup();
  }
}

PKCS11_SLOT* P11Engine::findTokenSlot() const {
  PKCS11_SLOT* slot = PKCS11_find_token(ctx_.get(), slots_.get_slots(), slots_.get_nslots());
  if (!slot || !slot->token) {
    LOG_ERROR << "Couldn't find a token";
    return NULL;
  }
  int rv;
  PKCS11_is_logged_in(slot, 1, &rv);
  if (rv == 0) {
    if (PKCS11_open_session(slot, 1)) {
      LOG_ERROR << "Error creating rw session in to the slot: " << ERR_error_string(ERR_get_error(), NULL);
    }

    if (PKCS11_login(slot, 0, config_.pass.c_str())) {
      LOG_ERROR << "Error logging in to the token: " << ERR_error_string(ERR_get_error(), NULL);
      return NULL;
    }
  }
  return slot;
}

bool P11Engine::readUptanePublicKey(std::string* key_out) {
  if (config_.module.empty()) return false;
  if (config_.uptane_key_id.length() % 2) return false;  // id is a hex string

  PKCS11_SLOT* slot = findTokenSlot();
  if (!slot) return false;

  PKCS11_KEY* keys;
  unsigned int nkeys;
  int rc = PKCS11_enumerate_public_keys(slot->token, &keys, &nkeys);
  if (rc < 0) {
    LOG_ERROR << "Error enumerating public keys in PKCS11 device: " << ERR_error_string(ERR_get_error(), NULL);
    return false;
  }
  PKCS11_KEY* key = NULL;
  {
    boost::scoped_array<unsigned char> id_hex(new unsigned char[config_.uptane_key_id.length() / 2]);
    Utils::hex2bin(config_.uptane_key_id, id_hex.get());

    for (int i = 0; i < nkeys; i++) {
      if ((keys[i].id_len == config_.uptane_key_id.length() / 2) &&
          !memcmp(keys[i].id, id_hex.get(), config_.uptane_key_id.length() / 2)) {
        key = &keys[i];
        break;
      }
    }
  }
  if (key == NULL) {
    LOG_ERROR << "Requested public key was not found";
    return false;
  }
  EVP_PKEY* evp_key = PKCS11_get_public_key(key);
  BIO* mem = BIO_new(BIO_s_mem());
  PEM_write_bio_PUBKEY(mem, evp_key);

  char* pem_key = NULL;
  int length = BIO_get_mem_data(mem, &pem_key);
  key_out->assign(pem_key, length);

  BIO_free_all(mem);
  return true;
}

bool P11Engine::generateUptaneKeyPair() {
  PKCS11_SLOT* slot = findTokenSlot();
  if (!slot) return false;

  boost::scoped_array<unsigned char> id_hex(new unsigned char[config_.uptane_key_id.length() / 2]);
  Utils::hex2bin(config_.uptane_key_id, id_hex.get());

  if (PKCS11_generate_key(slot->token, EVP_PKEY_RSA, 2048, NULL, id_hex.get(), (config_.uptane_key_id.length() / 2))) {
    LOG_ERROR << "Error of generating keypair on the device:" << ERR_error_string(ERR_get_error(), NULL);

    return false;
  }

  return true;
}

bool P11Engine::readTlsCert(std::string* cert_out) const {
  const std::string& id = config_.tls_clientcert_id;

  if (config_.module.empty()) return false;
  if (id.length() % 2) return false;  // id is a hex string

  PKCS11_SLOT* slot = findTokenSlot();
  if (!slot) return false;

  PKCS11_CERT* certs;
  unsigned int ncerts;
  int rc = PKCS11_enumerate_certs(slot->token, &certs, &ncerts);
  if (rc < 0) {
    LOG_ERROR << "Error enumerating certificates in PKCS11 device: " << ERR_error_string(ERR_get_error(), NULL);
    return false;
  }

  PKCS11_CERT* cert = NULL;
  {
    boost::scoped_array<unsigned char> id_hex(new unsigned char[id.length() / 2]);
    Utils::hex2bin(id, id_hex.get());

    for (int i = 0; i < ncerts; i++) {
      if ((certs[i].id_len == id.length() / 2) && !memcmp(certs[i].id, id_hex.get(), id.length() / 2)) {
        cert = &certs[i];
        break;
      }
    }
  }
  if (cert == NULL) {
    LOG_ERROR << "Requested certificate was not found";
    return false;
  }
  BIO* mem = BIO_new(BIO_s_mem());
  PEM_write_bio_X509(mem, cert->x509);

  char* pem_key = NULL;
  int length = BIO_get_mem_data(mem, &pem_key);
  cert_out->assign(pem_key, length);

  BIO_free_all(mem);
  return true;
}
<commit_msg>Fix a memory leak.<commit_after>#include "p11engine.h"

#include <openssl/evp.h>
#include <openssl/pem.h>
#include <boost/scoped_array.hpp>

#include "utils.h"

#ifdef TEST_PKCS11_ENGINE_PATH
#define kPkcs11Path TEST_PKCS11_ENGINE_PATH
#else
#define kPkcs11Path "/usr/lib/engines/libpkcs11.so"
#endif

P11Engine* P11EngineGuard::instance = NULL;
int P11EngineGuard::ref_counter = 0;

P11Engine::P11Engine(const P11Config& config) : config_(config), ctx_(config_.module), slots_(ctx_.get()) {
  if (config_.module.empty()) return;

  PKCS11_SLOT* slot = PKCS11_find_token(ctx_.get(), slots_.get_slots(), slots_.get_nslots());
  if (!slot || !slot->token) throw std::runtime_error("Couldn't find pkcs11 token");

  LOG_DEBUG << "Slot manufacturer......: " << slot->manufacturer;
  LOG_DEBUG << "Slot description.......: " << slot->description;
  LOG_DEBUG << "Slot token label.......: " << slot->token->label;
  LOG_DEBUG << "Slot token manufacturer: " << slot->token->manufacturer;
  LOG_DEBUG << "Slot token model.......: " << slot->token->model;
  LOG_DEBUG << "Slot token serialnr....: " << slot->token->serialnr;

  uri_prefix_ = std::string("pkcs11:serial=") + slot->token->serialnr + ";pin-value=" + config_.pass + ";id=%";

  ENGINE_load_builtin_engines();
  ssl_engine_ = ENGINE_by_id("dynamic");
  if (!ssl_engine_) throw std::runtime_error("SSL pkcs11 engine initialization failed");

  if (!ENGINE_ctrl_cmd_string(ssl_engine_, "SO_PATH", kPkcs11Path, 0))
    throw std::runtime_error(std::string("Engine command failed: SO_PATH ") + kPkcs11Path);

  if (!ENGINE_ctrl_cmd_string(ssl_engine_, "ID", "pkcs11", 0))
    throw std::runtime_error("Engine command failed: ID pksc11");

  if (!ENGINE_ctrl_cmd_string(ssl_engine_, "LIST_ADD", "1", 0))
    throw std::runtime_error("Engine command failed: LIST_ADD 1");

  if (!ENGINE_ctrl_cmd_string(ssl_engine_, "LOAD", NULL, 0)) throw std::runtime_error("Engine command failed: LOAD");

  if (!ENGINE_ctrl_cmd_string(ssl_engine_, "MODULE_PATH", config_.module.c_str(), 0))
    throw std::runtime_error(std::string("Engine command failed: MODULE_PATH ") + config_.module.string());

  if (!ENGINE_ctrl_cmd_string(ssl_engine_, "PIN", config_.pass.c_str(), 0))
    throw std::runtime_error(std::string("Engine command failed: PIN ") + config_.pass);

  if (!ENGINE_init(ssl_engine_)) throw std::runtime_error("Engine initialization failed");
}

P11Engine::~P11Engine() {
  if (!config_.module.empty()) {
    ENGINE_finish(ssl_engine_);
    ENGINE_cleanup();
  }
}

PKCS11_SLOT* P11Engine::findTokenSlot() const {
  PKCS11_SLOT* slot = PKCS11_find_token(ctx_.get(), slots_.get_slots(), slots_.get_nslots());
  if (!slot || !slot->token) {
    LOG_ERROR << "Couldn't find a token";
    return NULL;
  }
  int rv;
  PKCS11_is_logged_in(slot, 1, &rv);
  if (rv == 0) {
    if (PKCS11_open_session(slot, 1)) {
      LOG_ERROR << "Error creating rw session in to the slot: " << ERR_error_string(ERR_get_error(), NULL);
    }

    if (PKCS11_login(slot, 0, config_.pass.c_str())) {
      LOG_ERROR << "Error logging in to the token: " << ERR_error_string(ERR_get_error(), NULL);
      return NULL;
    }
  }
  return slot;
}

bool P11Engine::readUptanePublicKey(std::string* key_out) {
  if (config_.module.empty()) return false;
  if (config_.uptane_key_id.length() % 2) return false;  // id is a hex string

  PKCS11_SLOT* slot = findTokenSlot();
  if (!slot) return false;

  PKCS11_KEY* keys;
  unsigned int nkeys;
  int rc = PKCS11_enumerate_public_keys(slot->token, &keys, &nkeys);
  if (rc < 0) {
    LOG_ERROR << "Error enumerating public keys in PKCS11 device: " << ERR_error_string(ERR_get_error(), NULL);
    return false;
  }
  PKCS11_KEY* key = NULL;
  {
    boost::scoped_array<unsigned char> id_hex(new unsigned char[config_.uptane_key_id.length() / 2]);
    Utils::hex2bin(config_.uptane_key_id, id_hex.get());

    for (int i = 0; i < nkeys; i++) {
      if ((keys[i].id_len == config_.uptane_key_id.length() / 2) &&
          !memcmp(keys[i].id, id_hex.get(), config_.uptane_key_id.length() / 2)) {
        key = &keys[i];
        break;
      }
    }
  }
  if (key == NULL) {
    LOG_ERROR << "Requested public key was not found";
    return false;
  }
  EVP_PKEY* evp_key = PKCS11_get_public_key(key);
  BIO* mem = BIO_new(BIO_s_mem());
  PEM_write_bio_PUBKEY(mem, evp_key);

  char* pem_key = NULL;
  int length = BIO_get_mem_data(mem, &pem_key);
  key_out->assign(pem_key, length);

  EVP_PKEY_free(evp_key);
  BIO_free_all(mem);
  return true;
}

bool P11Engine::generateUptaneKeyPair() {
  PKCS11_SLOT* slot = findTokenSlot();
  if (!slot) return false;

  boost::scoped_array<unsigned char> id_hex(new unsigned char[config_.uptane_key_id.length() / 2]);
  Utils::hex2bin(config_.uptane_key_id, id_hex.get());

  if (PKCS11_generate_key(slot->token, EVP_PKEY_RSA, 2048, NULL, id_hex.get(), (config_.uptane_key_id.length() / 2))) {
    LOG_ERROR << "Error of generating keypair on the device:" << ERR_error_string(ERR_get_error(), NULL);

    return false;
  }

  return true;
}

bool P11Engine::readTlsCert(std::string* cert_out) const {
  const std::string& id = config_.tls_clientcert_id;

  if (config_.module.empty()) return false;
  if (id.length() % 2) return false;  // id is a hex string

  PKCS11_SLOT* slot = findTokenSlot();
  if (!slot) return false;

  PKCS11_CERT* certs;
  unsigned int ncerts;
  int rc = PKCS11_enumerate_certs(slot->token, &certs, &ncerts);
  if (rc < 0) {
    LOG_ERROR << "Error enumerating certificates in PKCS11 device: " << ERR_error_string(ERR_get_error(), NULL);
    return false;
  }

  PKCS11_CERT* cert = NULL;
  {
    boost::scoped_array<unsigned char> id_hex(new unsigned char[id.length() / 2]);
    Utils::hex2bin(id, id_hex.get());

    for (int i = 0; i < ncerts; i++) {
      if ((certs[i].id_len == id.length() / 2) && !memcmp(certs[i].id, id_hex.get(), id.length() / 2)) {
        cert = &certs[i];
        break;
      }
    }
  }
  if (cert == NULL) {
    LOG_ERROR << "Requested certificate was not found";
    return false;
  }
  BIO* mem = BIO_new(BIO_s_mem());
  PEM_write_bio_X509(mem, cert->x509);

  char* pem_key = NULL;
  int length = BIO_get_mem_data(mem, &pem_key);
  cert_out->assign(pem_key, length);

  BIO_free_all(mem);
  return true;
}
<|endoftext|>


<commit_before><commit_msg>Update gizmo transform every frame when objects are selected<commit_after><|endoftext|>


<commit_before><commit_msg>Fixed typo<commit_after><|endoftext|>


<commit_before>#include "typedbytes.h"
#include "stdio.h"

#include <string>
#include <vector>

#define IS_TYPEDBYTES_BYTE_SEQUENCE(type) ((type) >= 50 && (type) <= 200)

static inline void push_opaque_typecode(typedbytes_opaque& buffer,
                                        TypedBytesType code) {
  buffer.push_back((unsigned char) code);
}

static inline void push_opaque_bytes(typedbytes_opaque& buffer,
                                     unsigned char* bytes, size_t size) {
  while (size > 0) {
    buffer.push_back(*bytes);
    ++bytes;
    --size;
  }
}

static inline void push_opaque_length(typedbytes_opaque& buffer,
                                      typedbytes_length len) {
  len = bswap32(len);
  push_opaque_bytes(buffer, (unsigned char*) &len, sizeof(typedbytes_length));
}

bool TypedBytesInFile::_read_opaque_primitive(typedbytes_opaque& buffer,
                                              TypedBytesType type) {
  // TODO check the fread commands in this function
  unsigned char bytebuf = 0;
  int32_t intbuf = 0;
  int64_t longbuf = 0;
  typedbytes_length len = 0;

  // NOTE the typecode has already been pushed

  // translate this type to avoid nastiness in the switch.
  if (IS_TYPEDBYTES_BYTE_SEQUENCE(type))
    type = TypedBytesByteSequence;

  switch (type) {
  case TypedBytesByte:
  case TypedBytesBoolean:
    fread(&bytebuf, sizeof(unsigned char), 1, stream_);
    push_opaque_bytes(buffer, &bytebuf, sizeof(unsigned char));
    break;

  case TypedBytesInteger:
  case TypedBytesFloat:
    fread(&intbuf, sizeof(int32_t), 1, stream_);
    push_opaque_bytes(buffer, (unsigned char*) &intbuf, sizeof(int32_t));
    break;

  case TypedBytesLong:
  case TypedBytesDouble:
    fread(&longbuf, sizeof(int64_t), 1, stream_);
    push_opaque_bytes(buffer, (unsigned char*) &longbuf, sizeof(int64_t));
    break;

  case TypedBytesString:
  case TypedBytesByteSequence:
    len = _read_length();
    while (len > 0) {
      // stream_ to buffer in longbuf bytes at a time.
      if (len >= 8) {
        fread(&longbuf, sizeof(int64_t), 1, stream_);
        push_opaque_bytes(buffer, (unsigned char*) &longbuf, sizeof(int64_t));
        len -= sizeof(int64_t);
      } else {
        fread(&longbuf, len, 1, stream_);
        push_opaque_bytes(buffer, (unsigned char*) &longbuf, len);
        break;
      }
    }
    break;

  default:
    return false;
  }
  return true;
}

bool TypedBytesInFile::_read_opaque(typedbytes_opaque& buffer, bool list) {
  TypedBytesType type = next_type();
  push_opaque_typecode(buffer, type);
  typedbytes_length len;
  switch (type) {
  case TypedBytesByteSequence:
  case TypedBytesByte:
  case TypedBytesBoolean:
  case TypedBytesInteger:
  case TypedBytesLong:
  case TypedBytesFloat:
  case TypedBytesDouble:
  case TypedBytesString:
    _read_opaque_primitive(buffer, type);
    break;
  case TypedBytesVector:
    len = read_typedbytes_sequence_length();
    push_opaque_length(buffer, len);
    for (int i = 0; i < len; ++i) {
      _read_opaque(buffer, false);
    }
    break;
  case TypedBytesMap:
    len = read_typedbytes_sequence_length();
    push_opaque_length(buffer, len);
    for (int i = 0; i < len; ++i) {
      _read_opaque(buffer, false);
      _read_opaque(buffer, false);
    }
    break;
  case TypedBytesList:
    while (last_code_ != TypedBytesListEnd) {
      _read_opaque(buffer, true);
    }
    break;
  default:
    return list && type == TypedBytesListEnd;
  }
  return true;
}

bool TypedBytesInFile::read_opaque(typedbytes_opaque& buffer) {
  return _read_opaque(buffer, false);
}

bool TypedBytesInFile::skip_next() {
  // TODO, rewrite these functions to avoid loading into memory
  typedbytes_opaque value;
  return read_opaque(value);
}

TypedBytesType TypedBytesInFile::next_type() {
  unsigned char code = next_type_code();
  if (code <= 10 || code == 255) {
    return (TypedBytesType) code;
  } else if (IS_TYPEDBYTES_BYTE_SEQUENCE(code)) {
    return TypedBytesByteSequence;
  } else if (code == TypedBytesTypeError) {
    // error flag already set in this case.
    return TypedBytesTypeError;
  } else {
    // TODO set error flag
    return TypedBytesTypeError;
  }
}

unsigned char TypedBytesInFile::next_type_code() {
  int ch = fgetc(stream_);
  // reset last_length_
  last_length_ = -1;
  if (ch == EOF) {
    // TODO set error flag
    last_code_ = TypedBytesTypeError;
    return (unsigned char) TypedBytesTypeError;
  } else {
    last_code_ = (TypedBytesType) ch;
    return (unsigned char) ch;
  }
}

size_t TypedBytesInFile::_read_bytes(void *ptr, size_t nbytes, size_t nelem) {
  size_t nread = fread(ptr, nbytes, nelem, stream_);
  // TODO set error flag and determine more intelligent action.
  assert(nread == nelem);
  // reset last_length_
  last_length_ = -1;
  return nread;
}

int32_t TypedBytesInFile::_read_length() {
  int32_t len = 0;
  _read_bytes(&len, sizeof(int32_t), 1);
  len = bswap32(len);
  return len;
}

bool TypedBytesInFile::_read_data_block(unsigned char* data, size_t size) {
  assert(last_length_ >= 0);
  typedbytes_length curlen = last_length_;
  if (size > (size_t) curlen) {
    return false;
  }
  size_t nread = _read_bytes(data, sizeof(unsigned char), (size_t) size);
  // NOTE _read_bytes resets last_length_, so we have to reset it back
  if (nread != size) {
    // TODO update error
    return false;
  }
  last_length_ = curlen - size;
  assert(last_length_ >= 0);
  return true;
}

#ifdef TYPEDBYTES_STRICT_TYPE
# define typedbytes_check_type_code(x) (assert((x) == last_code_))
#else
# define typedbytes_check_type_code(x)
#endif

signed char TypedBytesInFile::read_byte() {
  typedbytes_check_type_code(TypedBytesByte);
  signed char rval = 0;
  _read_bytes(&rval, sizeof(signed char), 1);
  return (rval);
}

bool TypedBytesInFile::read_bool() {
  typedbytes_check_type_code(TypedBytesBoolean);
  signed char rval = 0;
  _read_bytes(&rval, sizeof(signed char), 1);
  return (bool) rval;
}

float TypedBytesInFile::read_float() {
  typedbytes_check_type_code(TypedBytesFloat);
  int32_t val = 0;
  _read_bytes(&val, sizeof(int32_t), 1);
  val = bswap32(val);
  float rval;
  memcpy(&rval, &val, sizeof(int32_t));
  return rval;
}

double TypedBytesInFile::read_double() {
  typedbytes_check_type_code(TypedBytesDouble);
  int64_t val = 0;
  _read_bytes(&val, sizeof(int64_t), 1);
  val = bswap64(val);
  double rval;
  memcpy(&rval, &val, sizeof(int64_t));
  return rval;
}

double TypedBytesInFile::convert_double() {
  switch (last_code_) {
  case TypedBytesFloat:
    return (double) read_float();
  case TypedBytesDouble:
    return read_double();
  default:
    return (double) convert_long();
  }
}

typedbytes_long TypedBytesInFile::convert_long() {
  if (last_code_ == TypedBytesLong)
    return read_long();
  return (long) convert_int();
}

int TypedBytesInFile::convert_int() {
  switch (last_code_) {
  case TypedBytesByte:
    return (int) read_byte();
  case TypedBytesBoolean:
    return (int) read_bool();
  case TypedBytesInteger:
    return read_int();
  default:
    assert(last_code_ == TypedBytesTypeError);
    return 0;
  }
}

int TypedBytesInFile::read_int() {
  typedbytes_check_type_code(TypedBytesInteger);
  int32_t rval = 0;
  _read_bytes(&rval, sizeof(int32_t), 1);
  rval = bswap32(rval);
  return (int) rval;
}

typedbytes_long TypedBytesInFile::read_long() {
  typedbytes_check_type_code(TypedBytesLong);
  int64_t rval = 0;
  _read_bytes(&rval, sizeof(int64_t), 1);
  rval = bswap64(rval);
  return (typedbytes_long) rval;
}

typedbytes_length TypedBytesInFile::read_string_length() {
  typedbytes_check_type_code(TypedBytesString);
  typedbytes_length len = _read_length();
  last_length_ = len;
  return len;
}

bool TypedBytesInFile::read_string_data(unsigned char* data, size_t size) {
  typedbytes_check_type_code(TypedBytesString);
  return _read_data_block(data, size);
}

bool TypedBytesInFile::read_string(std::string& str) {
  typedbytes_check_type_code(TypedBytesString);
  typedbytes_length len = _read_length();
  str.resize(len);
  assert(len >= 0);
  // TODO check for error
  _read_bytes(&str[0], sizeof(unsigned char), (size_t) len);
  return true;
}

typedbytes_length TypedBytesInFile::read_byte_sequence_length() {
#ifdef TYPEDBYTES_STRICT_TYPE
  if (last_code_ == TypedBytesByteSequence ||
      IS_TYPEDBYTES_BYTE_SEQUENCE(last_code_)) {
    // do nothing here
  } else {
    typedbytes_check_type_code(TypedBytesTypeError);
  }
#endif
  last_length_ = _read_length();
  return last_length_;
}

bool TypedBytesInFile::read_byte_sequence(unsigned char* data, size_t size) {
#ifdef TYPEDBYTES_STRICT_TYPE
  if (last_code_ == TypedBytesByteSequence ||
      IS_TYPEDBYTES_BYTE_SEQUENCE(last_code_)) {
    // do nothing here
  } else {
    typedbytes_check_type_code(TypedBytesTypeError);
  }
#endif
  return _read_data_block(data, size);
}

typedbytes_length TypedBytesInFile::read_typedbytes_sequence_length() {
#ifdef TYPEDBYTES_STRICT_TYPE
  if (last_code_ == TypedBytesVector || last_code_ == TypedBytesMap) {
    // do nothing here
  } else {
    typedbytes_check_type_code(TypedBytesTypeError);
  }
#endif
  return _read_length();
}

bool TypedBytesOutFile::_write_length(typedbytes_length len) {
  len = bswap32(len);
  return fwrite(&len, sizeof(typedbytes_length), 1, stream_) == 1;
}

bool TypedBytesOutFile::_write_code(TypedBytesType t) {
  unsigned char code = (unsigned char) t;
  return _write_bytes(&code, 1, 1);
}

bool TypedBytesOutFile::write_bool(bool val) {
  signed char sval = 0;
  if (val) {
    sval = 1;
  }
  return _write_code(TypedBytesBoolean) && _write_bytes(&sval, 1, 1);
}

bool TypedBytesOutFile::write_int(int val) {
  int32_t sval = bswap32(val);
  return _write_code(TypedBytesInteger) &&
    _write_bytes(&sval, sizeof(int32_t), 1);
}

bool TypedBytesOutFile::write_long(typedbytes_long val) {
  val = bswap64(val);
  return _write_code(TypedBytesLong) &&
    _write_bytes(&val, sizeof(typedbytes_long), 1);
}

bool TypedBytesOutFile::write_float(float val) {
  int32_t sval = 0;
  memcpy(&sval, &val, sizeof(int32_t));
  sval = bswap32(sval);
  return _write_code(TypedBytesFloat) && _write_bytes(&sval, sizeof(int32_t), 1);
}

bool TypedBytesOutFile::write_double(double val) {
  int64_t sval = 0;
  memcpy(&sval, &val, sizeof(int64_t));
  sval = bswap64(sval);
  return _write_code(TypedBytesDouble) &&
    _write_bytes(&sval, sizeof(int64_t), 1);
}
<commit_msg>cleanup<commit_after>#include "typedbytes.h"
#include "stdio.h"

#include <string>
#include <vector>

#define IS_TYPEDBYTES_BYTE_SEQUENCE(type) ((type) >= 50 && (type) <= 200)

static inline void push_opaque_typecode(typedbytes_opaque& buffer,
                                        TypedBytesType code) {
  buffer.push_back((unsigned char) code);
}

static inline void push_opaque_bytes(typedbytes_opaque& buffer,
                                     unsigned char* bytes, size_t size) {
  while (size > 0) {
    buffer.push_back(*bytes);
    ++bytes;
    --size;
  }
}

static inline void push_opaque_length(typedbytes_opaque& buffer,
                                      typedbytes_length len) {
  len = bswap32(len);
  push_opaque_bytes(buffer, (unsigned char*) &len, sizeof(typedbytes_length));
}

bool TypedBytesInFile::_read_opaque_primitive(typedbytes_opaque& buffer,
                                              TypedBytesType type) {
  // TODO check the fread commands in this function
  unsigned char bytebuf = 0;
  int32_t intbuf = 0;
  int64_t longbuf = 0;
  typedbytes_length len = 0;

  // NOTE the typecode has already been pushed

  // translate this type to avoid nastiness in the switch.
  if (IS_TYPEDBYTES_BYTE_SEQUENCE(type))
    type = TypedBytesByteSequence;

  switch (type) {
  case TypedBytesByte:
  case TypedBytesBoolean:
    fread(&bytebuf, sizeof(unsigned char), 1, stream_);
    push_opaque_bytes(buffer, &bytebuf, sizeof(unsigned char));
    break;

  case TypedBytesInteger:
  case TypedBytesFloat:
    fread(&intbuf, sizeof(int32_t), 1, stream_);
    push_opaque_bytes(buffer, (unsigned char*) &intbuf, sizeof(int32_t));
    break;

  case TypedBytesLong:
  case TypedBytesDouble:
    fread(&longbuf, sizeof(int64_t), 1, stream_);
    push_opaque_bytes(buffer, (unsigned char*) &longbuf, sizeof(int64_t));
    break;

  case TypedBytesString:
  case TypedBytesByteSequence:
    len = _read_length();
    while (len > 0) {
      // stream_ to buffer in longbuf bytes at a time.
      if (len >= 8) {
        fread(&longbuf, sizeof(int64_t), 1, stream_);
        push_opaque_bytes(buffer, (unsigned char*) &longbuf, sizeof(int64_t));
        len -= sizeof(int64_t);
      } else {
        fread(&longbuf, len, 1, stream_);
        push_opaque_bytes(buffer, (unsigned char*) &longbuf, len);
        break;
      }
    }
    break;

  default:
    return false;
  }
  return true;
}

bool TypedBytesInFile::_read_opaque(typedbytes_opaque& buffer, bool list) {
  TypedBytesType type = next_type();
  push_opaque_typecode(buffer, type);
  typedbytes_length len;
  switch (type) {
  case TypedBytesByteSequence:
  case TypedBytesByte:
  case TypedBytesBoolean:
  case TypedBytesInteger:
  case TypedBytesLong:
  case TypedBytesFloat:
  case TypedBytesDouble:
  case TypedBytesString:
    _read_opaque_primitive(buffer, type);
    break;
  case TypedBytesVector:
    len = read_typedbytes_sequence_length();
    push_opaque_length(buffer, len);
    for (int i = 0; i < len; ++i) {
      _read_opaque(buffer, false);
    }
    break;
  case TypedBytesMap:
    len = read_typedbytes_sequence_length();
    push_opaque_length(buffer, len);
    for (int i = 0; i < len; ++i) {
      _read_opaque(buffer, false);
      _read_opaque(buffer, false);
    }
    break;
  case TypedBytesList:
    while (last_code_ != TypedBytesListEnd) {
      _read_opaque(buffer, true);
    }
    break;
  default:
    return list && type == TypedBytesListEnd;
  }
  return true;
}

bool TypedBytesInFile::read_opaque(typedbytes_opaque& buffer) {
  return _read_opaque(buffer, false);
}

bool TypedBytesInFile::skip_next() {
  // TODO, rewrite these functions to avoid loading into memory
  typedbytes_opaque value;
  return read_opaque(value);
}

TypedBytesType TypedBytesInFile::next_type() {
  unsigned char code = next_type_code();
  if (code <= 10 || code == 255) {
    return (TypedBytesType) code;
  } else if (IS_TYPEDBYTES_BYTE_SEQUENCE(code)) {
    return TypedBytesByteSequence;
  } else if (code == TypedBytesTypeError) {
    // error flag already set in this case.
    return TypedBytesTypeError;
  } else {
    // TODO set error flag
    return TypedBytesTypeError;
  }
}

unsigned char TypedBytesInFile::next_type_code() {
  int ch = fgetc(stream_);
  // reset last_length_
  last_length_ = -1;
  if (ch == EOF) {
    // TODO set error flag
    last_code_ = TypedBytesTypeError;
    return (unsigned char) TypedBytesTypeError;
  } else {
    last_code_ = (TypedBytesType) ch;
    return (unsigned char) ch;
  }
}

size_t TypedBytesInFile::_read_bytes(void *ptr, size_t nbytes, size_t nelem) {
  size_t nread = fread(ptr, nbytes, nelem, stream_);
  // TODO set error flag and determine more intelligent action.
  assert(nread == nelem);
  // reset last_length_
  last_length_ = -1;
  return nread;
}

int32_t TypedBytesInFile::_read_length() {
  int32_t len = 0;
  _read_bytes(&len, sizeof(int32_t), 1);
  len = bswap32(len);
  return len;
}

bool TypedBytesInFile::_read_data_block(unsigned char* data, size_t size) {
  assert(last_length_ >= 0);
  typedbytes_length curlen = last_length_;
  if (size > (size_t) curlen) {
    return false;
  }
  size_t nread = _read_bytes(data, sizeof(unsigned char), (size_t) size);
  // NOTE _read_bytes resets last_length_, so we have to reset it back
  if (nread != size) {
    // TODO update error
    return false;
  }
  last_length_ = curlen - size;
  assert(last_length_ >= 0);
  return true;
}

#ifdef TYPEDBYTES_STRICT_TYPE
# define TYPEDBYTES_CHECK_TYPE_CODE(x) (assert((x) == last_code_))
#else
# define TYPEDBYTES_CHECK_TYPE_CODE(x)
#endif

signed char TypedBytesInFile::read_byte() {
  TYPEDBYTES_CHECK_TYPE_CODE(TypedBytesByte);
  signed char rval = 0;
  _read_bytes(&rval, sizeof(signed char), 1);
  return (rval);
}

bool TypedBytesInFile::read_bool() {
  TYPEDBYTES_CHECK_TYPE_CODE(TypedBytesBoolean);
  signed char rval = 0;
  _read_bytes(&rval, sizeof(signed char), 1);
  return (bool) rval;
}

float TypedBytesInFile::read_float() {
  TYPEDBYTES_CHECK_TYPE_CODE(TypedBytesFloat);
  int32_t val = 0;
  _read_bytes(&val, sizeof(int32_t), 1);
  val = bswap32(val);
  float rval;
  memcpy(&rval, &val, sizeof(int32_t));
  return rval;
}

double TypedBytesInFile::read_double() {
  TYPEDBYTES_CHECK_TYPE_CODE(TypedBytesDouble);
  int64_t val = 0;
  _read_bytes(&val, sizeof(int64_t), 1);
  val = bswap64(val);
  double rval;
  memcpy(&rval, &val, sizeof(int64_t));
  return rval;
}

double TypedBytesInFile::convert_double() {
  switch (last_code_) {
  case TypedBytesFloat:
    return (double) read_float();
  case TypedBytesDouble:
    return read_double();
  default:
    return (double) convert_long();
  }
}

typedbytes_long TypedBytesInFile::convert_long() {
  if (last_code_ == TypedBytesLong)
    return read_long();
  return (long) convert_int();
}

int TypedBytesInFile::convert_int() {
  switch (last_code_) {
  case TypedBytesByte:
    return (int) read_byte();
  case TypedBytesBoolean:
    return (int) read_bool();
  case TypedBytesInteger:
    return read_int();
  default:
    assert(last_code_ == TypedBytesTypeError);
    return 0;
  }
}

int TypedBytesInFile::read_int() {
  TYPEDBYTES_CHECK_TYPE_CODE(TypedBytesInteger);
  int32_t rval = 0;
  _read_bytes(&rval, sizeof(int32_t), 1);
  rval = bswap32(rval);
  return (int) rval;
}

typedbytes_long TypedBytesInFile::read_long() {
  TYPEDBYTES_CHECK_TYPE_CODE(TypedBytesLong);
  int64_t rval = 0;
  _read_bytes(&rval, sizeof(int64_t), 1);
  rval = bswap64(rval);
  return (typedbytes_long) rval;
}

typedbytes_length TypedBytesInFile::read_string_length() {
  TYPEDBYTES_CHECK_TYPE_CODE(TypedBytesString);
  typedbytes_length len = _read_length();
  last_length_ = len;
  return len;
}

bool TypedBytesInFile::read_string_data(unsigned char* data, size_t size) {
  TYPEDBYTES_CHECK_TYPE_CODE(TypedBytesString);
  return _read_data_block(data, size);
}

bool TypedBytesInFile::read_string(std::string& str) {
  TYPEDBYTES_CHECK_TYPE_CODE(TypedBytesString);
  typedbytes_length len = _read_length();
  str.resize(len);
  assert(len >= 0);
  // TODO check for error
  _read_bytes(&str[0], sizeof(unsigned char), (size_t) len);
  return true;
}

typedbytes_length TypedBytesInFile::read_byte_sequence_length() {
#ifdef TYPEDBYTES_STRICT_TYPE
  if (last_code_ != TypedBytesByteSequence &&
      !IS_TYPEDBYTES_BYTE_SEQUENCE(last_code_))
    TYPEDBYTES_CHECK_TYPE_CODE(TypedBytesTypeError);
#endif
  last_length_ = _read_length();
  return last_length_;
}

bool TypedBytesInFile::read_byte_sequence(unsigned char* data, size_t size) {
#ifdef TYPEDBYTES_STRICT_TYPE
  if (last_code_ != TypedBytesByteSequence &&
      !IS_TYPEDBYTES_BYTE_SEQUENCE(last_code_))
    TYPEDBYTES_CHECK_TYPE_CODE(TypedBytesTypeError);
#endif
  return _read_data_block(data, size);
}

typedbytes_length TypedBytesInFile::read_typedbytes_sequence_length() {
#ifdef TYPEDBYTES_STRICT_TYPE
  if (last_code_ != TypedBytesVector && last_code_ != TypedBytesMap)
    TYPEDBYTES_CHECK_TYPE_CODE(TypedBytesTypeError);
#endif
  return _read_length();
}

bool TypedBytesOutFile::_write_length(typedbytes_length len) {
  len = bswap32(len);
  return fwrite(&len, sizeof(typedbytes_length), 1, stream_) == 1;
}

bool TypedBytesOutFile::_write_code(TypedBytesType t) {
  unsigned char code = (unsigned char) t;
  return _write_bytes(&code, 1, 1);
}

bool TypedBytesOutFile::write_bool(bool val) {
  signed char sval = 0;
  if (val)
    sval = 1;
  return _write_code(TypedBytesBoolean) && _write_bytes(&sval, 1, 1);
}

bool TypedBytesOutFile::write_int(int val) {
  int32_t sval = bswap32(val);
  return _write_code(TypedBytesInteger) &&
    _write_bytes(&sval, sizeof(int32_t), 1);
}

bool TypedBytesOutFile::write_long(typedbytes_long val) {
  val = bswap64(val);
  return _write_code(TypedBytesLong) &&
    _write_bytes(&val, sizeof(typedbytes_long), 1);
}

bool TypedBytesOutFile::write_float(float val) {
  int32_t sval = 0;
  memcpy(&sval, &val, sizeof(int32_t));
  sval = bswap32(sval);
  return _write_code(TypedBytesFloat) && _write_bytes(&sval, sizeof(int32_t), 1);
}

bool TypedBytesOutFile::write_double(double val) {
  int64_t sval = 0;
  memcpy(&sval, &val, sizeof(int64_t));
  sval = bswap64(sval);
  return _write_code(TypedBytesDouble) &&
    _write_bytes(&sval, sizeof(int64_t), 1);
}
<|endoftext|>


<commit_before>// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements.  See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership.  The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License.  You may obtain a copy of the License at
//
//   http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied.  See the License for the
// specific language governing permissions and limitations
// under the License.

#include "olap/olap_meta.h"

#include <vector>
#include <sstream>

#include "olap/olap_define.h"
#include "rocksdb/db.h"
#include "rocksdb/slice.h"
#include "rocksdb/options.h"
#include "rocksdb/slice_transform.h"
#include "common/logging.h"
#include "util/doris_metrics.h"
#include "util/runtime_profile.h"

using rocksdb::DB;
using rocksdb::DBOptions;
using rocksdb::ColumnFamilyDescriptor;
using rocksdb::ColumnFamilyHandle;
using rocksdb::ColumnFamilyOptions;
using rocksdb::ReadOptions;
using rocksdb::WriteOptions;
using rocksdb::Slice;
using rocksdb::Iterator;
using rocksdb::Status;
using rocksdb::kDefaultColumnFamilyName;
using rocksdb::NewFixedPrefixTransform;

namespace doris {
const std::string META_POSTFIX = "/meta";
const size_t PREFIX_LENGTH = 4;

OlapMeta::OlapMeta(const std::string& root_path)
        : _root_path(root_path),
        _db(nullptr) {
}

OlapMeta::~OlapMeta() {
    for (auto handle : _handles) {
        delete handle;
    }
    if (_db != NULL) {
        _db->Close();
        delete _db;
        _db= NULL;
    }
}

OLAPStatus OlapMeta::init() {
    // init db
    DBOptions options;
    options.IncreaseParallelism();
    options.create_if_missing = true;
    options.create_missing_column_families = true;
    std::string db_path = _root_path + META_POSTFIX;
    std::vector<ColumnFamilyDescriptor> column_families;
    // default column family is required
    column_families.emplace_back(DEFAULT_COLUMN_FAMILY, ColumnFamilyOptions());
    column_families.emplace_back(DORIS_COLUMN_FAMILY, ColumnFamilyOptions());

    // meta column family add prefix extrator to improve performance and ensure correctness
    ColumnFamilyOptions meta_column_family;
    meta_column_family.prefix_extractor.reset(NewFixedPrefixTransform(PREFIX_LENGTH));
    column_families.emplace_back(META_COLUMN_FAMILY, meta_column_family);
    Status s = DB::Open(options, db_path, column_families, &_handles, &_db);
    if (!s.ok() || _db == NULL) {
        LOG(WARNING) << "rocks db open failed, reason:" << s.ToString();
        return OLAP_ERR_META_OPEN_DB;
    }
    return OLAP_SUCCESS;
}

OLAPStatus OlapMeta::get(const int column_family_index, const std::string& key, std::string& value) {
    DorisMetrics::meta_read_request_total.increment(1);
    rocksdb::ColumnFamilyHandle* handle = _handles[column_family_index];
    int64_t duration_ns = 0;
    Status s = Status::OK();
    {
        SCOPED_RAW_TIMER(&duration_ns);
        s = _db->Get(ReadOptions(), handle, Slice(key), &value);
    }
    DorisMetrics::meta_read_request_duration_us.increment(duration_ns / 1000);
    if (s.IsNotFound()) {
        LOG(WARNING) << "rocks db key not found:" << key;
        return OLAP_ERR_META_KEY_NOT_FOUND;
    } else if (!s.ok()) {
        LOG(WARNING) << "rocks db get key:" << key << " failed, reason:" << s.ToString();
        return OLAP_ERR_META_GET;
    }
    return OLAP_SUCCESS;
}

OLAPStatus OlapMeta::put(const int column_family_index, const std::string& key, const std::string& value) {
    DorisMetrics::meta_write_request_total.increment(1);
    rocksdb::ColumnFamilyHandle* handle = _handles[column_family_index];
    int64_t duration_ns = 0;
    Status s = Status::OK();
    {
        SCOPED_RAW_TIMER(&duration_ns);
        WriteOptions write_options;
        write_options.sync = config::sync_tablet_meta;
        s = _db->Put(write_options, handle, Slice(key), Slice(value));
    }
    DorisMetrics::meta_write_request_duration_us.increment(duration_ns / 1000);
    if (!s.ok()) {
        LOG(WARNING) << "rocks db put key:" << key << " failed, reason:" << s.ToString();
        return OLAP_ERR_META_PUT;
    }
    return OLAP_SUCCESS;
}

OLAPStatus OlapMeta::remove(const int column_family_index, const std::string& key) {
    DorisMetrics::meta_write_request_total.increment(1);
    rocksdb::ColumnFamilyHandle* handle = _handles[column_family_index];
    Status s = Status::OK();
    int64_t duration_ns = 0;
    {
        SCOPED_RAW_TIMER(&duration_ns);
        WriteOptions write_options;
        write_options.sync = config::sync_tablet_meta;
        s = _db->Delete(write_options, handle, Slice(key));
    }
    DorisMetrics::meta_write_request_duration_us.increment(duration_ns / 1000);
    if (!s.ok()) {
        LOG(WARNING) << "rocks db delete key:" << key << " failed, reason:" << s.ToString();
        return OLAP_ERR_META_DELETE;
    }
    return OLAP_SUCCESS;
}

OLAPStatus OlapMeta::iterate(const int column_family_index, const std::string& prefix,
        std::function<bool(const std::string&, const std::string&)> const& func) {
    rocksdb::ColumnFamilyHandle* handle = _handles[column_family_index];
    std::unique_ptr<Iterator> it(_db->NewIterator(ReadOptions(), handle));
    if (prefix == "") {
        it->SeekToFirst();
    } else {
        it->Seek(prefix);
    }
    Status status = it->status();
    if (!status.ok()) {
        LOG(WARNING) << "rocksdb seek failed. reason:" << status.ToString();
        return OLAP_ERR_META_ITERATOR;
    }
    for (; it->Valid(); it->Next()) {
        if (prefix != "") {
            if (!it->key().starts_with(prefix)) {
                return OLAP_SUCCESS;
            }
        }
        std::string key = it->key().ToString();
        std::string value = it->value().ToString();
        bool ret = func(key, value);
        if (!ret) {
            break;
        }
    }
    return OLAP_SUCCESS;
}

std::string OlapMeta::get_root_path() {
    return _root_path;
}

}
<commit_msg>Optimize error handling of rocksdb (#841)<commit_after>// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements.  See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership.  The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License.  You may obtain a copy of the License at
//
//   http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied.  See the License for the
// specific language governing permissions and limitations
// under the License.

#include "olap/olap_meta.h"

#include <vector>
#include <sstream>

#include "olap/olap_define.h"
#include "rocksdb/db.h"
#include "rocksdb/slice.h"
#include "rocksdb/options.h"
#include "rocksdb/slice_transform.h"
#include "common/logging.h"
#include "util/doris_metrics.h"
#include "util/runtime_profile.h"

using rocksdb::DB;
using rocksdb::DBOptions;
using rocksdb::ColumnFamilyDescriptor;
using rocksdb::ColumnFamilyHandle;
using rocksdb::ColumnFamilyOptions;
using rocksdb::ReadOptions;
using rocksdb::WriteOptions;
using rocksdb::Slice;
using rocksdb::Iterator;
using rocksdb::Status;
using rocksdb::kDefaultColumnFamilyName;
using rocksdb::NewFixedPrefixTransform;

namespace doris {
const std::string META_POSTFIX = "/meta";
const size_t PREFIX_LENGTH = 4;

OlapMeta::OlapMeta(const std::string& root_path)
        : _root_path(root_path),
        _db(nullptr) {
}

OlapMeta::~OlapMeta() {
    for (auto handle : _handles) {
        delete handle;
    }
    if (_db != NULL) {
        _db->Close();
        delete _db;
        _db= NULL;
    }
}

OLAPStatus OlapMeta::init() {
    // init db
    DBOptions options;
    options.IncreaseParallelism();
    options.create_if_missing = true;
    options.create_missing_column_families = true;
    std::string db_path = _root_path + META_POSTFIX;
    std::vector<ColumnFamilyDescriptor> column_families;
    // default column family is required
    column_families.emplace_back(DEFAULT_COLUMN_FAMILY, ColumnFamilyOptions());
    column_families.emplace_back(DORIS_COLUMN_FAMILY, ColumnFamilyOptions());

    // meta column family add prefix extrator to improve performance and ensure correctness
    ColumnFamilyOptions meta_column_family;
    meta_column_family.prefix_extractor.reset(NewFixedPrefixTransform(PREFIX_LENGTH));
    column_families.emplace_back(META_COLUMN_FAMILY, meta_column_family);
    Status s = DB::Open(options, db_path, column_families, &_handles, &_db);
    if (!s.ok() || _db == NULL) {
        LOG(WARNING) << "rocks db open failed, reason:" << s.ToString();
        return OLAP_ERR_META_OPEN_DB;
    }
    return OLAP_SUCCESS;
}

OLAPStatus OlapMeta::get(const int column_family_index, const std::string& key, std::string& value) {
    DorisMetrics::meta_read_request_total.increment(1);
    rocksdb::ColumnFamilyHandle* handle = _handles[column_family_index];
    int64_t duration_ns = 0;
    Status s = Status::OK();
    {
        SCOPED_RAW_TIMER(&duration_ns);
        s = _db->Get(ReadOptions(), handle, Slice(key), &value);
    }
    DorisMetrics::meta_read_request_duration_us.increment(duration_ns / 1000);
    if (s.IsNotFound()) {
        LOG(WARNING) << "rocks db key not found:" << key;
        return OLAP_ERR_META_KEY_NOT_FOUND;
    } else if (!s.ok()) {
        LOG(WARNING) << "rocks db get key:" << key << " failed, reason:" << s.ToString();
        return OLAP_ERR_META_GET;
    }
    return OLAP_SUCCESS;
}

OLAPStatus OlapMeta::put(const int column_family_index, const std::string& key, const std::string& value) {
    DorisMetrics::meta_write_request_total.increment(1);
    rocksdb::ColumnFamilyHandle* handle = _handles[column_family_index];
    int64_t duration_ns = 0;
    Status s = Status::OK();
    {
        SCOPED_RAW_TIMER(&duration_ns);
        WriteOptions write_options;
        write_options.sync = config::sync_tablet_meta;
        s = _db->Put(write_options, handle, Slice(key), Slice(value));
    }
    DorisMetrics::meta_write_request_duration_us.increment(duration_ns / 1000);
    if (!s.ok()) {
        LOG(WARNING) << "rocks db put key:" << key << " failed, reason:" << s.ToString();
        return OLAP_ERR_META_PUT;
    }
    return OLAP_SUCCESS;
}

OLAPStatus OlapMeta::remove(const int column_family_index, const std::string& key) {
    DorisMetrics::meta_write_request_total.increment(1);
    rocksdb::ColumnFamilyHandle* handle = _handles[column_family_index];
    Status s = Status::OK();
    int64_t duration_ns = 0;
    {
        SCOPED_RAW_TIMER(&duration_ns);
        WriteOptions write_options;
        write_options.sync = config::sync_tablet_meta;
        s = _db->Delete(write_options, handle, Slice(key));
    }
    DorisMetrics::meta_write_request_duration_us.increment(duration_ns / 1000);
    if (!s.ok()) {
        LOG(WARNING) << "rocks db delete key:" << key << " failed, reason:" << s.ToString();
        return OLAP_ERR_META_DELETE;
    }
    return OLAP_SUCCESS;
}

OLAPStatus OlapMeta::iterate(const int column_family_index, const std::string& prefix,
        std::function<bool(const std::string&, const std::string&)> const& func) {
    rocksdb::ColumnFamilyHandle* handle = _handles[column_family_index];
    std::unique_ptr<Iterator> it(_db->NewIterator(ReadOptions(), handle));
    if (prefix == "") {
        it->SeekToFirst();
    } else {
        it->Seek(prefix);
    }
    Status status = it->status();
    if (!status.ok()) {
        LOG(WARNING) << "rocksdb seek failed. reason:" << status.ToString();
        return OLAP_ERR_META_ITERATOR;
    }
    for (; it->Valid(); it->Next()) {
        if (prefix != "") {
            if (!it->key().starts_with(prefix)) {
                return OLAP_SUCCESS;
            }
        }
        std::string key = it->key().ToString();
        std::string value = it->value().ToString();
        bool ret = func(key, value);
        if (!ret) {
            break;
        }
    }
    if (!it->status().ok()) {
        LOG(WARNING) << "rocksdb iterator failed. reason:" << status.ToString();
        return OLAP_ERR_META_ITERATOR;
    }
    return OLAP_SUCCESS;
}

std::string OlapMeta::get_root_path() {
    return _root_path;
}

}
<|endoftext|>


<commit_before>/******************************************************************
 *
 * Copyright 2016 Samsung Electronics All Rights Reserved.
 *
 *
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 ******************************************************************/

#include <iostream>

#include <unistd.h>
#include "NSConsumerService.h"
#include "NSMessage.h"
#include "NSProvider.h"
#include "NSTopicsList.h"
#include "ocstack.h"

#define TAG "NotiConsumerWrapperExample"
using namespace std;
using namespace OIC::Service;

bool isExit = false;
std::string REMOTE_SERVER_ADDRESS;
std::string mainProvider;

void onNotificationPostedCb(OIC::Service::NSMessage *notification)
{
    std::cout << "id : " << notification->getMessageId() << std::endl;
    std::cout << "title : " << notification->getTitle() << std::endl;
    std::cout << "content : " <<  notification->getContentText() << std::endl;
    std::cout << "source : " <<  notification->getSourceName() << std::endl;
    std::cout << "topic : " <<  notification->getTopic() << std::endl;

    auto provider = NSConsumerService::getInstance()->getProvider(notification->getProviderId());
    if (provider != nullptr)
    {
        provider->sendSyncInfo(notification->getMessageId(),
                               OIC::Service::NSSyncInfo::NSSyncType::NS_SYNC_READ);
    }
}

void onNotificationSyncCb(OIC::Service::NSSyncInfo *sync)
{
    std::cout << "Sync ID : " <<  sync->getMessageId() << std::endl;
    std::cout << "Sync STATE : " << (int) sync->getState() << std::endl;
}

void onProviderStateChangedCb(OIC::Service::NSProviderState state)
{
    std::cout << "onProviderStateChangedCb" << std::endl;
    if (state == OIC::Service::NSProviderState::ALLOW)
    {
        std::cout << "Provider Subscription Accepted" << std::endl;
    }
    else if (state == OIC::Service::NSProviderState::DENY)
    {
        std::cout << "Provider Subscription Denied" << std::endl;
    }
    else if (state == OIC::Service::NSProviderState::TOPIC)
    {
        OIC::Service::NSProvider *provider = NSConsumerService::getInstance()->getProvider(mainProvider);
        if (provider != nullptr)
        {
            auto topicList = provider->getTopicList();
            if (topicList != nullptr)
            {
                for (auto it : topicList->getTopicsList())
                {
                    std::cout << "Topic Name: " << it->getTopicName() << std::endl;
                    std::cout << "Topic state: " << (int) it->getState() << std::endl;
                }
            }
        }
    }
    else if (state == OIC::Service::NSProviderState::STOPPED)
    {
        std::cout << "Provider Stopped" << std::endl;
    }
}

void onDiscoverNotificationCb(OIC::Service::NSProvider *provider)
{
    std::cout << "notification resource discovered" << std::endl;
    std::cout << "SetListeners for callbacks" << std::endl;
    provider->setListener(onProviderStateChangedCb, onNotificationPostedCb, onNotificationSyncCb);
    if (!provider->isSubscribed())
    {
        std::cout << "startSubscribing" << std::endl;
        provider->subscribe();
    }
    if (mainProvider.empty())
    {
        mainProvider = provider->getProviderId();
    }
}

void *OCProcessThread(void *ptr)
{
    (void) ptr;

    while (!isExit)
    {
        usleep(2000);
        if (OCProcess() != OC_STACK_OK)
        {
            OCStop();
            break;
        }
    }

    return NULL;
}

int main(void)
{
    pthread_t OCThread = NULL;

    std::cout << "start Iotivity" << std::endl;
    if (OCInit1(OC_CLIENT, OC_DEFAULT_FLAGS, OC_DEFAULT_FLAGS) != OC_STACK_OK)
    {
        std::cout << "OCInit fail" << std::endl;
        return 0;
    }

    pthread_create(&OCThread, NULL, OCProcessThread, NULL);

    std::cout << "Start notification consumer service" << std::endl;
    while (!isExit)
    {
        int num = 0;

        std::cout << "1. Start Consumer" << std::endl;
        std::cout << "2. Stop Consumer" << std::endl;
        std::cout << "3. GetTopicList" << std::endl;
        std::cout << "4. UpdateTopicList" << std::endl;
#ifdef WITH_CLOUD
        std::cout << "5. Enable  NS Consumer RemoteService" << std::endl;
#endif
        std::cout << "6. Exit" << std::endl;

        std::cout << "Input: " << std::endl;
        std::cin >> num;
        switch (num)
        {
            case 1:
                std::cout << "1. Start the Notification Consumer" << std::endl;
                NSConsumerService::getInstance()->start(onDiscoverNotificationCb);
                break;
            case 2:
                std::cout << "2. Stop the Notification Consumer" << std::endl;
                NSConsumerService::getInstance()->stop();
                break;
            case 3:
                {
                    std::cout <<  "GetTopicList" << std::endl;
                    OIC::Service::NSProvider *provider = NSConsumerService::getInstance()->getProvider(mainProvider);
                    if (provider != nullptr)
                    {
                        auto topicList = provider->getTopicList();
                        if (topicList != nullptr)
                        {
                            for (auto it : topicList->getTopicsList())
                            {
                                std::cout << "Topic Name: " << it->getTopicName() << std::endl;
                                std::cout << "Topic state: " << (int) it->getState() << std::endl;
                            }
                        }
                    }
                }
                break;
            case 4:
                {
                    std::cout <<  "UpdateTopicList" << std::endl;
                    OIC::Service::NSProvider *provider = NSConsumerService::getInstance()->getProvider(mainProvider);
                    if (provider != nullptr)
                    {
                        NSTopicsList *topicList = new NSTopicsList();
                        topicList->addTopic("OCF_TOPIC1", NSTopic::NSTopicState::SUBSCRIBED);
                        topicList->addTopic("OCF_TOPIC2", NSTopic::NSTopicState::SUBSCRIBED);
                        topicList->addTopic("OCF_TOPIC3", NSTopic::NSTopicState::UNSUBSCRIBED);

                        provider->updateTopicList(topicList);
                    }
                }
                break;
#ifdef WITH_CLOUD
            case 5:
                {
                    std::cout << "5. Enable NS Consumer RemoteService" << std::endl;
                    std::cout << "Input the Server Address :";
                    std::cin >> REMOTE_SERVER_ADDRESS;
                    NSConsumerService::getInstance()->enableRemoteService(REMOTE_SERVER_ADDRESS);
                    break;
                }
#endif
            case 6:
                std::cout << "6. Exit" << std::endl;
                isExit = true;
                break;
            default:
                break;
        }
    }

    return 0;
}
<commit_msg>[IOT-1430] bug fix for seg fault on start consumer.<commit_after>/******************************************************************
 *
 * Copyright 2016 Samsung Electronics All Rights Reserved.
 *
 *
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 ******************************************************************/

#include <iostream>

#include <unistd.h>
#include "NSConsumerService.h"
#include "NSMessage.h"
#include "NSProvider.h"
#include "NSTopicsList.h"
#include "ocstack.h"

#define TAG "NotiConsumerWrapperExample"
using namespace std;
using namespace OIC::Service;

bool isExit = false;
std::string REMOTE_SERVER_ADDRESS;
std::string mainProvider;

FILE* server_fopen(const char *path, const char *mode)
{
    (void)path;
    return fopen("oic_ns_provider_db.dat", mode);
}

void onNotificationPostedCb(OIC::Service::NSMessage *notification)
{
    std::cout << "id : " << notification->getMessageId() << std::endl;
    std::cout << "title : " << notification->getTitle() << std::endl;
    std::cout << "content : " <<  notification->getContentText() << std::endl;
    std::cout << "source : " <<  notification->getSourceName() << std::endl;
    std::cout << "topic : " <<  notification->getTopic() << std::endl;

    auto provider = NSConsumerService::getInstance()->getProvider(notification->getProviderId());
    if (provider != nullptr)
    {
        provider->sendSyncInfo(notification->getMessageId(),
                               OIC::Service::NSSyncInfo::NSSyncType::NS_SYNC_READ);
    }
}

void onNotificationSyncCb(OIC::Service::NSSyncInfo *sync)
{
    std::cout << "Sync ID : " <<  sync->getMessageId() << std::endl;
    std::cout << "Sync STATE : " << (int) sync->getState() << std::endl;
}

void onProviderStateChangedCb(OIC::Service::NSProviderState state)
{
    std::cout << "onProviderStateChangedCb" << std::endl;
    if (state == OIC::Service::NSProviderState::ALLOW)
    {
        std::cout << "Provider Subscription Accepted" << std::endl;
    }
    else if (state == OIC::Service::NSProviderState::DENY)
    {
        std::cout << "Provider Subscription Denied" << std::endl;
    }
    else if (state == OIC::Service::NSProviderState::TOPIC)
    {
        OIC::Service::NSProvider *provider = NSConsumerService::getInstance()->getProvider(mainProvider);
        if (provider != nullptr)
        {
            auto topicList = provider->getTopicList();
            if (topicList != nullptr)
            {
                for (auto it : topicList->getTopicsList())
                {
                    std::cout << "Topic Name: " << it->getTopicName() << std::endl;
                    std::cout << "Topic state: " << (int) it->getState() << std::endl;
                }
            }
        }
    }
    else if (state == OIC::Service::NSProviderState::STOPPED)
    {
        std::cout << "Provider Stopped" << std::endl;
    }
}

void onDiscoverNotificationCb(OIC::Service::NSProvider *provider)
{
    std::cout << "notification resource discovered" << std::endl;
    std::cout << "SetListeners for callbacks" << std::endl;
    provider->setListener(onProviderStateChangedCb, onNotificationPostedCb, onNotificationSyncCb);
    if (!provider->isSubscribed())
    {
        std::cout << "startSubscribing" << std::endl;
        provider->subscribe();
    }
    if (mainProvider.empty())
    {
        mainProvider = provider->getProviderId();
    }
}

void *OCProcessThread(void *ptr)
{
    (void) ptr;

    while (!isExit)
    {
        usleep(2000);
        if (OCProcess() != OC_STACK_OK)
        {
            OCStop();
            break;
        }
    }

    return NULL;
}

int main(void)
{
    pthread_t OCThread = NULL;

    std::cout << "start Iotivity" << std::endl;

    // open oic_db
    static OCPersistentStorage ps = {server_fopen, fread, fwrite, fclose, unlink};
    OCRegisterPersistentStorageHandler(&ps);

    if (OCInit1(OC_CLIENT_SERVER, OC_DEFAULT_FLAGS, OC_DEFAULT_FLAGS) != OC_STACK_OK)
    {
        std::cout << "OCInit fail" << std::endl;
        return 0;
    }

    pthread_create(&OCThread, NULL, OCProcessThread, NULL);

    std::cout << "Start notification consumer service" << std::endl;
    while (!isExit)
    {
        int num = 0;

        std::cout << "1. Start Consumer" << std::endl;
        std::cout << "2. Stop Consumer" << std::endl;
        std::cout << "3. GetTopicList" << std::endl;
        std::cout << "4. UpdateTopicList" << std::endl;
#ifdef WITH_CLOUD
        std::cout << "5. Enable  NS Consumer RemoteService" << std::endl;
#endif
        std::cout << "6. Exit" << std::endl;

        std::cout << "Input: " << std::endl;
        std::cin >> num;
        switch (num)
        {
            case 1:
                std::cout << "1. Start the Notification Consumer" << std::endl;
                NSConsumerService::getInstance()->start(onDiscoverNotificationCb);
                break;
            case 2:
                std::cout << "2. Stop the Notification Consumer" << std::endl;
                NSConsumerService::getInstance()->stop();
                break;
            case 3:
                {
                    std::cout <<  "GetTopicList" << std::endl;
                    OIC::Service::NSProvider *provider = NSConsumerService::getInstance()->getProvider(mainProvider);
                    if (provider != nullptr)
                    {
                        auto topicList = provider->getTopicList();
                        if (topicList != nullptr)
                        {
                            for (auto it : topicList->getTopicsList())
                            {
                                std::cout << "Topic Name: " << it->getTopicName() << std::endl;
                                std::cout << "Topic state: " << (int) it->getState() << std::endl;
                            }
                        }
                    }
                }
                break;
            case 4:
                {
                    std::cout <<  "UpdateTopicList" << std::endl;
                    OIC::Service::NSProvider *provider = NSConsumerService::getInstance()->getProvider(mainProvider);
                    if (provider != nullptr)
                    {
                        NSTopicsList *topicList = new NSTopicsList();
                        topicList->addTopic("OCF_TOPIC1", NSTopic::NSTopicState::SUBSCRIBED);
                        topicList->addTopic("OCF_TOPIC2", NSTopic::NSTopicState::SUBSCRIBED);
                        topicList->addTopic("OCF_TOPIC3", NSTopic::NSTopicState::UNSUBSCRIBED);

                        provider->updateTopicList(topicList);
                    }
                }
                break;
#ifdef WITH_CLOUD
            case 5:
                {
                    std::cout << "5. Enable NS Consumer RemoteService" << std::endl;
                    std::cout << "Input the Server Address :";
                    std::cin >> REMOTE_SERVER_ADDRESS;
                    NSConsumerService::getInstance()->enableRemoteService(REMOTE_SERVER_ADDRESS);
                    break;
                }
#endif
            case 6:
                std::cout << "6. Exit" << std::endl;
                isExit = true;
                break;
            default:
                break;
        }
    }

    return 0;
}
<|endoftext|>


<commit_before>/*
 * This file is part of telepathy-accounts-kcm
 *
 * Copyright (C) 2009 Collabora Ltd. <http://www.collabora.co.uk/>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 */

#include "account-item.h"

#include "accounts-list-model.h"
#include "edit-account-dialog.h"

#include <KApplication>
#include <KDebug>
#include <KIcon>
#include <KLocalizedString>

#include <QtCore/QTimer>
#include <QtGui/QPainter>

#include <TelepathyQt4/PendingOperation>
#include <TelepathyQt4/PendingReady>

AccountItem::AccountItem(const Tp::AccountPtr &account, AccountsListModel *parent)
 : QObject(parent),
   m_account(account),
   m_icon(new KIcon())
{
    kDebug();

    //connect AccountPtr signals to AccountItem signals
    connect(m_account.data(),
            SIGNAL(stateChanged(bool)),
            SIGNAL(updated()));
    connect(m_account.data(),
            SIGNAL(displayNameChanged(const QString&)),
            SIGNAL(updated()));
    connect(m_account.data(),
            SIGNAL(connectionStatusChanged(Tp::ConnectionStatus)),
            SIGNAL(updated()));

    generateIcon();
}

AccountItem::~AccountItem()
{
    kDebug();

    delete m_icon;
}

Tp::AccountPtr AccountItem::account() const
{
    return m_account;
}

void AccountItem::remove()
{
    kDebug() << "Account about to be removed";

    Tp::PendingOperation *op = m_account->remove();
    connect(op,
            SIGNAL(finished(Tp::PendingOperation*)),
            SLOT(onAccountRemoved(Tp::PendingOperation*)));
}

const KIcon& AccountItem::icon() const
{
    Q_ASSERT(m_icon != 0);

    return *m_icon;
}

const QString AccountItem::connectionStateString() const
{
    switch (m_account->connectionStatus()) {
    case Tp::ConnectionStatusConnected:
        return i18n("Online");
    case Tp::ConnectionStatusConnecting:
        return i18n("Connecting");
    case Tp::ConnectionStatusDisconnected:
        return i18n("Disconnected");
    default:
        return "Unknown";
    }
}

const KIcon AccountItem::connectionStateIcon() const
{
    switch (m_account->connectionStatus()) {
    case Tp::ConnectionStatusConnected:
        return KIcon("user-online");
    case Tp::ConnectionStatusConnecting:
        return KIcon("user-away"); //FIXME this is bit misleading
    case Tp::ConnectionStatusDisconnected:
        return KIcon("user-offline");
    default:
        return KIcon("user-offline");
    }
}

const QString AccountItem::connectionStatusReason() const
{
    switch (m_account->connectionStatusReason())
    {
    case Tp::ConnectionStatusReasonAuthenticationFailed:
        return i18n("Authentication Failed");
    case Tp::ConnectionStatusReasonNetworkError:
        return i18n("Network Error");
    default:
        return QString();
    }
}

void AccountItem::generateIcon()
{
    kDebug();

    QString iconPath = account()->iconName();

    //if the icon has not been setted, we use the protocol icon
    if(iconPath.isEmpty()) {
        iconPath = QString("im-%1").arg(account()->protocolName());
    }

    delete m_icon;
    m_icon = new KIcon(iconPath);

    if(!account()->isValid()) {
        //we paint a warning symbol in the right-bottom corner
        QPixmap pixmap = m_icon->pixmap(32, 32);
        QPainter painter(&pixmap);
        KIcon("dialog-error").paint(&painter, 15, 15, 16, 16);

        delete m_icon;
        m_icon = new KIcon(pixmap);
    }

    Q_EMIT(updated());
}

void AccountItem::onAccountRemoved(Tp::PendingOperation *op)
{
    kDebug();

    if (op->isError()) {
        kDebug() << "An error occurred removing the Account."
                 << op->errorName()
                 << op->errorMessage();
        return;
    }

    Q_EMIT removed();
}

void AccountItem::onTitleForCustomPages(QString mandatoryPage, QList<QString> optionalPage)
{
	kDebug();
	emit setTitleForCustomPages(mandatoryPage, optionalPage);
}

#include "account-item.moc"

<commit_msg>Listen to Tp::Account::removed().<commit_after>/*
 * This file is part of telepathy-accounts-kcm
 *
 * Copyright (C) 2009 Collabora Ltd. <http://www.collabora.co.uk/>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 */

#include "account-item.h"

#include "accounts-list-model.h"
#include "edit-account-dialog.h"

#include <KApplication>
#include <KDebug>
#include <KIcon>
#include <KLocalizedString>

#include <QtCore/QTimer>
#include <QtGui/QPainter>

#include <TelepathyQt4/PendingOperation>
#include <TelepathyQt4/PendingReady>

AccountItem::AccountItem(const Tp::AccountPtr &account, AccountsListModel *parent)
 : QObject(parent),
   m_account(account),
   m_icon(new KIcon())
{
    kDebug();

    //connect AccountPtr signals to AccountItem signals
    connect(m_account.data(),
            SIGNAL(stateChanged(bool)),
            SIGNAL(updated()));
    connect(m_account.data(),
            SIGNAL(displayNameChanged(const QString&)),
            SIGNAL(updated()));
    connect(m_account.data(),
            SIGNAL(connectionStatusChanged(Tp::ConnectionStatus)),
            SIGNAL(updated()));
    connect(m_account.data(),
            SIGNAL(removed()),
            SIGNAL(removed()));

    generateIcon();
}

AccountItem::~AccountItem()
{
    kDebug();

    delete m_icon;
}

Tp::AccountPtr AccountItem::account() const
{
    return m_account;
}

void AccountItem::remove()
{
    kDebug() << "Account about to be removed";

    Tp::PendingOperation *op = m_account->remove();
    connect(op,
            SIGNAL(finished(Tp::PendingOperation*)),
            SLOT(onAccountRemoved(Tp::PendingOperation*)));
}

const KIcon& AccountItem::icon() const
{
    Q_ASSERT(m_icon != 0);

    return *m_icon;
}

const QString AccountItem::connectionStateString() const
{
    switch (m_account->connectionStatus()) {
    case Tp::ConnectionStatusConnected:
        return i18n("Online");
    case Tp::ConnectionStatusConnecting:
        return i18n("Connecting");
    case Tp::ConnectionStatusDisconnected:
        return i18n("Disconnected");
    default:
        return "Unknown";
    }
}

const KIcon AccountItem::connectionStateIcon() const
{
    switch (m_account->connectionStatus()) {
    case Tp::ConnectionStatusConnected:
        return KIcon("user-online");
    case Tp::ConnectionStatusConnecting:
        return KIcon("user-away"); //FIXME this is bit misleading
    case Tp::ConnectionStatusDisconnected:
        return KIcon("user-offline");
    default:
        return KIcon("user-offline");
    }
}

const QString AccountItem::connectionStatusReason() const
{
    switch (m_account->connectionStatusReason())
    {
    case Tp::ConnectionStatusReasonAuthenticationFailed:
        return i18n("Authentication Failed");
    case Tp::ConnectionStatusReasonNetworkError:
        return i18n("Network Error");
    default:
        return QString();
    }
}

void AccountItem::generateIcon()
{
    kDebug();

    QString iconPath = account()->iconName();

    //if the icon has not been setted, we use the protocol icon
    if(iconPath.isEmpty()) {
        iconPath = QString("im-%1").arg(account()->protocolName());
    }

    delete m_icon;
    m_icon = new KIcon(iconPath);

    if(!account()->isValid()) {
        //we paint a warning symbol in the right-bottom corner
        QPixmap pixmap = m_icon->pixmap(32, 32);
        QPainter painter(&pixmap);
        KIcon("dialog-error").paint(&painter, 15, 15, 16, 16);

        delete m_icon;
        m_icon = new KIcon(pixmap);
    }

    Q_EMIT(updated());
}

void AccountItem::onAccountRemoved(Tp::PendingOperation *op)
{
    kDebug();

    if (op->isError()) {
        kDebug() << "An error occurred removing the Account."
                 << op->errorName()
                 << op->errorMessage();
        return;
    }
}

void AccountItem::onTitleForCustomPages(QString mandatoryPage, QList<QString> optionalPage)
{
	kDebug();
	emit setTitleForCustomPages(mandatoryPage, optionalPage);
}

#include "account-item.moc"

<|endoftext|>


<commit_before>void main(int argc, int** argv)
{
   double dt=0.1*ns;
   double dx=0.1*nm;
   double Ee=1000*V/cm;

   double t=0;
   for (int i=-imin; i<imax; i++) {
      p[i]=-n[i]=gaus(i);
   }
   while (t<100*ns) {
      for (int i=-imin; i<imax; i++) {
         E[i]=0;
         for (int j=-imin; j<i; j++) {
            E[i]+=q/dielec*(p[j]-n[j])*dx;
         }
         E[i]+=Ee;

         pSlope_x[i]=(p[i+1]-p[i])/dx;
         nSlope_x[i]=(n[i+1]-n[i])/dx;

         pSlope_t[i] - nSlope_t[i] = - mu*E[i]*(pSlope_x[i]-nSlope_x[i]) - q*mu/dielec*(p[i]-n[i])*(p[i]-n[i]);
      }

      t=t+dt;
   }
}
double gaus(int)
{
   return 1;
}
<commit_msg>finished evolving<commit_after>void main(int argc, int** argv)
{
   double dt=0.1*ns;
   double dx=0.1*nm;
   double Ee=1000*V/cm;

   // initialize arrays
   const int N = 1000;
   double p[2*N+1], n[2*N+1], E[2*N+1];
   for (int i=-N; i<=N; i++) {
      p[i]=n[i]=gaus(i);
      E[i]=0;
      for (int j=-N; j<=i; j++) {
         dE_dx[j]=q*(p[j]-n[j])/epsilon;
         E[i]+=dE_dx[j]*dx;
      }
      E[i]+=Ee;
   }

   // evolve
   double t=0;
   while (t<100*ns) {
      for (int i=-N; i<=N; i++) {
         // update electron distribution
         dn_dx = (n[i+1]-n[i])/dx;
         dn_dt = mu_e*(dn_dx*E[i]+n[i]*dE_dx[i]);
         n[i]+=dn_dt*dt;

         // update hole distribution
         dp_dx = (p[i+1]-p[i])/dx;
         dp_dt = -mu_h*(dp_dx*E[i]+p[i]*dE_dx[i]);
         p[i]+=dp_dt*dt;

         // update electric field distribution
         E[i]=0;
         for (int j=-N; j<=i; j++) {
            dE_dx[j]=q*(p[j]-n[j])/epsilon;
            E[i]+=dE_dx[j]*dx;
         }
         E[i]+=Ee;
      }
      t+=dt;
   }

   return;
}

double gaus(int)
{
   return 1;
}
<|endoftext|>


<commit_before>/*
 * Copyright (C) 2014 Cloudius Systems, Ltd.
 */

#ifndef DATABASE_HH_
#define DATABASE_HH_

#include "dht/i_partitioner.hh"
#include "core/sstring.hh"
#include "core/shared_ptr.hh"
#include "net/byteorder.hh"
#include "utils/UUID.hh"
#include "db_clock.hh"
#include "gc_clock.hh"
#include <functional>
#include <boost/any.hpp>
#include <cstdint>
#include <boost/variant.hpp>
#include <unordered_map>
#include <map>
#include <set>
#include <vector>
#include <iostream>
#include <boost/functional/hash.hpp>
#include <experimental/optional>
#include <string.h>
#include "types.hh"
#include "tuple.hh"
#include "core/future.hh"
#include "cql3/column_specification.hh"
#include <limits>
#include <cstddef>
#include "schema.hh"
#include "timestamp.hh"
#include "tombstone.hh"
#include "atomic_cell.hh"
#include "bytes.hh"
#include "query.hh"

using partition_key_type = tuple_type<>;
using clustering_key_type = tuple_type<>;
using clustering_prefix_type = tuple_prefix;
using partition_key = bytes;
using clustering_key = bytes;
using clustering_prefix = clustering_prefix_type::value_type;

using row = std::map<column_id, atomic_cell_or_collection>;

struct deletable_row final {
    tombstone t;
    row cells;
};

using row_tombstone_set = std::map<bytes, tombstone, serialized_compare>;

class mutation_partition final {
private:
    tombstone _tombstone;
    row _static_row;
    std::map<clustering_key, deletable_row, key_compare> _rows;
    row_tombstone_set _row_tombstones;
public:
    mutation_partition(schema_ptr s)
        : _rows(key_compare(s->clustering_key_type))
        , _row_tombstones(serialized_compare(s->clustering_key_prefix_type))
    { }
    void apply(tombstone t) { _tombstone.apply(t); }
    void apply_delete(schema_ptr schema, const clustering_prefix& prefix, tombstone t);
    void apply_row_tombstone(schema_ptr schema, bytes prefix, tombstone t) {
        apply_row_tombstone(schema, {std::move(prefix), std::move(t)});
    }
    void apply_row_tombstone(schema_ptr schema, std::pair<bytes, tombstone> row_tombstone);
    void apply(schema_ptr schema, const mutation_partition& p);
    const row_tombstone_set& row_tombstones() const { return _row_tombstones; }
    row& static_row() { return _static_row; }
    row& clustered_row(const clustering_key& key) { return _rows[key].cells; }
    row& clustered_row(clustering_key&& key) { return _rows[std::move(key)].cells; }
    row* find_row(const clustering_key& key);
    tombstone tombstone_for_row(schema_ptr schema, const clustering_key& key);
    friend std::ostream& operator<<(std::ostream& os, const mutation_partition& mp);
};

class mutation final {
public:
    schema_ptr schema;
    partition_key key;
    mutation_partition p;
public:
    mutation(partition_key key_, schema_ptr schema_)
        : schema(std::move(schema_))
        , key(std::move(key_))
        , p(schema)
    { }

    mutation(mutation&&) = default;
    mutation(const mutation&) = default;

    void set_static_cell(const column_definition& def, atomic_cell_or_collection value) {
        update_column(p.static_row(), def, std::move(value));
    }

    void set_clustered_cell(const clustering_prefix& prefix, const column_definition& def, atomic_cell_or_collection value) {
        auto& row = p.clustered_row(serialize_value(*schema->clustering_key_type, prefix));
        update_column(row, def, std::move(value));
    }

    void set_clustered_cell(const clustering_key& key, const column_definition& def, atomic_cell_or_collection value) {
        auto& row = p.clustered_row(key);
        update_column(row, def, std::move(value));
    }
private:
    static void update_column(row& row, const column_definition& def, atomic_cell_or_collection&& value) {
        // our mutations are not yet immutable
        auto id = def.id;
        auto i = row.lower_bound(id);
        if (i == row.end() || i->first != id) {
            row.emplace_hint(i, id, std::move(value));
        } else {
            merge_column(def, i->second, value);
        }
    }
    friend std::ostream& operator<<(std::ostream& os, const mutation& m);
};

struct column_family {
    column_family(schema_ptr schema);
    mutation_partition& find_or_create_partition(const bytes& key);
    row& find_or_create_row(const bytes& partition_key, const bytes& clustering_key);
    mutation_partition* find_partition(const bytes& key);
    row* find_row(const bytes& partition_key, const bytes& clustering_key);
    schema_ptr _schema;
    // partition key -> partition
    std::map<bytes, mutation_partition, key_compare> partitions;
    void apply(const mutation& m);
    // Returns at most "cmd.limit" rows
    future<lw_shared_ptr<query::result>> query(const query::read_command& cmd);
private:
    // Returns at most "limit" rows
    query::result::partition get_partition_slice(mutation_partition& partition,
        const query::partition_slice& slice, uint32_t limit);
};

class keyspace {
public:
    std::unordered_map<sstring, column_family> column_families;
    future<> populate(sstring datadir);
    schema_ptr find_schema(const sstring& cf_name);
    column_family* find_column_family(const sstring& cf_name);
};

// Policy for distributed<database>:
//   broadcast metadata writes
//   local metadata reads
//   use shard_of() for data

class database {
public:
    std::unordered_map<sstring, keyspace> keyspaces;
    future<> init_from_data_directory(sstring datadir);
    future<> populate(sstring datadir);
    keyspace* find_keyspace(const sstring& name);
    future<> stop() { return make_ready_future<>(); }
    void assign(database&& db) {
        *this = std::move(db);
    }
    unsigned shard_of(const dht::token& t);
    future<lw_shared_ptr<query::result>> query(const query::read_command& cmd);
};

// FIXME: stub
class secondary_index_manager {};

#endif /* DATABASE_HH_ */
<commit_msg>db: add mutation::set_cell() helper<commit_after>/*
 * Copyright (C) 2014 Cloudius Systems, Ltd.
 */

#ifndef DATABASE_HH_
#define DATABASE_HH_

#include "dht/i_partitioner.hh"
#include "core/sstring.hh"
#include "core/shared_ptr.hh"
#include "net/byteorder.hh"
#include "utils/UUID.hh"
#include "db_clock.hh"
#include "gc_clock.hh"
#include <functional>
#include <boost/any.hpp>
#include <cstdint>
#include <boost/variant.hpp>
#include <unordered_map>
#include <map>
#include <set>
#include <vector>
#include <iostream>
#include <boost/functional/hash.hpp>
#include <experimental/optional>
#include <string.h>
#include "types.hh"
#include "tuple.hh"
#include "core/future.hh"
#include "cql3/column_specification.hh"
#include <limits>
#include <cstddef>
#include "schema.hh"
#include "timestamp.hh"
#include "tombstone.hh"
#include "atomic_cell.hh"
#include "bytes.hh"
#include "query.hh"

using partition_key_type = tuple_type<>;
using clustering_key_type = tuple_type<>;
using clustering_prefix_type = tuple_prefix;
using partition_key = bytes;
using clustering_key = bytes;
using clustering_prefix = clustering_prefix_type::value_type;

using row = std::map<column_id, atomic_cell_or_collection>;

struct deletable_row final {
    tombstone t;
    row cells;
};

using row_tombstone_set = std::map<bytes, tombstone, serialized_compare>;

class mutation_partition final {
private:
    tombstone _tombstone;
    row _static_row;
    std::map<clustering_key, deletable_row, key_compare> _rows;
    row_tombstone_set _row_tombstones;
public:
    mutation_partition(schema_ptr s)
        : _rows(key_compare(s->clustering_key_type))
        , _row_tombstones(serialized_compare(s->clustering_key_prefix_type))
    { }
    void apply(tombstone t) { _tombstone.apply(t); }
    void apply_delete(schema_ptr schema, const clustering_prefix& prefix, tombstone t);
    void apply_row_tombstone(schema_ptr schema, bytes prefix, tombstone t) {
        apply_row_tombstone(schema, {std::move(prefix), std::move(t)});
    }
    void apply_row_tombstone(schema_ptr schema, std::pair<bytes, tombstone> row_tombstone);
    void apply(schema_ptr schema, const mutation_partition& p);
    const row_tombstone_set& row_tombstones() const { return _row_tombstones; }
    row& static_row() { return _static_row; }
    row& clustered_row(const clustering_key& key) { return _rows[key].cells; }
    row& clustered_row(clustering_key&& key) { return _rows[std::move(key)].cells; }
    row* find_row(const clustering_key& key);
    tombstone tombstone_for_row(schema_ptr schema, const clustering_key& key);
    friend std::ostream& operator<<(std::ostream& os, const mutation_partition& mp);
};

class mutation final {
public:
    schema_ptr schema;
    partition_key key;
    mutation_partition p;
public:
    mutation(partition_key key_, schema_ptr schema_)
        : schema(std::move(schema_))
        , key(std::move(key_))
        , p(schema)
    { }

    mutation(mutation&&) = default;
    mutation(const mutation&) = default;

    void set_static_cell(const column_definition& def, atomic_cell_or_collection value) {
        update_column(p.static_row(), def, std::move(value));
    }

    void set_clustered_cell(const clustering_prefix& prefix, const column_definition& def, atomic_cell_or_collection value) {
        auto& row = p.clustered_row(serialize_value(*schema->clustering_key_type, prefix));
        update_column(row, def, std::move(value));
    }

    void set_clustered_cell(const clustering_key& key, const column_definition& def, atomic_cell_or_collection value) {
        auto& row = p.clustered_row(key);
        update_column(row, def, std::move(value));
    }
    void set_cell(const clustering_prefix& prefix, const column_definition& def, atomic_cell_or_collection value) {
        if (def.is_static()) {
            set_static_cell(def, std::move(value));
        } else if (def.is_regular()) {
            set_clustered_cell(prefix, def, std::move(value));
        } else {
            throw std::runtime_error("attemting to store into a key cell");
        }
    }
private:
    static void update_column(row& row, const column_definition& def, atomic_cell_or_collection&& value) {
        // our mutations are not yet immutable
        auto id = def.id;
        auto i = row.lower_bound(id);
        if (i == row.end() || i->first != id) {
            row.emplace_hint(i, id, std::move(value));
        } else {
            merge_column(def, i->second, value);
        }
    }
    friend std::ostream& operator<<(std::ostream& os, const mutation& m);
};

struct column_family {
    column_family(schema_ptr schema);
    mutation_partition& find_or_create_partition(const bytes& key);
    row& find_or_create_row(const bytes& partition_key, const bytes& clustering_key);
    mutation_partition* find_partition(const bytes& key);
    row* find_row(const bytes& partition_key, const bytes& clustering_key);
    schema_ptr _schema;
    // partition key -> partition
    std::map<bytes, mutation_partition, key_compare> partitions;
    void apply(const mutation& m);
    // Returns at most "cmd.limit" rows
    future<lw_shared_ptr<query::result>> query(const query::read_command& cmd);
private:
    // Returns at most "limit" rows
    query::result::partition get_partition_slice(mutation_partition& partition,
        const query::partition_slice& slice, uint32_t limit);
};

class keyspace {
public:
    std::unordered_map<sstring, column_family> column_families;
    future<> populate(sstring datadir);
    schema_ptr find_schema(const sstring& cf_name);
    column_family* find_column_family(const sstring& cf_name);
};

// Policy for distributed<database>:
//   broadcast metadata writes
//   local metadata reads
//   use shard_of() for data

class database {
public:
    std::unordered_map<sstring, keyspace> keyspaces;
    future<> init_from_data_directory(sstring datadir);
    future<> populate(sstring datadir);
    keyspace* find_keyspace(const sstring& name);
    future<> stop() { return make_ready_future<>(); }
    void assign(database&& db) {
        *this = std::move(db);
    }
    unsigned shard_of(const dht::token& t);
    future<lw_shared_ptr<query::result>> query(const query::read_command& cmd);
};

// FIXME: stub
class secondary_index_manager {};

#endif /* DATABASE_HH_ */
<|endoftext|>