1/* -*- Mode: C; tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- */
2/*
3 *     Copyright 2014-2020 Couchbase, Inc.
4 *
5 *   Licensed under the Apache License, Version 2.0 (the "License");
6 *   you may not use this file except in compliance with the License.
7 *   You may obtain a copy of the License at
8 *
9 *       http://www.apache.org/licenses/LICENSE-2.0
10 *
11 *   Unless required by applicable law or agreed to in writing, software
12 *   distributed under the License is distributed on an "AS IS" BASIS,
13 *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 *   See the License for the specific language governing permissions and
15 *   limitations under the License.
16 */
17
18#include <libcouchbase/couchbase.h>
19#include <libcouchbase/pktfwd.h>
20#include "mc/mcreq.h"
21#include "mc/forward.h"
22#include "internal.h"
23#include "rdb/rope.h"
24
25LIBCOUCHBASE_API
26lcb_STATUS lcb_pktfwd3(lcb_INSTANCE *instance, const void *cookie, const lcb_CMDPKTFWD *cmd)
27{
28    int fwdopts = 0;
29    mc_PIPELINE *pl;
30    mc_PACKET *packet;
31    nb_IOV *iov, iov_s;
32    unsigned niov;
33    mc_IOVINFO ioi = {{0}};
34    lcb_STATUS err;
35
36    if (cmd->nomap) {
37        fwdopts |= MC_FWD_OPT_NOMAP;
38        if (cmd->server_index >= LCBT_NSERVERS(instance)) {
39            return LCB_ERR_NO_MATCHING_SERVER;
40        } else {
41            pl = (mc_PIPELINE *)LCBT_GET_SERVER(instance, cmd->server_index);
42        }
43    }
44
45    if (cmd->vb.vtype != LCB_KV_IOV) {
46        iov_s.iov_base = (void *)cmd->vb.u_buf.contig.bytes;
47        iov_s.iov_len = cmd->vb.u_buf.contig.nbytes;
48        iov = &iov_s;
49        niov = 1;
50
51        if (cmd->vb.vtype == LCB_KV_COPY) {
52            fwdopts |= MC_FWD_OPT_COPY;
53        }
54    } else {
55        iov = (nb_IOV *)cmd->vb.u_buf.multi.iov;
56        niov = cmd->vb.u_buf.multi.niov;
57        ioi.total = cmd->vb.u_buf.multi.total_length;
58    }
59    mc_iovinfo_init(&ioi, iov, niov);
60
61    err = mc_forward_packet(&instance->cmdq, &ioi, &packet, &pl, fwdopts);
62    if (err != LCB_SUCCESS) {
63        return err;
64    }
65
66    /* set the cookie */
67    packet->u_rdata.reqdata.cookie = cookie;
68    packet->u_rdata.reqdata.start = gethrtime();
69    packet->u_rdata.reqdata.deadline =
70        packet->u_rdata.reqdata.start + LCB_US2NS(LCBT_SETTING(instance, operation_timeout));
71    return err;
72}
73
74LIBCOUCHBASE_API
75void lcb_backbuf_ref(lcb_BACKBUF buf)
76{
77    rdb_seg_ref(buf);
78}
79
80LIBCOUCHBASE_API
81void lcb_backbuf_unref(lcb_BACKBUF buf)
82{
83    rdb_seg_unref(buf);
84}
85