Beispiel #1
0
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;
        }
    }
Beispiel #3
0
        /*! 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);
            }
        }
Beispiel #4
0
// 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();
}
Beispiel #6
0
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.";
        }
    }
}
Beispiel #7
0
    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;
    }
Beispiel #8
0
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);
}
Beispiel #10
0
        /*! 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);
        }
Beispiel #11
0
    /*! 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);
     }
 }
Beispiel #13
0
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();
}
Beispiel #14
0
/* 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);
        }
    }
}
Beispiel #15
0
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)";
}
Beispiel #16
0
int gcomm::PC::handle_down(Datagram& wb, const ProtoDownMeta& dm)
{
    if (wb.len() == 0)
    {
        gu_throw_error(EMSGSIZE);
    }
    return send_down(wb, dm);
}
Beispiel #17
0
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";
    }
}
Beispiel #18
0
 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);
}
Beispiel #20
0
    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
                                   << '\'' ;
    }
Beispiel #21
0
        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";
            }
        }
Beispiel #22
0
    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;
    }
Beispiel #23
0
    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);
    }
Beispiel #24
0
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_);
}
Beispiel #25
0
    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 << "'";
    }
Beispiel #26
0
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";
    }
}
Beispiel #27
0
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);
    }
}
Beispiel #28
0
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));
}
Beispiel #29
0
 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;
 }
Beispiel #30
0
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_;
    }
}