6 #include "memcached_p.h"
8 #include <Cutelyst/Application>
9 #include <Cutelyst/Engine>
10 #include <Cutelyst/Context>
13 #include <QStringList>
14 #include <QLoggingCategory>
16 Q_LOGGING_CATEGORY(C_MEMCACHED,
"cutelyst.plugin.memcached", QtWarningMsg)
20 static thread_local
Memcached *mcd =
nullptr;
24 Plugin(parent), d_ptr(new MemcachedPrivate)
37 d->defaultConfig = defaultConfig;
44 const QVariantMap map = app->
engine()->
config(QStringLiteral(
"Cutelyst_Memcached_Plugin"));
47 const QStringList serverList = map.value(QStringLiteral(
"servers"), d->defaultConfig.value(QStringLiteral(
"servers"))).toString().split(u
';');
49 if (serverList.empty()) {
50 config.push_back(QStringLiteral(
"--SERVER=localhost"));
53 for (
const QString &flag : {
54 QStringLiteral(
"verify_key"),
55 QStringLiteral(
"remove_failed_servers"),
56 QStringLiteral(
"binary_protocol"),
57 QStringLiteral(
"buffer_requests"),
58 QStringLiteral(
"hash_with_namespace"),
59 QStringLiteral(
"noreply"),
60 QStringLiteral(
"randomize_replica_read"),
61 QStringLiteral(
"sort_hosts"),
62 QStringLiteral(
"support_cas"),
63 QStringLiteral(
"use_udp"),
64 QStringLiteral(
"tcp_nodelay"),
65 QStringLiteral(
"tcp_keepalive")
67 if (map.value(flag, d->defaultConfig.value(flag,
false)).toBool()) {
68 const QString flagStr = u
"--" + flag.toUpper().replace(u
'_', u
'-');
69 config.push_back(flagStr);
73 const bool useUDP = map.value(QStringLiteral(
"use_udp"), d->defaultConfig.value(QStringLiteral(
"use_udp"),
false)).toBool();
75 for (
const QString &opt : {
76 QStringLiteral(
"connect_timeout"),
77 QStringLiteral(
"distribution"),
78 QStringLiteral(
"hash"),
79 QStringLiteral(
"number_of_replicas"),
80 QStringLiteral(
"namespace"),
81 QStringLiteral(
"retry_timeout"),
82 QStringLiteral(
"server_failure_limit"),
83 QStringLiteral(
"snd_timeout"),
84 QStringLiteral(
"socket_recv_size"),
85 QStringLiteral(
"socket_send_size"),
86 QStringLiteral(
"poll_timeout"),
87 QStringLiteral(
"io_bytes_watermark"),
88 QStringLiteral(
"io_key_prefetch"),
89 QStringLiteral(
"io_msg_watermark"),
90 QStringLiteral(
"rcv_timeout")
92 const QString _val = map.value(opt, d->defaultConfig.value(opt)).toString();
93 if (!_val.isEmpty()) {
94 const QString optStr = u
"--" + opt.toUpper().replace(u
'_', u
'-') + u
'=' + _val;
95 config.push_back(optStr);
99 const QByteArray configString = config.join(u
' ').toUtf8();
103 qCInfo(C_MEMCACHED,
"Setting up connection to memcached servers using libmemcached %s with the following configuration string: \"%s\"", memcached_lib_version(), configString.constData());
105 memcached_st *new_memc = memcached(configString.constData(), configString.size());
109 if (!serverList.empty()) {
110 for (
const QString &server : serverList) {
111 const auto serverParts = QStringView(server).split(u
',');
115 bool isSocket =
false;
116 if (!serverParts.empty()) {
117 const auto part0 = serverParts.at(0);
118 if (!part0.isEmpty()) {
119 name = part0.toString();
120 isSocket = name.startsWith(u
'/');
122 if (serverParts.size() > 1) {
123 const auto part1 = serverParts.at(1);
124 if (!part1.isEmpty()) {
126 weight = part1.toUInt();
128 port = part1.toUInt();
131 if (!isSocket && (serverParts.size() > 2)) {
132 const auto part2 = serverParts.at(2);
133 if (!part2.isEmpty()) {
134 weight = part2.toUInt();
139 if (!name.isEmpty()) {
140 memcached_return_t rc;
142 rc = memcached_server_add_unix_socket_with_weight(new_memc, name.toUtf8().constData(), weight);
143 if (Q_LIKELY(memcached_success(rc))) {
144 qCInfo(C_MEMCACHED,
"Added memcached server on socket %s with weight %u.", qPrintable(name), weight);
146 qCWarning(C_MEMCACHED,
"Failed to add memcached server on socket %s with weight %u: %s", qPrintable(name), weight, memcached_strerror(new_memc, rc));
150 rc = memcached_server_add_udp_with_weight(new_memc, name.toUtf8().constData(), port, weight);
152 rc = memcached_server_add_with_weight(new_memc, name.toUtf8().constData(), port, weight);
154 if (Q_LIKELY(memcached_success(rc))) {
155 qCInfo(C_MEMCACHED,
"Added memcached server on host %s:%u with weight %u.", qPrintable(name), port, weight);
157 qCWarning(C_MEMCACHED,
"Failed to add memcached server on host %s:%u with weight %u: %s", qPrintable(name), port, weight, memcached_strerror(new_memc, rc));
163 if (Q_UNLIKELY(memcached_server_count(new_memc) == 0)) {
164 qCWarning(C_MEMCACHED,
"Failed to add any memcached server. Adding default server on localhost port 11211.");
165 memcached_return_t rc = memcached_server_add(new_memc,
"localhost", 11211);
166 if (Q_UNLIKELY(!memcached_success(rc))) {
167 qCCritical(C_MEMCACHED,
"Failed to add default memcached server. Memcached plugin will not work without a configured server! %s", memcached_strerror(new_memc, rc));
168 memcached_free(new_memc);
174 d->compression = map.value(QStringLiteral(
"compression"), d->defaultConfig.value(QStringLiteral(
"compression"),
false)).toBool();
175 d->compressionLevel = map.value(QStringLiteral(
"compression_level"), d->defaultConfig.value(QStringLiteral(
"compression_level"), -1)).toInt();
176 d->compressionThreshold = map.value(QStringLiteral(
"compression_threshold"), d->defaultConfig.value(QStringLiteral(
"compression_threshold"), 100)).toInt();
177 if (d->compression) {
178 qCInfo(C_MEMCACHED,
"Compression: enabled (Compression level: %i, Compression threshold: %i bytes)", d->compressionLevel, d->compressionThreshold);
180 qCInfo(C_MEMCACHED,
"Compression: disabled");
183 const QString encKey = map.value(QStringLiteral(
"encryption_key")).toString();
184 if (!encKey.isEmpty()) {
185 const QByteArray encKeyBa = encKey.toUtf8();
186 const memcached_return_t rt = memcached_set_encoding_key(new_memc, encKeyBa.constData(), encKeyBa.size());
187 if (Q_LIKELY(memcached_success(rt))) {
188 qCInfo(C_MEMCACHED,
"Encryption: enabled");
190 qCWarning(C_MEMCACHED,
"Failed to enable encryption: %s", memcached_strerror(new_memc, rt));
193 qCInfo(C_MEMCACHED,
"Encryption: disabled");
196 #ifdef LIBMEMCACHED_WITH_SASL_SUPPORT
197 #if LIBMEMCACHED_WITH_SASL_SUPPORT == 1
198 const QString saslUser = map.value(QStringLiteral(
"sasl_user")).toString();
199 const QString saslPass = map.value(QStringLiteral(
"sasl_password")).toString();
200 if (!saslUser.isEmpty() && !saslPass.isEmpty()) {
201 const memcached_return_t rt = memcached_set_sasl_auth_data(new_memc, saslUser.toUtf8().constData(), saslPass.toUtf8().constData());
202 if (Q_LIKELY(memcached_success(rt))) {
203 qCInfo(C_MEMCACHED,
"SASL authentication: enabled");
204 d->saslEnabled =
true;
206 qCWarning(C_MEMCACHED,
"Failed to enable SASL authentication: %s", memcached_strerror(new_memc, rt));
209 qCInfo(C_MEMCACHED,
"SASL authentication: disabled");
215 memcached_free(d->memc);
227 qCCritical(C_MEMCACHED) <<
"Failed to configure the connection to the memcached server(s)";
236 qCCritical(C_MEMCACHED) <<
"Memcached plugin not registered";
243 const QByteArray _key = key.toUtf8();
245 MemcachedPrivate::Flags flags;
246 QByteArray _value = value;
248 if (mcd->d_ptr->compression && (_value.size() > mcd->d_ptr->compressionThreshold)) {
249 flags |= MemcachedPrivate::Compressed;
250 _value = qCompress(value, mcd->d_ptr->compressionLevel);
253 const memcached_return_t rt = memcached_set(mcd->d_ptr->memc,
261 const bool ok = memcached_success(rt);
264 qCWarning(C_MEMCACHED,
"Failed to store key \"%s\": %s", _key.constData(), memcached_strerror(mcd->d_ptr->memc, rt));
267 MemcachedPrivate::setReturnType(returnType, rt);
275 qCCritical(C_MEMCACHED) <<
"Memcached plugin not registered";
282 const QByteArray _key = key.toUtf8();
283 const QByteArray _groupKey = groupKey.toUtf8();
285 MemcachedPrivate::Flags flags;
286 QByteArray _value = value;
288 if (mcd->d_ptr->compression && (_value.size() > mcd->d_ptr->compressionThreshold)) {
289 flags |= MemcachedPrivate::Compressed;
290 _value = qCompress(value, mcd->d_ptr->compressionLevel);
293 const memcached_return_t rt = memcached_set_by_key(mcd->d_ptr->memc,
294 _groupKey.constData(),
303 const bool ok = memcached_success(rt);
306 qCWarning(C_MEMCACHED,
"Failed to store key \"%s\" on group \"%s\": %s", _key.constData(), _groupKey.constData(), memcached_strerror(mcd->d_ptr->memc, rt));
309 MemcachedPrivate::setReturnType(returnType, rt);
317 qCCritical(C_MEMCACHED) <<
"Memcached plugin not registered";
324 const QByteArray _key = key.toUtf8();
326 MemcachedPrivate::Flags flags;
327 QByteArray _value = value;
329 if (mcd->d_ptr->compression && (_value.size() > mcd->d_ptr->compressionThreshold)) {
330 flags |= MemcachedPrivate::Compressed;
331 _value = qCompress(value, mcd->d_ptr->compressionLevel);
334 const memcached_return_t rt = memcached_add(mcd->d_ptr->memc,
342 const bool ok = memcached_success(rt);
344 if (!ok && (rt != MEMCACHED_NOTSTORED)) {
345 qCWarning(C_MEMCACHED,
"Failed to add key \"%s\": %s", _key.constData(), memcached_strerror(mcd->d_ptr->memc, rt));
348 MemcachedPrivate::setReturnType(returnType, rt);
356 qCCritical(C_MEMCACHED) <<
"Memcached plugin not registered";
363 const QByteArray _key = key.toUtf8();
364 const QByteArray _groupKey = groupKey.toUtf8();
366 MemcachedPrivate::Flags flags;
367 QByteArray _value = value;
369 if (mcd->d_ptr->compression && (_value.size() > mcd->d_ptr->compressionThreshold)) {
370 flags |= MemcachedPrivate::Compressed;
371 _value = qCompress(value, mcd->d_ptr->compressionLevel);
374 const memcached_return_t rt = memcached_add_by_key(mcd->d_ptr->memc,
375 _groupKey.constData(),
384 const bool ok = memcached_success(rt);
386 if (!ok && (rt != MEMCACHED_NOTSTORED)) {
387 qCWarning(C_MEMCACHED,
"Failed to add key \"%s\" on group \"%s\": %s", _key.constData(), _groupKey.constData(), memcached_strerror(mcd->d_ptr->memc, rt));
390 MemcachedPrivate::setReturnType(returnType, rt);
398 qCCritical(C_MEMCACHED) <<
"Memcached plugin not registered";
405 const QByteArray _key = key.toUtf8();
407 MemcachedPrivate::Flags flags;
408 QByteArray _value = value;
410 if (mcd->d_ptr->compression && (_value.size() > mcd->d_ptr->compressionThreshold)) {
411 flags |= MemcachedPrivate::Compressed;
412 _value = qCompress(value, mcd->d_ptr->compressionLevel);
415 const memcached_return_t rt = memcached_replace(mcd->d_ptr->memc,
423 const bool ok = memcached_success(rt);
425 if (!ok && (rt != MEMCACHED_NOTSTORED)) {
426 qCWarning(C_MEMCACHED,
"Failed to replace key \"%s\": %s", _key.constData(), memcached_strerror(mcd->d_ptr->memc, rt));
429 MemcachedPrivate::setReturnType(returnType, rt);
437 qCCritical(C_MEMCACHED) <<
"Memcached plugin not registered";
444 const QByteArray _groupKey = groupKey.toUtf8();
445 const QByteArray _key = key.toUtf8();
447 MemcachedPrivate::Flags flags;
448 QByteArray _value = value;
450 if (mcd->d_ptr->compression && (_value.size() > mcd->d_ptr->compressionThreshold)) {
451 flags |= MemcachedPrivate::Compressed;
452 _value = qCompress(value, mcd->d_ptr->compressionLevel);
455 const memcached_return_t rt = memcached_replace_by_key(mcd->d_ptr->memc,
456 _groupKey.constData(),
465 const bool ok = memcached_success(rt);
467 if (!ok && (rt != MEMCACHED_NOTSTORED)) {
468 qCWarning(C_MEMCACHED,
"Failed to replace key \"%s\" on group \"%s\": %s", _key.constData(), _groupKey.constData(), memcached_strerror(mcd->d_ptr->memc, rt));
471 MemcachedPrivate::setReturnType(returnType, rt);
481 qCCritical(C_MEMCACHED) <<
"Memcached plugin not registered";
488 memcached_return_t rt;
489 const QByteArray _key = key.toUtf8();
492 std::vector<const char *> keys;
493 std::vector<size_t> sizes;
494 keys.push_back(_key.constData());
495 sizes.push_back(_key.size());
496 rt = memcached_mget(mcd->d_ptr->memc,
501 if (memcached_success(rt)) {
502 memcached_result_st *result = memcached_fetch_result(mcd->d_ptr->memc, NULL, &rt);
504 retData = QByteArray(memcached_result_value(result), memcached_result_length(result));
506 *
cas = memcached_result_cas(result);
508 MemcachedPrivate::Flags flags = MemcachedPrivate::Flags(memcached_result_flags(result));
509 if (flags.testFlag(MemcachedPrivate::Compressed)) {
510 retData = qUncompress(retData);
515 memcached_fetch_result(mcd->d_ptr->memc, NULL, NULL);
517 memcached_result_free(result);
520 if (!ok && (rt != MEMCACHED_NOTFOUND)) {
521 qCWarning(C_MEMCACHED,
"Failed to get data for key \"%s\": %s", _key.constData(), memcached_strerror(mcd->d_ptr->memc, rt));
524 MemcachedPrivate::setReturnType(returnType, rt);
534 qCCritical(C_MEMCACHED) <<
"Memcached plugin not registered";
541 memcached_return_t rt;
542 const QByteArray _groupKey = groupKey.toUtf8();
543 const QByteArray _key = key.toUtf8();
546 std::vector<const char *> keys;
547 std::vector<size_t> sizes;
548 keys.push_back(_key.constData());
549 sizes.push_back(_key.size());
550 rt = memcached_mget_by_key(mcd->d_ptr->memc,
551 _groupKey.constData(),
557 if (memcached_success(rt)) {
558 memcached_result_st *result = memcached_fetch_result(mcd->d_ptr->memc, NULL, &rt);
560 retData = QByteArray(memcached_result_value(result), memcached_result_length(result));
562 *
cas = memcached_result_cas(result);
564 MemcachedPrivate::Flags flags = MemcachedPrivate::Flags(memcached_result_flags(result));
565 if (flags.testFlag(MemcachedPrivate::Compressed)) {
566 retData = qUncompress(retData);
571 memcached_fetch_result(mcd->d_ptr->memc, NULL, NULL);
573 memcached_result_free(result);
576 if (!ok && (rt != MEMCACHED_NOTFOUND)) {
577 qCWarning(C_MEMCACHED,
"Failed to get data for key \"%s\" on group \"%s\": %s", _key.constData(), _groupKey.constData(), memcached_strerror(mcd->d_ptr->memc, rt));
580 MemcachedPrivate::setReturnType(returnType, rt);
588 qCCritical(C_MEMCACHED) <<
"Memcached plugin not registered";
595 const QByteArray _key = key.toUtf8();
597 const memcached_return_t rt = memcached_delete(mcd->d_ptr->memc,
602 const bool ok = memcached_success(rt);
604 if (!ok && (rt != MEMCACHED_NOTFOUND)) {
605 qCWarning(C_MEMCACHED,
"Failed to remove data for key \"%s\": %s", _key.constData(), memcached_strerror(mcd->d_ptr->memc, rt));
608 MemcachedPrivate::setReturnType(returnType, rt);
616 qCCritical(C_MEMCACHED) <<
"Memcached plugin not registered";
623 const QByteArray _groupKey = groupKey.toUtf8();
624 const QByteArray _key = key.toUtf8();
626 const memcached_return_t rt = memcached_delete_by_key(mcd->d_ptr->memc,
627 _groupKey.constData(),
633 const bool ok = memcached_success(rt);
635 if (!ok && (rt != MEMCACHED_NOTFOUND)) {
636 qCWarning(C_MEMCACHED,
"Failed to remove data for key \"%s\" on group \"%s\": %s", _key.constData(), _groupKey.constData(), memcached_strerror(mcd->d_ptr->memc, rt));
639 MemcachedPrivate::setReturnType(returnType, rt);
647 qCCritical(C_MEMCACHED) <<
"Memcached plugin not registered";
654 const QByteArray _key = key.toUtf8();
656 const memcached_return_t rt = memcached_exist(mcd->d_ptr->memc,
660 const bool ok = memcached_success(rt);
662 if (!ok && (rt != MEMCACHED_NOTFOUND)) {
663 qCWarning(C_MEMCACHED,
"Failed to check existence of key \"%s\": %s", _key.constData(), memcached_strerror(mcd->d_ptr->memc, rt));
666 MemcachedPrivate::setReturnType(returnType, rt);
674 qCCritical(C_MEMCACHED) <<
"Memcached plugin not registered";
681 const QByteArray _groupKey = groupKey.toUtf8();
682 const QByteArray _key = key.toUtf8();
684 const memcached_return_t rt = memcached_exist_by_key(mcd->d_ptr->memc,
685 _groupKey.constData(),
690 const bool ok = memcached_success(rt);
692 if (!ok && (rt != MEMCACHED_NOTFOUND)) {
693 qCWarning(C_MEMCACHED,
"Failed to check existence of key \"%s\" in group \"%s\"", _key.constData(), _groupKey.constData());
696 MemcachedPrivate::setReturnType(returnType, rt);
704 qCCritical(C_MEMCACHED) <<
"Memcached plugin not registered";
711 const QByteArray _key = key.toUtf8();
713 const memcached_return_t rt = memcached_increment(mcd->d_ptr->memc,
719 const bool ok = memcached_success(rt);
721 if (!ok && (rt != MEMCACHED_NOTFOUND)) {
722 qCWarning(C_MEMCACHED,
"Failed to increment key \"%s\" by %u: %s", _key.constData(), offset, memcached_strerror(mcd->d_ptr->memc, rt));
725 MemcachedPrivate::setReturnType(returnType, rt);
733 qCCritical(C_MEMCACHED) <<
"Memcached plugin not registered";
740 const QByteArray _group = groupKey.toUtf8();
741 const QByteArray _key = key.toUtf8();
743 const memcached_return_t rt = memcached_increment_by_key(mcd->d_ptr->memc,
751 const bool ok = memcached_success(rt);
753 if (!ok && (rt != MEMCACHED_NOTFOUND)) {
754 qCWarning(C_MEMCACHED,
"Failed to increment \"%s\" key on group \"%s\" by %lu: %s", _key.constData(), _group.constData(), offset, memcached_strerror(mcd->d_ptr->memc, rt));
757 MemcachedPrivate::setReturnType(returnType, rt);
765 qCCritical(C_MEMCACHED) <<
"Memcached plugin not registered";
772 const QByteArray _key = key.toUtf8();
774 const memcached_return_t rt = memcached_increment_with_initial(mcd->d_ptr->memc,
782 const bool ok = memcached_success(rt);
785 qCWarning(C_MEMCACHED,
"Failed to increment or initialize key \"%s\" by offset %lu or initial %lu: %s", _key.constData(), offset, initial, memcached_strerror(mcd->d_ptr->memc, rt));
788 MemcachedPrivate::setReturnType(returnType, rt);
796 qCCritical(C_MEMCACHED) <<
"Memcached plugin not registered";
803 const QByteArray _group = groupKey.toUtf8();
804 const QByteArray _key = key.toUtf8();
806 const memcached_return_t rt = memcached_increment_with_initial_by_key(mcd->d_ptr->memc,
816 const bool ok = memcached_success(rt);
818 qCWarning(C_MEMCACHED,
"Failed to increment or initialize key \"%s\" in group \"%s\" by offset %lu or initial %lu: %s", _key.constData(), _group.constData(), offset, initial, memcached_strerror(mcd->d_ptr->memc, rt));
821 MemcachedPrivate::setReturnType(returnType, rt);
829 qCCritical(C_MEMCACHED) <<
"Memcached plugin not registered";
836 const QByteArray _key = key.toUtf8();
838 const memcached_return_t rt = memcached_decrement(mcd->d_ptr->memc,
844 const bool ok = memcached_success(rt);
846 if (!ok && (rt != MEMCACHED_NOTFOUND)) {
847 qCWarning(C_MEMCACHED,
"Failed to decrement key \"%s\" by %u: %s", _key.constData(), offset, memcached_strerror(mcd->d_ptr->memc, rt));
850 MemcachedPrivate::setReturnType(returnType, rt);
858 qCCritical(C_MEMCACHED) <<
"Memcached plugin not registered";
865 const QByteArray _group = groupKey.toUtf8();
866 const QByteArray _key = key.toUtf8();
868 const memcached_return_t rt = memcached_decrement_by_key(mcd->d_ptr->memc,
876 const bool ok = memcached_success(rt);
878 if (!ok && (rt != MEMCACHED_NOTFOUND)) {
879 qCWarning(C_MEMCACHED,
"Failed to decrement \"%s\" key on group \"%s\" by %lu: %s", _key.constData(), _group.constData(), offset, memcached_strerror(mcd->d_ptr->memc, rt));
882 MemcachedPrivate::setReturnType(returnType, rt);
890 qCCritical(C_MEMCACHED) <<
"Memcached plugin not registered";
897 const QByteArray _key = key.toUtf8();
899 const memcached_return_t rt = memcached_decrement_with_initial(mcd->d_ptr->memc,
907 const bool ok = memcached_success(rt);
910 qCWarning(C_MEMCACHED,
"Failed to decrement or initialize key \"%s\" by offset %lu or initial %lu: %s", _key.constData(), offset, initial, memcached_strerror(mcd->d_ptr->memc, rt));
913 MemcachedPrivate::setReturnType(returnType, rt);
921 qCCritical(C_MEMCACHED) <<
"Memcached plugin not registered";
928 const QByteArray _group = groupKey.toUtf8();
929 const QByteArray _key = key.toUtf8();
931 const memcached_return_t rt = memcached_decrement_with_initial_by_key(mcd->d_ptr->memc,
941 const bool ok = memcached_success(rt);
943 qCWarning(C_MEMCACHED,
"Failed to increment or initialize key \"%s\" in group \"%s\" by offset %lu or initial %lu: %s", _key.constData(), _group.constData(), offset, initial, memcached_strerror(mcd->d_ptr->memc, rt));
946 MemcachedPrivate::setReturnType(returnType, rt);
954 qCCritical(C_MEMCACHED) <<
"Memcached plugin not registered";
961 const QByteArray _key = key.toUtf8();
963 MemcachedPrivate::Flags flags;
964 QByteArray _value = value;
966 if (mcd->d_ptr->compression && (_value.size() > mcd->d_ptr->compressionThreshold)) {
967 flags |= MemcachedPrivate::Compressed;
968 _value = qCompress(value, mcd->d_ptr->compressionLevel);
971 const memcached_return_t rt = memcached_cas(mcd->d_ptr->memc,
980 const bool ok = memcached_success(rt);
982 if (!ok && (rt != MEMCACHED_DATA_EXISTS)) {
983 qCWarning(C_MEMCACHED,
"Failed to compare and set (cas) key \"%s\": %s", _key.constData(), memcached_strerror(mcd->d_ptr->memc, rt));
986 MemcachedPrivate::setReturnType(returnType, rt);
994 qCCritical(C_MEMCACHED) <<
"Memcached plugin not registered";
1001 const QByteArray _group = groupKey.toUtf8();
1002 const QByteArray _key = key.toUtf8();
1004 MemcachedPrivate::Flags flags;
1005 QByteArray _value = value;
1007 if (mcd->d_ptr->compression && (_value.size() > mcd->d_ptr->compressionThreshold)) {
1008 flags |= MemcachedPrivate::Compressed;
1009 _value = qCompress(value, mcd->d_ptr->compressionLevel);
1012 const memcached_return_t rt = memcached_cas_by_key(mcd->d_ptr->memc,
1023 const bool ok = memcached_success(rt);
1025 if (!ok && (rt != MEMCACHED_DATA_EXISTS)) {
1026 qCWarning(C_MEMCACHED,
"Failed to compare and set (cas) key \"%s\" in group \"%s\": %s", _key.constData(), _group.constData(), memcached_strerror(mcd->d_ptr->memc, rt));
1029 MemcachedPrivate::setReturnType(returnType, rt);
1037 qCCritical(C_MEMCACHED) <<
"Memcached plugin not registered";
1044 const memcached_return_t rt = memcached_flush_buffers(mcd->d_ptr->memc);
1046 const bool ok = memcached_success(rt);
1049 qCWarning(C_MEMCACHED,
"Failed to flush buffers: %s", memcached_strerror(mcd->d_ptr->memc, rt));
1052 MemcachedPrivate::setReturnType(returnType, rt);
1060 qCCritical(C_MEMCACHED) <<
"Memcached plugin not registered";
1067 const memcached_return_t rt = memcached_flush(mcd->d_ptr->memc, expiration);
1069 const bool ok = memcached_success(rt);
1072 qCWarning(C_MEMCACHED,
"Failed to wipe clean (flush) server content: %s", memcached_strerror(mcd->d_ptr->memc, rt));
1075 MemcachedPrivate::setReturnType(returnType, rt);
1082 QHash<QString,QByteArray> ret;
1085 qCCritical(C_MEMCACHED) <<
"Memcached plugin not registered";
1093 qCWarning(C_MEMCACHED,
"Can not get multiple values without a list of keys.");
1100 std::vector<char *> _keys;
1101 _keys.reserve(keys.size());
1102 std::vector<size_t> _keysSizes;
1103 _keysSizes.reserve(keys.size());
1105 for (
const QString &key : keys) {
1106 const QByteArray _key = key.toUtf8();
1107 char *data =
new char[_key.size() + 1];
1108 qstrcpy(data, _key.data());
1109 _keys.push_back(data);
1110 _keysSizes.push_back(_key.size());
1113 memcached_return_t rt;
1116 rt = memcached_mget(mcd->d_ptr->memc,
1121 if (memcached_success(rt)) {
1123 ret.reserve(keys.size());
1124 while ((rt != MEMCACHED_END) && (rt != MEMCACHED_NOTFOUND)) {
1125 memcached_result_st *result = memcached_fetch_result(mcd->d_ptr->memc, NULL, &rt);
1127 const QString rk = QString::fromUtf8(memcached_result_key_value(result), memcached_result_key_length(result));
1128 QByteArray rd(memcached_result_value(result), memcached_result_length(result));
1130 casValues->insert(rk, memcached_result_cas(result));
1132 MemcachedPrivate::Flags flags = MemcachedPrivate::Flags(memcached_result_flags(result));
1133 if (flags.testFlag(MemcachedPrivate::Compressed)) {
1134 rd = qUncompress(rd);
1138 memcached_result_free(result);
1142 for (
char *c : _keys) {
1147 qCWarning(C_MEMCACHED,
"Failed to get values for multiple keys: %s", memcached_strerror(mcd->d_ptr->memc, rt));
1150 MemcachedPrivate::setReturnType(returnType, rt);
1157 QHash<QString, QByteArray> ret;
1160 qCCritical(C_MEMCACHED) <<
"Memcached plugin not registered";
1167 if (groupKey.isEmpty()) {
1168 qCWarning(C_MEMCACHED,
"Can not get multiple values from specific server when groupKey is empty.");
1176 qCWarning(C_MEMCACHED,
"Can not get multiple values without a list of keys.");
1183 const QByteArray _group = groupKey.toUtf8();
1185 std::vector<char *> _keys;
1186 _keys.reserve(keys.size());
1187 std::vector<size_t> _keysSizes;
1188 _keysSizes.reserve(keys.size());
1190 for (
const QString &key : keys) {
1191 const QByteArray _key = key.toUtf8();
1192 char *data =
new char[_key.size() + 1];
1193 strcpy(data, _key.data());
1194 _keys.push_back(data);
1195 _keysSizes.push_back(_key.size());
1198 memcached_return_t rt;
1201 rt = memcached_mget_by_key(mcd->d_ptr->memc,
1210 if (memcached_success(rt)) {
1212 ret.reserve(keys.size());
1213 while ((rt != MEMCACHED_END) && (rt != MEMCACHED_NOTFOUND)) {
1214 memcached_result_st *result = memcached_fetch_result(mcd->d_ptr->memc, NULL, &rt);
1216 const QString rk = QString::fromUtf8(memcached_result_key_value(result), memcached_result_key_length(result));
1217 QByteArray rd(memcached_result_value(result), memcached_result_length(result));
1219 casValues->insert(rk, memcached_result_cas(result));
1221 MemcachedPrivate::Flags flags = MemcachedPrivate::Flags(memcached_result_flags(result));
1222 if (flags.testFlag(MemcachedPrivate::Compressed)) {
1223 rd = qUncompress(rd);
1227 memcached_result_free(result);
1231 for (
char *c : _keys) {
1236 qCWarning(C_MEMCACHED,
"Failed to get values for multiple keys in group \"%s\": %s", _group.constData(), memcached_strerror(mcd->d_ptr->memc, rt));
1239 MemcachedPrivate::setReturnType(returnType, rt);
1247 qCCritical(C_MEMCACHED) <<
"Memcached plugin not registered";
1254 const QByteArray _key = key.toUtf8();
1256 const memcached_return_t rt = memcached_touch(mcd->d_ptr->memc,
1261 const bool ok = memcached_success(rt);
1264 qCWarning(C_MEMCACHED,
"Failed to touch key \"%s\" with new expiration time %lu: %s", _key.constData(), expiration, memcached_strerror(mcd->d_ptr->memc, rt));
1267 MemcachedPrivate::setReturnType(returnType, rt);
1275 qCCritical(C_MEMCACHED) <<
"Memcached plugin not registered";
1282 const QByteArray _group = groupKey.toUtf8();
1283 const QByteArray _key = key.toUtf8();
1285 const memcached_return_t rt = memcached_touch_by_key(mcd->d_ptr->memc,
1292 const bool ok = memcached_success(rt);
1295 qCWarning(C_MEMCACHED,
"Failed to touch key \"%s\" in group \"%s\" with new expiration time %lu: %s", _key.constData(), _group.constData(), expiration, memcached_strerror(mcd->d_ptr->memc, rt));
1298 MemcachedPrivate::setReturnType(returnType, rt);
1307 return c->
translate(
"Cutelyst::Memcached",
"The request was successfully executed.");
1309 return c->
translate(
"Cutelyst::Memcached",
"An unknown failure has occurred in the Memcached server.");
1311 return c->
translate(
"Cutelyst::Memcached",
"A DNS failure has occurred.");
1313 return c->
translate(
"Cutelyst::Memcached",
"An unknown error has occured while trying to connect to a Memcached server.");
1315 return c->
translate(
"Cutelyst::Memcached",
"An error has occured while trying to write to a Memcached server.");
1317 return c->
translate(
"Cutelyst::Memcached",
"An error has occured while trying to read from a Memcached server.");
1319 return c->
translate(
"Cutelyst::Memcached",
"An unknown error has occured while trying to read from a Memcached server. This only occures when either there is a bug in the server, or in rare cases where an ethernet NIC is reporting dubious information.");
1321 return c->
translate(
"Cutelyst::Memcached",
"An unknown error has occured in the Memcached protocol.");
1323 return c->
translate(
"Cutelyst::Memcached",
"An unknown Memcached client error has occured internally.");
1325 return c->
translate(
"Cutelyst::Memcached",
"An unknown error has occured in the Memcached server.");
1327 return c->
translate(
"Cutelyst::Memcached",
"A general error occured.");
1329 return c->
translate(
"Cutelyst::Memcached",
"The data for the given key alrey exists.");
1331 return c->
translate(
"Cutelyst::Memcached",
"The data requested with the key given was not found.");
1333 return c->
translate(
"Cutelyst::Memcached",
"The request to store an object failed.");
1335 return c->
translate(
"Cutelyst::Memcached",
"The requested object has been successfully stored on the server.");
1337 return c->
translate(
"Cutelyst::Memcached",
"The object requested was not found.");
1339 return c->
translate(
"Cutelyst::Memcached",
"An error has occurred while trying to allocate memory.");
1341 return c->
translate(
"Cutelyst::Memcached",
"The read operation was only partcially successful.");
1343 return c->
translate(
"Cutelyst::Memcached",
"A multi request has been made, and some underterminate number of errors have occurred.");
1345 return c->
translate(
"Cutelyst::Memcached",
"No servers have been added to the Memcached plugin.");
1347 return c->
translate(
"Cutelyst::Memcached",
"The Memcached server has completed returning all of the objects requested.");
1349 return c->
translate(
"Cutelyst::Memcached",
"The object requested by the key has been deleted.");
1351 return c->
translate(
"Cutelyst::Memcached",
"A “stat” command has been returned in the protocol.");
1353 return c->
translate(
"Cutelyst::Memcached",
"An error has occurred in the driver which has set errno.");
1355 return c->
translate(
"Cutelyst::Memcached",
"The given method is not supported in the Memcached server.");
1357 return c->
translate(
"Cutelyst::Memcached",
"A request has been made, but the Memcached server has not finished the fetch of the last request.");
1359 return c->
translate(
"Cutelyst::Memcached",
"The operation has timed out.");
1361 return c->
translate(
"Cutelyst::Memcached",
"The request has been buffered.");
1363 return c->
translate(
"Cutelyst::Memcached",
"The key provided is not a valid key.");
1365 return c->
translate(
"Cutelyst::Memcached",
"The Memcached server you are connecting to has an invalid protocol. Most likely you are connecting to an older server that does not speak the binary protocol.");
1367 return c->
translate(
"Cutelyst::Memcached",
"The requested Memcached server has been marked dead.");
1369 return c->
translate(
"Cutelyst::Memcached",
"The Memcached server you are communicating with has a stat key which has not be defined in the protocol.");
1371 return c->
translate(
"Cutelyst::Memcached",
"Item is too large for the Memcached server to store.");
1373 return c->
translate(
"Cutelyst::Memcached",
"The arguments supplied to the given function were not valid.");
1375 return c->
translate(
"Cutelyst::Memcached",
"The key that has been provided is too large for the given Memcached server.");
1377 return c->
translate(
"Cutelyst::Memcached",
"An unknown issue has occured during SASL authentication.");
1379 return c->
translate(
"Cutelyst::Memcached",
"The credentials provided are not valid for this Memcached server.");
1381 return c->
translate(
"Cutelyst::Memcached",
"Authentication has been paused.");
1383 return c->
translate(
"Cutelyst::Memcached",
"An error has occurred while trying to parse the configuration string.");
1385 return c->
translate(
"Cutelyst::Memcached",
"An error has occurred in parsing the configuration string.");
1387 return c->
translate(
"Cutelyst::Memcached",
"The method that was requested has been deprecated.");
1389 return c->
translate(
"Cutelyst::Memcached",
"The Cutelyst Memcached plugin has not been registered to the application.");
1391 return c->
translate(
"Cutelyst::Memcached",
"An unknown error has occured.");
1397 return QVersionNumber::fromString(QLatin1String(memcached_lib_version()));
1445 case MEMCACHED_IN_PROGRESS:
return Memcached::InProgress;
1446 case MEMCACHED_SERVER_TEMPORARILY_DISABLED:
return Memcached::ServerTemporaryDisabled;
1447 case MEMCACHED_SERVER_MEMORY_ALLOCATION_FAILURE:
return Memcached::ServerMemoryAllocationFailure;
1448 case MEMCACHED_MAXIMUM_RETURN:
return Memcached::MaximumReturn;
1456 *rt1 = MemcachedPrivate::returnTypeConvert(rt2);
1460 #include "moc_memcached.cpp"
The Cutelyst Application.
Engine * engine() const noexcept
void loadTranslations(const QString &filename, const QString &directory=QString(), const QString &prefix=QString(), const QString &suffix=QString())
void postForked(Cutelyst::Application *app)
QString translate(const char *context, const char *sourceText, const char *disambiguation=nullptr, int n=-1) const
QVariantMap config(const QString &entity) const
user configuration for the application
Cutelyst Memcached plugin.
static bool replaceByKey(const QString &groupKey, const QString &key, const QByteArray &value, time_t expiration, MemcachedReturnType *returnType=nullptr)
static bool existByKey(const QString &groupKey, const QString &key, MemcachedReturnType *returnType=nullptr)
static bool incrementByKey(const QString &groupKey, const QString &key, uint64_t offset, uint64_t *value=nullptr, MemcachedReturnType *returnType=nullptr)
static bool add(const QString &key, const QByteArray &value, time_t expiration, MemcachedReturnType *returnType=nullptr)
@ MemoryAllocationFailure
static QByteArray get(const QString &key, uint64_t *cas=nullptr, MemcachedReturnType *returnType=nullptr)
static bool casByKey(const QString &groupKey, const QString &key, const QByteArray &value, time_t expiration, uint64_t cas, MemcachedReturnType *returnType=nullptr)
static bool increment(const QString &key, uint32_t offset, uint64_t *value=nullptr, MemcachedReturnType *returnType=nullptr)
virtual bool setup(Application *app) override
static bool flush(time_t expiration, MemcachedReturnType *returnType=nullptr)
static bool exist(const QString &key, MemcachedReturnType *returnType=nullptr)
static bool decrementByKey(const QString &groupKey, const QString &key, uint64_t offset, uint64_t *value=nullptr, MemcachedReturnType *returnType=nullptr)
static bool removeByKey(const QString &groupKey, const QString &key, MemcachedReturnType *returnType=nullptr)
static bool incrementWithInitial(const QString &key, uint64_t offset, uint64_t initial, time_t expiration, uint64_t *value=nullptr, MemcachedReturnType *returnType=nullptr)
static bool cas(const QString &key, const QByteArray &value, time_t expiration, uint64_t cas, MemcachedReturnType *returnType=nullptr)
static bool touch(const QString &key, time_t expiration, MemcachedReturnType *returnType=nullptr)
static QHash< QString, QByteArray > mgetByKey(const QString &groupKey, const QStringList &keys, QHash< QString, uint64_t > *casValues=nullptr, MemcachedReturnType *returnType=nullptr)
static bool flushBuffers(MemcachedReturnType *returnType=nullptr)
static bool decrementWithInitialByKey(const QString &groupKey, const QString &key, uint64_t offset, uint64_t initial, time_t expiration, uint64_t *value=nullptr, MemcachedReturnType *returnType=nullptr)
virtual ~Memcached() override
static const time_t expirationNotAdd
static bool set(const QString &key, const QByteArray &value, time_t expiration, MemcachedReturnType *returnType=nullptr)
static bool incrementWithInitialByKey(const QString &groupKey, const QString &key, uint64_t offset, uint64_t initial, time_t expiration, uint64_t *value=nullptr, MemcachedReturnType *returnType=nullptr)
static bool decrement(const QString &key, uint32_t offset, uint64_t *value=nullptr, MemcachedReturnType *returnType=nullptr)
static QString errorString(Context *c, MemcachedReturnType rt)
static bool touchByKey(const QString &groupKey, const QString &key, time_t expiration, MemcachedReturnType *returnType=nullptr)
static bool decrementWithInitial(const QString &key, uint64_t offset, uint64_t initial, time_t expiration, uint64_t *value=nullptr, MemcachedReturnType *returnType=nullptr)
void setDefaultConfig(const QVariantMap &defaultConfig)
static bool setByKey(const QString &groupKey, const QString &key, const QByteArray &value, time_t expiration, MemcachedReturnType *returnType=nullptr)
static QHash< QString, QByteArray > mget(const QStringList &keys, QHash< QString, uint64_t > *casValues=nullptr, MemcachedReturnType *returnType=nullptr)
static bool remove(const QString &key, MemcachedReturnType *returnType=nullptr)
static bool replace(const QString &key, const QByteArray &value, time_t expiration, MemcachedReturnType *returnType=nullptr)
static bool addByKey(const QString &groupKey, const QString &key, const QByteArray &value, time_t expiration, MemcachedReturnType *returnType=nullptr)
static QByteArray getByKey(const QString &groupKey, const QString &key, uint64_t *cas=nullptr, MemcachedReturnType *returnType=nullptr)
Memcached(Application *parent)
static QVersionNumber libMemcachedVersion()
Returns the version of the currently used libmemcached.
The Cutelyst namespace holds all public Cutelyst API.