Ejemplo n.º 1
0
void readPackAndWrite(
    uint64_t& writeSize, packet::Packet& pkt,
    cybozu::util::File& fileW, bool doWriteDiff, DiscardType discardType,
    uint64_t fsyncIntervalSize,
    std::vector<char>& zero, AlignedArray& buf)
{
    const char *const FUNC = __func__;
    size_t size;
    pkt.read(size);
    verifyDiffPackSize(size, FUNC);
    buf.resize(size);
    pkt.read(buf.data(), buf.size());

    verifyDiffPack(buf.data(), buf.size(), true);
    if (doWriteDiff) {
        fileW.write(buf.data(), buf.size());
    } else {
        MemoryDiffPack pack(buf.data(), buf.size());
        issueDiffPack(fileW, discardType, pack, zero);
    }
    writeSize += buf.size();
    if (writeSize >= fsyncIntervalSize) {
        fileW.fdatasync();
        writeSize = 0;
    }
}
Ejemplo n.º 2
0
void readAndSendHash(
    uint64_t& hashLb,
    packet::Packet& pkt, packet::StreamControl2& ctrl, Reader &reader,
    uint64_t sizeLb, size_t bulkLb,
    cybozu::murmurhash3::Hasher& hasher, AlignedArray& buf)
{
    const uint64_t lb = std::min<uint64_t>(sizeLb - hashLb, bulkLb);
    buf.resize(lb * LOGICAL_BLOCK_SIZE);
    reader.read(buf.data(), buf.size());
    const cybozu::murmurhash3::Hash hash = hasher(buf.data(), buf.size());
    doRetrySockIo(2, "ctrl.send.next", [&]() { ctrl.sendNext(); });
    pkt.write(hash);
    hashLb += lb;
}
uint64_t readAndValidateLogPackIo(cybozu::util::File& file, const device::SuperBlock& super, const LogPackHeader& logh)
{
    const uint32_t pbs = super.getPhysicalBlockSize();
    assert(logh.isValid());
    AlignedArray buf;
    for (size_t i = 0; i < logh.nRecords(); i++) {
        const WlogRecord &rec = logh.record(i);
        if (!rec.hasDataForChecksum()) continue;
        const uint64_t pb = super.getOffsetFromLsid(rec.lsid);
        const size_t ioSize = rec.ioSizeLb() * LBS;
        buf.resize(ioSize);
        file.pread(buf.data(), ioSize, pb * pbs);
        const uint32_t csum = cybozu::util::calcChecksum(buf.data(), buf.size(), logh.salt());
        if (csum == rec.checksum) continue;
        LOGs.info() << "INVALID_LOGPACK_IO" << rec << csum;
    }
    return logh.nextLogpackLsid();
}
Ejemplo n.º 4
0
void setRandomData(AlignedArray& buf, Rand& rand)
{
    size_t off = 0;
    while (off < buf.size()) {
        const size_t size = std::min<size_t>(buf.size() - off, 16);
        rand.fill(buf.data() + off, size);
        off += 512;
    }
}
Ejemplo n.º 5
0
/*
 * @zero is used as zero-filled buffer. It may be resized.
 */
