6 #include "memcached_p.h"
8 #include <Cutelyst/Application>
9 #include <Cutelyst/Context>
10 #include <Cutelyst/Engine>
12 #include <QLoggingCategory>
13 #include <QStringList>
15 Q_LOGGING_CATEGORY(C_MEMCACHED,
"cutelyst.plugin.memcached", QtWarningMsg)
20 static thread_local
Memcached *mcd =
nullptr;
21 const time_t Memcached::expirationNotAdd{
static_cast<time_t
>(MEMCACHED_EXPIRATION_NOT_ADD)};
22 const std::chrono::seconds Memcached::expirationNotAddDuration{
23 static_cast<std::chrono::seconds::rep
>(MEMCACHED_EXPIRATION_NOT_ADD)};
27 , d_ptr(new MemcachedPrivate)
31 Memcached::Memcached(
Application *parent,
const QVariantMap &defaultConfig)
33 , d_ptr(new MemcachedPrivate(defaultConfig))
37 Memcached::~Memcached() =
default;
39 void Memcached::setDefaultConfig(
const QVariantMap &defaultConfig)
42 d->defaultConfig = defaultConfig;
49 d->loadedConfig = app->
engine()->
config(u
"Cutelyst_Memcached_Plugin"_qs);
52 const QStringList serverList = d->config(u
"servers"_qs).toString().split(u
';');
54 if (serverList.
empty()) {
55 memcConfig.
push_back(u
"--SERVER=localhost"_qs);
58 for (
const QString &flag : {u
"verify_key"_qs,
59 u
"remove_failed_servers"_qs,
60 u
"binary_protocol"_qs,
61 u
"buffer_requests"_qs,
62 u
"hash_with_namespace"_qs,
64 u
"randomize_replica_read"_qs,
69 u
"tcp_keepalive"_qs}) {
70 if (d->config(flag,
false).toBool()) {
76 const bool useUDP = d->config(u
"use_udp"_qs,
false).toBool();
79 u
"connect_timeout"_qs,
82 u
"number_of_replicas"_qs,
85 u
"server_failure_limit"_qs,
87 u
"socket_recv_size"_qs,
88 u
"socket_send_size"_qs,
90 u
"io_bytes_watermark"_qs,
91 u
"io_key_prefetch"_qs,
92 u
"io_msg_watermark"_qs,
95 const QString _val = d->config(opt).toString();
106 qCInfo(C_MEMCACHED) <<
"Setting up connection to memcached servers using libmemcached"
107 << memcached_lib_version()
108 <<
"with the following configuration string:" << configString;
110 memcached_st *new_memc = memcached(configString.
constData(), configString.
size());
114 if (!serverList.
empty()) {
115 for (
const QString &server : serverList) {
118 uint16_t port = MemcachedPrivate::defaultPort;
120 bool isSocket =
false;
121 if (!serverParts.empty()) {
122 const auto part0 = serverParts.
at(0);
123 if (!part0.isEmpty()) {
124 name = part0.toString();
127 if (serverParts.size() > 1) {
128 const auto part1 = serverParts.at(1);
129 if (!part1.isEmpty()) {
131 weight = part1.toUInt();
133 port = part1.toUInt();
136 if (!isSocket && (serverParts.size() > 2)) {
137 const auto part2 = serverParts.at(2);
138 if (!part2.isEmpty()) {
139 weight = part2.toUInt();
145 memcached_return_t rc{MEMCACHED_FAILURE};
147 rc = memcached_server_add_unix_socket_with_weight(
149 if (Q_LIKELY(memcached_success(rc))) {
150 qCInfo(C_MEMCACHED) <<
"Added memcached server on socket" << name
151 <<
"with weight" << weight;
153 qCWarning(C_MEMCACHED).nospace()
154 <<
"Failed to add memcached server on socket " << name
155 <<
" with weight " << weight <<
": "
156 << memcached_strerror(new_memc, rc);
160 rc = memcached_server_add_udp_with_weight(
163 rc = memcached_server_add_with_weight(
166 if (Q_LIKELY(memcached_success(rc))) {
167 qCInfo(C_MEMCACHED).nospace().noquote()
168 <<
"Added memcached server on host " << name <<
":" << port
169 <<
" with weight" << weight;
171 qCWarning(C_MEMCACHED).nospace().noquote()
172 <<
"Failed to add memcached server no host " << name <<
":" << port
173 <<
" with weight " << weight <<
": "
174 << memcached_strerror(new_memc, rc);
180 if (Q_UNLIKELY(memcached_server_count(new_memc) == 0)) {
181 qCWarning(C_MEMCACHED)
182 <<
"Failed to add any memcached server. Adding default server on localhost"
184 memcached_return_t rc =
185 memcached_server_add(new_memc,
"localhost", MemcachedPrivate::defaultPort);
186 if (Q_UNLIKELY(!memcached_success(rc))) {
187 qCCritical(C_MEMCACHED)
188 <<
"Failed to add default memcached server. Memcached plugin will not"
189 <<
"work without a configured server!" << memcached_strerror(new_memc, rc);
190 memcached_free(new_memc);
196 d->compression = d->config(u
"compression"_qs,
false).toBool();
197 d->compressionLevel = d->config(u
"compression_level"_qs, -1).toInt();
198 d->compressionThreshold =
199 d->config(u
"compression_threshold"_qs, MemcachedPrivate::defaultCompressionThreshold)
201 if (d->compression) {
202 qCInfo(C_MEMCACHED).nospace()
203 <<
"Compression: enabled (Compression level: " << d->compressionLevel
204 <<
", Compression threshold: " << d->compressionThreshold <<
" bytes";
206 qCInfo(C_MEMCACHED) <<
"Compression: disabled";
209 const QString encKey = d->config(u
"encryption_key"_qs).toString();
212 const memcached_return_t rt =
213 memcached_set_encoding_key(new_memc, encKeyBa.
constData(), encKeyBa.
size());
214 if (Q_LIKELY(memcached_success(rt))) {
215 qCInfo(C_MEMCACHED) <<
"Encryption: enabled";
217 qCWarning(C_MEMCACHED)
218 <<
"Failed to enable encryption:" << memcached_strerror(new_memc, rt);
221 qCInfo(C_MEMCACHED) <<
"Encryption: disabled";
224 #ifdef LIBMEMCACHED_WITH_SASL_SUPPORT
225 # if LIBMEMCACHED_WITH_SASL_SUPPORT == 1
226 const QString saslUser = d->config(u
"sasl_user"_qs).toString();
227 const QString saslPass = d->config(u
"sasl_password"_qs).toString();
229 const memcached_return_t rt = memcached_set_sasl_auth_data(
231 if (Q_LIKELY(memcached_success(rt))) {
232 qCInfo(C_MEMCACHED) <<
"SASL authentication: enabled";
233 d->saslEnabled =
true;
235 qCWarning(C_MEMCACHED)
236 <<
"Failed to enable SASL authentication:" << memcached_strerror(new_memc, rt);
239 qCInfo(C_MEMCACHED) <<
"SASL authentication: disabled";
245 memcached_free(d->memc);
255 qCCritical(C_MEMCACHED) <<
"Failed to configure the connection to the memcached server(s)";
264 ReturnType *returnType)
266 if (!MemcachedPrivate::isRegistered(mcd, returnType)) {
270 MemcachedPrivate::Flags flags;
271 const QByteArray _value = MemcachedPrivate::compressIfNeeded(value, flags);
273 const memcached_return_t rt = memcached_set(mcd->d_ptr->memc,
281 const bool ok = memcached_success(rt);
284 qCWarning(C_MEMCACHED).nospace()
285 <<
"Failed to store key " << key <<
": " << memcached_strerror(mcd->d_ptr->memc, rt);
288 MemcachedPrivate::setReturnType(returnType, rt);
297 ReturnType *returnType)
299 if (!MemcachedPrivate::isRegistered(mcd, returnType)) {
303 MemcachedPrivate::Flags flags;
304 const QByteArray _value = MemcachedPrivate::compressIfNeeded(value, flags);
306 const memcached_return_t rt = memcached_set_by_key(mcd->d_ptr->memc,
316 const bool ok = memcached_success(rt);
319 qCWarning(C_MEMCACHED).nospace()
320 <<
"Failed to store key " << key <<
" on group " << groupKey <<
": "
321 << memcached_strerror(mcd->d_ptr->memc, rt);
324 MemcachedPrivate::setReturnType(returnType, rt);
332 ReturnType *returnType)
334 if (!MemcachedPrivate::isRegistered(mcd, returnType)) {
338 MemcachedPrivate::Flags flags;
339 const QByteArray _value = MemcachedPrivate::compressIfNeeded(value, flags);
341 const memcached_return_t rt = memcached_add(mcd->d_ptr->memc,
349 const bool ok = memcached_success(rt);
351 if (!ok && (rt != MEMCACHED_NOTSTORED)) {
352 qCWarning(C_MEMCACHED).nospace()
353 <<
"Failed to add key " << key <<
": " << memcached_strerror(mcd->d_ptr->memc, rt);
356 MemcachedPrivate::setReturnType(returnType, rt);
365 ReturnType *returnType)
367 if (!MemcachedPrivate::isRegistered(mcd, returnType)) {
371 MemcachedPrivate::Flags flags;
372 const QByteArray _value = MemcachedPrivate::compressIfNeeded(value, flags);
374 const memcached_return_t rt = memcached_add_by_key(mcd->d_ptr->memc,
384 const bool ok = memcached_success(rt);
386 if (!ok && (rt != MEMCACHED_NOTSTORED)) {
387 qCWarning(C_MEMCACHED).nospace() <<
"Failed to add key " << key <<
" on group " << groupKey
388 <<
": " << memcached_strerror(mcd->d_ptr->memc, rt);
391 MemcachedPrivate::setReturnType(returnType, rt);
399 ReturnType *returnType)
401 if (!MemcachedPrivate::isRegistered(mcd, returnType)) {
405 MemcachedPrivate::Flags flags;
406 const QByteArray _value = MemcachedPrivate::compressIfNeeded(value, flags);
408 const memcached_return_t rt = memcached_replace(mcd->d_ptr->memc,
416 const bool ok = memcached_success(rt);
418 if (!ok && (rt != MEMCACHED_NOTSTORED)) {
419 qCWarning(C_MEMCACHED).nospace()
420 <<
"Failed to replace key " << key <<
": " << memcached_strerror(mcd->d_ptr->memc, rt);
423 MemcachedPrivate::setReturnType(returnType, rt);
432 ReturnType *returnType)
434 if (!MemcachedPrivate::isRegistered(mcd, returnType)) {
438 MemcachedPrivate::Flags flags;
439 const QByteArray _value = MemcachedPrivate::compressIfNeeded(value, flags);
441 const memcached_return_t rt = memcached_replace_by_key(mcd->d_ptr->memc,
451 const bool ok = memcached_success(rt);
453 if (!ok && (rt != MEMCACHED_NOTSTORED)) {
454 qCWarning(C_MEMCACHED).nospace()
455 <<
"Failed to replace key " << key <<
" on group " << groupKey <<
": "
456 << memcached_strerror(mcd->d_ptr->memc, rt);
459 MemcachedPrivate::setReturnType(returnType, rt);
468 if (!MemcachedPrivate::isRegistered(mcd, returnType)) {
472 memcached_return_t rt{MEMCACHED_FAILURE};
475 std::vector<const char *> keys;
476 std::vector<size_t> sizes;
478 sizes.push_back(key.
size());
479 rt = memcached_mget(mcd->d_ptr->memc, &keys[0], &sizes[0], keys.size());
481 if (memcached_success(rt)) {
482 memcached_result_st *result = memcached_fetch_result(mcd->d_ptr->memc,
nullptr, &rt);
486 static_cast<QByteArray::size_type
>(memcached_result_length(result)));
488 *cas = memcached_result_cas(result);
490 retData = MemcachedPrivate::uncompressIfNeeded(retData, result);
494 memcached_fetch_result(mcd->d_ptr->memc,
nullptr,
nullptr);
496 memcached_result_free(result);
499 if (!ok && (rt != MEMCACHED_NOTFOUND)) {
500 qCWarning(C_MEMCACHED).nospace() <<
"Failed to get data for key " << key <<
": "
501 << memcached_strerror(mcd->d_ptr->memc, rt);
504 MemcachedPrivate::setReturnType(returnType, rt);
512 ReturnType *returnType)
516 if (!MemcachedPrivate::isRegistered(mcd, returnType)) {
522 std::vector<const char *> keys;
523 std::vector<size_t> sizes;
525 sizes.push_back(key.
size());
526 memcached_return_t rt = memcached_mget_by_key(
527 mcd->d_ptr->memc, groupKey.
constData(), groupKey.
size(), &keys[0], &sizes[0], keys.size());
529 if (memcached_success(rt)) {
530 memcached_result_st *result = memcached_fetch_result(mcd->d_ptr->memc,
nullptr, &rt);
534 static_cast<QByteArray::size_type
>(memcached_result_length(result)));
536 *cas = memcached_result_cas(result);
538 retData = MemcachedPrivate::uncompressIfNeeded(retData, result);
542 memcached_fetch_result(mcd->d_ptr->memc,
nullptr,
nullptr);
544 memcached_result_free(result);
547 if (!ok && (rt != MEMCACHED_NOTFOUND)) {
548 qCWarning(C_MEMCACHED).nospace()
549 <<
"Failed to get data for key " << key <<
" on group " << groupKey <<
": "
550 << memcached_strerror(mcd->d_ptr->memc, rt);
553 MemcachedPrivate::setReturnType(returnType, rt);
558 bool Memcached::remove(
QByteArrayView key, ReturnType *returnType)
560 if (!MemcachedPrivate::isRegistered(mcd, returnType)) {
564 const memcached_return_t rt =
565 memcached_delete(mcd->d_ptr->memc, key.
constData(), key.
size(), 0);
567 const bool ok = memcached_success(rt);
569 if (!ok && (rt != MEMCACHED_NOTFOUND)) {
570 qCWarning(C_MEMCACHED).nospace() <<
"Failed to remove data for key " << key <<
": "
571 << memcached_strerror(mcd->d_ptr->memc, rt);
574 MemcachedPrivate::setReturnType(returnType, rt);
581 if (!MemcachedPrivate::isRegistered(mcd, returnType)) {
585 const memcached_return_t rt = memcached_delete_by_key(
588 const bool ok = memcached_success(rt);
590 if (!ok && (rt != MEMCACHED_NOTFOUND)) {
591 qCWarning(C_MEMCACHED).nospace()
592 <<
"Failed to remove data for key " << key <<
" on group " << groupKey <<
": "
593 << memcached_strerror(mcd->d_ptr->memc, rt);
596 MemcachedPrivate::setReturnType(returnType, rt);
603 if (!MemcachedPrivate::isRegistered(mcd, returnType)) {
607 const memcached_return_t rt = memcached_exist(mcd->d_ptr->memc, key.
constData(), key.
size());
609 const bool ok = memcached_success(rt);
611 if (!ok && (rt != MEMCACHED_NOTFOUND)) {
612 qCWarning(C_MEMCACHED).nospace() <<
"Failed to check existence of key " << key <<
": "
613 << memcached_strerror(mcd->d_ptr->memc, rt);
616 MemcachedPrivate::setReturnType(returnType, rt);
623 if (!MemcachedPrivate::isRegistered(mcd, returnType)) {
627 const memcached_return_t rt = memcached_exist_by_key(
630 const bool ok = memcached_success(rt);
632 if (!ok && (rt != MEMCACHED_NOTFOUND)) {
633 qCWarning(C_MEMCACHED).nospace()
634 <<
"Failed to check existence of key " << key <<
" in group " << groupKey <<
": "
635 << memcached_strerror(mcd->d_ptr->memc, rt);
638 MemcachedPrivate::setReturnType(returnType, rt);
646 ReturnType *returnType)
648 if (!MemcachedPrivate::isRegistered(mcd, returnType)) {
652 const memcached_return_t rt =
653 memcached_increment(mcd->d_ptr->memc, key.
constData(), key.
size(), offset, value);
655 const bool ok = memcached_success(rt);
657 if (!ok && (rt != MEMCACHED_NOTFOUND)) {
658 qCWarning(C_MEMCACHED).nospace() <<
"Failed to increment key " << key <<
" by " << offset
659 <<
": " << memcached_strerror(mcd->d_ptr->memc, rt);
662 MemcachedPrivate::setReturnType(returnType, rt);
671 ReturnType *returnType)
673 if (!MemcachedPrivate::isRegistered(mcd, returnType)) {
677 const memcached_return_t rt = memcached_increment_by_key(mcd->d_ptr->memc,
685 const bool ok = memcached_success(rt);
687 if (!ok && (rt != MEMCACHED_NOTFOUND)) {
688 qCWarning(C_MEMCACHED).nospace()
689 <<
"Failed to increment key " << key <<
" in group " << groupKey <<
" by " << offset
690 <<
": " << memcached_strerror(mcd->d_ptr->memc, rt);
693 MemcachedPrivate::setReturnType(returnType, rt);
703 ReturnType *returnType)
705 if (!MemcachedPrivate::isRegistered(mcd, returnType)) {
709 const memcached_return_t rt = memcached_increment_with_initial(
710 mcd->d_ptr->memc, key.
constData(), key.
size(), offset, initial, expiration, value);
712 const bool ok = memcached_success(rt);
715 qCWarning(C_MEMCACHED).nospace()
716 <<
"Failed to increment or initialize key " << key <<
" by offset " << offset
717 <<
" or initial " << initial <<
": " << memcached_strerror(mcd->d_ptr->memc, rt);
720 MemcachedPrivate::setReturnType(returnType, rt);
725 bool Memcached::incrementWithInitialByKey(
QByteArrayView groupKey,
731 ReturnType *returnType)
733 if (!MemcachedPrivate::isRegistered(mcd, returnType)) {
737 const memcached_return_t rt = memcached_increment_with_initial_by_key(mcd->d_ptr->memc,
747 const bool ok = memcached_success(rt);
749 qCWarning(C_MEMCACHED).nospace()
750 <<
"Failed to increment or initializes key " << key <<
" in group " << groupKey
751 <<
" by offset " << offset <<
" or initial " << initial <<
": "
752 << memcached_strerror(mcd->d_ptr->memc, rt);
755 MemcachedPrivate::setReturnType(returnType, rt);
763 ReturnType *returnType)
765 if (!MemcachedPrivate::isRegistered(mcd, returnType)) {
769 const memcached_return_t rt =
770 memcached_decrement(mcd->d_ptr->memc, key.
constData(), key.
size(), offset, value);
772 const bool ok = memcached_success(rt);
774 if (!ok && (rt != MEMCACHED_NOTFOUND)) {
775 qCWarning(C_MEMCACHED).nospace() <<
"Failed to decrement key " << key <<
" by " << offset
776 <<
": " << memcached_strerror(mcd->d_ptr->memc, rt);
779 MemcachedPrivate::setReturnType(returnType, rt);
788 ReturnType *returnType)
790 if (!MemcachedPrivate::isRegistered(mcd, returnType)) {
794 const memcached_return_t rt = memcached_decrement_by_key(mcd->d_ptr->memc,
802 const bool ok = memcached_success(rt);
804 if (!ok && (rt != MEMCACHED_NOTFOUND)) {
805 qCWarning(C_MEMCACHED).nospace()
806 <<
"Failed to decrement key " << key <<
" in group " << groupKey <<
" by " << offset
807 <<
": " << memcached_strerror(mcd->d_ptr->memc, rt);
810 MemcachedPrivate::setReturnType(returnType, rt);
820 ReturnType *returnType)
822 if (!MemcachedPrivate::isRegistered(mcd, returnType)) {
826 const memcached_return_t rt = memcached_decrement_with_initial(
827 mcd->d_ptr->memc, key.
constData(), key.
size(), offset, initial, expiration, value);
829 const bool ok = memcached_success(rt);
832 qCWarning(C_MEMCACHED).nospace()
833 <<
"Failed to decrement of initialize key " << key <<
" by offset " << offset
834 <<
" or initialize " << initial <<
": " << memcached_strerror(mcd->d_ptr->memc, rt);
837 MemcachedPrivate::setReturnType(returnType, rt);
842 bool Memcached::decrementWithInitialByKey(
QByteArrayView groupKey,
848 ReturnType *returnType)
850 if (!MemcachedPrivate::isRegistered(mcd, returnType)) {
854 const memcached_return_t rt = memcached_decrement_with_initial_by_key(mcd->d_ptr->memc,
864 const bool ok = memcached_success(rt);
866 qCWarning(C_MEMCACHED).nospace()
867 <<
"Failed to decrement or initialize key " << key <<
" in group " << groupKey
868 <<
" by offset " << offset <<
" or initial " << initial <<
": "
869 << memcached_strerror(mcd->d_ptr->memc, rt);
872 MemcachedPrivate::setReturnType(returnType, rt);
881 ReturnType *returnType)
883 if (!MemcachedPrivate::isRegistered(mcd, returnType)) {
887 MemcachedPrivate::Flags flags;
888 const QByteArray _value = MemcachedPrivate::compressIfNeeded(value, flags);
890 const memcached_return_t rt = memcached_cas(mcd->d_ptr->memc,
899 const bool ok = memcached_success(rt);
901 if (!ok && (rt != MEMCACHED_DATA_EXISTS)) {
902 qCWarning(C_MEMCACHED).nospace() <<
"Failed to compare and set (cas) key " << key <<
": "
903 << memcached_strerror(mcd->d_ptr->memc, rt);
906 MemcachedPrivate::setReturnType(returnType, rt);
916 ReturnType *returnType)
918 if (!MemcachedPrivate::isRegistered(mcd, returnType)) {
922 MemcachedPrivate::Flags flags;
923 const QByteArray _value = MemcachedPrivate::compressIfNeeded(value, flags);
925 const memcached_return_t rt = memcached_cas_by_key(mcd->d_ptr->memc,
936 const bool ok = memcached_success(rt);
938 if (!ok && (rt != MEMCACHED_DATA_EXISTS)) {
939 qCWarning(C_MEMCACHED).nospace()
940 <<
"Failed to compare and set (cas) key " << key <<
" in group " << groupKey <<
": "
941 << memcached_strerror(mcd->d_ptr->memc, rt);
944 MemcachedPrivate::setReturnType(returnType, rt);
949 bool Memcached::flushBuffers(ReturnType *returnType)
951 if (!MemcachedPrivate::isRegistered(mcd, returnType)) {
955 const memcached_return_t rt = memcached_flush_buffers(mcd->d_ptr->memc);
957 const bool ok = memcached_success(rt);
960 qCWarning(C_MEMCACHED) <<
"Failed to flush buffers:"
961 << memcached_strerror(mcd->d_ptr->memc, rt);
964 MemcachedPrivate::setReturnType(returnType, rt);
969 bool Memcached::flush(time_t expiration, ReturnType *returnType)
971 if (!MemcachedPrivate::isRegistered(mcd, returnType)) {
975 const memcached_return_t rt = memcached_flush(mcd->d_ptr->memc, expiration);
977 const bool ok = memcached_success(rt);
980 qCWarning(C_MEMCACHED) <<
"Failed to wipe (flush) server content:"
981 << memcached_strerror(mcd->d_ptr->memc, rt);
984 MemcachedPrivate::setReturnType(returnType, rt);
991 ReturnType *returnType)
995 if (!MemcachedPrivate::isRegistered(mcd, returnType)) {
1000 qCWarning(C_MEMCACHED) <<
"Can not get multiple values without a list of keys.";
1002 *returnType = ReturnType::BadKeyProvided;
1007 std::vector<const char *> _keys;
1009 std::vector<size_t> _keysSizes;
1010 _keysSizes.reserve(keys.
size());
1012 for (
const auto &key : keys) {
1013 _keys.push_back(key.
data());
1014 _keysSizes.push_back(key.
size());
1019 memcached_return_t rt =
1020 memcached_mget(mcd->d_ptr->memc, &_keys[0], &_keysSizes[0], _keys.size());
1022 if (memcached_success(rt)) {
1025 while ((rt != MEMCACHED_END) && (rt != MEMCACHED_NOTFOUND)) {
1026 memcached_result_st *result = memcached_fetch_result(mcd->d_ptr->memc,
nullptr, &rt);
1029 QByteArray(memcached_result_key_value(result),
1030 static_cast<qsizetype
>(memcached_result_key_length(result)));
1031 QByteArray rd(memcached_result_value(result),
1032 static_cast<qsizetype
>(memcached_result_length(result)));
1034 casValues->
insert(rk, memcached_result_cas(result));
1036 rd = MemcachedPrivate::uncompressIfNeeded(rd, result);
1039 memcached_result_free(result);
1044 qCWarning(C_MEMCACHED) <<
"Failed to get values for multiple keys:"
1045 << memcached_strerror(mcd->d_ptr->memc, rt);
1048 MemcachedPrivate::setReturnType(returnType, rt);
1056 ReturnType *returnType)
1060 if (!MemcachedPrivate::isRegistered(mcd, returnType)) {
1065 qCWarning(C_MEMCACHED)
1066 <<
"Can not get multiple values from specific server when groupKey is empty.";
1068 *returnType = ReturnType::BadKeyProvided;
1074 qCWarning(C_MEMCACHED) <<
"Can not get multiple values without a list of keys.";
1076 *returnType = ReturnType::BadKeyProvided;
1081 std::vector<const char *> _keys;
1083 std::vector<size_t> _keysSizes;
1084 _keysSizes.reserve(keys.
size());
1086 for (
const auto &key : keys) {
1087 _keys.push_back(key.
data());
1088 _keysSizes.push_back(key.
size());
1093 memcached_return_t rt = memcached_mget_by_key(mcd->d_ptr->memc,
1100 if (memcached_success(rt)) {
1103 while ((rt != MEMCACHED_END) && (rt != MEMCACHED_NOTFOUND)) {
1104 memcached_result_st *result = memcached_fetch_result(mcd->d_ptr->memc,
nullptr, &rt);
1107 QByteArray(memcached_result_key_value(result),
1108 static_cast<qsizetype
>(memcached_result_key_length(result)));
1109 QByteArray rd(memcached_result_value(result),
1110 static_cast<qsizetype
>(memcached_result_length(result)));
1112 casValues->
insert(rk, memcached_result_cas(result));
1114 rd = MemcachedPrivate::uncompressIfNeeded(rd, result);
1117 memcached_result_free(result);
1122 qCWarning(C_MEMCACHED).nospace()
1123 <<
"Failed to get values for multiple keys in group " << groupKey <<
": "
1124 << memcached_strerror(mcd->d_ptr->memc, rt);
1127 MemcachedPrivate::setReturnType(returnType, rt);
1132 bool Memcached::touch(
QByteArrayView key, time_t expiration, ReturnType *returnType)
1134 if (!MemcachedPrivate::isRegistered(mcd, returnType)) {
1138 const memcached_return_t rt =
1139 memcached_touch(mcd->d_ptr->memc, key.
constData(), key.
size(), expiration);
1141 const bool ok = memcached_success(rt);
1144 qCWarning(C_MEMCACHED).nospace()
1145 <<
"Failed to touch key " << key <<
" with new expiration time " << expiration
1146 <<
" seconds: " << memcached_strerror(mcd->d_ptr->memc, rt);
1149 MemcachedPrivate::setReturnType(returnType, rt);
1157 ReturnType *returnType)
1159 if (!MemcachedPrivate::isRegistered(mcd, returnType)) {
1163 const memcached_return_t rt = memcached_touch_by_key(mcd->d_ptr->memc,
1170 const bool ok = memcached_success(rt);
1173 qCWarning(C_MEMCACHED).nospace()
1174 <<
"Failed to touch key " << key <<
" in group " << groupKey
1175 <<
" with new expiration time " << expiration
1176 <<
" seconds: " << memcached_strerror(mcd->d_ptr->memc, rt);
1179 MemcachedPrivate::setReturnType(returnType, rt);
1187 using enum Memcached::ReturnType;
1190 return c->
qtTrId(
"cutelyst-memc-rt-success");
1193 return c->
qtTrId(
"cutelyst-memc-rt-failure");
1194 case HostLookupFailure:
1196 return c->
qtTrId(
"cutelyst-memc-rt-hostlookupfailure");
1197 case ConnectionFailure:
1199 return c->
qtTrId(
"cutelyst-memc-rt-connectionfailure");
1202 return c->
qtTrId(
"cutelyst-memc-rt-writefailure");
1205 return c->
qtTrId(
"cutelyst-memc-rt-readfailure");
1206 case UnknownReadFailure:
1210 return c->
qtTrId(
"cutelyst-memc-rt-unknownreadfailure");
1213 return c->
qtTrId(
"cutelyst-memc-rt-protocolerror");
1216 return c->
qtTrId(
"cutelyst-memc-rt-clienterror");
1219 return c->
qtTrId(
"cutelyst-memc-rt-servererror");
1222 return c->
qtTrId(
"cutelyst-memc-rt-error");
1225 return c->
qtTrId(
"cutelyst-memc-rt-dataexists");
1226 case DataDoesNotExist:
1228 return c->
qtTrId(
"cutelyst-memc-rt-datadoesnotexist");
1231 return c->
qtTrId(
"cutelyst-memc-rt-notstored");
1234 return c->
qtTrId(
"cutelyst-memc-rt-stored");
1237 return c->
qtTrId(
"cutelyst-memc-notfound");
1238 case MemoryAllocationFailure:
1240 return c->
qtTrId(
"cutelyst-memc-rt-memallocfailure");
1243 return c->
qtTrId(
"cutelyst-memc-rt-partread");
1247 return c->
qtTrId(
"cutelyst-memc-rt-someerrors");
1250 return c->
qtTrId(
"cutelyst-memc-rt-noservers");
1253 return c->
qtTrId(
"cutelyst-memc-rt-end");
1256 return c->
qtTrId(
"cutelyst-memc-rt-deleted");
1259 return c->
qtTrId(
"cutelyst-memc-rt-stat");
1262 return qtTrId(
"cutelyst-memc-rt-errno");
1265 return c->
qtTrId(
"cutelyst-memc-rt-notsupported");
1266 case FetchNotFinished:
1269 return c->
qtTrId(
"cutelyst-memc-rt-fetchnotfinished");
1272 return c->
qtTrId(
"cutelyst-memc-rt-timeout");
1275 return c->
qtTrId(
"cutelyst-memc-rt-buffered");
1276 case BadKeyProvided:
1278 return c->
qtTrId(
"cutelyst-memc-rt-badkeyprov");
1279 case InvalidHostProtocol:
1282 return c->
qtTrId(
"cutelyst-memc-rt-invalidhostprot");
1283 case ServerMarkedDead:
1285 return c->
qtTrId(
"cutelyst-memc-rt-servermarkeddead");
1286 case UnknownStatKey:
1289 return c->
qtTrId(
"cutelyst-memc-rt-unknownstatkey");
1292 return c->
qtTrId(
"cutelyst-memc-rt-e2big");
1293 case InvalidArguments:
1295 return c->
qtTrId(
"cutelyst-memc-rt-invalidarg");
1298 return c->
qtTrId(
"cutelyst-memc-rt-key2big");
1301 return c->
qtTrId(
"cutelyst-memc-rt-authproblem");
1304 return c->
qtTrId(
"cutelyst-memc-rt-authfailure");
1307 return c->
qtTrId(
"cutelyst-memc-rt-authcont");
1310 return c->
qtTrId(
"cutelyst-memc-rt-parseerr");
1311 case ParseUserError:
1313 return c->
qtTrId(
"cutelyst-memc-rt-parseusererr");
1316 return c->
qtTrId(
"cutelyst-memc-rt-deprecated");
1317 case PluginNotRegisterd:
1319 return c->
qtTrId(
"cutelyst-memc-rt-pluginnotregistered");
1322 return c->
qtTrId(
"cutelyst-memc-rt-unknown-err");
1336 Memcached::ReturnType MemcachedPrivate::returnTypeConvert(memcached_return_t rt)
1339 using enum Memcached::ReturnType;
1340 case MEMCACHED_SUCCESS:
return Success;
1341 case MEMCACHED_FAILURE:
return Failure;
1342 case MEMCACHED_HOST_LOOKUP_FAILURE:
return HostLookupFailure;
1343 case MEMCACHED_CONNECTION_FAILURE:
return ConnectionFailure;
1344 case MEMCACHED_CONNECTION_BIND_FAILURE:
return HostLookupFailure;
1345 case MEMCACHED_WRITE_FAILURE:
return WriteFailure;
1346 case MEMCACHED_READ_FAILURE:
return ReadFailure;
1347 case MEMCACHED_UNKNOWN_READ_FAILURE:
return UnknownReadFailure;
1348 case MEMCACHED_PROTOCOL_ERROR:
return ProtocolError;
1349 case MEMCACHED_CLIENT_ERROR:
return ClientError;
1350 case MEMCACHED_SERVER_ERROR:
return ServerError;
1351 case MEMCACHED_ERROR:
return Error;
1352 case MEMCACHED_DATA_EXISTS:
return DataExists;
1353 case MEMCACHED_DATA_DOES_NOT_EXIST:
return DataDoesNotExist;
1354 case MEMCACHED_NOTSTORED:
return NotStored;
1355 case MEMCACHED_STORED:
return Stored;
1356 case MEMCACHED_NOTFOUND:
return NotFound;
1357 case MEMCACHED_MEMORY_ALLOCATION_FAILURE:
return MemoryAllocationFailure;
1358 case MEMCACHED_PARTIAL_READ:
return PartialRead;
1359 case MEMCACHED_SOME_ERRORS:
return SomeErrors;
1360 case MEMCACHED_NO_SERVERS:
return NoServers;
1361 case MEMCACHED_END:
return End;
1362 case MEMCACHED_DELETED:
return Deleted;
1363 case MEMCACHED_STAT:
return Stat;
1364 case MEMCACHED_ERRNO:
return Errno;
1365 case MEMCACHED_NOT_SUPPORTED:
return NotSupported;
1366 case MEMCACHED_FETCH_NOTFINISHED:
return FetchNotFinished;
1367 case MEMCACHED_TIMEOUT:
return Timeout;
1368 case MEMCACHED_BUFFERED:
return Buffered;
1369 case MEMCACHED_BAD_KEY_PROVIDED:
return BadKeyProvided;
1370 case MEMCACHED_INVALID_HOST_PROTOCOL:
return InvalidHostProtocol;
1371 case MEMCACHED_SERVER_MARKED_DEAD:
return ServerMarkedDead;
1372 case MEMCACHED_UNKNOWN_STAT_KEY:
return UnknownStatKey;
1373 case MEMCACHED_E2BIG:
return E2Big;
1374 case MEMCACHED_INVALID_ARGUMENTS:
return InvalidArguments;
1375 case MEMCACHED_KEY_TOO_BIG:
return KeyTooBig;
1376 case MEMCACHED_AUTH_PROBLEM:
return AuthProblem;
1377 case MEMCACHED_AUTH_FAILURE:
return AuthFailure;
1378 case MEMCACHED_AUTH_CONTINUE:
return AuthContinue;
1379 case MEMCACHED_PARSE_ERROR:
return ParseError;
1380 case MEMCACHED_PARSE_USER_ERROR:
return ParseUserError;
1381 case MEMCACHED_DEPRECATED:
return Deprecated;
1382 case MEMCACHED_IN_PROGRESS:
return InProgress;
1383 case MEMCACHED_SERVER_TEMPORARILY_DISABLED:
return ServerTemporaryDisabled;
1384 case MEMCACHED_SERVER_MEMORY_ALLOCATION_FAILURE:
return ServerMemoryAllocationFailure;
1385 case MEMCACHED_MAXIMUM_RETURN:
return MaximumReturn;
1386 default:
return Success;
1396 void MemcachedPrivate::setReturnType(Memcached::ReturnType *rt1, memcached_return_t rt2)
1399 *rt1 = MemcachedPrivate::returnTypeConvert(rt2);
1408 bool MemcachedPrivate::isRegistered(
Memcached *ptr, Memcached::ReturnType *rt)
1411 qCCritical(C_MEMCACHED) <<
"Memcached plugin not registered";
1413 *rt = Memcached::ReturnType::PluginNotRegisterd;
1427 if (mcd->d_ptr->compression && (value.size() > mcd->d_ptr->compressionThreshold)) {
1428 flags |= MemcachedPrivate::Compressed;
1429 return qCompress(value, mcd->d_ptr->compressionLevel);
1441 memcached_result_st *result)
1443 const MemcachedPrivate::Flags flags{memcached_result_flags(result)};
1444 if (flags.testFlag(MemcachedPrivate::Compressed)) {
1445 return qUncompress(value);
1460 return loadedConfig.
value(key, defaultConfig.value(key, defaultValue));
1463 #include "moc_memcached.cpp"
The Cutelyst application.
Engine * engine() const noexcept
void loadTranslations(const QString &filename, const QString &directory={}, const QString &prefix={}, const QString &suffix={})
void postForked(Cutelyst::Application *app)
QString qtTrId(const char *id, int n=-1) const
QVariantMap config(const QString &entity) const
Cutelyst Memcached plugin.
bool setup(Application *app) override
Base class for Cutelyst Plugins.
The Cutelyst namespace holds all public Cutelyst API.
const char * constData() const const
void push_back(QByteArrayView str)
qsizetype size() const const
QByteArrayView::const_pointer constData() const const
QByteArrayView::const_pointer data() const const
bool isEmpty() const const
qsizetype size() const const
QHash::iterator insert(const Key &key, const T &value)
void reserve(qsizetype size)
void push_back(QList::parameter_type value)
qsizetype size() const const
QMetaObject::Connection connect(const QObject *sender, PointerToMemberFunction signal, Functor functor)
const QChar at(qsizetype position) const const
bool isEmpty() const const
QString & replace(QChar before, QChar after, Qt::CaseSensitivity cs)
bool startsWith(QChar c, Qt::CaseSensitivity cs) const const
QString toUpper() const const
QByteArray toUtf8() const const
QString join(QChar separator) const const
QList< QStringView > split(QChar sep, Qt::SplitBehavior behavior, Qt::CaseSensitivity cs) const const
QVersionNumber fromString(QAnyStringView string, qsizetype *suffixIndex)