Skip to content

Commit 93d687a

Browse files
committed
PCBC-360, PCBC-376: Major refactor for PHP 7 and reentrant transcoders.
This includes major changes to most components to support PHP 7. This also includes a major change to the operation handling flow to correct issues when callbacks (ex: transcoders) call back into the library. Change-Id: I90c68f250863bf723b8d6327d8a77c2e2e7fa3ae
1 parent 5ef73fb commit 93d687a

23 files changed

+1788
-798
lines changed

bucket.c

Lines changed: 826 additions & 464 deletions
Large diffs are not rendered by default.

bucket.h

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,15 +3,17 @@
33

44
#include <php.h>
55
#include "couchbase.h"
6+
#include "zap.h"
67

78
typedef struct bucket_object {
8-
zend_object std;
9-
zval *error;
10-
zval *encoder;
11-
zval *decoder;
12-
zval *prefix;
9+
zap_ZEND_OBJECT_START
1310

14-
pcbc_lcb *conn;
11+
zapval encoder;
12+
zapval decoder;
13+
zapval prefix;
14+
pcbc_lcb *conn;
15+
16+
zap_ZEND_OBJECT_END
1517
} bucket_object;
1618

1719
#endif // BUCKET_H_

cas.c

Lines changed: 13 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
11
#include <libcouchbase/couchbase.h>
22
#include <php.h>
3+
#include "cas.h"
34

45
int le_cas;
56

