cutelyst 3.9.1
A C++ Web Framework built on top of Qt, using the simple approach of Catalyst (Perl) framework.
memcached.cpp
1/*
2 * SPDX-FileCopyrightText: (C) 2017-2022 Matthias Fehring <mf@huessenbergnetz.de>
3 * SPDX-License-Identifier: BSD-3-Clause
4 */
5
6#include "memcached_p.h"
7
8#include <Cutelyst/Application>
9#include <Cutelyst/Context>
10#include <Cutelyst/Engine>
11#include <utility>
12
13#include <QLoggingCategory>
14#include <QStringList>
15
16Q_LOGGING_CATEGORY(C_MEMCACHED, "cutelyst.plugin.memcached", QtWarningMsg)
17
18using namespace Cutelyst;
19
20static thread_local Memcached *mcd = nullptr;
21const time_t Memcached::expirationNotAdd = MEMCACHED_EXPIRATION_NOT_ADD;
22
24 : Plugin(parent)
25 , d_ptr(new MemcachedPrivate)
26{
27}
28
32
33void Memcached::setDefaultConfig(const QVariantMap &defaultConfig)
34{
35 Q_D(Memcached);
36 d->defaultConfig = defaultConfig;
37}
38
40{
41 Q_D(Memcached);
42
43 const QVariantMap map = app->engine()->config(QStringLiteral("Cutelyst_Memcached_Plugin"));
44 QStringList config;
45
46 const QStringList serverList =
47 map.value(QStringLiteral("servers"), d->defaultConfig.value(QStringLiteral("servers")))
48 .toString()
49 .split(u';');
50
51 if (serverList.empty()) {
52 config.push_back(QStringLiteral("--SERVER=localhost"));
53 }
54
55 for (const QString &flag : {
56 QStringLiteral("verify_key"),
57 QStringLiteral("remove_failed_servers"),
58 QStringLiteral("binary_protocol"),
59 QStringLiteral("buffer_requests"),
60 QStringLiteral("hash_with_namespace"),
61 QStringLiteral("noreply"),
62 QStringLiteral("randomize_replica_read"),
63 QStringLiteral("sort_hosts"),
64 QStringLiteral("support_cas"),
65 QStringLiteral("use_udp"),
66 QStringLiteral("tcp_nodelay"),
67 QStringLiteral("tcp_keepalive"),
68 }) {
69 if (map.value(flag, d->defaultConfig.value(flag, false)).toBool()) {
70 const QString flagStr = u"--" + flag.toUpper().replace(u'_', u'-');
71 config.push_back(flagStr);
72 }
73 }
74
75 const bool useUDP = map.value(QStringLiteral("use_udp"),
76 d->defaultConfig.value(QStringLiteral("use_udp"), false))
77 .toBool();
78
79 for (const QString &opt : {
80 QStringLiteral("connect_timeout"),
81 QStringLiteral("distribution"),
82 QStringLiteral("hash"),
83 QStringLiteral("number_of_replicas"),
84 QStringLiteral("namespace"),
85 QStringLiteral("retry_timeout"),
86 QStringLiteral("server_failure_limit"),
87 QStringLiteral("snd_timeout"),
88 QStringLiteral("socket_recv_size"),
89 QStringLiteral("socket_send_size"),
90 QStringLiteral("poll_timeout"),
91 QStringLiteral("io_bytes_watermark"),
92 QStringLiteral("io_key_prefetch"),
93 QStringLiteral("io_msg_watermark"),
94 QStringLiteral("rcv_timeout"),
95 }) {
96 const QString _val = map.value(opt, d->defaultConfig.value(opt)).toString();
97 if (!_val.isEmpty()) {
98 const QString optStr = u"--" + opt.toUpper().replace(u'_', u'-') + u'=' + _val;
99 config.push_back(optStr); // clazy:exclude=reserve-candidates
100 }
101 }
102
103 const QByteArray configString = config.join(u' ').toUtf8();
104
105 bool ok = false;
106
107 qCInfo(C_MEMCACHED,
108 "Setting up connection to memcached servers using libmemcached %s with the following "
109 "configuration string: \"%s\"",
110 memcached_lib_version(),
111 configString.constData());
112
113 memcached_st *new_memc = memcached(configString.constData(), configString.size());
114
115 if (new_memc) {
116
117 if (!serverList.empty()) {
118 for (const QString &server : serverList) {
119 const auto serverParts = QStringView(server).split(u',');
120 QString name;
121 uint port = 11211;
122 uint32_t weight = 1;
123 bool isSocket = false;
124 if (!serverParts.empty()) {
125 const auto part0 = serverParts.at(0);
126 if (!part0.isEmpty()) {
127 name = part0.toString();
128 isSocket = name.startsWith(u'/');
129 }
130 if (serverParts.size() > 1) {
131 const auto part1 = serverParts.at(1);
132 if (!part1.isEmpty()) {
133 if (isSocket) {
134 weight = part1.toUInt();
135 } else {
136 port = part1.toUInt();
137 }
138 }
139 if (!isSocket && (serverParts.size() > 2)) {
140 const auto part2 = serverParts.at(2);
141 if (!part2.isEmpty()) {
142 weight = part2.toUInt();
143 }
144 }
145 }
146 }
147 if (!name.isEmpty()) {
148 memcached_return_t rc;
149 if (isSocket) {
150 rc = memcached_server_add_unix_socket_with_weight(
151 new_memc, name.toUtf8().constData(), weight);
152 if (Q_LIKELY(memcached_success(rc))) {
153 qCInfo(C_MEMCACHED,
154 "Added memcached server on socket %s with weight %u.",
155 qPrintable(name),
156 weight);
157 } else {
158 qCWarning(
159 C_MEMCACHED,
160 "Failed to add memcached server on socket %s with weight %u: %s",
161 qPrintable(name),
162 weight,
163 memcached_strerror(new_memc, rc));
164 }
165 } else {
166 if (useUDP) {
167 rc = memcached_server_add_udp_with_weight(
168 new_memc, name.toUtf8().constData(), port, weight);
169 } else {
170 rc = memcached_server_add_with_weight(
171 new_memc, name.toUtf8().constData(), port, weight);
172 }
173 if (Q_LIKELY(memcached_success(rc))) {
174 qCInfo(C_MEMCACHED,
175 "Added memcached server on host %s:%u with weight %u.",
176 qPrintable(name),
177 port,
178 weight);
179 } else {
180 qCWarning(
181 C_MEMCACHED,
182 "Failed to add memcached server on host %s:%u with weight %u: %s",
183 qPrintable(name),
184 port,
185 weight,
186 memcached_strerror(new_memc, rc));
187 }
188 }
189 }
190 }
191
192 if (Q_UNLIKELY(memcached_server_count(new_memc) == 0)) {
193 qCWarning(C_MEMCACHED,
194 "Failed to add any memcached server. Adding default server on localhost "
195 "port 11211.");
196 memcached_return_t rc = memcached_server_add(new_memc, "localhost", 11211);
197 if (Q_UNLIKELY(!memcached_success(rc))) {
198 qCCritical(C_MEMCACHED,
199 "Failed to add default memcached server. Memcached plugin will not "
200 "work without a configured server! %s",
201 memcached_strerror(new_memc, rc));
202 memcached_free(new_memc);
203 return false;
204 }
205 }
206 }
207
208 d->compression = map.value(QStringLiteral("compression"),
209 d->defaultConfig.value(QStringLiteral("compression"), false))
210 .toBool();
211 d->compressionLevel =
212 map.value(QStringLiteral("compression_level"),
213 d->defaultConfig.value(QStringLiteral("compression_level"), -1))
214 .toInt();
215 d->compressionThreshold =
216 map.value(QStringLiteral("compression_threshold"),
217 d->defaultConfig.value(QStringLiteral("compression_threshold"), 100))
218 .toInt();
219 if (d->compression) {
220 qCInfo(C_MEMCACHED,
221 "Compression: enabled (Compression level: %i, Compression threshold: %i bytes)",
222 d->compressionLevel,
223 d->compressionThreshold);
224 } else {
225 qCInfo(C_MEMCACHED, "Compression: disabled");
226 }
227
228 const QString encKey = map.value(QStringLiteral("encryption_key")).toString();
229 if (!encKey.isEmpty()) {
230 const QByteArray encKeyBa = encKey.toUtf8();
231 const memcached_return_t rt =
232 memcached_set_encoding_key(new_memc, encKeyBa.constData(), encKeyBa.size());
233 if (Q_LIKELY(memcached_success(rt))) {
234 qCInfo(C_MEMCACHED, "Encryption: enabled");
235 } else {
236 qCWarning(C_MEMCACHED,
237 "Failed to enable encryption: %s",
238 memcached_strerror(new_memc, rt));
239 }
240 } else {
241 qCInfo(C_MEMCACHED, "Encryption: disabled");
242 }
243
244#ifdef LIBMEMCACHED_WITH_SASL_SUPPORT
245# if LIBMEMCACHED_WITH_SASL_SUPPORT == 1
246 const QString saslUser = map.value(QStringLiteral("sasl_user")).toString();
247 const QString saslPass = map.value(QStringLiteral("sasl_password")).toString();
248 if (!saslUser.isEmpty() && !saslPass.isEmpty()) {
249 const memcached_return_t rt = memcached_set_sasl_auth_data(
250 new_memc, saslUser.toUtf8().constData(), saslPass.toUtf8().constData());
251 if (Q_LIKELY(memcached_success(rt))) {
252 qCInfo(C_MEMCACHED, "SASL authentication: enabled");
253 d->saslEnabled = true;
254 } else {
255 qCWarning(C_MEMCACHED,
256 "Failed to enable SASL authentication: %s",
257 memcached_strerror(new_memc, rt));
258 }
259 } else {
260 qCInfo(C_MEMCACHED, "SASL authentication: disabled");
261 }
262# endif
263#endif
264
265 if (d->memc) {
266 memcached_free(d->memc);
267 }
268 d->memc = new_memc;
269 ok = true;
270 }
271
272 if (ok) {
273 connect(app, &Application::postForked, this, [=] { mcd = this; });
274 app->loadTranslations(QStringLiteral("plugin_memcached"));
275 } else {
276 qCCritical(C_MEMCACHED) << "Failed to configure the connection to the memcached server(s)";
277 }
278
279 return ok;
280}
281
282bool Memcached::set(const QString &key,
283 const QByteArray &value,
284 time_t expiration,
286{
287 if (!mcd) {
288 qCCritical(C_MEMCACHED) << "Memcached plugin not registered";
289 if (returnType) {
290 *returnType = Memcached::PluginNotRegisterd;
291 }
292 return false;
293 }
294
295 const QByteArray _key = key.toUtf8();
296
297 MemcachedPrivate::Flags flags;
298 QByteArray _value = value;
299
300 if (mcd->d_ptr->compression && (_value.size() > mcd->d_ptr->compressionThreshold)) {
301 flags |= MemcachedPrivate::Compressed;
302 _value = qCompress(value, mcd->d_ptr->compressionLevel);
303 }
304
305 const memcached_return_t rt = memcached_set(mcd->d_ptr->memc,
306 _key.constData(),
307 _key.size(),
308 _value.constData(),
309 _value.size(),
310 expiration,
311 flags);
312
313 const bool ok = memcached_success(rt);
314
315 if (!ok) {
316 qCWarning(C_MEMCACHED,
317 "Failed to store key \"%s\": %s",
318 _key.constData(),
319 memcached_strerror(mcd->d_ptr->memc, rt));
320 }
321
322 MemcachedPrivate::setReturnType(returnType, rt);
323
324 return ok;
325}
326
327bool Memcached::setByKey(const QString &groupKey,
328 const QString &key,
329 const QByteArray &value,
330 time_t expiration,
331 MemcachedReturnType *returnType)
332{
333 if (!mcd) {
334 qCCritical(C_MEMCACHED) << "Memcached plugin not registered";
335 if (returnType) {
336 *returnType = Memcached::PluginNotRegisterd;
337 }
338 return false;
339 }
340
341 const QByteArray _key = key.toUtf8();
342 const QByteArray _groupKey = groupKey.toUtf8();
343
344 MemcachedPrivate::Flags flags;
345 QByteArray _value = value;
346
347 if (mcd->d_ptr->compression && (_value.size() > mcd->d_ptr->compressionThreshold)) {
348 flags |= MemcachedPrivate::Compressed;
349 _value = qCompress(value, mcd->d_ptr->compressionLevel);
350 }
351
352 const memcached_return_t rt = memcached_set_by_key(mcd->d_ptr->memc,
353 _groupKey.constData(),
354 _groupKey.size(),
355 _key.constData(),
356 _key.size(),
357 _value.constData(),
358 _value.size(),
359 expiration,
360 flags);
361
362 const bool ok = memcached_success(rt);
363
364 if (!ok) {
365 qCWarning(C_MEMCACHED,
366 "Failed to store key \"%s\" on group \"%s\": %s",
367 _key.constData(),
368 _groupKey.constData(),
369 memcached_strerror(mcd->d_ptr->memc, rt));
370 }
371
372 MemcachedPrivate::setReturnType(returnType, rt);
373
374 return ok;
375}
376
377bool Memcached::add(const QString &key,
378 const QByteArray &value,
379 time_t expiration,
380 MemcachedReturnType *returnType)
381{
382 if (!mcd) {
383 qCCritical(C_MEMCACHED) << "Memcached plugin not registered";
384 if (returnType) {
385 *returnType = Memcached::PluginNotRegisterd;
386 }
387 return false;
388 }
389
390 const QByteArray _key = key.toUtf8();
391
392 MemcachedPrivate::Flags flags;
393 QByteArray _value = value;
394
395 if (mcd->d_ptr->compression && (_value.size() > mcd->d_ptr->compressionThreshold)) {
396 flags |= MemcachedPrivate::Compressed;
397 _value = qCompress(value, mcd->d_ptr->compressionLevel);
398 }
399
400 const memcached_return_t rt = memcached_add(mcd->d_ptr->memc,
401 _key.constData(),
402 _key.size(),
403 _value.constData(),
404 _value.size(),
405 expiration,
406 flags);
407
408 const bool ok = memcached_success(rt);
409
410 if (!ok && (rt != MEMCACHED_NOTSTORED)) {
411 qCWarning(C_MEMCACHED,
412 "Failed to add key \"%s\": %s",
413 _key.constData(),
414 memcached_strerror(mcd->d_ptr->memc, rt));
415 }
416
417 MemcachedPrivate::setReturnType(returnType, rt);
418
419 return ok;
420}
421
422bool Memcached::addByKey(const QString &groupKey,
423 const QString &key,
424 const QByteArray &value,
425 time_t expiration,
426 MemcachedReturnType *returnType)
427{
428 if (!mcd) {
429 qCCritical(C_MEMCACHED) << "Memcached plugin not registered";
430 if (returnType) {
431 *returnType = Memcached::PluginNotRegisterd;
432 }
433 return false;
434 }
435
436 const QByteArray _key = key.toUtf8();
437 const QByteArray _groupKey = groupKey.toUtf8();
438
439 MemcachedPrivate::Flags flags;
440 QByteArray _value = value;
441
442 if (mcd->d_ptr->compression && (_value.size() > mcd->d_ptr->compressionThreshold)) {
443 flags |= MemcachedPrivate::Compressed;
444 _value = qCompress(value, mcd->d_ptr->compressionLevel);
445 }
446
447 const memcached_return_t rt = memcached_add_by_key(mcd->d_ptr->memc,
448 _groupKey.constData(),
449 _groupKey.size(),
450 _key.constData(),
451 _key.size(),
452 _value.constData(),
453 _value.size(),
454 expiration,
455 flags);
456
457 const bool ok = memcached_success(rt);
458
459 if (!ok && (rt != MEMCACHED_NOTSTORED)) {
460 qCWarning(C_MEMCACHED,
461 "Failed to add key \"%s\" on group \"%s\": %s",
462 _key.constData(),
463 _groupKey.constData(),
464 memcached_strerror(mcd->d_ptr->memc, rt));
465 }
466
467 MemcachedPrivate::setReturnType(returnType, rt);
468
469 return ok;
470}
471
473 const QByteArray &value,
474 time_t expiration,
475 MemcachedReturnType *returnType)
476{
477 if (!mcd) {
478 qCCritical(C_MEMCACHED) << "Memcached plugin not registered";
479 if (returnType) {
480 *returnType = Memcached::PluginNotRegisterd;
481 }
482 return false;
483 }
484
485 const QByteArray _key = key.toUtf8();
486
487 MemcachedPrivate::Flags flags;
488 QByteArray _value = value;
489
490 if (mcd->d_ptr->compression && (_value.size() > mcd->d_ptr->compressionThreshold)) {
491 flags |= MemcachedPrivate::Compressed;
492 _value = qCompress(value, mcd->d_ptr->compressionLevel);
493 }
494
495 const memcached_return_t rt = memcached_replace(mcd->d_ptr->memc,
496 _key.constData(),
497 _key.size(),
498 _value.constData(),
499 _value.size(),
500 expiration,
501 flags);
502
503 const bool ok = memcached_success(rt);
504
505 if (!ok && (rt != MEMCACHED_NOTSTORED)) {
506 qCWarning(C_MEMCACHED,
507 "Failed to replace key \"%s\": %s",
508 _key.constData(),
509 memcached_strerror(mcd->d_ptr->memc, rt));
510 }
511
512 MemcachedPrivate::setReturnType(returnType, rt);
513
514 return ok;
515}
516
517bool Memcached::replaceByKey(const QString &groupKey,
518 const QString &key,
519 const QByteArray &value,
520 time_t expiration,
521 MemcachedReturnType *returnType)
522{
523 if (!mcd) {
524 qCCritical(C_MEMCACHED) << "Memcached plugin not registered";
525 if (returnType) {
526 *returnType = Memcached::PluginNotRegisterd;
527 }
528 return false;
529 }
530
531 const QByteArray _groupKey = groupKey.toUtf8();
532 const QByteArray _key = key.toUtf8();
533
534 MemcachedPrivate::Flags flags;
535 QByteArray _value = value;
536
537 if (mcd->d_ptr->compression && (_value.size() > mcd->d_ptr->compressionThreshold)) {
538 flags |= MemcachedPrivate::Compressed;
539 _value = qCompress(value, mcd->d_ptr->compressionLevel);
540 }
541
542 const memcached_return_t rt = memcached_replace_by_key(mcd->d_ptr->memc,
543 _groupKey.constData(),
544 _groupKey.size(),
545 _key.constData(),
546 _key.size(),
547 _value.constData(),
548 _value.size(),
549 expiration,
550 flags);
551
552 const bool ok = memcached_success(rt);
553
554 if (!ok && (rt != MEMCACHED_NOTSTORED)) {
555 qCWarning(C_MEMCACHED,
556 "Failed to replace key \"%s\" on group \"%s\": %s",
557 _key.constData(),
558 _groupKey.constData(),
559 memcached_strerror(mcd->d_ptr->memc, rt));
560 }
561
562 MemcachedPrivate::setReturnType(returnType, rt);
563
564 return ok;
565}
566
568 uint64_t *cas,
570{
571 QByteArray retData;
572
573 if (!mcd) {
574 qCCritical(C_MEMCACHED) << "Memcached plugin not registered";
575 if (returnType) {
576 *returnType = Memcached::PluginNotRegisterd;
577 }
578 return retData;
579 }
580
581 memcached_return_t rt;
582 const QByteArray _key = key.toUtf8();
583 bool ok = false;
584
585 std::vector<const char *> keys;
586 std::vector<size_t> sizes;
587 keys.push_back(_key.constData());
588 sizes.push_back(_key.size());
589 rt = memcached_mget(mcd->d_ptr->memc, &keys[0], &sizes[0], keys.size());
590
591 if (memcached_success(rt)) {
592 memcached_result_st *result = memcached_fetch_result(mcd->d_ptr->memc, NULL, &rt);
593 if (result) {
594 retData = QByteArray(memcached_result_value(result), memcached_result_length(result));
595 if (cas) {
596 *cas = memcached_result_cas(result);
597 }
598 MemcachedPrivate::Flags flags = MemcachedPrivate::Flags(memcached_result_flags(result));
599 if (flags.testFlag(MemcachedPrivate::Compressed)) {
600 retData = qUncompress(retData);
601 }
602 ok = true;
603 // fetch another result even if there is no one to get
604 // a NULL for the internal of libmemcached
605 memcached_fetch_result(mcd->d_ptr->memc, NULL, NULL);
606 }
607 memcached_result_free(result);
608 }
609
610 if (!ok && (rt != MEMCACHED_NOTFOUND)) {
611 qCWarning(C_MEMCACHED,
612 "Failed to get data for key \"%s\": %s",
613 _key.constData(),
614 memcached_strerror(mcd->d_ptr->memc, rt));
615 }
616
617 MemcachedPrivate::setReturnType(returnType, rt);
618
619 return retData;
620}
621
623 const QString &key,
624 uint64_t *cas,
625 MemcachedReturnType *returnType)
626{
627 QByteArray retData;
628
629 if (!mcd) {
630 qCCritical(C_MEMCACHED) << "Memcached plugin not registered";
631 if (returnType) {
632 *returnType = Memcached::PluginNotRegisterd;
633 }
634 return retData;
635 }
636
637 memcached_return_t rt;
638 const QByteArray _groupKey = groupKey.toUtf8();
639 const QByteArray _key = key.toUtf8();
640 bool ok = false;
641
642 std::vector<const char *> keys;
643 std::vector<size_t> sizes;
644 keys.push_back(_key.constData());
645 sizes.push_back(_key.size());
646 rt = memcached_mget_by_key(mcd->d_ptr->memc,
647 _groupKey.constData(),
648 _groupKey.size(),
649 &keys[0],
650 &sizes[0],
651 keys.size());
652
653 if (memcached_success(rt)) {
654 memcached_result_st *result = memcached_fetch_result(mcd->d_ptr->memc, NULL, &rt);
655 if (result) {
656 retData = QByteArray(memcached_result_value(result), memcached_result_length(result));
657 if (cas) {
658 *cas = memcached_result_cas(result);
659 }
660 MemcachedPrivate::Flags flags = MemcachedPrivate::Flags(memcached_result_flags(result));
661 if (flags.testFlag(MemcachedPrivate::Compressed)) {
662 retData = qUncompress(retData);
663 }
664 ok = true;
665 // fetch another result even if there is no one to get
666 // a NULL for the internal of libmemcached
667 memcached_fetch_result(mcd->d_ptr->memc, NULL, NULL);
668 }
669 memcached_result_free(result);
670 }
671
672 if (!ok && (rt != MEMCACHED_NOTFOUND)) {
673 qCWarning(C_MEMCACHED,
674 "Failed to get data for key \"%s\" on group \"%s\": %s",
675 _key.constData(),
676 _groupKey.constData(),
677 memcached_strerror(mcd->d_ptr->memc, rt));
678 }
679
680 MemcachedPrivate::setReturnType(returnType, rt);
681
682 return retData;
683}
684
685bool Memcached::remove(const QString &key, MemcachedReturnType *returnType)
686{
687 if (!mcd) {
688 qCCritical(C_MEMCACHED) << "Memcached plugin not registered";
689 if (returnType) {
690 *returnType = Memcached::PluginNotRegisterd;
691 }
692 return false;
693 }
694
695 const QByteArray _key = key.toUtf8();
696
697 const memcached_return_t rt =
698 memcached_delete(mcd->d_ptr->memc, _key.constData(), _key.size(), 0);
699
700 const bool ok = memcached_success(rt);
701
702 if (!ok && (rt != MEMCACHED_NOTFOUND)) {
703 qCWarning(C_MEMCACHED,
704 "Failed to remove data for key \"%s\": %s",
705 _key.constData(),
706 memcached_strerror(mcd->d_ptr->memc, rt));
707 }
708
709 MemcachedPrivate::setReturnType(returnType, rt);
710
711 return ok;
712}
713
714bool Memcached::removeByKey(const QString &groupKey,
715 const QString &key,
716 MemcachedReturnType *returnType)
717{
718 if (!mcd) {
719 qCCritical(C_MEMCACHED) << "Memcached plugin not registered";
720 if (returnType) {
721 *returnType = Memcached::PluginNotRegisterd;
722 }
723 return false;
724 }
725
726 const QByteArray _groupKey = groupKey.toUtf8();
727 const QByteArray _key = key.toUtf8();
728
729 const memcached_return_t rt = memcached_delete_by_key(mcd->d_ptr->memc,
730 _groupKey.constData(),
731 _groupKey.size(),
732 _key.constData(),
733 _key.size(),
734 0);
735
736 const bool ok = memcached_success(rt);
737
738 if (!ok && (rt != MEMCACHED_NOTFOUND)) {
739 qCWarning(C_MEMCACHED,
740 "Failed to remove data for key \"%s\" on group \"%s\": %s",
741 _key.constData(),
742 _groupKey.constData(),
743 memcached_strerror(mcd->d_ptr->memc, rt));
744 }
745
746 MemcachedPrivate::setReturnType(returnType, rt);
747
748 return ok;
749}
750
751bool Memcached::exist(const QString &key, MemcachedReturnType *returnType)
752{
753 if (!mcd) {
754 qCCritical(C_MEMCACHED) << "Memcached plugin not registered";
755 if (returnType) {
756 *returnType = Memcached::PluginNotRegisterd;
757 }
758 return false;
759 }
760
761 const QByteArray _key = key.toUtf8();
762
763 const memcached_return_t rt = memcached_exist(mcd->d_ptr->memc, _key.constData(), _key.size());
764
765 const bool ok = memcached_success(rt);
766
767 if (!ok && (rt != MEMCACHED_NOTFOUND)) {
768 qCWarning(C_MEMCACHED,
769 "Failed to check existence of key \"%s\": %s",
770 _key.constData(),
771 memcached_strerror(mcd->d_ptr->memc, rt));
772 }
773
774 MemcachedPrivate::setReturnType(returnType, rt);
775
776 return ok;
777}
778
779bool Memcached::existByKey(const QString &groupKey,
780 const QString &key,
781 MemcachedReturnType *returnType)
782{
783 if (!mcd) {
784 qCCritical(C_MEMCACHED) << "Memcached plugin not registered";
785 if (returnType) {
786 *returnType = Memcached::PluginNotRegisterd;
787 }
788 return false;
789 }
790
791 const QByteArray _groupKey = groupKey.toUtf8();
792 const QByteArray _key = key.toUtf8();
793
794 const memcached_return_t rt = memcached_exist_by_key(
795 mcd->d_ptr->memc, _groupKey.constData(), _groupKey.size(), _key.constData(), _key.size());
796
797 const bool ok = memcached_success(rt);
798
799 if (!ok && (rt != MEMCACHED_NOTFOUND)) {
800 qCWarning(C_MEMCACHED,
801 "Failed to check existence of key \"%s\" in group \"%s\"",
802 _key.constData(),
803 _groupKey.constData());
804 }
805
806 MemcachedPrivate::setReturnType(returnType, rt);
807
808 return ok;
809}
810
812 uint32_t offset,
813 uint64_t *value,
814 MemcachedReturnType *returnType)
815{
816 if (!mcd) {
817 qCCritical(C_MEMCACHED) << "Memcached plugin not registered";
818 if (returnType) {
819 *returnType = Memcached::PluginNotRegisterd;
820 }
821 return false;
822 }
823
824 const QByteArray _key = key.toUtf8();
825
826 const memcached_return_t rt =
827 memcached_increment(mcd->d_ptr->memc, _key.constData(), _key.size(), offset, value);
828
829 const bool ok = memcached_success(rt);
830
831 if (!ok && (rt != MEMCACHED_NOTFOUND)) {
832 qCWarning(C_MEMCACHED,
833 "Failed to increment key \"%s\" by %u: %s",
834 _key.constData(),
835 offset,
836 memcached_strerror(mcd->d_ptr->memc, rt));
837 }
838
839 MemcachedPrivate::setReturnType(returnType, rt);
840
841 return ok;
842}
843
845 const QString &key,
846 uint64_t offset,
847 uint64_t *value,
848 MemcachedReturnType *returnType)
849{
850 if (!mcd) {
851 qCCritical(C_MEMCACHED) << "Memcached plugin not registered";
852 if (returnType) {
853 *returnType = Memcached::PluginNotRegisterd;
854 }
855 return false;
856 }
857
858 const QByteArray _group = groupKey.toUtf8();
859 const QByteArray _key = key.toUtf8();
860
861 const memcached_return_t rt = memcached_increment_by_key(mcd->d_ptr->memc,
862 _group.constData(),
863 _group.size(),
864 _key.constData(),
865 _key.size(),
866 offset,
867 value);
868
869 const bool ok = memcached_success(rt);
870
871 if (!ok && (rt != MEMCACHED_NOTFOUND)) {
872 qCWarning(C_MEMCACHED,
873 "Failed to increment \"%s\" key on group \"%s\" by %lu: %s",
874 _key.constData(),
875 _group.constData(),
876 offset,
877 memcached_strerror(mcd->d_ptr->memc, rt));
878 }
879
880 MemcachedPrivate::setReturnType(returnType, rt);
881
882 return ok;
883}
884
886 uint64_t offset,
887 uint64_t initial,
888 time_t expiration,
889 uint64_t *value,
890 MemcachedReturnType *returnType)
891{
892 if (!mcd) {
893 qCCritical(C_MEMCACHED) << "Memcached plugin not registered";
894 if (returnType) {
895 *returnType = Memcached::PluginNotRegisterd;
896 }
897 return false;
898 }
899
900 const QByteArray _key = key.toUtf8();
901
902 const memcached_return_t rt = memcached_increment_with_initial(
903 mcd->d_ptr->memc, _key.constData(), _key.size(), offset, initial, expiration, value);
904
905 const bool ok = memcached_success(rt);
906
907 if (!ok) {
908 qCWarning(C_MEMCACHED,
909 "Failed to increment or initialize key \"%s\" by offset %lu or initial %lu: %s",
910 _key.constData(),
911 offset,
912 initial,
913 memcached_strerror(mcd->d_ptr->memc, rt));
914 }
915
916 MemcachedPrivate::setReturnType(returnType, rt);
917
918 return ok;
919}
920
922 const QString &key,
923 uint64_t offset,
924 uint64_t initial,
925 time_t expiration,
926 uint64_t *value,
927 MemcachedReturnType *returnType)
928{
929 if (!mcd) {
930 qCCritical(C_MEMCACHED) << "Memcached plugin not registered";
931 if (returnType) {
932 *returnType = Memcached::PluginNotRegisterd;
933 }
934 return false;
935 }
936
937 const QByteArray _group = groupKey.toUtf8();
938 const QByteArray _key = key.toUtf8();
939
940 const memcached_return_t rt = memcached_increment_with_initial_by_key(mcd->d_ptr->memc,
941 _group.constData(),
942 _group.size(),
943 _key.constData(),
944 _key.size(),
945 offset,
946 initial,
947 expiration,
948 value);
949
950 const bool ok = memcached_success(rt);
951 if (!ok) {
952 qCWarning(C_MEMCACHED,
953 "Failed to increment or initialize key \"%s\" in group \"%s\" by offset %lu or "
954 "initial %lu: %s",
955 _key.constData(),
956 _group.constData(),
957 offset,
958 initial,
959 memcached_strerror(mcd->d_ptr->memc, rt));
960 }
961
962 MemcachedPrivate::setReturnType(returnType, rt);
963
964 return ok;
965}
966
968 uint32_t offset,
969 uint64_t *value,
970 MemcachedReturnType *returnType)
971{
972 if (!mcd) {
973 qCCritical(C_MEMCACHED) << "Memcached plugin not registered";
974 if (returnType) {
975 *returnType = Memcached::PluginNotRegisterd;
976 }
977 return false;
978 }
979
980 const QByteArray _key = key.toUtf8();
981
982 const memcached_return_t rt =
983 memcached_decrement(mcd->d_ptr->memc, _key.constData(), _key.size(), offset, value);
984
985 const bool ok = memcached_success(rt);
986
987 if (!ok && (rt != MEMCACHED_NOTFOUND)) {
988 qCWarning(C_MEMCACHED,
989 "Failed to decrement key \"%s\" by %u: %s",
990 _key.constData(),
991 offset,
992 memcached_strerror(mcd->d_ptr->memc, rt));
993 }
994
995 MemcachedPrivate::setReturnType(returnType, rt);
996
997 return ok;
998}
999
1001 const QString &key,
1002 uint64_t offset,
1003 uint64_t *value,
1004 MemcachedReturnType *returnType)
1005{
1006 if (!mcd) {
1007 qCCritical(C_MEMCACHED) << "Memcached plugin not registered";
1008 if (returnType) {
1009 *returnType = Memcached::PluginNotRegisterd;
1010 }
1011 return false;
1012 }
1013
1014 const QByteArray _group = groupKey.toUtf8();
1015 const QByteArray _key = key.toUtf8();
1016
1017 const memcached_return_t rt = memcached_decrement_by_key(mcd->d_ptr->memc,
1018 _group.constData(),
1019 _group.size(),
1020 _key.constData(),
1021 _key.size(),
1022 offset,
1023 value);
1024
1025 const bool ok = memcached_success(rt);
1026
1027 if (!ok && (rt != MEMCACHED_NOTFOUND)) {
1028 qCWarning(C_MEMCACHED,
1029 "Failed to decrement \"%s\" key on group \"%s\" by %lu: %s",
1030 _key.constData(),
1031 _group.constData(),
1032 offset,
1033 memcached_strerror(mcd->d_ptr->memc, rt));
1034 }
1035
1036 MemcachedPrivate::setReturnType(returnType, rt);
1037
1038 return ok;
1039}
1040
1042 uint64_t offset,
1043 uint64_t initial,
1044 time_t expiration,
1045 uint64_t *value,
1046 MemcachedReturnType *returnType)
1047{
1048 if (!mcd) {
1049 qCCritical(C_MEMCACHED) << "Memcached plugin not registered";
1050 if (returnType) {
1051 *returnType = Memcached::PluginNotRegisterd;
1052 }
1053 return false;
1054 }
1055
1056 const QByteArray _key = key.toUtf8();
1057
1058 const memcached_return_t rt = memcached_decrement_with_initial(
1059 mcd->d_ptr->memc, _key.constData(), _key.size(), offset, initial, expiration, value);
1060
1061 const bool ok = memcached_success(rt);
1062
1063 if (!ok) {
1064 qCWarning(C_MEMCACHED,
1065 "Failed to decrement or initialize key \"%s\" by offset %lu or initial %lu: %s",
1066 _key.constData(),
1067 offset,
1068 initial,
1069 memcached_strerror(mcd->d_ptr->memc, rt));
1070 }
1071
1072 MemcachedPrivate::setReturnType(returnType, rt);
1073
1074 return ok;
1075}
1076
1078 const QString &key,
1079 uint64_t offset,
1080 uint64_t initial,
1081 time_t expiration,
1082 uint64_t *value,
1083 MemcachedReturnType *returnType)
1084{
1085 if (!mcd) {
1086 qCCritical(C_MEMCACHED) << "Memcached plugin not registered";
1087 if (returnType) {
1088 *returnType = Memcached::PluginNotRegisterd;
1089 }
1090 return false;
1091 }
1092
1093 const QByteArray _group = groupKey.toUtf8();
1094 const QByteArray _key = key.toUtf8();
1095
1096 const memcached_return_t rt = memcached_decrement_with_initial_by_key(mcd->d_ptr->memc,
1097 _group.constData(),
1098 _group.size(),
1099 _key.constData(),
1100 _key.size(),
1101 offset,
1102 initial,
1103 expiration,
1104 value);
1105
1106 const bool ok = memcached_success(rt);
1107 if (!ok) {
1108 qCWarning(C_MEMCACHED,
1109 "Failed to increment or initialize key \"%s\" in group \"%s\" by offset %lu or "
1110 "initial %lu: %s",
1111 _key.constData(),
1112 _group.constData(),
1113 offset,
1114 initial,
1115 memcached_strerror(mcd->d_ptr->memc, rt));
1116 }
1117
1118 MemcachedPrivate::setReturnType(returnType, rt);
1119
1120 return ok;
1121}
1122
1123bool Memcached::cas(const QString &key,
1124 const QByteArray &value,
1125 time_t expiration,
1126 uint64_t cas,
1127 MemcachedReturnType *returnType)
1128{
1129 if (!mcd) {
1130 qCCritical(C_MEMCACHED) << "Memcached plugin not registered";
1131 if (returnType) {
1132 *returnType = Memcached::PluginNotRegisterd;
1133 }
1134 return false;
1135 }
1136
1137 const QByteArray _key = key.toUtf8();
1138
1139 MemcachedPrivate::Flags flags;
1140 QByteArray _value = value;
1141
1142 if (mcd->d_ptr->compression && (_value.size() > mcd->d_ptr->compressionThreshold)) {
1143 flags |= MemcachedPrivate::Compressed;
1144 _value = qCompress(value, mcd->d_ptr->compressionLevel);
1145 }
1146
1147 const memcached_return_t rt = memcached_cas(mcd->d_ptr->memc,
1148 _key.constData(),
1149 _key.size(),
1150 _value.constData(),
1151 _value.size(),
1152 expiration,
1153 flags,
1154 cas);
1155
1156 const bool ok = memcached_success(rt);
1157
1158 if (!ok && (rt != MEMCACHED_DATA_EXISTS)) {
1159 qCWarning(C_MEMCACHED,
1160 "Failed to compare and set (cas) key \"%s\": %s",
1161 _key.constData(),
1162 memcached_strerror(mcd->d_ptr->memc, rt));
1163 }
1164
1165 MemcachedPrivate::setReturnType(returnType, rt);
1166
1167 return ok;
1168}
1169
1170bool Memcached::casByKey(const QString &groupKey,
1171 const QString &key,
1172 const QByteArray &value,
1173 time_t expiration,
1174 uint64_t cas,
1175 MemcachedReturnType *returnType)
1176{
1177 if (!mcd) {
1178 qCCritical(C_MEMCACHED) << "Memcached plugin not registered";
1179 if (returnType) {
1180 *returnType = Memcached::PluginNotRegisterd;
1181 }
1182 return false;
1183 }
1184
1185 const QByteArray _group = groupKey.toUtf8();
1186 const QByteArray _key = key.toUtf8();
1187
1188 MemcachedPrivate::Flags flags;
1189 QByteArray _value = value;
1190
1191 if (mcd->d_ptr->compression && (_value.size() > mcd->d_ptr->compressionThreshold)) {
1192 flags |= MemcachedPrivate::Compressed;
1193 _value = qCompress(value, mcd->d_ptr->compressionLevel);
1194 }
1195
1196 const memcached_return_t rt = memcached_cas_by_key(mcd->d_ptr->memc,
1197 _group.constData(),
1198 _group.size(),
1199 _key.constData(),
1200 _key.size(),
1201 _value.constData(),
1202 _value.size(),
1203 expiration,
1204 flags,
1205 cas);
1206
1207 const bool ok = memcached_success(rt);
1208
1209 if (!ok && (rt != MEMCACHED_DATA_EXISTS)) {
1210 qCWarning(C_MEMCACHED,
1211 "Failed to compare and set (cas) key \"%s\" in group \"%s\": %s",
1212 _key.constData(),
1213 _group.constData(),
1214 memcached_strerror(mcd->d_ptr->memc, rt));
1215 }
1216
1217 MemcachedPrivate::setReturnType(returnType, rt);
1218
1219 return ok;
1220}
1221
1223{
1224 if (!mcd) {
1225 qCCritical(C_MEMCACHED) << "Memcached plugin not registered";
1226 if (returnType) {
1227 *returnType = Memcached::PluginNotRegisterd;
1228 }
1229 return false;
1230 }
1231
1232 const memcached_return_t rt = memcached_flush_buffers(mcd->d_ptr->memc);
1233
1234 const bool ok = memcached_success(rt);
1235
1236 if (!ok) {
1237 qCWarning(
1238 C_MEMCACHED, "Failed to flush buffers: %s", memcached_strerror(mcd->d_ptr->memc, rt));
1239 }
1240
1241 MemcachedPrivate::setReturnType(returnType, rt);
1242
1243 return ok;
1244}
1245
1246bool Memcached::flush(time_t expiration, MemcachedReturnType *returnType)
1247{
1248 if (!mcd) {
1249 qCCritical(C_MEMCACHED) << "Memcached plugin not registered";
1250 if (returnType) {
1251 *returnType = Memcached::PluginNotRegisterd;
1252 }
1253 return false;
1254 }
1255
1256 const memcached_return_t rt = memcached_flush(mcd->d_ptr->memc, expiration);
1257
1258 const bool ok = memcached_success(rt);
1259
1260 if (!ok) {
1261 qCWarning(C_MEMCACHED,
1262 "Failed to wipe clean (flush) server content: %s",
1263 memcached_strerror(mcd->d_ptr->memc, rt));
1264 }
1265
1266 MemcachedPrivate::setReturnType(returnType, rt);
1267
1268 return ok;
1269}
1270
1272 QHash<QString, uint64_t> *casValues,
1273 MemcachedReturnType *returnType)
1274{
1276
1277 if (!mcd) {
1278 qCCritical(C_MEMCACHED) << "Memcached plugin not registered";
1279 if (returnType) {
1280 *returnType = Memcached::PluginNotRegisterd;
1281 }
1282 return ret;
1283 }
1284
1285 if (keys.empty()) {
1286 qCWarning(C_MEMCACHED, "Can not get multiple values without a list of keys.");
1287 if (returnType) {
1288 *returnType = Memcached::BadKeyProvided;
1289 }
1290 return ret;
1291 }
1292
1293 std::vector<char *> _keys;
1294 _keys.reserve(keys.size());
1295 std::vector<size_t> _keysSizes;
1296 _keysSizes.reserve(keys.size());
1297
1298 for (const QString &key : keys) {
1299 const QByteArray _key = key.toUtf8();
1300 char *data = new char[_key.size() + 1];
1301 qstrcpy(data, _key.data());
1302 _keys.push_back(data);
1303 _keysSizes.push_back(_key.size());
1304 }
1305
1306 memcached_return_t rt;
1307 bool ok = false;
1308
1309 rt = memcached_mget(mcd->d_ptr->memc, &_keys[0], &_keysSizes[0], _keys.size());
1310
1311 if (memcached_success(rt)) {
1312 ok = true;
1313 ret.reserve(keys.size());
1314 while ((rt != MEMCACHED_END) && (rt != MEMCACHED_NOTFOUND)) {
1315 memcached_result_st *result = memcached_fetch_result(mcd->d_ptr->memc, NULL, &rt);
1316 if (result) {
1317 const QString rk = QString::fromUtf8(memcached_result_key_value(result),
1318 memcached_result_key_length(result));
1319 QByteArray rd(memcached_result_value(result), memcached_result_length(result));
1320 if (casValues) {
1321 casValues->insert(rk, memcached_result_cas(result));
1322 }
1323 MemcachedPrivate::Flags flags =
1324 MemcachedPrivate::Flags(memcached_result_flags(result));
1325 if (flags.testFlag(MemcachedPrivate::Compressed)) {
1326 rd = qUncompress(rd);
1327 }
1328 ret.insert(rk, rd);
1329 }
1330 memcached_result_free(result);
1331 }
1332 }
1333
1334 for (char *c : _keys) {
1335 delete[] c;
1336 }
1337
1338 if (!ok) {
1339 qCWarning(C_MEMCACHED,
1340 "Failed to get values for multiple keys: %s",
1341 memcached_strerror(mcd->d_ptr->memc, rt));
1342 }
1343
1344 MemcachedPrivate::setReturnType(returnType, rt);
1345
1346 return ret;
1347}
1348
1350 const QStringList &keys,
1351 QHash<QString, uint64_t> *casValues,
1352 MemcachedReturnType *returnType)
1353{
1355
1356 if (!mcd) {
1357 qCCritical(C_MEMCACHED) << "Memcached plugin not registered";
1358 if (returnType) {
1359 *returnType = Memcached::PluginNotRegisterd;
1360 }
1361 return ret;
1362 }
1363
1364 if (groupKey.isEmpty()) {
1365 qCWarning(C_MEMCACHED,
1366 "Can not get multiple values from specific server when groupKey is empty.");
1367 if (returnType) {
1368 *returnType = Memcached::BadKeyProvided;
1369 }
1370 return ret;
1371 }
1372
1373 if (keys.empty()) {
1374 qCWarning(C_MEMCACHED, "Can not get multiple values without a list of keys.");
1375 if (returnType) {
1376 *returnType = Memcached::BadKeyProvided;
1377 }
1378 return ret;
1379 }
1380
1381 const QByteArray _group = groupKey.toUtf8();
1382
1383 std::vector<char *> _keys;
1384 _keys.reserve(keys.size());
1385 std::vector<size_t> _keysSizes;
1386 _keysSizes.reserve(keys.size());
1387
1388 for (const QString &key : keys) {
1389 const QByteArray _key = key.toUtf8();
1390 char *data = new char[_key.size() + 1];
1391 strcpy(data, _key.data());
1392 _keys.push_back(data);
1393 _keysSizes.push_back(_key.size());
1394 }
1395
1396 memcached_return_t rt;
1397 bool ok = false;
1398
1399 rt = memcached_mget_by_key(mcd->d_ptr->memc,
1400 _group.constData(),
1401 _group.size(),
1402 &_keys[0],
1403 &_keysSizes[0],
1404 _keys.size());
1405
1406 if (memcached_success(rt)) {
1407 ok = true;
1408 ret.reserve(keys.size());
1409 while ((rt != MEMCACHED_END) && (rt != MEMCACHED_NOTFOUND)) {
1410 memcached_result_st *result = memcached_fetch_result(mcd->d_ptr->memc, NULL, &rt);
1411 if (result) {
1412 const QString rk = QString::fromUtf8(memcached_result_key_value(result),
1413 memcached_result_key_length(result));
1414 QByteArray rd(memcached_result_value(result), memcached_result_length(result));
1415 if (casValues) {
1416 casValues->insert(rk, memcached_result_cas(result));
1417 }
1418 MemcachedPrivate::Flags flags =
1419 MemcachedPrivate::Flags(memcached_result_flags(result));
1420 if (flags.testFlag(MemcachedPrivate::Compressed)) {
1421 rd = qUncompress(rd);
1422 }
1423 ret.insert(rk, rd);
1424 }
1425 memcached_result_free(result);
1426 }
1427 }
1428
1429 for (char *c : _keys) {
1430 delete[] c;
1431 }
1432
1433 if (!ok) {
1434 qCWarning(C_MEMCACHED,
1435 "Failed to get values for multiple keys in group \"%s\": %s",
1436 _group.constData(),
1437 memcached_strerror(mcd->d_ptr->memc, rt));
1438 }
1439
1440 MemcachedPrivate::setReturnType(returnType, rt);
1441
1442 return ret;
1443}
1444
1445bool Memcached::touch(const QString &key, time_t expiration, MemcachedReturnType *returnType)
1446{
1447 if (!mcd) {
1448 qCCritical(C_MEMCACHED) << "Memcached plugin not registered";
1449 if (returnType) {
1450 *returnType = Memcached::PluginNotRegisterd;
1451 }
1452 return false;
1453 }
1454
1455 const QByteArray _key = key.toUtf8();
1456
1457 const memcached_return_t rt =
1458 memcached_touch(mcd->d_ptr->memc, _key.constData(), _key.size(), expiration);
1459
1460 const bool ok = memcached_success(rt);
1461
1462 if (!ok) {
1463 qCWarning(C_MEMCACHED,
1464 "Failed to touch key \"%s\" with new expiration time %lu: %s",
1465 _key.constData(),
1466 expiration,
1467 memcached_strerror(mcd->d_ptr->memc, rt));
1468 }
1469
1470 MemcachedPrivate::setReturnType(returnType, rt);
1471
1472 return ok;
1473}
1474
1475bool Memcached::touchByKey(const QString &groupKey,
1476 const QString &key,
1477 time_t expiration,
1478 MemcachedReturnType *returnType)
1479{
1480 if (!mcd) {
1481 qCCritical(C_MEMCACHED) << "Memcached plugin not registered";
1482 if (returnType) {
1483 *returnType = Memcached::PluginNotRegisterd;
1484 }
1485 return false;
1486 }
1487
1488 const QByteArray _group = groupKey.toUtf8();
1489 const QByteArray _key = key.toUtf8();
1490
1491 const memcached_return_t rt = memcached_touch_by_key(mcd->d_ptr->memc,
1492 _group.constData(),
1493 _group.size(),
1494 _key.constData(),
1495 _key.size(),
1496 expiration);
1497
1498 const bool ok = memcached_success(rt);
1499
1500 if (!ok) {
1501 qCWarning(C_MEMCACHED,
1502 "Failed to touch key \"%s\" in group \"%s\" with new expiration time %lu: %s",
1503 _key.constData(),
1504 _group.constData(),
1505 expiration,
1506 memcached_strerror(mcd->d_ptr->memc, rt));
1507 }
1508
1509 MemcachedPrivate::setReturnType(returnType, rt);
1510
1511 return ok;
1512}
1513
1515{
1516 switch (rt) {
1517 case Memcached::Success:
1518 return c->translate("Cutelyst::Memcached", "The request was successfully executed.");
1519 case Memcached::Failure:
1520 return c->translate("Cutelyst::Memcached",
1521 "An unknown failure has occurred in the Memcached server.");
1523 return c->translate("Cutelyst::Memcached", "A DNS failure has occurred.");
1525 return c->translate(
1526 "Cutelyst::Memcached",
1527 "An unknown error has occurred while trying to connect to a Memcached server.");
1529 return c->translate("Cutelyst::Memcached",
1530 "An error has occurred while trying to write to a Memcached server.");
1532 return c->translate("Cutelyst::Memcached",
1533 "An error has occurred while trying to read from a Memcached server.");
1535 return c->translate(
1536 "Cutelyst::Memcached",
1537 "An unknown error has occurred while trying to read from a Memcached server. This only "
1538 "occures when either there is a bug in the server, or in rare cases where an ethernet "
1539 "NIC is reporting dubious information.");
1541 return c->translate("Cutelyst::Memcached",
1542 "An unknown error has occurred in the Memcached protocol.");
1544 return c->translate("Cutelyst::Memcached",
1545 "An unknown Memcached client error has occurred internally.");
1547 return c->translate("Cutelyst::Memcached",
1548 "An unknown error has occurred in the Memcached server.");
1549 case Memcached::Error:
1550 return c->translate("Cutelyst::Memcached", "A general error occurred.");
1552 return c->translate("Cutelyst::Memcached", "The data for the given key alrey exists.");
1554 return c->translate("Cutelyst::Memcached",
1555 "The data requested with the key given was not found.");
1557 return c->translate("Cutelyst::Memcached", "The request to store an object failed.");
1558 case Memcached::Stored:
1559 return c->translate("Cutelyst::Memcached",
1560 "The requested object has been successfully stored on the server.");
1562 return c->translate("Cutelyst::Memcached", "The object requested was not found.");
1564 return c->translate("Cutelyst::Memcached",
1565 "An error has occurred while trying to allocate memory.");
1567 return c->translate("Cutelyst::Memcached",
1568 "The read operation was only partcially successful.");
1570 return c->translate("Cutelyst::Memcached",
1571 "A multi request has been made, and some underterminate number of "
1572 "errors have occurred.");
1574 return c->translate("Cutelyst::Memcached",
1575 "No servers have been added to the Memcached plugin.");
1576 case Memcached::End:
1577 return c->translate(
1578 "Cutelyst::Memcached",
1579 "The Memcached server has completed returning all of the objects requested.");
1580 case Memcached::Deleted:
1581 return c->translate("Cutelyst::Memcached",
1582 "The object requested by the key has been deleted.");
1583 case Memcached::Stat:
1584 return c->translate("Cutelyst::Memcached",
1585 "A “stat” command has been returned in the protocol.");
1586 case Memcached::Errno:
1587 return c->translate("Cutelyst::Memcached",
1588 "An error has occurred in the driver which has set errno.");
1590 return c->translate("Cutelyst::Memcached",
1591 "The given method is not supported in the Memcached server.");
1593 return c->translate("Cutelyst::Memcached",
1594 "A request has been made, but the Memcached server has not finished "
1595 "the fetch of the last request.");
1596 case Memcached::Timeout:
1597 return c->translate("Cutelyst::Memcached", "The operation has timed out.");
1599 return c->translate("Cutelyst::Memcached", "The request has been buffered.");
1601 return c->translate("Cutelyst::Memcached", "The key provided is not a valid key.");
1603 return c->translate(
1604 "Cutelyst::Memcached",
1605 "The Memcached server you are connecting to has an invalid protocol. Most likely you "
1606 "are connecting to an older server that does not speak the binary protocol.");
1608 return c->translate("Cutelyst::Memcached",
1609 "The requested Memcached server has been marked dead.");
1611 return c->translate("Cutelyst::Memcached",
1612 "The Memcached server you are communicating with has a stat key which "
1613 "has not be defined in the protocol.");
1614 case Memcached::E2Big:
1615 return c->translate("Cutelyst::Memcached",
1616 "Item is too large for the Memcached server to store.");
1618 return c->translate("Cutelyst::Memcached",
1619 "The arguments supplied to the given function were not valid.");
1621 return c->translate(
1622 "Cutelyst::Memcached",
1623 "The key that has been provided is too large for the given Memcached server.");
1625 return c->translate("Cutelyst::Memcached",
1626 "An unknown issue has occurred during SASL authentication.");
1628 return c->translate("Cutelyst::Memcached",
1629 "The credentials provided are not valid for this Memcached server.");
1631 return c->translate("Cutelyst::Memcached", "Authentication has been paused.");
1633 return c->translate(
1634 "Cutelyst::Memcached",
1635 "An error has occurred while trying to parse the configuration string.");
1637 return c->translate("Cutelyst::Memcached",
1638 "An error has occurred in parsing the configuration string.");
1640 return c->translate("Cutelyst::Memcached",
1641 "The method that was requested has been deprecated.");
1643 return c->translate(
1644 "Cutelyst::Memcached",
1645 "The Cutelyst Memcached plugin has not been registered to the application.");
1646 default:
1647 return c->translate("Cutelyst::Memcached", "An unknown error has occurred.");
1648 }
1649}
1650
1655
1656// clang-format off
1657Memcached::MemcachedReturnType MemcachedPrivate::returnTypeConvert(memcached_return_t rt)
1658{
1659 switch (rt) {
1660 case MEMCACHED_SUCCESS: return Memcached::Success;
1661 case MEMCACHED_FAILURE: return Memcached::Failure;
1662 case MEMCACHED_HOST_LOOKUP_FAILURE: return Memcached::HostLookupFailure;
1663 case MEMCACHED_CONNECTION_FAILURE: return Memcached::ConnectionFailure;
1664 case MEMCACHED_CONNECTION_BIND_FAILURE: return Memcached::HostLookupFailure;
1665 case MEMCACHED_WRITE_FAILURE: return Memcached::WriteFailure;
1666 case MEMCACHED_READ_FAILURE: return Memcached::ReadFailure;
1667 case MEMCACHED_UNKNOWN_READ_FAILURE: return Memcached::UnknownReadFailure;
1668 case MEMCACHED_PROTOCOL_ERROR: return Memcached::ProtocolError;
1669 case MEMCACHED_CLIENT_ERROR: return Memcached::ClientError;
1670 case MEMCACHED_SERVER_ERROR: return Memcached::ServerError;
1671 case MEMCACHED_ERROR: return Memcached::Error;
1672 case MEMCACHED_DATA_EXISTS: return Memcached::DataExists;
1673 case MEMCACHED_DATA_DOES_NOT_EXIST: return Memcached::DataDoesNotExist;
1674 case MEMCACHED_NOTSTORED: return Memcached::NotStored;
1675 case MEMCACHED_STORED: return Memcached::Stored;
1676 case MEMCACHED_NOTFOUND: return Memcached::NotFound;
1677 case MEMCACHED_MEMORY_ALLOCATION_FAILURE: return Memcached::MemoryAllocationFailure;
1678 case MEMCACHED_PARTIAL_READ: return Memcached::PartialRead;
1679 case MEMCACHED_SOME_ERRORS: return Memcached::SomeErrors;
1680 case MEMCACHED_NO_SERVERS: return Memcached::NoServers;
1681 case MEMCACHED_END: return Memcached::End;
1682 case MEMCACHED_DELETED: return Memcached::Deleted;
1683 case MEMCACHED_STAT: return Memcached::Stat;
1684 case MEMCACHED_ERRNO: return Memcached::Errno;
1685 case MEMCACHED_NOT_SUPPORTED: return Memcached::NotSupported;
1686 case MEMCACHED_FETCH_NOTFINISHED: return Memcached::FetchNotFinished;
1687 case MEMCACHED_TIMEOUT: return Memcached::Timeout;
1688 case MEMCACHED_BUFFERED: return Memcached::Buffered;
1689 case MEMCACHED_BAD_KEY_PROVIDED: return Memcached::BadKeyProvided;
1690 case MEMCACHED_INVALID_HOST_PROTOCOL: return Memcached::InvalidHostProtocol;
1691 case MEMCACHED_SERVER_MARKED_DEAD: return Memcached::ServerMarkedDead;
1692 case MEMCACHED_UNKNOWN_STAT_KEY: return Memcached::UnknownStatKey;
1693 case MEMCACHED_E2BIG: return Memcached::E2Big;
1694 case MEMCACHED_INVALID_ARGUMENTS: return Memcached::InvalidArguments;
1695 case MEMCACHED_KEY_TOO_BIG: return Memcached::KeyTooBig;
1696 case MEMCACHED_AUTH_PROBLEM: return Memcached::AuthProblem;
1697 case MEMCACHED_AUTH_FAILURE: return Memcached::AuthFailure;
1698 case MEMCACHED_AUTH_CONTINUE: return Memcached::AuthContinue;
1699 case MEMCACHED_PARSE_ERROR: return Memcached::ParseError;
1700 case MEMCACHED_PARSE_USER_ERROR: return Memcached::ParseUserError;
1701 case MEMCACHED_DEPRECATED: return Memcached::Deprecated;
1702 case MEMCACHED_IN_PROGRESS: return Memcached::InProgress;
1703 case MEMCACHED_SERVER_TEMPORARILY_DISABLED: return Memcached::ServerTemporaryDisabled;
1704 case MEMCACHED_SERVER_MEMORY_ALLOCATION_FAILURE: return Memcached::ServerMemoryAllocationFailure;
1705 case MEMCACHED_MAXIMUM_RETURN: return Memcached::MaximumReturn;
1706 default: return Memcached::Success;
1707 }
1708}
1709// clang-format on
1710
1711void MemcachedPrivate::setReturnType(Memcached::MemcachedReturnType *rt1, memcached_return_t rt2)
1712{
1713 if (rt1) {
1714 *rt1 = MemcachedPrivate::returnTypeConvert(rt2);
1715 }
1716}
1717
1718#include "moc_memcached.cpp"
The Cutelyst Application.
Definition application.h:43
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)
The Cutelyst Context.
Definition context.h:39
QString translate(const char *context, const char *sourceText, const char *disambiguation=nullptr, int n=-1) const
Definition context.cpp:490
QVariantMap config(const QString &entity) const
user configuration for the application
Definition engine.cpp:290
Cutelyst Memcached plugin.
Definition memcached.h:158
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)
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
Definition memcached.cpp:39
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
Definition memcached.cpp:29
static const time_t expirationNotAdd
Definition memcached.h:691
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)
Definition memcached.cpp:33
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)
Definition memcached.cpp:23
static QVersionNumber libMemcachedVersion()
Returns the version of the currently used libmemcached.
Plugin(Application *parent)
Definition plugin.cpp:12
The Cutelyst namespace holds all public Cutelyst API.
Definition Mainpage.dox:8
const char * constData() const const
char * data()
int size() const const
iterator insert(const Key &key, const T &value)
void reserve(int size)
bool empty() const const
void push_back(const T &value)
int size() const const
QMetaObject::Connection connect(const QObject *sender, const char *signal, const QObject *receiver, const char *method, Qt::ConnectionType type)
QObject * parent() const const
QString fromUtf8(const char *str, int size)
bool isEmpty() const const
QString & replace(int position, int n, QChar after)
bool startsWith(const QString &s, Qt::CaseSensitivity cs) const const
QString toUpper() const const
QByteArray toUtf8() const const
QString join(const QString &separator) const const
QList< QStringView > split(QStringView sep, Qt::SplitBehavior behavior, Qt::CaseSensitivity cs) const const
QVersionNumber fromString(const QString &string, int *suffixIndex)