1
+ /**
2
+ * Copyright 2021 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/get_multi", __FILE__, __LINE__
20
+
21
+ extern zend_class_entry * pcbc_get_result_impl_ce ;
22
+ extern zend_class_entry * pcbc_get_options_ce ;
23
+
24
+ struct get_multi_cookie {
25
+ lcb_STATUS rc ;
26
+ zval * return_value ;
27
+ size_t index ;
28
+ };
29
+
30
+ void get_multi_callback (lcb_INSTANCE * instance , int cbtype , const lcb_RESPGET * resp )
31
+ {
32
+ struct get_multi_cookie * cookie = NULL ;
33
+ const lcb_KEY_VALUE_ERROR_CONTEXT * ectx = NULL ;
34
+ lcb_respget_cookie (resp , (void * * )& cookie );
35
+ zval * return_value = zend_hash_index_find (HASH_OF (cookie -> return_value ), cookie -> index );
36
+ if (return_value == NULL ) {
37
+ cookie -> rc = LCB_ERR_INVALID_RANGE ;
38
+ return ;
39
+ }
40
+ cookie -> rc = lcb_respget_status (resp );
41
+ pcbc_update_property_long (pcbc_get_result_impl_ce , return_value , ("status" ), cookie -> rc );
42
+ lcb_respget_error_context (resp , & ectx );
43
+
44
+ set_property_str (ectx , lcb_errctx_kv_context , pcbc_get_result_impl_ce , "err_ctx" );
45
+ set_property_str (ectx , lcb_errctx_kv_ref , pcbc_get_result_impl_ce , "err_ref" );
46
+ set_property_str (ectx , lcb_errctx_kv_key , pcbc_get_result_impl_ce , "key" );
47
+ if (cookie -> rc == LCB_SUCCESS ) {
48
+ set_property_num (uint32_t , lcb_respget_flags , pcbc_get_result_impl_ce , "flags" );
49
+ set_property_num (uint8_t , lcb_respget_datatype , pcbc_get_result_impl_ce , "datatype" );
50
+ set_property_str (resp , lcb_respget_value , pcbc_get_result_impl_ce , "data" );
51
+ {
52
+ uint64_t data ;
53
+ lcb_respget_cas (resp , & data );
54
+ zend_string * b64 ;
55
+ b64 = php_base64_encode ((unsigned char * )& data , sizeof (data ));
56
+ pcbc_update_property_str (pcbc_get_result_impl_ce , return_value , ("cas" ), b64 );
57
+ zend_string_release (b64 );
58
+ }
59
+ }
60
+ (void )instance ;
61
+ (void )cbtype ;
62
+ }
63
+
64
+ PHP_METHOD (Collection , getMulti )
65
+ {
66
+ zval * ids = NULL ;
67
+ zval * options = NULL ;
68
+
69
+ int rv = zend_parse_parameters_throw (ZEND_NUM_ARGS (), "A|O!" , & ids , & options , pcbc_get_options_ce );
70
+ if (rv == FAILURE ) {
71
+ RETURN_NULL ();
72
+ }
73
+ PCBC_RESOLVE_COLLECTION ;
74
+
75
+ zval decoder = {0 };
76
+ ZVAL_NULL (& decoder );
77
+ zend_long timeout = 0 ;
78
+ if (options ) {
79
+ zval ret ;
80
+ const zval * prop ;
81
+ prop = pcbc_read_property (pcbc_get_options_ce , options , ("timeout" ), 0 , & ret );
82
+ if (Z_TYPE_P (prop ) == IS_LONG ) {
83
+ timeout = Z_LVAL_P (prop );
84
+ }
85
+ prop = pcbc_read_property (pcbc_get_options_ce , options , ("decoder" ), 0 , & ret );
86
+ if (Z_TYPE_P (prop ) != IS_NULL ) {
87
+ ZVAL_COPY (& decoder , prop );
88
+ }
89
+ }
90
+
91
+ lcbtrace_SPAN * span = NULL ;
92
+ lcbtrace_TRACER * tracer = lcb_get_tracer (bucket -> conn -> lcb );
93
+ if (tracer ) {
94
+ span = lcbtrace_span_start (tracer , "php/" LCBTRACE_OP_GET "_multi" , 0 , NULL );
95
+ lcbtrace_span_add_tag_str (span , LCBTRACE_TAG_COMPONENT , pcbc_client_string );
96
+ lcbtrace_span_add_tag_str (span , LCBTRACE_TAG_SERVICE , LCBTRACE_TAG_SERVICE_KV );
97
+ }
98
+
99
+ size_t num_of_ids = zend_hash_num_elements (Z_ARRVAL_P (ids ));
100
+ struct get_multi_cookie * cookies = calloc (num_of_ids , sizeof (struct get_multi_cookie ));
101
+ array_init_size (return_value , num_of_ids );
102
+ lcb_sched_enter (bucket -> conn -> lcb );
103
+ const zval * id ;
104
+ lcb_STATUS err = LCB_SUCCESS ;
105
+ size_t index = 0 ;
106
+ ZEND_HASH_FOREACH_VAL (HASH_OF (ids ), id )
107
+ {
108
+ if (Z_TYPE_P (id ) != IS_STRING ) {
109
+ err = LCB_ERR_INVALID_ARGUMENT ;
110
+ lcb_sched_fail (bucket -> conn -> lcb );
111
+ break ;
112
+ }
113
+ zval result ;
114
+ object_init_ex (& result , pcbc_get_result_impl_ce );
115
+ add_next_index_zval (return_value , & result );
116
+ cookies [index ].rc = LCB_SUCCESS ;
117
+ cookies [index ].return_value = return_value ;
118
+ cookies [index ].index = index ;
119
+ pcbc_update_property (pcbc_get_result_impl_ce , & result , ("decoder" ),
120
+ Z_TYPE (decoder ) == IS_NULL ? & bucket -> decoder : & decoder );
121
+
122
+ lcb_CMDGET * cmd ;
123
+ lcb_cmdget_create (& cmd );
124
+ lcb_cmdget_collection (cmd , scope_str , scope_len , collection_str , collection_len );
125
+ lcb_cmdget_key (cmd , Z_STRVAL_P (id ), Z_STRLEN_P (id ));
126
+ if (timeout > 0 ) {
127
+ lcb_cmdget_timeout (cmd , timeout );
128
+ }
129
+ if (span ) {
130
+ lcb_cmdget_parent_span (cmd , span );
131
+ }
132
+ err = lcb_get (bucket -> conn -> lcb , & cookies [index ], cmd );
133
+ lcb_cmdget_destroy (cmd );
134
+ if (err != LCB_SUCCESS ) {
135
+ lcb_sched_fail (bucket -> conn -> lcb );
136
+ break ;
137
+ }
138
+ ++ index ;
139
+ }
140
+ ZEND_HASH_FOREACH_END ();
141
+ lcb_sched_leave (bucket -> conn -> lcb );
142
+
143
+ if (err == LCB_SUCCESS ) {
144
+ lcb_RESPCALLBACK prev_cb =
145
+ lcb_install_callback (bucket -> conn -> lcb , LCB_CALLBACK_GET , (lcb_RESPCALLBACK )get_multi_callback );
146
+ lcb_wait (bucket -> conn -> lcb , LCB_WAIT_DEFAULT );
147
+ lcb_install_callback (bucket -> conn -> lcb , LCB_CALLBACK_GET , prev_cb );
148
+ }
149
+ free (cookies );
150
+
151
+ if (span ) {
152
+ lcbtrace_span_finish (span , LCBTRACE_NOW );
153
+ }
154
+ if (err != LCB_SUCCESS ) {
155
+ throw_lcb_exception (err , NULL );
156
+ }
157
+ }
158
+
159
+ PHP_MINIT_FUNCTION (CollectionGetMulti )
160
+ {
161
+ return SUCCESS ;
162
+ }
163
+
164
+ /*
165
+ * vim: et ts=4 sw=4 sts=4
166
+ */
0 commit comments