1 /**
2 * Copyright 2016-2017 Couchbase, Inc.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #include "couchbase.h"
18
19 #define LOGARGS(instance, lvl) LCB_LOG_##lvl, instance, "pcbc/n1ix_list", __FILE__, __LINE__
20
21 typedef struct {
22 opcookie_res header;
23 PCBC_ZVAL *specs;
24 int nspecs;
25 } opcookie_n1ix_list_res;
26
n1ix_list_callback(lcb_t instance,int cbtype,const lcb_RESPN1XMGMT * resp)27 static void n1ix_list_callback(lcb_t instance, int cbtype, const lcb_RESPN1XMGMT *resp)
28 {
29 opcookie_n1ix_list_res *result = ecalloc(1, sizeof(opcookie_n1ix_list_res));
30 int i;
31 TSRMLS_FETCH();
32
33 result->header.err = resp->rc;
34 if (result->header.err != LCB_SUCCESS) {
35 pcbc_log(LOGARGS(instance, ERROR), "Failed to list indexes. %d: %.*s", (int)resp->inner->htresp->htstatus,
36 (int)resp->inner->nrow, (char *)resp->inner->row);
37 }
38 result->nspecs = resp->nspecs;
39 result->specs = ecalloc(result->nspecs, sizeof(PCBC_ZVAL));
40 for (i = 0; i < result->nspecs; ++i) {
41 const lcb_N1XSPEC *spec = resp->specs[i];
42 int last_error;
43 PCBC_ZVAL value, json;
44
45 PCBC_ZVAL_ALLOC(value);
46 PCBC_ZVAL_ALLOC(json);
47 PCBC_JSON_COPY_DECODE(PCBC_P(json), spec->rawjson, spec->nrawjson, PHP_JSON_OBJECT_AS_ARRAY, last_error);
48 if (last_error != 0) {
49 pcbc_log(LOGARGS(instance, WARN), "Failed to decode value as JSON: json_last_error=%d", last_error);
50 ZVAL_NULL(PCBC_P(value));
51 } else {
52 pcbc_n1ix_init(PCBC_P(value), PCBC_P(json) TSRMLS_CC);
53 }
54
55 zval_ptr_dtor(&json);
56 result->specs[i] = value;
57 }
58
59 opcookie_push((opcookie *)resp->cookie, &result->header);
60 }
61
proc_n1ix_list_results(zval * return_value,opcookie * cookie TSRMLS_DC)62 static lcb_error_t proc_n1ix_list_results(zval *return_value, opcookie *cookie TSRMLS_DC)
63 {
64 opcookie_n1ix_list_res *result = (opcookie_n1ix_list_res *)opcookie_next_res(cookie, NULL);
65 lcb_error_t err = opcookie_get_first_error(cookie);
66 int i;
67
68 if (result) {
69 if (err == LCB_SUCCESS) {
70 array_init(return_value);
71 for (i = 0; i < result->nspecs; ++i) {
72 add_index_zval(return_value, i, PCBC_P(result->specs[i]));
73 }
74 }
75 efree(result->specs);
76 }
77
78 return err;
79 }
80
pcbc_n1ix_list(pcbc_bucket_manager_t * manager,zval * return_value TSRMLS_DC)81 int pcbc_n1ix_list(pcbc_bucket_manager_t *manager, zval *return_value TSRMLS_DC)
82 {
83 lcb_CMDN1XMGMT cmd = {0};
84 opcookie *cookie;
85 lcb_error_t err;
86
87 cmd.callback = n1ix_list_callback;
88 cookie = opcookie_init();
89
90 cmd.spec.nkeyspace = strlen(manager->conn->bucketname);
91 cmd.spec.keyspace = manager->conn->bucketname;
92 err = lcb_n1x_list(manager->conn->lcb, cookie, &cmd);
93
94 if (err == LCB_SUCCESS) {
95 lcb_wait(manager->conn->lcb);
96 err = proc_n1ix_list_results(return_value, cookie TSRMLS_CC);
97 }
98
99 opcookie_destroy(cookie);
100
101 if (err != LCB_SUCCESS) {
102 throw_lcb_exception(err);
103 return FAILURE;
104 }
105 return SUCCESS;
106 }
107