inline void issueDiffPack(cybozu::util::File& file, DiscardType discardType, MemoryDiffPack& pack, std::vector<char>& zero)
{
    const DiffPackHeader& head = pack.header();
    DiffRecord rec;
    AlignedArray array; // buffer for uncompressed data.
    for (size_t i = 0; i < head.n_records; i++) {
        const DiffRecord& inRec = head[i];
        const char *iodata = nullptr;
        if (inRec.isNormal()) {
            if (inRec.isCompressed()) {
                uncompressDiffIo(inRec, pack.data(i), rec, array, false);
                iodata = array.data();
            } else {
                rec = inRec;
                iodata = pack.data(i);
            }
        } else {
            rec = inRec;
        }
        issueIo(file, discardType, rec, iodata, zero);
    }
}
Ejemplo n.º 6
0
inline bool dirtyHashSyncClient(
    packet::Packet &pkt, Reader &reader,
    uint64_t sizeLb, uint64_t bulkLb, uint32_t hashSeed,
    const std::atomic<int> &stopState, const ProcessStatus &ps,
    const std::atomic<uint64_t>& maxLbPerSec)
{
    const char *const FUNC = __func__;
    packet::StreamControl2 recvCtl(pkt.sock());
    packet::StreamControl2 sendCtl(pkt.sock());
    DiffPacker packer;
    walb::PackCompressor compr(::WALB_DIFF_CMPR_SNAPPY);
    cybozu::murmurhash3::Hasher hasher(hashSeed);
    ThroughputStabilizer thStab;

    uint64_t addr = 0;
    uint64_t remainingLb = sizeLb;
    AlignedArray buf;
    size_t cHash = 0, cSend = 0, cDummy = 0;
    try {
    for (;;) {
        if (stopState == ForceStopping || ps.isForceShutdown()) {
            return false;
        }
        dirty_hash_sync_local::doRetrySockIo(4, "ctrl.recv", [&]() { recvCtl.recv(); });
        if (recvCtl.isNext()) {
            if (remainingLb == 0) throw cybozu::Exception(FUNC) << "has next but remainingLb is zero";
        } else {
            if (remainingLb == 0) break;
            throw cybozu::Exception(FUNC) << "no next but remainingLb is not zero" << remainingLb;
        }
        cybozu::murmurhash3::Hash recvHash;
        pkt.read(recvHash);
        cHash++;

        const uint32_t lb = std::min<uint64_t>(remainingLb, bulkLb);
        buf.resize(lb * LOGICAL_BLOCK_SIZE);
        reader.read(buf.data(), buf.size());

        // to avoid socket timeout.
        dirty_hash_sync_local::doRetrySockIo(4, "ctrl.send.dummy", [&]() { sendCtl.sendDummy(); });
        cDummy++; cSend++;

        const cybozu::murmurhash3::Hash bdHash = hasher(buf.data(), buf.size());
        const uint64_t bgnAddr = packer.empty() ? addr : packer.header()[0].io_address;
        if (addr - bgnAddr >= DIRTY_HASH_SYNC_MAX_PACK_AREA_LB && !packer.empty()) {
            dirty_hash_sync_local::doRetrySockIo(4, "ctrl.send.next0", [&]() { sendCtl.sendNext(); });
            cSend++;
            dirty_hash_sync_local::compressAndSend(pkt, packer, compr);
        }
        if (recvHash != bdHash && !packer.add(addr, lb, buf.data())) {
            dirty_hash_sync_local::doRetrySockIo(4, "ctrl.send.next1", [&]() { sendCtl.sendNext(); });
            cSend++;
            dirty_hash_sync_local::compressAndSend(pkt, packer, compr);
            packer.add(addr, lb, buf.data());
        }
        pkt.flush();
        remainingLb -= lb;
        addr += lb;
        thStab.setMaxLbPerSec(maxLbPerSec.load());
        thStab.addAndSleepIfNecessary(lb, 10, 100);
    }
    } catch (...) {
        LOGs.warn() << "SEND_CTL" << cHash << cSend << cDummy;
        throw;
    }
    if (!packer.empty()) {
        dirty_hash_sync_local::doRetrySockIo(4, "ctrl.send.next2", [&]() { sendCtl.sendNext(); });
        cSend++;
        dirty_hash_sync_local::compressAndSend(pkt, packer, compr);
    }
    if (recvCtl.isError()) {
        throw cybozu::Exception(FUNC) << "recvCtl";
    }
    dirty_hash_sync_local::doRetrySockIo(4, "ctrl.send.next2", [&]() { sendCtl.sendEnd(); });
    pkt.flush();

    LOGs.debug() << "SEND_CTL" << cHash << cSend << cDummy;
    return true;
}