6-
static void cas_dtor(zend_rsrc_list_entry *rsrc TSRMLS_DC)
7+
static zap_DTORRES_FUNC(cas_dtor)
78
{
89
lcb_cas_t *cas_data = (lcb_cas_t*)rsrc->ptr;
910
if (cas_data) {
@@ -12,24 +13,20 @@ static void cas_dtor(zend_rsrc_list_entry *rsrc TSRMLS_DC)
1213
}
1314

1415
void couchbase_init_cas(INIT_FUNC_ARGS) {
15-
le_cas = zend_register_list_destructors_ex(cas_dtor, NULL, "CouchbaseCAS", module_number);
16+
le_cas = zend_register_list_destructors_ex(cas_dtor, NULL, "CouchbaseCAS", module_number);
1617
}
1718

1819
lcb_cas_t cas_retrieve(zval * zcas TSRMLS_DC) {
19-
lcb_cas_t *cas = 0;
20-
ZEND_FETCH_RESOURCE_NO_RETURN(cas, lcb_cas_t*, &zcas, -1, "CouchbaseCAS", le_cas);
21-
if (cas) {
22-
return *cas;
23-
} else {
24-
return 0;
25-
}
20+
lcb_cas_t *cas = (lcb_cas_t*)zap_fetch_resource(zcas, "CouchbaseCAS", le_cas);
21+
if (cas) {
22+
return *cas;
23+
} else {
24+
return 0;
25+
}
2626
}
2727

28-
zval * cas_create(lcb_cas_t value TSRMLS_DC) {
29-
zval *cas;
30-
void *cas_data = emalloc(sizeof(lcb_cas_t));
31-
*((lcb_cas_t*)cas_data) = value;
32-
MAKE_STD_ZVAL(cas);
33-
ZEND_REGISTER_RESOURCE(cas, cas_data, le_cas);
34-
return cas;
28+
void cas_create(zapval *casout, lcb_cas_t value TSRMLS_DC) {
29+
void *cas_data = emalloc(sizeof(lcb_cas_t));
30+
*((lcb_cas_t*)cas_data) = value;
31+
zapval_alloc_res(*casout, cas_data, le_cas);
3532
}

cas.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,13 @@
33

44
#include <php.h>
55
#include <libcouchbase/couchbase.h>
6+
#include "zap.h"
67

78
void couchbase_init_cas(INIT_FUNC_ARGS);
89
lcb_cas_t cas_retrieve(zval * zcas TSRMLS_DC);
9-
zval * cas_create(lcb_cas_t value TSRMLS_DC);
10+
void cas_create(zapval *casout, lcb_cas_t value TSRMLS_DC);
11+
12+
#define alloc_cas(z, v) \
13+
cas_create(&z, v)
1014

1115
#endif // CAS_H_

cluster.c

Lines changed: 73 additions & 79 deletions
Original file line numberDiff line numberDiff line change
@@ -1,96 +1,83 @@
1-
#include <libcouchbase/couchbase.h>
21
#include "couchbase.h"
3-
#include "phphelpers.h"
2+
#include "ext/standard/php_var.h"
43
#include "exception.h"
4+
#include "zap.h"
55
#include "cluster.h"
6-
#include "metadoc.h"
6+
#include "opcookie.h"
77

8-
zend_object_handlers cluster_handlers;
8+
zap_class_entry cluster_class;
9+
zend_class_entry *cluster_ce;
10+
11+
#define PHP_THISOBJ() zap_fetch_this(cluster_object)
912

10-
void cluster_free_storage(void *object TSRMLS_DC)
13+
zap_FREEOBJ_FUNC(cluster_free_storage)
1114
{
12-
cluster_object *obj = (cluster_object *)object;
15+
cluster_object *obj = zap_get_object(cluster_object, object);
1316

14-
zend_hash_destroy(obj->std.properties);
15-
FREE_HASHTABLE(obj->std.properties);
17+
if (obj->lcb != NULL) {
18+
lcb_destroy(obj->lcb);
19+
obj->lcb = NULL;
20+
}
1621

17-
efree(obj);
22+
zend_object_std_dtor(&obj->std TSRMLS_CC);
23+
zap_free_object_storage(obj);
1824
}
1925

20-
zend_object_value cluster_create_handler(zend_class_entry *type TSRMLS_DC)
26+
zap_CREATEOBJ_FUNC(cluster_create_handler)
2127
{
22-
zend_object_value retval;
23-
24-
cluster_object *obj = (cluster_object *)emalloc(sizeof(cluster_object));
25-
memset(obj, 0, sizeof(cluster_object));
26-
obj->std.ce = type;
28+
cluster_object *obj = zap_alloc_object_storage(cluster_object, type);
2729

28-
ALLOC_HASHTABLE(obj->std.properties);
29-
zend_hash_init(obj->std.properties, 0, NULL, ZVAL_PTR_DTOR, 0);
30-
phlp_object_properties_init(&obj->std, type);
30+
zend_object_std_init(&obj->std, type TSRMLS_CC);
31+
zap_object_properties_init(&obj->std, type);
3132

32-
retval.handle = zend_objects_store_put(obj, NULL,
33-
cluster_free_storage, NULL TSRMLS_CC);
34-
retval.handlers = &cluster_handlers;
33+
obj->lcb = NULL;
3534

36-
return retval;
35+
return zap_finalize_object(obj, &cluster_class);
3736
}
3837

3938
typedef struct {
40-
zval *retval;
41-
cluster_object *owner;
42-
} copcookie;
43-
44-
copcookie * copcookie_init(cluster_object *clusterobj, zval *return_value) {
45-
copcookie *cookie = emalloc(sizeof(copcookie));
46-
cookie->owner = clusterobj;
47-
cookie->retval = return_value;
48-
ZVAL_NULL(cookie->retval);
49-
return cookie;
50-
}
51-
52-
void ccookie_error(const copcookie *cookie, cluster_object *data, zval *doc,
53-
lcb_error_t error TSRMLS_DC) {
54-
zval *zerror = create_lcb_exception(error TSRMLS_CC);
55-
if (Z_TYPE_P(cookie->retval) == IS_ARRAY) {
56-
metadoc_from_error(doc, zerror TSRMLS_CC);
57-
} else {
58-
data->error = zerror;
59-
}
60-
}
39+
opcookie_res header;
40+
zapval bytes;
41+
} opcookie_http_res;
6142

6243
static void http_complete_callback(lcb_http_request_t request, lcb_t instance,
6344
const void *cookie, lcb_error_t error,
6445
const lcb_http_resp_t *resp) {
65-
cluster_object *data = (cluster_object*)lcb_get_cookie(instance);
66-
zval *doc = ((copcookie*)cookie)->retval;
67-
TSRMLS_FETCH();
46+
opcookie_http_res *result = ecalloc(1, sizeof(opcookie_http_res));
47+
TSRMLS_FETCH();
6848

69-
if (error == LCB_SUCCESS) {
70-
ZVAL_STRINGL(doc, resp->v.v0.bytes, resp->v.v0.nbytes, 1);
71-
} else {
72-
ccookie_error(cookie, data, NULL, error TSRMLS_CC);
73-
}
49+
result->header.err = error;
50+
zapval_alloc_stringl(
51+
result->bytes, resp->v.v0.bytes, resp->v.v0.nbytes);
52+
53+
opcookie_push((opcookie*)cookie, &result->header);
7454
}
7555

76-
static int pcbc_wait(cluster_object *obj TSRMLS_DC)
56+
static lcb_error_t proc_http_results(cluster_object *cluster, zval *return_value,
57+
opcookie *cookie TSRMLS_DC)
7758
{
78-
lcb_t instance = obj->lcb;
79-
obj->error = NULL;
80-
81-
lcb_wait(instance);
82-
83-
if (obj->error) {
84-
zend_throw_exception_object(obj->error TSRMLS_CC);
85-
obj->error = NULL;
86-
return 0;
87-
}
88-
89-
return 1;
59+
opcookie_http_res *res;
60+
lcb_error_t err = LCB_SUCCESS;
61+
62+
// Any error should cause everything to fail... for now?
63+
err = opcookie_get_first_error(cookie);
64+
65+
if (err == LCB_SUCCESS) {
66+
// TODO: This could leak with multiple results... It also copies
67+
// which might not be needed...
68+
FOREACH_OPCOOKIE_RES(opcookie_http_res, res, cookie) {
69+
zap_zval_stringl_p(return_value,
70+
zapval_strval_p(&res->bytes), zapval_strlen_p(&res->bytes))
71+
}
72+
}
73+
74+
FOREACH_OPCOOKIE_RES(opcookie_http_res, res, cookie) {
75+
zapval_destroy(res->bytes);
76+
}
77+
78+
return err;
9079
}
9180

92-
zend_class_entry *cluster_ce;
93-
9481
PHP_METHOD(Cluster, __construct)
9582
{
9683
cluster_object *data = PHP_THISOBJ();
@@ -187,11 +174,12 @@ PHP_METHOD(Cluster, http_request)
187174
{
188175
cluster_object *data = PHP_THISOBJ();
189176
lcb_http_cmd_t cmd = { 0 };
190-
copcookie *cookie;
177+
opcookie *cookie;
191178
lcb_http_type_t type;
192179
lcb_http_method_t method;
193180
const char *contenttype;
194181
zval *ztype, *zmethod, *zpath, *zbody, *zcontenttype;
182+
lcb_error_t err;
195183

196184
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "zzzzz",
197185
&ztype, &zmethod, &zpath, &zbody, &zcontenttype) == FAILURE) {
@@ -240,12 +228,21 @@ PHP_METHOD(Cluster, http_request)
240228
cmd.v.v0.chunked = 0;
241229
cmd.v.v0.content_type = contenttype;
242230

243-
cookie = copcookie_init(data, return_value);
231+
cookie = opcookie_init();
232+
233+
err = lcb_make_http_request(data->lcb, cookie, type, &cmd, NULL);
234+
235+
if (err == LCB_SUCCESS) {
236+
lcb_wait(data->lcb);
237+
238+
err = proc_http_results(data, return_value, cookie TSRMLS_CC);
239+
}
244240

245-
lcb_make_http_request(data->lcb, cookie, type, &cmd, NULL);
246-
pcbc_wait(data TSRMLS_CC);
241+
opcookie_destroy(cookie);
247242

248-
efree(cookie);
243+
if (err != LCB_SUCCESS) {
244+
throw_lcb_exception(err);
245+
}
249246
}
250247

251248
zend_function_entry cluster_methods[] = {
@@ -256,12 +253,9 @@ zend_function_entry cluster_methods[] = {
256253
};
257254

258255
void couchbase_init_cluster(INIT_FUNC_ARGS) {
259-
zend_class_entry ce;
260-
INIT_CLASS_ENTRY(ce, "_CouchbaseCluster", cluster_methods);
261-
ce.create_object = cluster_create_handler;
262-
cluster_ce = zend_register_internal_class(&ce TSRMLS_CC);
263-
264-
memcpy(&cluster_handlers,
265-
zend_get_std_object_handlers(), sizeof(zend_object_handlers));
266-
cluster_handlers.clone_obj = NULL;
256+
zap_init_class_entry(&cluster_class, "_CouchbaseCluster",
257+
cluster_methods);
258+
cluster_class.create_obj = cluster_create_handler;
259+
cluster_class.free_obj = cluster_free_storage;
260+
cluster_ce = zap_register_internal_class(&cluster_class, cluster_object);
267261
}

cluster.h

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,16 @@
11
#ifndef CLUSTER_H_
22
#define CLUSTER_H_
33

4-
#include <libcouchbase/couchbase.h>
54
#include <php.h>
5+
#include "couchbase.h"
6+
#include "zap.h"
67

78
typedef struct cluster_object {
8-
zend_object std;
9-
lcb_t lcb;
10-
zval *error;
9+
zap_ZEND_OBJECT_START
10+
11+
lcb_t lcb;
12+
13+
zap_ZEND_OBJECT_END
1114
} cluster_object;
1215

1316
#endif // CLUSTER_H_

config.m4

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ if test "$PHP_COUCHBASE" != "no"; then
4040
couchbase.c \
4141
exception.c \
4242
metadoc.c \
43+
opcookie.c \
4344
transcoding.c \
4445
fastlz/fastlz.c \
4546
, $ext_shared)

config.w32

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ if (PHP_COUCHBASE != "no") {
88
"couchbase.c " +
99
"exception.c " +
1010
"metadoc.c " +
11+
"opcookie.c " +
1112
"transcoding.c ";
1213

1314
if (CHECK_LIB("libcouchbase.lib", "couchbase", PHP_COUCHBASE) &&

couchbase.c

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
#include "metadoc.h"
44
#include "phpstubstr.h"
55
#include "fastlz/fastlz.h"
6+
#include "zap.h"
67

78
#if HAVE_ZLIB
89
#include <zlib.h>
@@ -150,10 +151,10 @@ PHP_FUNCTION(couchbase_zlib_compress)
150151
compress((uint8_t*)dataOut + 4, &dataOutSize, dataIn, dataSize);
151152
*(uint32_t*)dataOut = dataSize;
152153

153-
RETURN_STRINGL(dataOut, 4 + dataOutSize, 0);
154+
zap_zval_stringl_p(return_value, dataOut, 4 + dataOutSize);
155+
efree(dataOut);
154156
#else
155157
zend_throw_exception(NULL, "The zlib library was not available when the couchbase extension was built.", 0 TSRMLS_CC);
156-
RETURN_NULL();
157158
#endif
158159
}
159160

@@ -175,10 +176,10 @@ PHP_FUNCTION(couchbase_zlib_decompress)
175176
dataOut = emalloc(dataOutSize);
176177
uncompress(dataOut, &dataOutSize, (uint8_t*)dataIn + 4, dataSize - 4);
177178

178-
RETURN_STRINGL(dataOut, dataOutSize, 0);
179+
zap_zval_stringl_p(return_value, dataOut, dataOutSize);
180+
efree(dataOut);
179181
#else
180182
zend_throw_exception(NULL, "The zlib library was not available when the couchbase extension was built.", 0 TSRMLS_CC);
181-
RETURN_NULL();
182183
#endif
183184
}
184185

@@ -200,7 +201,9 @@ PHP_FUNCTION(couchbase_fastlz_compress)
200201
dataOutSize = fastlz_compress(dataIn, dataSize, (uint8_t*)dataOut + 4);
201202
*(uint32_t*)dataOut = dataSize;
202203

203-
RETURN_STRINGL(dataOut, 4 + dataOutSize, 0);
204+
zap_zval_stringl_p(return_value, dataOut, 4 + dataOutSize);
205+
206+
efree(dataOut);
204207
}
205208

206209
PHP_FUNCTION(couchbase_fastlz_decompress)
@@ -221,7 +224,9 @@ PHP_FUNCTION(couchbase_fastlz_decompress)
221224
dataOutSize = fastlz_decompress(
222225
(uint8_t*)dataIn + 4, dataSize - 4, dataOut, dataOutSize);
223226

224-
RETURN_STRINGL(dataOut, dataOutSize, 0);
227+
zap_zval_stringl_p(return_value, dataOut, dataOutSize);
228+
229+
efree(dataOut);
225230
}
226231

227232
static zend_function_entry couchbase_functions[] = {

couchbase.h

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,8 +41,6 @@ ZEND_EXTERN_MODULE_GLOBALS(couchbase)
4141
#define PCBCG(v) (couchbase_globals.v)
4242
#endif
4343

44-
#define PHP_THISOBJ() zend_object_store_get_object(getThis() TSRMLS_CC)
45-
4644
void couchbase_init_exceptions(INIT_FUNC_ARGS);
4745
void couchbase_init_cluster(INIT_FUNC_ARGS);
4846
void couchbase_init_bucket(INIT_FUNC_ARGS);

0 commit comments

Comments
 (0)