1 /**
2 * Copyright 2015-2017 DataStax, 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 "php_driver.h"
18 #include "php_driver_globals.h"
19 #include "php_driver_types.h"
20 #include "util/future.h"
21 #include "util/ref.h"
22
23 zend_class_entry *php_driver_default_cluster_ce = NULL;
24
25 static void
free_session(void * session)26 free_session(void *session)
27 {
28 cass_session_free((CassSession*) session);
29 }
30
PHP_METHOD(DefaultCluster,connect)31 PHP_METHOD(DefaultCluster, connect)
32 {
33 char *keyspace = NULL;
34 php5to7_size keyspace_len;
35 zval *timeout = NULL;
36 php_driver_cluster *self = NULL;
37 php_driver_session *session = NULL;
38 CassFuture *future = NULL;
39 char *hash_key;
40 php5to7_size hash_key_len = 0;
41 php_driver_psession *psession;
42
43
44 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|sz", &keyspace, &keyspace_len, &timeout) == FAILURE) {
45 return;
46 }
47
48 self = PHP_DRIVER_GET_CLUSTER(getThis());
49
50 object_init_ex(return_value, php_driver_default_session_ce);
51 session = PHP_DRIVER_GET_SESSION(return_value);
52
53 session->default_consistency = self->default_consistency;
54 session->default_page_size = self->default_page_size;
55 session->persist = self->persist;
56
57 if (!PHP5TO7_ZVAL_IS_UNDEF(session->default_timeout)) {
58 PHP5TO7_ZVAL_COPY(PHP5TO7_ZVAL_MAYBE_P(session->default_timeout),
59 PHP5TO7_ZVAL_MAYBE_P(self->default_timeout));
60 }
61
62 if (session->persist) {
63 php5to7_zend_resource_le *le;
64
65 hash_key_len = spprintf(&hash_key, 0, "%s:session:%s",
66 self->hash_key, SAFE_STR(keyspace));
67
68 if (PHP5TO7_ZEND_HASH_FIND(&EG(persistent_list), hash_key, hash_key_len + 1, le) &&
69 Z_RES_P(le)->type == php_le_php_driver_session()) {
70 psession = (php_driver_psession *) Z_RES_P(le)->ptr;
71 session->session = php_driver_add_ref(psession->session);
72 future = psession->future;
73 }
74 }
75
76 if (future == NULL) {
77 php5to7_zend_resource_le resource;
78
79 session->session = php_driver_new_peref(cass_session_new(), free_session, 1);
80
81 if (keyspace) {
82 future = cass_session_connect_keyspace((CassSession *) session->session->data,
83 self->cluster,
84 keyspace);
85 } else {
86 future = cass_session_connect((CassSession *) session->session->data,
87 self->cluster);
88 }
89
90 if (session->persist) {
91 psession = (php_driver_psession *) pecalloc(1, sizeof(php_driver_psession), 1);
92 psession->session = php_driver_add_ref(session->session);
93 psession->future = future;
94
95 #if PHP_MAJOR_VERSION >= 7
96 ZVAL_NEW_PERSISTENT_RES(&resource, 0, psession, php_le_php_driver_session());
97 PHP5TO7_ZEND_HASH_UPDATE(&EG(persistent_list), hash_key, hash_key_len + 1, &resource, sizeof(php5to7_zend_resource_le));
98 PHP_DRIVER_G(persistent_sessions)++;
99 #else
100 resource.type = php_le_php_driver_session();
101 resource.ptr = psession;
102 PHP5TO7_ZEND_HASH_UPDATE(&EG(persistent_list), hash_key, hash_key_len + 1, resource, sizeof(php5to7_zend_resource_le));
103 PHP_DRIVER_G(persistent_sessions)++;
104 #endif
105 }
106 }
107
108 if (php_driver_future_wait_timed(future, timeout TSRMLS_CC) == FAILURE) {
109 if (session->persist) {
110 efree(hash_key);
111 } else {
112 cass_future_free(future);
113 }
114
115 return;
116 }
117
118 if (php_driver_future_is_error(future TSRMLS_CC) == FAILURE) {
119 if (session->persist) {
120 (void) PHP5TO7_ZEND_HASH_DEL(&EG(persistent_list), hash_key, hash_key_len + 1);
121 efree(hash_key);
122 } else {
123 cass_future_free(future);
124 }
125
126 return;
127 }
128
129 if (session->persist)
130 efree(hash_key);
131 }
132
PHP_METHOD(DefaultCluster,connectAsync)133 PHP_METHOD(DefaultCluster, connectAsync)
134 {
135 char *hash_key = NULL;
136 php5to7_size hash_key_len = 0;
137 char *keyspace = NULL;
138 php5to7_size keyspace_len;
139 php_driver_cluster *self = NULL;
140 php_driver_future_session *future = NULL;
141
142 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|s", &keyspace, &keyspace_len) == FAILURE) {
143 return;
144 }
145
146 self = PHP_DRIVER_GET_CLUSTER(getThis());
147
148 object_init_ex(return_value, php_driver_future_session_ce);
149 future = PHP_DRIVER_GET_FUTURE_SESSION(return_value);
150
151 future->persist = self->persist;
152
153 if (self->persist) {
154 php5to7_zend_resource_le *le;
155
156 hash_key_len = spprintf(&hash_key, 0, "%s:session:%s",
157 self->hash_key, SAFE_STR(keyspace));
158
159 future->hash_key = hash_key;
160 future->hash_key_len = hash_key_len;
161
162 if (PHP5TO7_ZEND_HASH_FIND(&EG(persistent_list), hash_key, hash_key_len + 1, le) &&
163 Z_RES_P(le)->type == php_le_php_driver_session()) {
164 php_driver_psession *psession = (php_driver_psession *) Z_RES_P(le)->ptr;
165 future->session = php_driver_add_ref(psession->session);
166 future->future = psession->future;
167 return;
168 }
169 }
170
171 future->session = php_driver_new_peref(cass_session_new(), free_session, 1);
172
173 if (keyspace) {
174 future->future = cass_session_connect_keyspace((CassSession *) future->session->data,
175 self->cluster,
176 keyspace);
177 } else {
178 future->future = cass_session_connect((CassSession *) future->session->data,
179 self->cluster);
180 }
181
182 if (self->persist) {
183 php5to7_zend_resource_le resource;
184 php_driver_psession *psession =
185 (php_driver_psession *) pecalloc(1, sizeof(php_driver_psession), 1);
186 psession->session = php_driver_add_ref(future->session);
187 psession->future = future->future;
188
189 #if PHP_MAJOR_VERSION >= 7
190 ZVAL_NEW_PERSISTENT_RES(&resource, 0, psession, php_le_php_driver_session());
191 PHP5TO7_ZEND_HASH_UPDATE(&EG(persistent_list), hash_key, hash_key_len + 1, &resource, sizeof(php5to7_zend_resource_le));
192 PHP_DRIVER_G(persistent_sessions)++;
193 #else
194 resource.type = php_le_php_driver_session();
195 resource.ptr = psession;
196 PHP5TO7_ZEND_HASH_UPDATE(&EG(persistent_list), hash_key, hash_key_len + 1, resource, sizeof(php5to7_zend_resource_le));
197 PHP_DRIVER_G(persistent_sessions)++;
198 #endif
199
200 }
201 }
202
203 ZEND_BEGIN_ARG_INFO_EX(arginfo_connect, 0, ZEND_RETURN_VALUE, 0)
204 ZEND_ARG_INFO(0, keyspace)
205 ZEND_ARG_INFO(0, timeout)
206 ZEND_END_ARG_INFO()
207
208 ZEND_BEGIN_ARG_INFO_EX(arginfo_connectAsync, 0, ZEND_RETURN_VALUE, 0)
209 ZEND_ARG_INFO(0, keyspace)
210 ZEND_END_ARG_INFO()
211
212 static zend_function_entry php_driver_default_cluster_methods[] = {
213 PHP_ME(DefaultCluster, connect, arginfo_connect, ZEND_ACC_PUBLIC)
214 PHP_ME(DefaultCluster, connectAsync, arginfo_connectAsync, ZEND_ACC_PUBLIC)
215 PHP_FE_END
216 };
217
218 static zend_object_handlers php_driver_default_cluster_handlers;
219
220 static HashTable *
php_driver_default_cluster_properties(zval * object TSRMLS_DC)221 php_driver_default_cluster_properties(zval *object TSRMLS_DC)
222 {
223 HashTable *props = zend_std_get_properties(object TSRMLS_CC);
224
225 return props;
226 }
227
228 static int
php_driver_default_cluster_compare(zval * obj1,zval * obj2 TSRMLS_DC)229 php_driver_default_cluster_compare(zval *obj1, zval *obj2 TSRMLS_DC)
230 {
231 if (Z_OBJCE_P(obj1) != Z_OBJCE_P(obj2))
232 return 1; /* different classes */
233
234 return Z_OBJ_HANDLE_P(obj1) != Z_OBJ_HANDLE_P(obj1);
235 }
236
237 static void
php_driver_default_cluster_free(php5to7_zend_object_free * object TSRMLS_DC)238 php_driver_default_cluster_free(php5to7_zend_object_free *object TSRMLS_DC)
239 {
240 php_driver_cluster *self = PHP5TO7_ZEND_OBJECT_GET(cluster, object);
241
242 if (self->persist) {
243 efree(self->hash_key);
244 } else {
245 if (self->cluster) {
246 cass_cluster_free(self->cluster);
247 }
248 }
249
250 PHP5TO7_ZVAL_MAYBE_DESTROY(self->default_timeout);
251
252 zend_object_std_dtor(&self->zval TSRMLS_CC);
253 PHP5TO7_MAYBE_EFREE(self);
254 }
255
256 static php5to7_zend_object
php_driver_default_cluster_new(zend_class_entry * ce TSRMLS_DC)257 php_driver_default_cluster_new(zend_class_entry *ce TSRMLS_DC)
258 {
259 php_driver_cluster *self =
260 PHP5TO7_ZEND_OBJECT_ECALLOC(cluster, ce);
261
262 self->cluster = NULL;
263 self->default_consistency = PHP_DRIVER_DEFAULT_CONSISTENCY;
264 self->default_page_size = 5000;
265 self->persist = 0;
266 self->hash_key = NULL;
267
268 PHP5TO7_ZVAL_UNDEF(self->default_timeout);
269
270 PHP5TO7_ZEND_OBJECT_INIT_EX(cluster, default_cluster, self, ce);
271 }
272
php_driver_define_DefaultCluster(TSRMLS_D)273 void php_driver_define_DefaultCluster(TSRMLS_D)
274 {
275 zend_class_entry ce;
276
277 INIT_CLASS_ENTRY(ce, PHP_DRIVER_NAMESPACE "\\DefaultCluster", php_driver_default_cluster_methods);
278 php_driver_default_cluster_ce = zend_register_internal_class(&ce TSRMLS_CC);
279 zend_class_implements(php_driver_default_cluster_ce TSRMLS_CC, 1, php_driver_cluster_ce);
280 php_driver_default_cluster_ce->ce_flags |= PHP5TO7_ZEND_ACC_FINAL;
281 php_driver_default_cluster_ce->create_object = php_driver_default_cluster_new;
282
283 memcpy(&php_driver_default_cluster_handlers, zend_get_std_object_handlers(), sizeof(zend_object_handlers));
284 php_driver_default_cluster_handlers.get_properties = php_driver_default_cluster_properties;
285 php_driver_default_cluster_handlers.compare_objects = php_driver_default_cluster_compare;
286 }
287