/* -*- Mode: C; tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- */ /* * Copyright 2014-2020 Couchbase, Inc. * * 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. */ #define NOMINMAX // for win32, use std::min rather than min #include #include #include class RdbAllocator { public: rdb_ALLOCATOR *_inner; rdb_ROPESEG *alloc(size_t n) { return _inner->s_alloc(_inner, n); } rdb_ROPESEG *realloc(rdb_ROPESEG *prev, size_t n) { return _inner->s_realloc(_inner, prev, n); } void reserve(rdb_ROPEBUF *buf, size_t cap) { _inner->r_reserve(_inner, buf, cap); } void free(rdb_ROPESEG *seg) { _inner->s_release(_inner, seg); } void release() { _inner->a_release(_inner); } RdbAllocator(rdb_ALLOCATOR *inner) { _inner = inner; } }; struct IORope : public rdb_IOROPE { IORope(rdb_ALLOCATOR *allocator) { rdb_init(this, allocator); rdsize = 256; } IORope() { rdb_init(this, rdb_bigalloc_new()); rdsize = 256; } ~IORope() { rdb_cleanup(this); } IORope(const IORope &); std::string stlstr(size_t n) { char *buf = new char[n]; rdb_copyread(this, buf, n); std::string rv(buf, n); delete[] buf; return rv; } size_t usedSize() const { return recvd.nused; } void feed(const std::string &s) { size_t n_fed = 0; nb_IOV iov[32]; while (n_fed < s.size()) { unsigned niov = rdb_rdstart(this, iov, 32); unsigned cur_nfed = 0; for (unsigned ii = 0; ii < niov && n_fed < s.size(); ii++) { const char *frag = s.data() + n_fed; nb_IOV *curiov = iov + ii; // on win32 iov_len is not a size_t unsigned to_copy = std::min(s.size() - n_fed, (size_t)curiov->iov_len); memcpy(curiov->iov_base, frag, to_copy); n_fed += to_copy; cur_nfed += to_copy; } rdb_rdend(this, cur_nfed); } } void feed(const char *s) { feed(std::string(s)); } }; struct ReadPacket { std::vector< rdb_ROPESEG * > segments; std::vector< nb_IOV > iovs; ReadPacket(nb_IOV *iov, rdb_ROPESEG **segs, unsigned n) { segments.reserve(n); iovs.reserve(n); // Insert them. segments.insert(segments.begin(), segs, segs + n); iovs.insert(iovs.begin(), iov, iov + n); } ReadPacket(rdb_IOROPE *ior, unsigned nb) { segments.resize(2); iovs.resize(2); unsigned niov; while (true) { niov = rdb_refread_ex(ior, &iovs[0], &segments[0], iovs.size(), nb); if (niov != (unsigned)-1) { iovs.resize(niov); segments.resize(niov); break; } iovs.resize(iovs.size() * 2); segments.resize(segments.size() * 2); } } void refSegment(unsigned ix) { rdb_seg_ref(segments[ix]); } std::string asString() { std::string s; for (size_t ii = 0; ii < iovs.size(); ii++) { nb_IOV *cur = &iovs[ii]; s.append((const char *)cur->iov_base, cur->iov_len); } return s; } void unrefSegment(unsigned ix) { rdb_seg_unref(segments[ix]); } };