int galera::ist::Receiver::recv(TrxHandle** trx) { Consumer cons; gu::Lock lock(mutex_); if (running_ == false) { if (error_code_ != 0) { gu_throw_error(error_code_) << "IST receiver reported error"; } return EINTR; } consumers_.push(&cons); cond_.signal(); lock.wait(cons.cond()); if (cons.trx() == 0) { if (error_code_ != 0) { gu_throw_error(error_code_) << "IST receiver reported error"; } return EINTR; } *trx = cons.trx(); return 0; }
/*! * serializes this object into byte vector v, reallocating it if needed * returns the size of serialized object */ ssize_t serialize_to (std::vector<byte_t>& v) const { size_t const old_size (v.size()); size_t const new_size (serial_size() + old_size); try { v.resize (new_size, 0); } catch (std::length_error& l) { gu_throw_error(EMSGSIZE) << "length_error: " << l.what(); } catch (...) { gu_throw_error(ENOMEM) << "could not resize to " << new_size << " bytes"; } try { return serialize_to (&v[old_size], new_size - old_size); } catch (...) { v.resize (old_size); throw; } }
/*! Decrements lock counter and unlocks monitor if counter is 0; * throws EBUSY if lock counter is not 0 */ void unlock() { gu::Lock lock(mutex_); assert (locked_ >= 0); if (0 == locked_) { assert (locked_ != 0); gu_throw_error(EALREADY) << "Attempt to unlock an already unlocked monitor"; } locked_--; if (0 == locked_) { update_last_left(); drain_seqno_ = LLONG_MAX; cond_.broadcast(); log_debug << "Unlocked local monitor at " << last_left_; } else { gu_throw_error(EBUSY); } }
// takes ownership over str buffer StateRequest_v1::StateRequest_v1 (const void* str, ssize_t str_len) : len_(str_len), req_(reinterpret_cast<char*>(const_cast<void*>(str))), own_(false) { if (sst_offset() + 2*sizeof(uint32_t) > size_t(len_)) { assert(0); gu_throw_error (EINVAL) << "State transfer request is too short: " << len_ << ", must be at least: " << (sst_offset() + 2*sizeof(uint32_t)); } if (strncmp (req_, MAGIC.c_str(), MAGIC.length())) { assert(0); gu_throw_error (EINVAL) << "Wrong magic signature in state request v1."; } if (sst_offset() + sst_len() + 2*sizeof(uint32_t) > size_t(len_)) { gu_throw_error (EINVAL) << "Malformed state request v1: sst length: " << sst_len() << ", total length: " << len_; } if (ist_offset() + ist_len() + sizeof(uint32_t) != size_t(len_)) { gu_throw_error (EINVAL) << "Malformed state request v1: parsed field " "length " << sst_len() << " is not equal to total request length " << len_; } }
RecvLoop::RecvLoop (const Config& config) : config_(config), gconf_ (), params_(gconf_), parse_ (gconf_, config_.options()), gcs_ (gconf_, config_.name(), config_.address(), config_.group()) { /* set up signal handlers */ global_gcs = &gcs_; struct sigaction sa; memset (&sa, 0, sizeof(sa)); sa.sa_handler = signal_handler; if (sigaction (SIGTERM, &sa, NULL)) { gu_throw_error(errno) << "Falied to install signal hadler for signal " << "SIGTERM"; } if (sigaction (SIGINT, &sa, NULL)) { gu_throw_error(errno) << "Falied to install signal hadler for signal " << "SIGINT"; } loop(); }
void gu::Config::parse (param_map_t& pmap, const std::string& params) throw (Exception) { if (0 == params[0]) return; std::vector<std::string> pv = gu::tokenize (params, PARAM_SEP, ESCAPE); for (size_t i = 0; i < pv.size(); ++i) { std::vector<std::string> kvv = gu::tokenize (pv[i], KEY_VALUE_SEP, ESCAPE, true); assert(kvv.size() > 0); gu::trim(kvv[0]); const std::string& key = kvv[0]; if (!key.empty()) { if (kvv.size() == 1) { gu_throw_error(EINVAL) <<"Key without value: '" << key <<"' at position '" << i << "' in parameter list."; } if (kvv.size() > 2) { gu_throw_error(EINVAL) <<"More than one value for key '" << key <<"' at '" << pv[i] << "' in parameter list."; } gu::trim(kvv[1]); std::string& value = kvv[1]; param_map_t::iterator pi = pmap.find(key); if (pi != pmap.end()) { log_warn << "Element " << pv[i] << " overwrites previous value" << " '" << pi->second << "' of '" << key << "' by '" << value << "'"; } log_debug << "Found param '" << key << "' = '" << value << "'"; pmap[key] = value; } else if (kvv.size() > 1) { gu_throw_error(EINVAL) << "Empty key at '" << pv[i] << "' in parameter list."; } } }
bool FileDescriptor::write_byte (off_t offset) throw (gu::Exception) { unsigned char const byte (0); if (lseek (value, offset, SEEK_SET) != offset) gu_throw_error(errno) << "lseek() failed on '" << name << '\''; if (write (value, &byte, sizeof(byte)) != sizeof(byte)) gu_throw_error(errno) << "write() failed on '" << name << '\''; return true; }
void gu::Config::parse ( std::vector<std::pair<std::string, std::string> >& params_vector, const std::string& param_list) { assert(params_vector.empty()); // we probably want a clean list if (param_list.empty()) return; std::vector<std::string> pv = gu::tokenize (param_list, PARAM_SEP, ESCAPE); for (size_t i = 0; i < pv.size(); ++i) { std::vector<std::string> kvv = gu::tokenize (pv[i], KEY_VALUE_SEP, ESCAPE, true); assert(kvv.size() > 0); gu::trim(kvv[0]); const std::string& key = kvv[0]; if (!key.empty()) { if (kvv.size() == 1) { gu_throw_error(EINVAL) <<"Key without value: '" << key <<"' at position '" << i << "' in parameter list."; } if (kvv.size() > 2) { gu_throw_error(EINVAL) <<"More than one value for key '" << key <<"' at '" << pv[i] << "' in parameter list."; } gu::trim(kvv[1]); std::string& value = kvv[1]; params_vector.push_back(std::make_pair(key, value)); } else if (kvv.size() > 1) { gu_throw_error(EINVAL) << "Empty key at '" << pv[i] << "' in parameter list."; } } }
std::pair<size_t, size_t> galera::WriteSet::segment(const gu::byte_t* buf, size_t buf_len, size_t offset) { uint32_t data_len; offset = gu::unserialize4(buf, buf_len, offset, data_len); if (gu_unlikely(offset + data_len > buf_len)) { #ifdef NDEBUG gu_throw_error(EMSGSIZE); #else gu_throw_error(EMSGSIZE) << "offset: " << offset << ", data_len: " << data_len << ", buf_len: " << buf_len; #endif /* NDEBUG */ } return std::pair<size_t, size_t>(offset, data_len); }
/*! Locks the monitor and/or increments lock counter; * throws EALREADY if the monitor is already locked */ void lock() { gu::Lock lock(mutex_); assert(locked_ >= 0); if (locked_ > 0) { log_warn << "Attempt to lock an already locked monitor."; locked_++; if (locked_ > 0) { gu_throw_error(EALREADY); } else { gu_throw_fatal << "More than " << (locked_ - 1) << " concurrent locks."; } } if (last_entered_ != -1) { while (drain_seqno_ != LLONG_MAX) lock.wait(cond_); /*! @note: last_entered_ probably changed since last check */ drain_common(last_entered_, lock); /* would_block() should return true when drain_seqno_ is set * so the monitor should be totally empty at this point. */ } locked_ = 1; log_debug << "Locked local monitor at " << (last_left_ + 1); }
/*! prealloc() fallback */ void FileDescriptor::write_file (off_t const start) throw (gu::Exception) { off_t const page_size (sysconf (_SC_PAGE_SIZE)); // last byte of the start page off_t offset = (start / page_size + 1) * page_size - 1; // off_t const diff (size - offset); // log_info << "Preallocating " << diff << '/' << size << " bytes in '" // << name << "'..."; while (offset < size && write_byte (offset)) { offset += page_size; } if (offset > size && write_byte (size - 1) && fsync (value) == 0) { // log_info << "Preallocating " << diff << '/' << size // << " bytes in '" << name << "' done."; return; } gu_throw_error (errno) << "File preallocation failed"; }
String(const std::string& str = "") : str_(str) { if (str_.size() > str_size_) { gu_throw_error(EMSGSIZE); } }
void RecordSetInBase::throw_error (Error code) const { switch (code) { case E_PERM: gu_throw_error (EPERM) << "Access beyond record set end."; case E_FAULT: gu_throw_error (EFAULT) << "Corrupted record set: record extends " << next_ << " beyond set boundary " << size_; } log_fatal << "Unknown error in RecordSetIn."; abort(); }
/* returns false if checksum matched and true if failed */ void RecordSetInBase::checksum() const { int const cs(check_size(check_type_)); if (cs > 0) /* checksum records */ { Hash check; check.append (head_ + begin_, size_ - begin_); /* records */ check.append (head_, begin_ - cs); /* header */ assert(cs <= MAX_CHECKSUM_SIZE); byte_t result[MAX_CHECKSUM_SIZE]; check.gather<sizeof(result)>(result); const byte_t* const stored_checksum(head_ + begin_ - cs); if (gu_unlikely(memcmp (result, stored_checksum, cs))) { gu_throw_error(EINVAL) << "RecordSet checksum does not match:" << "\ncomputed: " << gu::Hexdump(result, cs) << "\nfound: " << gu::Hexdump(stored_checksum, cs); } } }
MMap::MMap (const FileDescriptor& fd, bool const sequential) : size (fd.size()), ptr (mmap (NULL, size, PROT_READ|PROT_WRITE, MAP_SHARED|MAP_NORESERVE, fd.get(), 0)), mapped (ptr != GU_MAP_FAILED) { if (!mapped) { gu_throw_error(errno) << "mmap() on '" << fd.name() << "' failed"; } #if !defined(__sun__) && !defined(__APPLE__) && !defined(__FreeBSD__) /* Solaris, Darwin, and FreeBSD do not have MADV_DONTFORK */ if (posix_madvise (ptr, size, MADV_DONTFORK)) { int const err(errno); log_warn << "Failed to set MADV_DONTFORK on " << fd.name() << ": " << err << " (" << strerror(err) << ")"; } #endif /* benefits are questionable */ if (sequential && posix_madvise (ptr, size, MADV_SEQUENTIAL)) { int const err(errno); log_warn << "Failed to set MADV_SEQUENTIAL on " << fd.name() << ": " << err << " (" << strerror(err) << ")"; } log_debug << "Memory mapped: " << ptr << " (" << size << " bytes)"; }
int gcomm::PC::handle_down(Datagram& wb, const ProtoDownMeta& dm) { if (wb.len() == 0) { gu_throw_error(EMSGSIZE); } return send_down(wb, dm); }
void set_fd_options(S& socket) { long flags(FD_CLOEXEC); if (fcntl(socket.native(), F_SETFD, flags) == -1) { gu_throw_error(errno) << "failed to set FD_CLOEXEC"; } }
inline size_t __private_serial_size(const gu::Buffer& sb) { BOOST_STATIC_ASSERT(std::numeric_limits<ST>::is_integer); if (sb.size() > std::numeric_limits<ST>::max()) gu_throw_error(ERANGE) << sb.size() << " unrepresentable in " << sizeof(ST) << " bytes."; return sizeof(ST) + sb.size(); }
galera::ReplicatorSMM::InitConfig::InitConfig(gu::Config& conf, const char* const node_address) { Replicator::register_params(conf); std::map<std::string, std::string>::const_iterator i; for (i = defaults.map_.begin(); i != defaults.map_.end(); ++i) { if (i->second.empty()) conf.add(i->first); else conf.add(i->first, i->second); } // what is would be a better protection? int const pv(gu::from_string<int>(conf.get(Param::proto_max))); if (pv > MAX_PROTO_VER) { log_warn << "Can't set '" << Param::proto_max << "' to " << pv << ": maximum supported value is " << MAX_PROTO_VER; conf.add(Param::proto_max, gu::to_string(MAX_PROTO_VER)); } conf.add(COMMON_BASE_HOST_KEY); conf.add(COMMON_BASE_PORT_KEY); if (node_address && strlen(node_address) > 0) { gu::URI na(node_address, false); try { std::string const host = na.get_host(); if (host == "0.0.0.0" || host == "0:0:0:0:0:0:0:0" || host == "::") { gu_throw_error(EINVAL) << "Bad value for 'node_address': '" << host << '\''; } conf.set(BASE_HOST_KEY, host); } catch (gu::NotSet& e) {} try { conf.set(BASE_PORT_KEY, na.get_port()); } catch (gu::NotSet& e) {} } /* register variables and defaults from other modules */ gcache::GCache::register_params(conf); gcs_register_params(reinterpret_cast<gu_config_t*>(&conf)); Certification::register_params(conf); ist::register_params(conf); }
inline void string2uuid (const std::string& str, wsrep_uuid_t& uuid) { ssize_t ret(gu_uuid_scan(str.c_str(), str.length(), reinterpret_cast<gu_uuid_t*>(&uuid))); if (ret == -1) gu_throw_error(EINVAL) << "could not parse UUID from '" << str << '\'' ; }
void join (gcs_seqno_t seqno) throw (gu::Exception) { long const err(gcs_join(conn_, seqno)); if (err < 0) { gu_throw_error (-err) << "gcs_join(" << seqno << ") failed"; } }
inline size_t __private_unserialize(const gu::byte_t* const buf, size_t const buflen, size_t offset, gu::Buffer& b) { BOOST_STATIC_ASSERT(std::numeric_limits<ST>::is_integer); ST len(0); size_t ret = offset + sizeof(len); if (ret > buflen) gu_throw_error(EMSGSIZE) << ret << " > " << buflen; offset = __private_unserialize<ST>(buf, buflen, offset, len); ret += len; if (ret > buflen) gu_throw_error(EMSGSIZE) << ret << " > " << buflen; b.resize(len); copy(buf + offset, buf + ret, b.begin()); return ret; }
size_t serialize(gu::byte_t* buf, const size_t buflen, const size_t offset) const { if (buflen < offset + sizeof(gu_uuid_t)) gu_throw_error (EMSGSIZE) << sizeof(gu_uuid_t) << " > " << (buflen - offset); memcpy(buf + offset, &uuid_, sizeof(gu_uuid_t)); return offset + sizeof(gu_uuid_t); }
void RecordSetInBase::parse_header_v1 (size_t const size) { assert (size > 1); int off = 1; off += uleb128_decode (head_ + off, size - off, size_); if (gu_unlikely(static_cast<size_t>(size_) > static_cast<size_t>(size))) { gu_throw_error (EPROTO) << "RecordSet size " << size_ << " exceeds buffer size " << size << "\nfirst 4 bytes: " << gu::Hexdump(head_, 4); } off += uleb128_decode (head_ + off, size - off, count_); if (gu_unlikely(static_cast<size_t>(size_) < static_cast<size_t>(count_))) { gu_throw_error (EPROTO) << "Corrupted RecordSet header: count " << count_ << " exceeds size " << size_; } /* verify header CRC */ uint32_t const crc_comp(gu_fast_hash32(head_, off)); uint32_t const crc_orig( gtoh(*(reinterpret_cast<const uint32_t*>(head_ + off)))); if (gu_unlikely(crc_comp != crc_orig)) { gu_throw_error (EPROTO) << "RecordSet header CRC mismatch: " << std::showbase << std::internal << std::hex << std::setfill('0') << std::setw(10) << "\ncomputed: " << crc_comp << "\nfound: " << crc_orig << std::dec; } off += VER1_CRC_SIZE; /* checksum is between header and records */ begin_ = off + check_size(check_type_); }
void FileDescriptor::flush () const throw (gu::Exception) { log_debug << "Flushing file '" << name << "'"; if (fsync (value) < 0) { gu_throw_error(errno) << "fsync() failed on '" + name + '\''; } log_debug << "Flushed file '" << name << "'"; }
void MMap::sync () const { log_info << "Flushing memory map to disk..."; if (msync (ptr, size, MS_SYNC) < 0) { gu_throw_error(errno) << "msync(" << ptr << ", " << size << ") failed"; } }
void gu::datetime::Period::parse(const std::string& str) throw (gu::Exception) { std::vector<RegEx::Match> parts = regex.match(str, GU_NUM_PARTS); if (parts[GU_P].is_set() == false) { if (str == "") { return; } else { gu_throw_error (EINVAL) << "Period " << str << " not valid"; } } if (parts[GU_YEAR].is_set()) { nsecs += from_string<long long>(parts[GU_YEAR].str())*Year; } if (parts[GU_MONTH].is_set()) { nsecs += from_string<long long>(parts[GU_MONTH].str())*Month; } if (parts[GU_DAY].is_set()) { nsecs += from_string<long long>(parts[GU_DAY].str())*Day; } if (parts[GU_HOUR].is_set()) { nsecs += from_string<long long>(parts[GU_HOUR].str())*Hour; } if (parts[GU_MIN].is_set()) { nsecs += from_string<long long>(parts[GU_MIN].str())*Min; } if (parts[GU_SEC].is_set()) { long long s(from_string<long long>(parts[GU_SEC].str())); nsecs += s*Sec; } if (parts[GU_SEC_D].is_set()) { double d(from_string<double>(parts[GU_SEC_D].str())); nsecs += static_cast<long long>(d*Sec); } }
StateRequest_v1::StateRequest_v1 ( const void* const sst_req, ssize_t const sst_req_len, const void* const ist_req, ssize_t const ist_req_len) : len_(MAGIC.length() + 1 + sizeof(uint32_t) + sst_req_len + sizeof(uint32_t) + ist_req_len), req_(reinterpret_cast<char*>(malloc(len_))), own_(true) { if (!req_) gu_throw_error (ENOMEM) << "Could not allocate state request v1"; if (sst_req_len > INT32_MAX || sst_req_len < 0) gu_throw_error (EMSGSIZE) << "SST request length (" << sst_req_len << ") unrepresentable"; if (ist_req_len > INT32_MAX || ist_req_len < 0) gu_throw_error (EMSGSIZE) << "IST request length (" << sst_req_len << ") unrepresentable"; char* ptr(req_); strcpy (ptr, MAGIC.c_str()); ptr += MAGIC.length() + 1; uint32_t* tmp(reinterpret_cast<uint32_t*>(ptr)); *tmp = htogl(sst_req_len); ptr += sizeof(uint32_t); memcpy (ptr, sst_req, sst_req_len); ptr += sst_req_len; tmp = reinterpret_cast<uint32_t*>(ptr); *tmp = htogl(ist_req_len); ptr += sizeof(uint32_t); memcpy (ptr, ist_req, ist_req_len); assert ((ptr - req_) == (len_ - ist_req_len)); }
inline size_t __private_serialize(const gu::Buffer& b, gu::byte_t* const buf, size_t const buflen, size_t offset) { size_t const ret = offset + __private_serial_size<ST>(b); if (ret > buflen) gu_throw_error(EMSGSIZE) << ret << " > " << buflen; offset = __private_serialize<ST>(static_cast<ST>(b.size()), buf, buflen, offset); copy(b.begin(), b.end(), buf + offset); return ret; }
RecordSet::RecordSet (Version ver, CheckType const ct) : size_ (0), count_ (0), version_ (ver), check_type_(ct) { if (gu_unlikely(uint(version_) > MAX_VERSION)) { gu_throw_error (EPROTO) << "Unsupported header version: " << version_; } }