2 +----------------------------------------------------------------------+
4 +----------------------------------------------------------------------+
5 | Copyright (c) 2010 Hyves (http://www.hyves.nl) |
6 | Copyright (c) 2010-present Facebook, Inc. (http://www.facebook.com) |
7 | Copyright (c) 1997-2010 The PHP Group |
8 +----------------------------------------------------------------------+
9 | This source file is subject to version 3.01 of the PHP license, |
10 | that is bundled with this package in the file LICENSE, and is |
11 | available through the world-wide-web at the following url: |
12 | http://www.php.net/license/3_01.txt |
13 | If you did not receive a copy of the PHP license and are unable to |
14 | obtain it through the world-wide-web, please send a note to |
15 | license@php.net so we can mail you a copy immediately. |
16 +----------------------------------------------------------------------+
19 #include "hphp/runtime/base/array-init.h"
20 #include "hphp/runtime/base/array-iterator.h"
21 #include "hphp/runtime/ext/extension.h"
22 #include "hphp/runtime/vm/native-data.h"
23 #include "hphp/runtime/ext/memcached/libmemcached_portability.h"
24 #include "hphp/runtime/base/builtin-functions.h"
25 #include "hphp/runtime/ext/json/ext_json.h"
26 #include "hphp/util/rds-local.h"
33 #include "hphp/system/systemlib.h"
36 ///////////////////////////////////////////////////////////////////////////////
38 // Payload value flags
39 #define MEMC_VAL_TYPE_MASK 0xf
41 #define MEMC_VAL_IS_STRING 0
42 #define MEMC_VAL_IS_LONG 1
43 #define MEMC_VAL_IS_DOUBLE 2
44 #define MEMC_VAL_IS_BOOL 3
45 #define MEMC_VAL_IS_SERIALIZED 4
46 #define MEMC_VAL_IS_IGBINARY 5
47 #define MEMC_VAL_IS_JSON 6
49 #define MEMC_VAL_COMPRESSED (1<<4)
50 #define MEMC_VAL_COMPRESSION_ZLIB (1<<5)
51 #define MEMC_VAL_COMPRESSION_FASTLZ (1<<6)
53 #define MEMC_COMPRESS_THRESHOLD 100
55 #if defined(LIBMEMCACHED_VERSION_HEX) && LIBMEMCACHED_VERSION_HEX < 0x00052000
56 # define MEMCACHED_SERVER_TEMPORARILY_DISABLED (1024 << 2)
59 #if defined(LIBMEMCACHED_VERSION_HEX) && LIBMEMCACHED_VERSION_HEX >= 0x01000002
60 # define HAVE_MEMCACHED_TOUCH 1
64 const int64_t q_Memcached$$OPT_COMPRESSION
= -1001;
65 const int64_t q_Memcached$$OPT_PREFIX_KEY
= -1002;
66 const int64_t q_Memcached$$OPT_SERIALIZER
= -1003;
69 const int64_t q_Memcached$$RES_PAYLOAD_FAILURE
= -1001;
72 const int64_t q_Memcached$$SERIALIZER_PHP
= 1;
73 const int64_t q_Memcached$$SERIALIZER_IGBINARY
= 2;
74 const int64_t q_Memcached$$SERIALIZER_JSON
= 3;
77 const int64_t q_Memcached$$GET_PRESERVE_ORDER
= 1;
86 struct MEMCACHEDGlobals final
{
87 std::string sess_prefix
;
90 static RDS_LOCAL_NO_CHECK(MEMCACHEDGlobals
*, s_memcached_globals
){nullptr};
91 #define MEMCACHEDG(name) (*s_memcached_globals)->name
94 struct MemcachedResultWrapper
{
95 memcached_result_st value
;
96 explicit MemcachedResultWrapper(memcached_st
*memcached
) {
97 memcached_result_create(memcached
, &value
);
99 ~MemcachedResultWrapper() {
100 memcached_result_free(&value
);
106 * Since libmemcachd is in C, we cannot use lambda functions as lambda functions
107 * are special typed and normally passed by templated types.
109 static memcached_return_t
memcached_dump_callback(const memcached_st
*,
111 size_t len
, void* context
) {
112 ((Array
*)context
)->append(Variant
{makeStaticString(key
, len
)});
113 return MEMCACHED_SUCCESS
;
116 const StaticString
s_MemcachedData("MemcachedData");
118 struct MemcachedData
{
122 serializer(q_Memcached$$SERIALIZER_PHP
),
123 rescode(MEMCACHED_SUCCESS
) {
124 memcached_create(&memcached
);
127 memcached_free(&memcached
);
130 memcached_st memcached
;
140 typedef std::shared_ptr
<Impl
> ImplPtr
;
143 bool handleError(memcached_return status
) {
145 case MEMCACHED_SUCCESS
:
146 case MEMCACHED_STORED
:
147 case MEMCACHED_DELETED
:
151 case MEMCACHED_BUFFERED
:
152 m_impl
->rescode
= status
;
155 m_impl
->rescode
= status
;
159 void toPayload(const Variant
& value
, std::vector
<char> &payload
,
162 if (value
.isString() || value
.isNumeric()) {
163 encoded
= value
.toString();
164 if (value
.isString()) flags
= MEMC_VAL_IS_STRING
;
165 else if (value
.isInteger()) flags
= MEMC_VAL_IS_LONG
;
166 else if (value
.isDouble()) flags
= MEMC_VAL_IS_DOUBLE
;
167 else if (value
.isBoolean()) flags
= MEMC_VAL_IS_BOOL
;
170 switch (m_impl
->serializer
) {
171 case q_Memcached$$SERIALIZER_JSON
:
172 encoded
= Variant::attach(HHVM_FN(json_encode
)(value
)).toString();
173 flags
= MEMC_VAL_IS_JSON
;
176 encoded
= f_serialize(value
);
177 flags
= MEMC_VAL_IS_SERIALIZED
;
182 if (m_impl
->compression
&& encoded
.length() >= MEMC_COMPRESS_THRESHOLD
) {
183 unsigned long payloadCompLength
= compressBound(encoded
.length());
184 payload
.resize(payloadCompLength
);
185 if (compress((Bytef
*)payload
.data(), &payloadCompLength
,
186 (const Bytef
*)encoded
.data(), encoded
.length()) == Z_OK
) {
187 payload
.resize(payloadCompLength
);
188 flags
|= MEMC_VAL_COMPRESSED
;
191 raise_warning("could not compress value");
195 payload
.insert(payload
.end(),
196 encoded
.data(), encoded
.data() + encoded
.length());
198 bool toObject(Variant
& value
, const memcached_result_st
&result
) {
199 const char *payload
= memcached_result_value(&result
);
200 size_t payloadLength
= memcached_result_length(&result
);
201 uint32_t flags
= memcached_result_flags(&result
);
203 String decompPayload
;
204 if (flags
& MEMC_VAL_COMPRESSED
) {
206 std::vector
<char> buffer
;
207 unsigned long bufferSize
;
212 if ((flags
& MEMC_VAL_COMPRESSION_FASTLZ
||
213 flags
& MEMC_VAL_COMPRESSION_ZLIB
)
214 && payloadLength
> sizeof(uint32_t)) {
215 memcpy(&maxLength
, payload
, sizeof(uint32_t));
216 if (maxLength
< std::numeric_limits
<uint32_t>::max()) {
217 buffer
.resize(maxLength
+ 1);
218 payloadLength
-= sizeof(uint32_t);
219 payload
+= sizeof(uint32_t);
220 bufferSize
= maxLength
;
222 if (flags
& MEMC_VAL_COMPRESSION_FASTLZ
) {
223 bufferSize
= fastlz_decompress(payload
, payloadLength
,
224 buffer
.data(), maxLength
);
225 done
= (bufferSize
> 0);
226 } else if (flags
& MEMC_VAL_COMPRESSION_ZLIB
) {
227 status
= uncompress((Bytef
*)buffer
.data(), &bufferSize
,
228 (const Bytef
*)payload
, (uLong
)payloadLength
);
229 done
= (status
== Z_OK
);
236 for (int factor
= 1; factor
<= 16; ++factor
) {
238 std::numeric_limits
<unsigned long>::max() / (1 << factor
)) {
241 bufferSize
= payloadLength
* (1 << factor
) + 1;
242 buffer
.resize(bufferSize
);
243 status
= uncompress((Bytef
*)buffer
.data(), &bufferSize
,
244 (const Bytef
*)payload
, (uLong
)payloadLength
);
245 if (status
== Z_OK
) {
248 } else if (status
!= Z_BUF_ERROR
) {
254 raise_warning("could not uncompress value");
258 String::attach(StringData::Make(buffer
.data(), bufferSize
, CopyString
));
261 String::attach(StringData::Make(payload
, payloadLength
, CopyString
));
264 switch (flags
& MEMC_VAL_TYPE_MASK
) {
265 case MEMC_VAL_IS_STRING
:
266 value
= decompPayload
;
268 case MEMC_VAL_IS_LONG
:
269 value
= decompPayload
.toInt64();
271 case MEMC_VAL_IS_DOUBLE
:
272 value
= decompPayload
.toDouble();
274 case MEMC_VAL_IS_BOOL
:
275 value
= decompPayload
.toBoolean();
277 case MEMC_VAL_IS_JSON
:
278 value
= Variant::attach(HHVM_FN(json_decode
)(decompPayload
));
280 case MEMC_VAL_IS_SERIALIZED
:
281 value
= unserialize_from_string(
283 VariableUnserializer::Type::Serialize
286 case MEMC_VAL_IS_IGBINARY
:
287 raise_warning("could not unserialize value, no igbinary support");
290 raise_warning("unknown payload type");
295 bool getMultiImpl(const String
& server_key
, const Array
& keys
, bool enableCas
,
296 Array
*returnValue
) {
297 std::vector
<const char*> keysCopy
;
298 keysCopy
.reserve(keys
.size());
299 std::vector
<size_t> keysLengthCopy
;
300 keysLengthCopy
.reserve(keys
.size());
301 for (ArrayIter
iter(keys
); iter
; ++iter
) {
302 Variant vKey
= iter
.second();
303 if (!vKey
.isString()) continue;
304 StringData
*key
= vKey
.getStringData();
305 if (key
->empty()) continue;
306 keysCopy
.push_back(key
->data());
307 keysLengthCopy
.push_back(key
->size());
308 if (returnValue
) returnValue
->set(String(key
), init_null(), true);
310 if (keysCopy
.size() == 0) {
311 m_impl
->rescode
= MEMCACHED_BAD_KEY_PROVIDED
;
315 memcached_behavior_set(&m_impl
->memcached
, MEMCACHED_BEHAVIOR_SUPPORT_CAS
,
317 const char *myServerKey
= server_key
.empty() ? nullptr : server_key
.c_str();
318 size_t myServerKeyLen
= server_key
.length();
319 return handleError(memcached_mget_by_key(&m_impl
->memcached
,
320 myServerKey
, myServerKeyLen
, keysCopy
.data(), keysLengthCopy
.data(),
323 bool fetchImpl(memcached_result_st
&result
, Array
&item
) {
324 memcached_return status
;
325 if (!memcached_fetch_result(&m_impl
->memcached
, &result
, &status
)) {
331 if (!toObject(value
, result
)) {
332 m_impl
->rescode
= q_Memcached$$RES_PAYLOAD_FAILURE
;
336 const char *key
= memcached_result_key_value(&result
);
337 size_t keyLength
= memcached_result_key_length(&result
);
338 String
sKey(key
, keyLength
, CopyString
);
339 double cas
= (double) memcached_result_cas(&result
);
341 item
= make_dict_array(s_key
, sKey
, s_value
, value
, s_cas
, cas
);
344 typedef memcached_return_t (*SetOperation
)(memcached_st
*,
345 const char *, size_t, const char *, size_t, const char *, size_t,
348 bool setOperationImpl(SetOperation op
, const String
& server_key
,
349 const String
& key
, const Variant
& value
,
351 m_impl
->rescode
= MEMCACHED_SUCCESS
;
353 m_impl
->rescode
= MEMCACHED_BAD_KEY_PROVIDED
;
357 std::vector
<char> payload
; uint32_t flags
;
358 toPayload(value
, payload
, flags
);
360 const String
& myServerKey
= server_key
.empty() ? key
: server_key
;
361 return handleError(op(&m_impl
->memcached
, myServerKey
.c_str(),
362 myServerKey
.length(), key
.c_str(), key
.length(),
363 payload
.data(), payload
.size(), expiration
, flags
));
366 Variant
incDecOp(bool isInc
,
367 const StringData
* server_key
, const StringData
* key
,
368 int64_t offset
, const Variant
& initial_value
, int64_t expiry
) {
369 m_impl
->rescode
= MEMCACHED_SUCCESS
;
370 if (key
->empty() || strchr(key
->data(), ' ')) {
371 m_impl
->rescode
= MEMCACHED_BAD_KEY_PROVIDED
;
375 raise_warning("offset has to be >= 0");
379 // Dispatch to the correct memcached_* function depending on initial_value,
380 // server_key, and isInc.
382 memcached_return_t status
;
384 bool use_initial
= initial_value
.isInteger();
385 auto mc
= &m_impl
->memcached
;
387 if (!isBinaryProtocol()) {
388 raise_warning("Initial value is only supported with binary protocol");
394 status
= memcached_increment_with_initial_by_key(
396 server_key
->data(), server_key
->size(), key
->data(), key
->size(),
397 offset
, initial_value
.asInt64Val(), expiry
, &value
);
399 status
= memcached_decrement_with_initial_by_key(
401 server_key
->data(), server_key
->size(), key
->data(), key
->size(),
402 offset
, initial_value
.asInt64Val(), expiry
, &value
);
406 status
= memcached_increment_with_initial(
407 mc
, key
->data(), key
->size(),
408 offset
, initial_value
.asInt64Val(), expiry
, &value
);
410 status
= memcached_decrement_with_initial(
411 mc
, key
->data(), key
->size(),
412 offset
, initial_value
.asInt64Val(), expiry
, &value
);
418 status
= memcached_increment_by_key(
420 server_key
->data(), server_key
->size(), key
->data(), key
->size(),
423 status
= memcached_decrement_by_key(
425 server_key
->data(), server_key
->size(), key
->data(), key
->size(),
430 status
= memcached_increment(
431 mc
, key
->data(), key
->size(), offset
, &value
);
433 status
= memcached_decrement(
434 mc
, key
->data(), key
->size(), offset
, &value
);
439 if (!handleError(status
)) return false;
440 return (int64_t)value
;
443 bool isBinaryProtocol() {
444 return memcached_behavior_get(&m_impl
->memcached
,
445 MEMCACHED_BEHAVIOR_BINARY_PROTOCOL
);
448 typedef std::map
<std::string
, ImplPtr
> ImplMap
;
449 static RDS_LOCAL(ImplMap
, s_persistentMap
);
452 void HHVM_METHOD(Memcached
, __construct
,
453 const Variant
& persistent_id
/*= null*/) {
454 auto data
= Native::data
<MemcachedData
>(this_
);
455 if (persistent_id
.isNull()) {
456 data
->m_impl
.reset(new MemcachedData::Impl
);
457 data
->m_impl
->is_persistent
= false;
458 data
->m_impl
->is_pristine
= true;
460 bool is_pristine
= false;
461 MemcachedData::ImplPtr
&impl
= (*data
->s_persistentMap
)[
462 persistent_id
.toString().toCppString()
465 impl
.reset(new MemcachedData::Impl
);
469 data
->m_impl
->is_persistent
= true;
470 data
->m_impl
->is_pristine
= is_pristine
;
474 bool HHVM_METHOD(Memcached
, quit
) {
475 auto data
= Native::data
<MemcachedData
>(this_
);
476 memcached_quit(&data
->m_impl
->memcached
);
480 Variant
HHVM_METHOD(Memcached
, getallkeys
) {
481 auto data
= Native::data
<MemcachedData
>(this_
);
482 memcached_dump_fn callbacks
[] = {
483 &memcached_dump_callback
,
487 memcached_return status
= memcached_dump(&data
->m_impl
->memcached
, callbacks
,
490 sizeof(memcached_dump_fn
));
491 if (!data
->handleError(status
)) {
499 Variant
getByKeyImpl(ObjectData
* const this_
, const String
& server_key
,
500 const String
& key
, const Variant
& cache_cb
,
501 Variant
* cas_token
) {
502 auto data
= Native::data
<MemcachedData
>(this_
);
503 data
->m_impl
->rescode
= MEMCACHED_SUCCESS
;
505 data
->m_impl
->rescode
= MEMCACHED_BAD_KEY_PROVIDED
;
509 memcached_behavior_set(&data
->m_impl
->memcached
,
510 MEMCACHED_BEHAVIOR_SUPPORT_CAS
,
512 const char *myServerKey
= server_key
.empty() ? nullptr : server_key
.c_str();
513 size_t myServerKeyLen
= server_key
.length();
514 const char *myKey
= key
.c_str();
515 size_t myKeyLen
= key
.length();
516 memcached_return status
= memcached_mget_by_key(&data
->m_impl
->memcached
,
517 myServerKey
, myServerKeyLen
, &myKey
, &myKeyLen
, 1);
518 if (!data
->handleError(status
)) return false;
521 MemcachedResultWrapper
result(&data
->m_impl
->memcached
);
522 if (!memcached_fetch_result(&data
->m_impl
->memcached
,
523 &result
.value
, &status
)) {
524 if (status
== MEMCACHED_END
) status
= MEMCACHED_NOTFOUND
;
525 if (status
== MEMCACHED_NOTFOUND
&& !cache_cb
.isNull()) {
526 raise_warning("Memcached::getbykey() no longer supports callbacks");
528 data
->handleError(status
);
532 if (!data
->toObject(returnValue
, result
.value
)) {
533 data
->m_impl
->rescode
= q_Memcached$$RES_PAYLOAD_FAILURE
;
537 *cas_token
= (double) memcached_result_cas(&result
.value
);
542 Variant
getMultiByKeyImpl(ObjectData
* const this_
, const String
& server_key
,
543 const Array
& keys
, Variant
* cas_tokens
, int flags
) {
544 auto data
= Native::data
<MemcachedData
>(this_
);
545 data
->m_impl
->rescode
= MEMCACHED_SUCCESS
;
547 bool preserveOrder
= flags
& q_Memcached$$GET_PRESERVE_ORDER
;
548 Array returnValue
= Array::CreateDict();
549 if (!data
->getMultiImpl(server_key
, keys
, cas_tokens
,
550 preserveOrder
? &returnValue
: nullptr)) {
554 Array cas_tokens_arr
;
557 *cas_tokens
= cas_tokens_arr
;
561 MemcachedResultWrapper
result(&data
->m_impl
->memcached
);
562 memcached_return status
;
563 while (memcached_fetch_result(&data
->m_impl
->memcached
, &result
.value
,
565 if (status
!= MEMCACHED_SUCCESS
) {
566 status
= MEMCACHED_SOME_ERRORS
;
567 data
->handleError(status
);
571 if (!data
->toObject(value
, result
.value
)) {
572 data
->m_impl
->rescode
= q_Memcached$$RES_PAYLOAD_FAILURE
;
575 const char *key
= memcached_result_key_value(&result
.value
);
576 size_t keyLength
= memcached_result_key_length(&result
.value
);
577 String
sKey(key
, keyLength
, CopyString
);
578 returnValue
.set(sKey
, value
, true);
580 double cas
= (double) memcached_result_cas(&result
.value
);
581 cas_tokens_arr
.set(sKey
, cas
, true);
586 } // anonymous namespace
588 Variant
HHVM_METHOD(Memcached
, getbykey
, const String
& server_key
,
590 const Variant
& cache_cb
/*= null*/) {
591 return getByKeyImpl(this_
, server_key
, key
, cache_cb
, nullptr);
594 Variant
HHVM_METHOD(Memcached
, getbykeywithcastoken
,
595 const String
& server_key
,
597 const Variant
& cache_cb
,
598 Variant
& cas_token
) {
599 return getByKeyImpl(this_
, server_key
, key
, cache_cb
, &cas_token
);
602 Variant
HHVM_METHOD(Memcached
, getmultibykey
, const String
& server_key
,
604 int64_t flags
/*= 0*/) {
605 return getMultiByKeyImpl(this_
, server_key
, keys
, nullptr, flags
);
608 Variant
HHVM_METHOD(Memcached
, getmultibykeywithcastokens
,
609 const String
& server_key
,
612 int64_t flags
/*= 0*/) {
613 return getMultiByKeyImpl(this_
, server_key
, keys
, &cas_tokens
, flags
);
616 bool HHVM_METHOD(Memcached
, getdelayedbykey
, const String
& server_key
,
617 const Array
& keys
, bool with_cas
/*= false*/,
618 const Variant
& value_cb
/*= uninit_variant*/) {
619 auto data
= Native::data
<MemcachedData
>(this_
);
620 data
->m_impl
->rescode
= MEMCACHED_SUCCESS
;
622 if (!data
->getMultiImpl(server_key
, keys
, with_cas
, nullptr)) return false;
623 if (value_cb
.isNull()) return true;
625 MemcachedResultWrapper
result(&data
->m_impl
->memcached
); Array item
;
626 while (data
->fetchImpl(result
.value
, item
)) {
627 vm_call_user_func(value_cb
, make_vec_array(Variant(this_
), item
));
630 if (data
->m_impl
->rescode
!= MEMCACHED_END
) return false;
631 data
->m_impl
->rescode
= MEMCACHED_SUCCESS
;
635 Variant
HHVM_METHOD(Memcached
, fetch
) {
636 auto data
= Native::data
<MemcachedData
>(this_
);
637 data
->m_impl
->rescode
= MEMCACHED_SUCCESS
;
639 MemcachedResultWrapper
result(&data
->m_impl
->memcached
); Array item
;
640 if (!data
->fetchImpl(result
.value
, item
)) return false;
645 Variant
HHVM_METHOD(Memcached
, fetchall
) {
646 auto data
= Native::data
<MemcachedData
>(this_
);
647 data
->m_impl
->rescode
= MEMCACHED_SUCCESS
;
650 MemcachedResultWrapper
result(&data
->m_impl
->memcached
); Array item
;
651 while (data
->fetchImpl(result
.value
, item
)) {
652 returnValue
.append(item
);
655 if (data
->m_impl
->rescode
!= MEMCACHED_END
) return false;
659 bool HHVM_METHOD(Memcached
, setbykey
, const String
& server_key
,
660 const String
& key
, const Variant
& value
,
661 int64_t expiration
/*= 0*/) {
662 auto data
= Native::data
<MemcachedData
>(this_
);
663 return data
->setOperationImpl(memcached_set_by_key
, server_key
, key
, value
,
667 bool HHVM_METHOD(Memcached
, addbykey
, const String
& server_key
,
668 const String
& key
, const Variant
& value
,
669 int64_t expiration
/*= 0*/) {
670 auto data
= Native::data
<MemcachedData
>(this_
);
671 return data
->setOperationImpl(memcached_add_by_key
, server_key
, key
, value
,
675 bool HHVM_METHOD(Memcached
, appendbykey
, const String
& server_key
,
677 const String
& value
) {
678 auto data
= Native::data
<MemcachedData
>(this_
);
679 if (data
->m_impl
->compression
) {
680 raise_warning("cannot append/prepend with compression turned on");
683 return data
->setOperationImpl(memcached_append_by_key
, server_key
, key
,
687 bool HHVM_METHOD(Memcached
, prependbykey
, const String
& server_key
,
689 const String
& value
) {
690 auto data
= Native::data
<MemcachedData
>(this_
);
691 if (data
->m_impl
->compression
) {
692 raise_warning("cannot append/prepend with compression turned on");
695 return data
->setOperationImpl(memcached_prepend_by_key
, server_key
, key
,
699 bool HHVM_METHOD(Memcached
, replacebykey
, const String
& server_key
,
701 const Variant
& value
,
702 int64_t expiration
/*= 0*/) {
703 auto data
= Native::data
<MemcachedData
>(this_
);
704 return data
->setOperationImpl(memcached_replace_by_key
, server_key
, key
,
708 bool HHVM_METHOD(Memcached
, casbykey
, double cas_token
,
709 const String
& server_key
,
711 const Variant
& value
,
712 int64_t expiration
/*= 0*/) {
713 auto data
= Native::data
<MemcachedData
>(this_
);
714 data
->m_impl
->rescode
= MEMCACHED_SUCCESS
;
716 data
->m_impl
->rescode
= MEMCACHED_BAD_KEY_PROVIDED
;
720 std::vector
<char> payload
; uint32_t flags
;
721 data
->toPayload(value
, payload
, flags
);
723 const String
& myServerKey
= server_key
.empty() ? key
: server_key
;
724 return data
->handleError(memcached_cas_by_key(&data
->m_impl
->memcached
,
725 myServerKey
.c_str(), myServerKey
.length(), key
.c_str(), key
.length(),
726 payload
.data(), payload
.size(), expiration
, flags
, (uint64_t)cas_token
));
729 bool HHVM_METHOD(Memcached
, deletebykey
, const String
& server_key
,
731 int64_t time
/*= 0*/) {
732 auto data
= Native::data
<MemcachedData
>(this_
);
733 data
->m_impl
->rescode
= MEMCACHED_SUCCESS
;
735 data
->m_impl
->rescode
= MEMCACHED_BAD_KEY_PROVIDED
;
739 const String
& myServerKey
= server_key
.empty() ? key
: server_key
;
740 return data
->handleError(memcached_delete_by_key(&data
->m_impl
->memcached
,
741 myServerKey
.c_str(), myServerKey
.length(),
742 key
.c_str(), key
.length(), time
));
745 Variant
HHVM_METHOD(Memcached
, deletemultibykey
, const String
& server_key
,
747 int64_t time
/*= 0*/) {
748 auto data
= Native::data
<MemcachedData
>(this_
);
749 data
->m_impl
->rescode
= MEMCACHED_SUCCESS
;
751 memcached_return status_memcached
;
753 Array returnValue
= Array::CreateDict();
754 for (ArrayIter
iter(keys
); iter
; ++iter
) {
755 Variant vKey
= iter
.second();
756 if (!vKey
.isString()) continue;
757 const String
& key
= vKey
.toString();
758 if (key
.empty()) continue;
759 const String
& myServerKey
= server_key
.empty() ? key
: server_key
;
760 status_memcached
= memcached_delete_by_key(&data
->m_impl
->memcached
,
761 myServerKey
.c_str(), myServerKey
.length(),
762 key
.c_str(), key
.length(), time
);
764 status
= data
->handleError(status_memcached
);
766 returnValue
.set(key
, status_memcached
, true);
768 returnValue
.set(key
, status
, true);
774 Variant
HHVM_METHOD(Memcached
, increment
,
776 int64_t offset
/* = 1 */,
777 const Variant
& initial_value
/* = false */,
778 int64_t expiry
/* = 0 */) {
779 return Native::data
<MemcachedData
>(this_
)->incDecOp(
780 true, nullptr, key
.get(), offset
, initial_value
, expiry
);
783 Variant
HHVM_METHOD(Memcached
, incrementbykey
,
784 const String
& server_key
,
786 int64_t offset
/* = 1 */,
787 const Variant
& initial_value
/* = false */,
788 int64_t expiry
/* = 0 */) {
789 return Native::data
<MemcachedData
>(this_
)->incDecOp(
790 true, server_key
.get(), key
.get(), offset
, initial_value
, expiry
);
793 Variant
HHVM_METHOD(Memcached
, decrement
,
795 int64_t offset
/* = 1 */,
796 const Variant
& initial_value
/* = false */,
797 int64_t expiry
/* = 0 */) {
798 return Native::data
<MemcachedData
>(this_
)->incDecOp(
799 false, nullptr, key
.get(), offset
, initial_value
, expiry
);
802 Variant
HHVM_METHOD(Memcached
, decrementbykey
,
803 const String
& server_key
,
805 int64_t offset
/* = 1 */,
806 const Variant
& initial_value
/* = false */,
807 int64_t expiry
/* = 0 */) {
808 return Native::data
<MemcachedData
>(this_
)->incDecOp(
809 false, server_key
.get(), key
.get(), offset
, initial_value
, expiry
);
812 bool HHVM_METHOD(Memcached
, addserver
, const String
& host
, int64_t port
,
813 int64_t weight
/*= 0*/) {
814 auto data
= Native::data
<MemcachedData
>(this_
);
815 data
->m_impl
->rescode
= MEMCACHED_SUCCESS
;
816 if (!host
.empty() && host
[0] == '/') {
817 return data
->handleError(memcached_server_add_unix_socket_with_weight(
818 &data
->m_impl
->memcached
, host
.c_str(), weight
));
820 return data
->handleError(memcached_server_add_with_weight(
821 &data
->m_impl
->memcached
, host
.c_str(), port
, weight
828 const StaticString
s_host("host"), s_port("port");
829 #ifdef LMCD_SERVER_QUERY_INCLUDES_WEIGHT
830 const StaticString
s_weight("weight");
834 doServerListCallback(const memcached_st
* /*ptr*/,
835 LMCD_SERVER_CALLBACK_INSTANCE_TYPE server
, void* context
) {
836 Array
*returnValue
= (Array
*) context
;
837 const char* hostname
= LMCD_SERVER_HOSTNAME(server
);
838 in_port_t port
= LMCD_SERVER_PORT(server
);
839 #ifdef LMCD_SERVER_QUERY_INCLUDES_WEIGHT
840 returnValue
->append(make_dict_array(
841 s_host
, String(hostname
, CopyString
),
842 s_port
, (int32_t)port
,
843 s_weight
, (int32_t)server
->weight
846 returnValue
->append(make_dict_array(
847 s_host
, String(hostname
, CopyString
),
848 s_port
, (int32_t)port
851 return MEMCACHED_SUCCESS
;
855 Array
HHVM_METHOD(Memcached
, getserverlist
) {
856 auto data
= Native::data
<MemcachedData
>(this_
);
857 Array returnValue
= Array::CreateVec();
858 memcached_server_function callbacks
[] = { doServerListCallback
};
859 memcached_server_cursor(&data
->m_impl
->memcached
, callbacks
, &returnValue
, 1);
863 bool HHVM_METHOD(Memcached
, resetserverlist
) {
864 auto data
= Native::data
<MemcachedData
>(this_
);
865 memcached_servers_reset(&data
->m_impl
->memcached
);
869 Variant
HHVM_METHOD(Memcached
, getserverbykey
, const String
& server_key
) {
870 auto data
= Native::data
<MemcachedData
>(this_
);
871 data
->m_impl
->rescode
= MEMCACHED_SUCCESS
;
872 if (server_key
.empty()) {
873 data
->m_impl
->rescode
= MEMCACHED_BAD_KEY_PROVIDED
;
877 memcached_return_t error
;
878 LMCD_SERVER_BY_KEY_INSTANCE_TYPE server
= memcached_server_by_key(
879 &data
->m_impl
->memcached
, server_key
.c_str(), server_key
.size(), &error
);
881 data
->handleError(error
);
885 const char* hostname
= LMCD_SERVER_HOSTNAME(server
);
886 in_port_t port
= LMCD_SERVER_PORT(server
);
887 #ifdef LMCD_SERVER_QUERY_INCLUDES_WEIGHT
888 return make_dict_array(
889 s_host
, String(hostname
, CopyString
),
890 s_port
, (int32_t)port
,
891 s_weight
, (int32_t)server
->weight
894 return make_dict_array(
895 s_host
, String(hostname
, CopyString
),
896 s_port
, (int32_t)port
902 struct StatsContext
{
903 memcached_stat_st
*stats
;
910 s_threads("threads"),
912 s_pointer_size("pointer_size"),
913 s_rusage_user_seconds("rusage_user_seconds"),
914 s_rusage_user_microseconds("rusage_user_microseconds"),
915 s_rusage_system_seconds("rusage_system_seconds"),
916 s_rusage_system_microseconds("rusage_system_microseconds"),
917 s_curr_items("curr_items"),
918 s_total_items("total_items"),
919 s_limit_maxbytes("limit_maxbytes"),
920 s_curr_connections("curr_connections"),
921 s_total_connections("total_connections"),
922 s_connection_structures("connection_structures"),
924 s_cmd_get("cmd_get"),
925 s_cmd_set("cmd_set"),
926 s_get_hits("get_hits"),
927 s_get_misses("get_misses"),
928 s_evictions("evictions"),
929 s_bytes_read("bytes_read"),
930 s_bytes_written("bytes_written"),
931 s_version("version");
934 doStatsCallback(const memcached_st
* /*ptr*/,
935 LMCD_SERVER_CALLBACK_INSTANCE_TYPE server
, void* inContext
) {
936 StatsContext
*context
= (StatsContext
*) inContext
;
937 char key
[NI_MAXHOST
+ 6];
938 const char* hostname
= LMCD_SERVER_HOSTNAME(server
);
939 in_port_t port
= LMCD_SERVER_PORT(server
);
940 snprintf(key
, sizeof(key
), "%s:%d", hostname
, port
);
941 memcached_stat_st
*stats
= context
->stats
;
942 ssize_t i
= context
->returnValue
.size();
944 context
->returnValue
.set(String(key
, CopyString
),
946 s_pid
, (int64_t)stats
[i
].pid
,
947 s_uptime
, (int64_t)stats
[i
].uptime
,
948 s_threads
, (int64_t)stats
[i
].threads
,
949 s_time
, (int64_t)stats
[i
].time
,
950 s_pointer_size
, (int64_t)stats
[i
].pointer_size
,
951 s_rusage_user_seconds
, (int64_t)stats
[i
].rusage_user_seconds
,
952 s_rusage_user_microseconds
, (int64_t)stats
[i
]
953 .rusage_user_microseconds
,
954 s_rusage_system_seconds
, (int64_t)stats
[i
].rusage_system_seconds
,
955 s_rusage_system_microseconds
, (int64_t)stats
[i
]
956 .rusage_system_microseconds
,
957 s_curr_items
, (int64_t)stats
[i
].curr_items
,
958 s_total_items
, (int64_t)stats
[i
].total_items
,
959 s_limit_maxbytes
, (int64_t)stats
[i
].limit_maxbytes
,
960 s_curr_connections
, (int64_t)stats
[i
].curr_connections
,
961 s_total_connections
, (int64_t)stats
[i
].total_connections
,
962 s_connection_structures
, (int64_t)stats
[i
].connection_structures
,
963 s_bytes
, (int64_t)stats
[i
].bytes
,
964 s_cmd_get
, (int64_t)stats
[i
].cmd_get
,
965 s_cmd_set
, (int64_t)stats
[i
].cmd_set
,
966 s_get_hits
, (int64_t)stats
[i
].get_hits
,
967 s_get_misses
, (int64_t)stats
[i
].get_misses
,
968 s_evictions
, (int64_t)stats
[i
].evictions
,
969 s_bytes_read
, (int64_t)stats
[i
].bytes_read
,
970 s_bytes_written
, (int64_t)stats
[i
].bytes_written
,
971 s_version
, String(stats
[i
].version
, CopyString
)
975 return MEMCACHED_SUCCESS
;
979 Variant
HHVM_METHOD(Memcached
, getstats
) {
980 auto data
= Native::data
<MemcachedData
>(this_
);
981 memcached_return_t error
;
982 memcached_stat_st
*stats
= memcached_stat(&data
->m_impl
->memcached
,
985 data
->handleError(error
);
989 memcached_server_function callbacks
[] = { doStatsCallback
};
990 StatsContext context
; context
.stats
= stats
;
991 memcached_server_cursor(&data
->m_impl
->memcached
, callbacks
, &context
, 1);
993 memcached_stat_free(&data
->m_impl
->memcached
, stats
);
994 return context
.returnValue
;
999 doVersionCallback(const memcached_st
* /*ptr*/,
1000 LMCD_SERVER_CALLBACK_INSTANCE_TYPE server
, void* context
) {
1001 Array
*returnValue
= (Array
*) context
;
1002 char key
[NI_MAXHOST
+ 6], version
[16];
1004 const char* hostname
= LMCD_SERVER_HOSTNAME(server
);
1005 in_port_t port
= LMCD_SERVER_PORT(server
);
1006 uint8_t majorVersion
= LMCD_SERVER_MAJOR_VERSION(server
);
1007 uint8_t minorVersion
= LMCD_SERVER_MINOR_VERSION(server
);
1008 uint8_t microVersion
= LMCD_SERVER_MICRO_VERSION(server
);
1010 // libmemcached starting with 0.46 use UINT8_MAX as the default version, not 0
1011 #if defined(LIBMEMCACHED_VERSION_HEX) && LIBMEMCACHED_VERSION_HEX <= 0x00045000
1012 if (majorVersion
== 0 && minorVersion
== 0 && microVersion
== 0) {
1013 majorVersion
= UINT8_MAX
;
1014 minorVersion
= UINT8_MAX
;
1015 microVersion
= UINT8_MAX
;
1019 snprintf(key
, sizeof(key
), "%s:%d", hostname
, port
);
1020 snprintf(version
, sizeof(version
), "%" PRIu8
".%" PRIu8
".%" PRIu8
,
1021 majorVersion
, minorVersion
, microVersion
);
1022 returnValue
->set(String(key
, CopyString
), String(version
, CopyString
));
1023 return MEMCACHED_SUCCESS
;
1027 Variant
HHVM_METHOD(Memcached
, getversion
) {
1028 auto data
= Native::data
<MemcachedData
>(this_
);
1029 memcached_version(&data
->m_impl
->memcached
);
1031 Array returnValue
= Array::CreateDict();
1032 memcached_server_function callbacks
[] = { doVersionCallback
};
1033 memcached_server_cursor(&data
->m_impl
->memcached
, callbacks
, &returnValue
, 1);
1037 bool HHVM_METHOD(Memcached
, flush
, int64_t delay
/*= 0*/) {
1038 auto data
= Native::data
<MemcachedData
>(this_
);
1039 return data
->handleError(memcached_flush(&data
->m_impl
->memcached
, delay
));
1042 Variant
HHVM_METHOD(Memcached
, getoption
, int64_t option
) {
1043 auto data
= Native::data
<MemcachedData
>(this_
);
1045 case q_Memcached$$OPT_COMPRESSION
:
1046 return data
->m_impl
->compression
;
1048 case q_Memcached$$OPT_PREFIX_KEY
:
1050 memcached_return retval
;
1051 char *result
= (char*) memcached_callback_get(&data
->m_impl
->memcached
,
1052 MEMCACHED_CALLBACK_PREFIX_KEY
, &retval
);
1053 if (retval
== MEMCACHED_SUCCESS
&& result
) {
1054 return String(result
, CopyString
);
1056 else return empty_string_variant();
1059 case q_Memcached$$OPT_SERIALIZER
:
1060 return data
->m_impl
->serializer
;
1062 case MEMCACHED_BEHAVIOR_SOCKET_SEND_SIZE
:
1063 case MEMCACHED_BEHAVIOR_SOCKET_RECV_SIZE
:
1064 if (memcached_server_count(&data
->m_impl
->memcached
) == 0) {
1065 raise_warning("no servers defined");
1071 // Assume that it's a libmemcached behavior option
1072 return (int64_t) memcached_behavior_get(&data
->m_impl
->memcached
,
1073 (memcached_behavior_t
)option
);
1077 bool HHVM_METHOD(Memcached
, setoption
, int64_t option
, const Variant
& value
) {
1078 auto data
= Native::data
<MemcachedData
>(this_
);
1080 case q_Memcached$$OPT_COMPRESSION
:
1081 data
->m_impl
->compression
= value
.toBoolean();
1084 case q_Memcached$$OPT_PREFIX_KEY
:
1086 String sValue
= value
.toString();
1087 char *key
= const_cast<char*>(sValue
.empty() ? nullptr : sValue
.c_str());
1088 if (memcached_callback_set(&data
->m_impl
->memcached
,
1089 MEMCACHED_CALLBACK_PREFIX_KEY
, key
) == MEMCACHED_BAD_KEY_PROVIDED
) {
1090 raise_warning("bad key provided");
1096 case MEMCACHED_BEHAVIOR_KETAMA_WEIGHTED
:
1098 uint64_t lValue
= value
.toInt64();
1099 if (memcached_behavior_set(&data
->m_impl
->memcached
,
1100 MEMCACHED_BEHAVIOR_KETAMA_WEIGHTED
, lValue
) == MEMCACHED_FAILURE
) {
1101 raise_warning("error setting memcached option");
1105 /* This is necessary because libmemcached doesn't reset hash/distribution
1106 * options on false case, like it does for MEMCACHED_BEHAVIOR_KETAMA
1107 * (non-weighted) case. We have to clean up ourselves.
1110 memcached_behavior_set_key_hash(&data
->m_impl
->memcached
,
1111 MEMCACHED_HASH_DEFAULT
);
1112 memcached_behavior_set_distribution_hash(&data
->m_impl
->memcached
,
1113 MEMCACHED_HASH_DEFAULT
);
1114 memcached_behavior_set_distribution(&data
->m_impl
->memcached
,
1115 MEMCACHED_DISTRIBUTION_MODULA
);
1120 case q_Memcached$$OPT_SERIALIZER
:
1122 int iValue
= value
.toInt32(10);
1124 case q_Memcached$$SERIALIZER_PHP
:
1125 case q_Memcached$$SERIALIZER_JSON
:
1126 data
->m_impl
->serializer
= iValue
;
1129 data
->m_impl
->serializer
= q_Memcached$$SERIALIZER_PHP
;
1130 raise_warning("invalid serializer provided");
1138 if ((option
< 0) || (option
>= MEMCACHED_BEHAVIOR_MAX
)) {
1139 raise_warning("error setting memcached option");
1143 // Assume that it's a libmemcached behavior option
1144 uint64_t lValue
= value
.toInt64();
1145 if (memcached_behavior_set(&data
->m_impl
->memcached
,
1146 (memcached_behavior_t
)option
, lValue
) == MEMCACHED_FAILURE
) {
1147 raise_warning("error setting memcached option");
1156 int64_t HHVM_METHOD(Memcached
, getresultcode
) {
1157 auto data
= Native::data
<MemcachedData
>(this_
);
1158 return data
->m_impl
->rescode
;
1161 String
HHVM_METHOD(Memcached
, getresultmessage
) {
1162 auto data
= Native::data
<MemcachedData
>(this_
);
1163 if (data
->m_impl
->rescode
== q_Memcached$$RES_PAYLOAD_FAILURE
) {
1164 return "PAYLOAD FAILURE";
1166 return memcached_strerror(&data
->m_impl
->memcached
,
1167 (memcached_return_t
)data
->m_impl
->rescode
);
1171 bool HHVM_METHOD(Memcached
, ispersistent
) {
1172 auto data
= Native::data
<MemcachedData
>(this_
);
1173 return data
->m_impl
->is_persistent
;
1176 bool HHVM_METHOD(Memcached
, ispristine
) {
1177 auto data
= Native::data
<MemcachedData
>(this_
);
1178 return data
->m_impl
->is_pristine
;
1181 bool HHVM_METHOD(Memcached
, touchbykey
,
1182 ATTRIBUTE_UNUSED
const String
& server_key
,
1183 ATTRIBUTE_UNUSED
const String
& key
,
1184 ATTRIBUTE_UNUSED
int64_t expiration
/*= 0*/) {
1186 #ifndef HAVE_MEMCACHED_TOUCH
1187 throw_not_supported(__func__
, "Not Implemented in libmemcached versions below"
1191 auto data
= Native::data
<MemcachedData
>(this_
);
1192 data
->m_impl
->rescode
= MEMCACHED_SUCCESS
;
1194 data
->m_impl
->rescode
= MEMCACHED_BAD_KEY_PROVIDED
;
1198 #if defined(LIBMEMCACHED_VERSION_HEX) && LIBMEMCACHED_VERSION_HEX < 0x01000016
1199 if (memcached_behavior_get(&data
->m_impl
->memcached
,
1200 MEMCACHED_BEHAVIOR_BINARY_PROTOCOL
)) {
1201 raise_warning("using touch command with binary protocol is not "
1202 "recommended with libmemcached versions below 1.0.16");
1206 memcached_return_t status
;
1207 const String
& myServerKey
= server_key
.empty() ? key
: server_key
;
1208 status
= memcached_touch_by_key(&data
->m_impl
->memcached
,
1209 myServerKey
.c_str(), myServerKey
.length(),
1210 key
.c_str(), key
.length(), expiration
);
1212 if (!data
->handleError(status
)) return false;
1213 data
->m_impl
->rescode
= MEMCACHED_SUCCESS
;
1218 ///////////////////////////////////////////////////////////////////////////////
1220 RDS_LOCAL(MemcachedData::ImplMap
, MemcachedData::s_persistentMap
);
1222 const StaticString
s_Memcached("Memcached");
1224 struct MemcachedExtension final
: Extension
{
1225 MemcachedExtension() : Extension("memcached", "2.2.0b1") {}
1226 void threadInit() override
{
1227 *s_memcached_globals
= new MEMCACHEDGlobals
;
1228 assertx(*s_memcached_globals
);
1230 IniSetting::Bind(this, IniSetting::PHP_INI_ALL
,
1231 "memcached.sess_prefix", &MEMCACHEDG(sess_prefix
));
1234 void threadShutdown() override
{
1235 delete *s_memcached_globals
;
1236 *s_memcached_globals
= nullptr;
1239 void moduleInit() override
{
1240 HHVM_ME(Memcached
, __construct
);
1241 HHVM_ME(Memcached
, quit
);
1242 HHVM_ME(Memcached
, getallkeys
);
1243 HHVM_ME(Memcached
, getbykey
);
1244 HHVM_ME(Memcached
, getbykeywithcastoken
);
1245 HHVM_ME(Memcached
, getmultibykey
);
1246 HHVM_ME(Memcached
, getmultibykeywithcastokens
);
1247 HHVM_ME(Memcached
, getdelayedbykey
);
1248 HHVM_ME(Memcached
, fetch
);
1249 HHVM_ME(Memcached
, fetchall
);
1250 HHVM_ME(Memcached
, setbykey
);
1251 HHVM_ME(Memcached
, addbykey
);
1252 HHVM_ME(Memcached
, appendbykey
);
1253 HHVM_ME(Memcached
, prependbykey
);
1254 HHVM_ME(Memcached
, replacebykey
);
1255 HHVM_ME(Memcached
, casbykey
);
1256 HHVM_ME(Memcached
, deletebykey
);
1257 HHVM_ME(Memcached
, deletemultibykey
);
1258 HHVM_ME(Memcached
, increment
);
1259 HHVM_ME(Memcached
, incrementbykey
);
1260 HHVM_ME(Memcached
, decrement
);
1261 HHVM_ME(Memcached
, decrementbykey
);
1262 HHVM_ME(Memcached
, addserver
);
1263 HHVM_ME(Memcached
, getserverlist
);
1264 HHVM_ME(Memcached
, resetserverlist
);
1265 HHVM_ME(Memcached
, getserverbykey
);
1266 HHVM_ME(Memcached
, getstats
);
1267 HHVM_ME(Memcached
, getversion
);
1268 HHVM_ME(Memcached
, flush
);
1269 HHVM_ME(Memcached
, getoption
);
1270 HHVM_ME(Memcached
, setoption
);
1271 HHVM_ME(Memcached
, getresultcode
);
1272 HHVM_ME(Memcached
, getresultmessage
);
1273 HHVM_ME(Memcached
, ispersistent
);
1274 HHVM_ME(Memcached
, ispristine
);
1275 HHVM_ME(Memcached
, touchbykey
);
1277 Native::registerNativeDataInfo
<MemcachedData
>(s_MemcachedData
.get());
1279 HHVM_RCC_BOOL(Memcached
, HAVE_IGBINARY
, false);
1280 HHVM_RCC_BOOL(Memcached
, HAVE_JSON
, true);
1282 HHVM_RCC_INT(Memcached
, DISTRIBUTION_CONSISTENT
,
1283 MEMCACHED_DISTRIBUTION_CONSISTENT
);
1284 HHVM_RCC_INT(Memcached
, DISTRIBUTION_CONSISTENT_KETAMA
,
1285 MEMCACHED_DISTRIBUTION_CONSISTENT_KETAMA
);
1286 #ifdef MEMCACHED_DISTRIBUTION_CONSISTENT_WEIGHTED
1287 HHVM_RCC_INT(Memcached
, DISTRIBUTION_CONSISTENT_WEIGHTED
,
1288 MEMCACHED_DISTRIBUTION_CONSISTENT_WEIGHTED
);
1290 HHVM_RCC_INT(Memcached
, DISTRIBUTION_MODULA
, MEMCACHED_DISTRIBUTION_MODULA
);
1291 HHVM_RCC_INT(Memcached
, GET_PRESERVE_ORDER
,
1292 q_Memcached$$GET_PRESERVE_ORDER
);
1293 HHVM_RCC_INT(Memcached
, HASH_CRC
, MEMCACHED_HASH_CRC
);
1294 HHVM_RCC_INT(Memcached
, HASH_DEFAULT
, MEMCACHED_HASH_DEFAULT
);
1295 HHVM_RCC_INT(Memcached
, HASH_FNV1_32
, MEMCACHED_HASH_FNV1_32
);
1296 HHVM_RCC_INT(Memcached
, HASH_FNV1_64
, MEMCACHED_HASH_FNV1_64
);
1297 HHVM_RCC_INT(Memcached
, HASH_FNV1A_32
, MEMCACHED_HASH_FNV1A_32
);
1298 HHVM_RCC_INT(Memcached
, HASH_FNV1A_64
, MEMCACHED_HASH_FNV1A_64
);
1299 HHVM_RCC_INT(Memcached
, HASH_HSIEH
, MEMCACHED_HASH_HSIEH
);
1300 HHVM_RCC_INT(Memcached
, HASH_MD5
, MEMCACHED_HASH_MD5
);
1301 HHVM_RCC_INT(Memcached
, HASH_MURMUR
, MEMCACHED_HASH_MURMUR
);
1302 HHVM_RCC_INT(Memcached
, OPT_BINARY_PROTOCOL
,
1303 MEMCACHED_BEHAVIOR_BINARY_PROTOCOL
);
1304 HHVM_RCC_INT(Memcached
, OPT_BUFFER_WRITES
,
1305 MEMCACHED_BEHAVIOR_BUFFER_REQUESTS
);
1306 HHVM_RCC_INT(Memcached
, OPT_CACHE_LOOKUPS
,
1307 MEMCACHED_BEHAVIOR_CACHE_LOOKUPS
);
1308 HHVM_RCC_INT(Memcached
, OPT_COMPRESSION
, q_Memcached$$OPT_COMPRESSION
);
1309 HHVM_RCC_INT(Memcached
, OPT_CONNECT_TIMEOUT
,
1310 MEMCACHED_BEHAVIOR_CONNECT_TIMEOUT
);
1311 HHVM_RCC_INT(Memcached
, OPT_DISTRIBUTION
, MEMCACHED_BEHAVIOR_DISTRIBUTION
);
1312 HHVM_RCC_INT(Memcached
, OPT_HASH
, MEMCACHED_BEHAVIOR_HASH
);
1313 HHVM_RCC_INT(Memcached
, OPT_LIBKETAMA_COMPATIBLE
,
1314 MEMCACHED_BEHAVIOR_KETAMA_WEIGHTED
);
1315 HHVM_RCC_INT(Memcached
, OPT_LIBKETAMA_HASH
, MEMCACHED_BEHAVIOR_KETAMA_HASH
);
1316 HHVM_RCC_INT(Memcached
, OPT_NO_BLOCK
, MEMCACHED_BEHAVIOR_NO_BLOCK
);
1317 HHVM_RCC_INT(Memcached
, OPT_POLL_TIMEOUT
, MEMCACHED_BEHAVIOR_POLL_TIMEOUT
);
1318 HHVM_RCC_INT(Memcached
, OPT_PREFIX_KEY
, q_Memcached$$OPT_PREFIX_KEY
);
1319 HHVM_RCC_INT(Memcached
, OPT_HASH_WITH_PREFIX_KEY
,
1320 MEMCACHED_BEHAVIOR_HASH_WITH_PREFIX_KEY
);
1321 HHVM_RCC_INT(Memcached
, OPT_RECV_TIMEOUT
, MEMCACHED_BEHAVIOR_RCV_TIMEOUT
);
1322 HHVM_RCC_INT(Memcached
, OPT_RETRY_TIMEOUT
,
1323 MEMCACHED_BEHAVIOR_RETRY_TIMEOUT
);
1324 HHVM_RCC_INT(Memcached
, OPT_SEND_TIMEOUT
, MEMCACHED_BEHAVIOR_SND_TIMEOUT
);
1325 HHVM_RCC_INT(Memcached
, OPT_SERIALIZER
, q_Memcached$$OPT_SERIALIZER
);
1326 HHVM_RCC_INT(Memcached
, OPT_SERVER_FAILURE_LIMIT
,
1327 MEMCACHED_BEHAVIOR_SERVER_FAILURE_LIMIT
);
1328 HHVM_RCC_INT(Memcached
, OPT_SOCKET_RECV_SIZE
,
1329 MEMCACHED_BEHAVIOR_SOCKET_RECV_SIZE
);
1330 HHVM_RCC_INT(Memcached
, OPT_SOCKET_SEND_SIZE
,
1331 MEMCACHED_BEHAVIOR_SOCKET_SEND_SIZE
);
1332 HHVM_RCC_INT(Memcached
, OPT_TCP_NODELAY
, MEMCACHED_BEHAVIOR_TCP_NODELAY
);
1333 HHVM_RCC_INT(Memcached
, RES_BAD_KEY_PROVIDED
, MEMCACHED_BAD_KEY_PROVIDED
);
1334 HHVM_RCC_INT(Memcached
, RES_BUFFERED
, MEMCACHED_BUFFERED
);
1335 HHVM_RCC_INT(Memcached
, RES_CLIENT_ERROR
, MEMCACHED_CLIENT_ERROR
);
1336 HHVM_RCC_INT(Memcached
, RES_CONNECTION_SOCKET_CREATE_FAILURE
,
1337 MEMCACHED_CONNECTION_SOCKET_CREATE_FAILURE
);
1338 HHVM_RCC_INT(Memcached
, RES_DATA_EXISTS
, MEMCACHED_DATA_EXISTS
);
1339 HHVM_RCC_INT(Memcached
, RES_END
, MEMCACHED_END
);
1340 HHVM_RCC_INT(Memcached
, RES_ERRNO
, MEMCACHED_ERRNO
);
1341 HHVM_RCC_INT(Memcached
, RES_FAILURE
, MEMCACHED_FAILURE
);
1342 HHVM_RCC_INT(Memcached
, RES_HOST_LOOKUP_FAILURE
,
1343 MEMCACHED_HOST_LOOKUP_FAILURE
);
1344 HHVM_RCC_INT(Memcached
, RES_INVALID_HOST_PROTOCOL
,
1345 MEMCACHED_INVALID_HOST_PROTOCOL
);
1346 HHVM_RCC_INT(Memcached
, RES_NO_SERVERS
, MEMCACHED_NO_SERVERS
);
1347 HHVM_RCC_INT(Memcached
, RES_NOT_SUPPORTED
, MEMCACHED_NOT_SUPPORTED
);
1348 HHVM_RCC_INT(Memcached
, RES_NOTFOUND
, MEMCACHED_NOTFOUND
);
1349 HHVM_RCC_INT(Memcached
, RES_NOTSTORED
, MEMCACHED_NOTSTORED
);
1350 HHVM_RCC_INT(Memcached
, RES_PARTIAL_READ
, MEMCACHED_PARTIAL_READ
);
1351 HHVM_RCC_INT(Memcached
, RES_PAYLOAD_FAILURE
,
1352 q_Memcached$$RES_PAYLOAD_FAILURE
);
1353 HHVM_RCC_INT(Memcached
, RES_PROTOCOL_ERROR
, MEMCACHED_PROTOCOL_ERROR
);
1354 HHVM_RCC_INT(Memcached
, RES_SERVER_ERROR
, MEMCACHED_SERVER_ERROR
);
1355 HHVM_RCC_INT(Memcached
, RES_SOME_ERRORS
, MEMCACHED_SOME_ERRORS
);
1356 HHVM_RCC_INT(Memcached
, RES_SUCCESS
, MEMCACHED_SUCCESS
);
1357 HHVM_RCC_INT(Memcached
, RES_TIMEOUT
, MEMCACHED_TIMEOUT
);
1358 HHVM_RCC_INT(Memcached
, RES_UNKNOWN_READ_FAILURE
,
1359 MEMCACHED_UNKNOWN_READ_FAILURE
);
1360 HHVM_RCC_INT(Memcached
, RES_WRITE_FAILURE
, MEMCACHED_WRITE_FAILURE
);
1361 HHVM_RCC_INT(Memcached
, SERIALIZER_IGBINARY
,
1362 q_Memcached$$SERIALIZER_IGBINARY
);
1363 HHVM_RCC_INT(Memcached
, SERIALIZER_JSON
, q_Memcached$$SERIALIZER_JSON
);
1364 HHVM_RCC_INT(Memcached
, SERIALIZER_PHP
, q_Memcached$$SERIALIZER_PHP
);
1365 HHVM_RCC_INT(Memcached
, OPT_VERIFY_KEY
, MEMCACHED_BEHAVIOR_VERIFY_KEY
);
1366 HHVM_RCC_INT(Memcached
, OPT_SORT_HOSTS
, MEMCACHED_BEHAVIOR_SORT_HOSTS
);
1367 HHVM_RCC_INT(Memcached
, RES_SERVER_MARKED_DEAD
,
1368 MEMCACHED_SERVER_MARKED_DEAD
);
1369 #if defined(LIBMEMCACHED_VERSION_HEX) && LIBMEMCACHED_VERSION_HEX >= 0x00049000
1370 HHVM_RCC_INT(Memcached
, OPT_REMOVE_FAILED_SERVERS
,
1371 MEMCACHED_BEHAVIOR_REMOVE_FAILED_SERVERS
);
1373 #if defined(LIBMEMCACHED_VERSION_HEX) && LIBMEMCACHED_VERSION_HEX >= 0x01000003
1374 HHVM_RCC_INT(Memcached
, OPT_DEAD_TIMEOUT
, MEMCACHED_BEHAVIOR_DEAD_TIMEOUT
);
1376 HHVM_RCC_INT(Memcached
, RES_SERVER_TEMPORARILY_DISABLED
,
1377 MEMCACHED_SERVER_TEMPORARILY_DISABLED
);
1378 HHVM_RCC_INT(Memcached
, LIBMEMCACHED_VERSION_HEX
, LIBMEMCACHED_VERSION_HEX
);
1379 HHVM_RCC_BOOL(Memcached
, GET_ERROR_RETURN_VALUE
, false);
1384 } s_memcached_extension
;