cutelyst 4.3.0
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
12#include <QLoggingCategory>
13#include <QStringList>
14
15Q_LOGGING_CATEGORY(C_MEMCACHED, "cutelyst.plugin.memcached", QtWarningMsg)
16
17using namespace Cutelyst;
18
19// NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables)
20static thread_local Memcached *mcd = nullptr;
21const time_t Memcached::expirationNotAdd{static_cast<time_t>(MEMCACHED_EXPIRATION_NOT_ADD)};
22const std::chrono::seconds Memcached::expirationNotAddDuration{
23 static_cast<std::chrono::seconds::rep>(MEMCACHED_EXPIRATION_NOT_ADD)};
24
26 : Plugin(parent)
27 , d_ptr(new MemcachedPrivate)
28{
29}
30
31Memcached::Memcached(Application *parent, const QVariantMap &defaultConfig)
32 : Plugin(parent)
33 , d_ptr(new MemcachedPrivate(defaultConfig))
34{
35}
36
37Memcached::~Memcached() = default;
38
39void Memcached::setDefaultConfig(const QVariantMap &defaultConfig)
40{
41 Q_D(Memcached);
42 d->defaultConfig = defaultConfig;
43}
44
46{
47 Q_D(Memcached);
48
49 d->loadedConfig = app->engine()->config(u"Cutelyst_Memcached_Plugin"_qs);
50 QStringList memcConfig;
51
52 const QStringList serverList = d->config(u"servers"_qs).toString().split(u';');
53
54 if (serverList.empty()) {
55 memcConfig.push_back(u"--SERVER=localhost"_qs);
56 }
57
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,
63 u"noreply"_qs,
64 u"randomize_replica_read"_qs,
65 u"sort_hosts"_qs,
66 u"support_cas"_qs,
67 u"use_udp"_qs,
68 u"tcp_nodelay"_qs,
69 u"tcp_keepalive"_qs}) {
70 if (d->config(flag, false).toBool()) {
71 const QString flagStr = u"--" + flag.toUpper().replace(u'_', u'-');
72 memcConfig.push_back(flagStr);
73 }
74 }
75
76 const bool useUDP = d->config(u"use_udp"_qs, false).toBool();
77
78 for (const QString &opt : {
79 u"connect_timeout"_qs,
80 u"distribution"_qs,
81 u"hash"_qs,
82 u"number_of_replicas"_qs,
83 u"namespace"_qs,
84 u"retry_timeout"_qs,
85 u"server_failure_limit"_qs,
86 u"snd_timeout"_qs,
87 u"socket_recv_size"_qs,
88 u"socket_send_size"_qs,
89 u"poll_timeout"_qs,
90 u"io_bytes_watermark"_qs,
91 u"io_key_prefetch"_qs,
92 u"io_msg_watermark"_qs,
93 u"rcv_timeout"_qs,
94 }) {
95 const QString _val = d->config(opt).toString();
96 if (!_val.isEmpty()) {
97 const QString optStr = u"--" + opt.toUpper().replace(u'_', u'-') + u'=' + _val;
98 memcConfig.push_back(optStr); // clazy:exclude=reserve-candidates
99 }
100 }
101
102 const QByteArray configString = memcConfig.join(u' ').toUtf8();
103
104 bool ok = false;
105
106 qCInfo(C_MEMCACHED) << "Setting up connection to memcached servers using libmemcached"
107 << memcached_lib_version()
108 << "with the following configuration string:" << configString;
109
110 memcached_st *new_memc = memcached(configString.constData(), configString.size());
111
112 if (new_memc) {
113
114 if (!serverList.empty()) {
115 for (const QString &server : serverList) {
116 const auto serverParts = QStringView(server).split(u',');
117 QString name;
118 uint16_t port = MemcachedPrivate::defaultPort;
119 uint32_t weight = 1;
120 bool isSocket = false;
121 if (!serverParts.empty()) {
122 const auto part0 = serverParts.at(0);
123 if (!part0.isEmpty()) {
124 name = part0.toString();
125 isSocket = name.startsWith(u'/');
126 }
127 if (serverParts.size() > 1) {
128 const auto part1 = serverParts.at(1);
129 if (!part1.isEmpty()) {
130 if (isSocket) {
131 weight = part1.toUInt();
132 } else {
133 port = part1.toUInt();
134 }
135 }
136 if (!isSocket && (serverParts.size() > 2)) {
137 const auto part2 = serverParts.at(2);
138 if (!part2.isEmpty()) {
139 weight = part2.toUInt();
140 }
141 }
142 }
143 }
144 if (!name.isEmpty()) {
145 memcached_return_t rc{MEMCACHED_FAILURE};
146 if (isSocket) {
147 rc = memcached_server_add_unix_socket_with_weight(
148 new_memc, name.toUtf8().constData(), weight);
149 if (Q_LIKELY(memcached_success(rc))) {
150 qCInfo(C_MEMCACHED) << "Added memcached server on socket" << name
151 << "with weight" << weight;
152 } else {
153 qCWarning(C_MEMCACHED).nospace()
154 << "Failed to add memcached server on socket " << name
155 << " with weight " << weight << ": "
156 << memcached_strerror(new_memc, rc);
157 }
158 } else {
159 if (useUDP) {
160 rc = memcached_server_add_udp_with_weight(
161 new_memc, name.toUtf8().constData(), port, weight);
162 } else {
163 rc = memcached_server_add_with_weight(
164 new_memc, name.toUtf8().constData(), port, weight);
165 }
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;
170 } else {
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);
175 }
176 }
177 }
178 }
179
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"
183 << "port 11211.";
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);
191 return false;
192 }
193 }
194 }
195
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)
200 .toInt();
201 if (d->compression) {
202 qCInfo(C_MEMCACHED).nospace()
203 << "Compression: enabled (Compression level: " << d->compressionLevel
204 << ", Compression threshold: " << d->compressionThreshold << " bytes";
205 } else {
206 qCInfo(C_MEMCACHED) << "Compression: disabled";
207 }
208
209 const QString encKey = d->config(u"encryption_key"_qs).toString();
210 if (!encKey.isEmpty()) {
211 const QByteArray encKeyBa = encKey.toUtf8();
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";
216 } else {
217 qCWarning(C_MEMCACHED)
218 << "Failed to enable encryption:" << memcached_strerror(new_memc, rt);
219 }
220 } else {
221 qCInfo(C_MEMCACHED) << "Encryption: disabled";
222 }
223
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();
228 if (!saslUser.isEmpty() && !saslPass.isEmpty()) {
229 const memcached_return_t rt = memcached_set_sasl_auth_data(
230 new_memc, saslUser.toUtf8().constData(), saslPass.toUtf8().constData());
231 if (Q_LIKELY(memcached_success(rt))) {
232 qCInfo(C_MEMCACHED) << "SASL authentication: enabled";
233 d->saslEnabled = true;
234 } else {
235 qCWarning(C_MEMCACHED)
236 << "Failed to enable SASL authentication:" << memcached_strerror(new_memc, rt);
237 }
238 } else {
239 qCInfo(C_MEMCACHED) << "SASL authentication: disabled";
240 }
241# endif
242#endif
243
244 if (d->memc) {
245 memcached_free(d->memc);
246 }
247 d->memc = new_memc;
248 ok = true;
249 }
250
251 if (ok) {
252 connect(app, &Application::postForked, this, [this] { mcd = this; });
253 app->loadTranslations(u"plugin_memcached"_qs);
254 } else {
255 qCCritical(C_MEMCACHED) << "Failed to configure the connection to the memcached server(s)";
256 }
257
258 return ok;
259}
260
262 const QByteArray &value,
263 time_t expiration,
264 ReturnType *returnType)
265{
266 if (!MemcachedPrivate::isRegistered(mcd, returnType)) {
267 return false;
268 }
269
270 MemcachedPrivate::Flags flags;
271 const QByteArray _value = MemcachedPrivate::compressIfNeeded(value, flags);
272
273 const memcached_return_t rt = memcached_set(mcd->d_ptr->memc,
274 key.constData(),
275 key.size(),
276 _value.constData(),
277 _value.size(),
278 expiration,
279 flags);
280
281 const bool ok = memcached_success(rt);
282
283 if (!ok) {
284 qCWarning(C_MEMCACHED).nospace()
285 << "Failed to store key " << key << ": " << memcached_strerror(mcd->d_ptr->memc, rt);
286 }
287
288 MemcachedPrivate::setReturnType(returnType, rt);
289
290 return ok;
291}
292
294 QByteArrayView key,
295 const QByteArray &value,
296 time_t expiration,
297 ReturnType *returnType)
298{
299 if (!MemcachedPrivate::isRegistered(mcd, returnType)) {
300 return false;
301 }
302
303 MemcachedPrivate::Flags flags;
304 const QByteArray _value = MemcachedPrivate::compressIfNeeded(value, flags);
305
306 const memcached_return_t rt = memcached_set_by_key(mcd->d_ptr->memc,
307 groupKey.constData(),
308 groupKey.size(),
309 key.constData(),
310 key.size(),
311 _value.constData(),
312 _value.size(),
313 expiration,
314 flags);
315
316 const bool ok = memcached_success(rt);
317
318 if (!ok) {
319 qCWarning(C_MEMCACHED).nospace()
320 << "Failed to store key " << key << " on group " << groupKey << ": "
321 << memcached_strerror(mcd->d_ptr->memc, rt);
322 }
323
324 MemcachedPrivate::setReturnType(returnType, rt);
325
326 return ok;
327}
328
330 const QByteArray &value,
331 time_t expiration,
332 ReturnType *returnType)
333{
334 if (!MemcachedPrivate::isRegistered(mcd, returnType)) {
335 return false;
336 }
337
338 MemcachedPrivate::Flags flags;
339 const QByteArray _value = MemcachedPrivate::compressIfNeeded(value, flags);
340
341 const memcached_return_t rt = memcached_add(mcd->d_ptr->memc,
342 key.constData(),
343 key.size(),
344 _value.constData(),
345 _value.size(),
346 expiration,
347 flags);
348
349 const bool ok = memcached_success(rt);
350
351 if (!ok && (rt != MEMCACHED_NOTSTORED)) {
352 qCWarning(C_MEMCACHED).nospace()
353 << "Failed to add key " << key << ": " << memcached_strerror(mcd->d_ptr->memc, rt);
354 }
355
356 MemcachedPrivate::setReturnType(returnType, rt);
357
358 return ok;
359}
360
362 QByteArrayView key,
363 const QByteArray &value,
364 time_t expiration,
365 ReturnType *returnType)
366{
367 if (!MemcachedPrivate::isRegistered(mcd, returnType)) {
368 return false;
369 }
370
371 MemcachedPrivate::Flags flags;
372 const QByteArray _value = MemcachedPrivate::compressIfNeeded(value, flags);
373
374 const memcached_return_t rt = memcached_add_by_key(mcd->d_ptr->memc,
375 groupKey.constData(),
376 groupKey.size(),
377 key.constData(),
378 key.size(),
379 _value.constData(),
380 _value.size(),
381 expiration,
382 flags);
383
384 const bool ok = memcached_success(rt);
385
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);
389 }
390
391 MemcachedPrivate::setReturnType(returnType, rt);
392
393 return ok;
394}
395
397 const QByteArray &value,
398 time_t expiration,
399 ReturnType *returnType)
400{
401 if (!MemcachedPrivate::isRegistered(mcd, returnType)) {
402 return false;
403 }
404
405 MemcachedPrivate::Flags flags;
406 const QByteArray _value = MemcachedPrivate::compressIfNeeded(value, flags);
407
408 const memcached_return_t rt = memcached_replace(mcd->d_ptr->memc,
409 key.constData(),
410 key.size(),
411 _value.constData(),
412 _value.size(),
413 expiration,
414 flags);
415
416 const bool ok = memcached_success(rt);
417
418 if (!ok && (rt != MEMCACHED_NOTSTORED)) {
419 qCWarning(C_MEMCACHED).nospace()
420 << "Failed to replace key " << key << ": " << memcached_strerror(mcd->d_ptr->memc, rt);
421 }
422
423 MemcachedPrivate::setReturnType(returnType, rt);
424
425 return ok;
426}
427
429 QByteArrayView key,
430 const QByteArray &value,
431 time_t expiration,
432 ReturnType *returnType)
433{
434 if (!MemcachedPrivate::isRegistered(mcd, returnType)) {
435 return false;
436 }
437
438 MemcachedPrivate::Flags flags;
439 const QByteArray _value = MemcachedPrivate::compressIfNeeded(value, flags);
440
441 const memcached_return_t rt = memcached_replace_by_key(mcd->d_ptr->memc,
442 groupKey.constData(),
443 groupKey.size(),
444 key.constData(),
445 key.size(),
446 _value.constData(),
447 _value.size(),
448 expiration,
449 flags);
450
451 const bool ok = memcached_success(rt);
452
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);
457 }
458
459 MemcachedPrivate::setReturnType(returnType, rt);
460
461 return ok;
462}
463
464QByteArray Memcached::get(QByteArrayView key, uint64_t *cas, ReturnType *returnType)
465{
466 QByteArray retData;
467
468 if (!MemcachedPrivate::isRegistered(mcd, returnType)) {
469 return retData;
470 }
471
472 memcached_return_t rt{MEMCACHED_FAILURE};
473 bool ok = false;
474
475 std::vector<const char *> keys;
476 std::vector<size_t> sizes;
477 keys.push_back(key.constData());
478 sizes.push_back(key.size());
479 rt = memcached_mget(mcd->d_ptr->memc, &keys[0], &sizes[0], keys.size());
480
481 if (memcached_success(rt)) {
482 memcached_result_st *result = memcached_fetch_result(mcd->d_ptr->memc, nullptr, &rt);
483 if (result) {
484 retData =
485 QByteArray(memcached_result_value(result),
486 static_cast<QByteArray::size_type>(memcached_result_length(result)));
487 if (cas) {
488 *cas = memcached_result_cas(result);
489 }
490 retData = MemcachedPrivate::uncompressIfNeeded(retData, result);
491 ok = true;
492 // fetch another result even if there is no one to get
493 // a NULL for the internal of libmemcached
494 memcached_fetch_result(mcd->d_ptr->memc, nullptr, nullptr);
495 }
496 memcached_result_free(result);
497 }
498
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);
502 }
503
504 MemcachedPrivate::setReturnType(returnType, rt);
505
506 return retData;
507}
508
510 QByteArrayView key,
511 uint64_t *cas,
512 ReturnType *returnType)
513{
514 QByteArray retData;
515
516 if (!MemcachedPrivate::isRegistered(mcd, returnType)) {
517 return retData;
518 }
519
520 bool ok = false;
521
522 std::vector<const char *> keys;
523 std::vector<size_t> sizes;
524 keys.push_back(key.constData());
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());
528
529 if (memcached_success(rt)) {
530 memcached_result_st *result = memcached_fetch_result(mcd->d_ptr->memc, nullptr, &rt);
531 if (result) {
532 retData =
533 QByteArray(memcached_result_value(result),
534 static_cast<QByteArray::size_type>(memcached_result_length(result)));
535 if (cas) {
536 *cas = memcached_result_cas(result);
537 }
538 retData = MemcachedPrivate::uncompressIfNeeded(retData, result);
539 ok = true;
540 // fetch another result even if there is no one to get
541 // a NULL for the internal of libmemcached
542 memcached_fetch_result(mcd->d_ptr->memc, nullptr, nullptr);
543 }
544 memcached_result_free(result);
545 }
546
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);
551 }
552
553 MemcachedPrivate::setReturnType(returnType, rt);
554
555 return retData;
556}
557
559{
560 if (!MemcachedPrivate::isRegistered(mcd, returnType)) {
561 return false;
562 }
563
564 const memcached_return_t rt =
565 memcached_delete(mcd->d_ptr->memc, key.constData(), key.size(), 0);
566
567 const bool ok = memcached_success(rt);
568
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);
572 }
573
574 MemcachedPrivate::setReturnType(returnType, rt);
575
576 return ok;
577}
578
580{
581 if (!MemcachedPrivate::isRegistered(mcd, returnType)) {
582 return false;
583 }
584
585 const memcached_return_t rt = memcached_delete_by_key(
586 mcd->d_ptr->memc, groupKey.constData(), groupKey.size(), key.constData(), key.size(), 0);
587
588 const bool ok = memcached_success(rt);
589
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);
594 }
595
596 MemcachedPrivate::setReturnType(returnType, rt);
597
598 return ok;
599}
600
602{
603 if (!MemcachedPrivate::isRegistered(mcd, returnType)) {
604 return false;
605 }
606
607 const memcached_return_t rt = memcached_exist(mcd->d_ptr->memc, key.constData(), key.size());
608
609 const bool ok = memcached_success(rt);
610
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);
614 }
615
616 MemcachedPrivate::setReturnType(returnType, rt);
617
618 return ok;
619}
620
622{
623 if (!MemcachedPrivate::isRegistered(mcd, returnType)) {
624 return false;
625 }
626
627 const memcached_return_t rt = memcached_exist_by_key(
628 mcd->d_ptr->memc, groupKey.constData(), groupKey.size(), key.constData(), key.size());
629
630 const bool ok = memcached_success(rt);
631
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);
636 }
637
638 MemcachedPrivate::setReturnType(returnType, rt);
639
640 return ok;
641}
642
644 uint32_t offset,
645 uint64_t *value,
646 ReturnType *returnType)
647{
648 if (!MemcachedPrivate::isRegistered(mcd, returnType)) {
649 return false;
650 }
651
652 const memcached_return_t rt =
653 memcached_increment(mcd->d_ptr->memc, key.constData(), key.size(), offset, value);
654
655 const bool ok = memcached_success(rt);
656
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);
660 }
661
662 MemcachedPrivate::setReturnType(returnType, rt);
663
664 return ok;
665}
666
668 QByteArrayView key,
669 uint64_t offset,
670 uint64_t *value,
671 ReturnType *returnType)
672{
673 if (!MemcachedPrivate::isRegistered(mcd, returnType)) {
674 return false;
675 }
676
677 const memcached_return_t rt = memcached_increment_by_key(mcd->d_ptr->memc,
678 groupKey.constData(),
679 groupKey.size(),
680 key.constData(),
681 key.size(),
682 offset,
683 value);
684
685 const bool ok = memcached_success(rt);
686
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);
691 }
692
693 MemcachedPrivate::setReturnType(returnType, rt);
694
695 return ok;
696}
697
699 uint64_t offset,
700 uint64_t initial,
701 time_t expiration,
702 uint64_t *value,
703 ReturnType *returnType)
704{
705 if (!MemcachedPrivate::isRegistered(mcd, returnType)) {
706 return false;
707 }
708
709 const memcached_return_t rt = memcached_increment_with_initial(
710 mcd->d_ptr->memc, key.constData(), key.size(), offset, initial, expiration, value);
711
712 const bool ok = memcached_success(rt);
713
714 if (!ok) {
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);
718 }
719
720 MemcachedPrivate::setReturnType(returnType, rt);
721
722 return ok;
723}
724
726 QByteArrayView key,
727 uint64_t offset,
728 uint64_t initial,
729 time_t expiration,
730 uint64_t *value,
731 ReturnType *returnType)
732{
733 if (!MemcachedPrivate::isRegistered(mcd, returnType)) {
734 return false;
735 }
736
737 const memcached_return_t rt = memcached_increment_with_initial_by_key(mcd->d_ptr->memc,
738 groupKey.constData(),
739 groupKey.size(),
740 key.constData(),
741 key.size(),
742 offset,
743 initial,
744 expiration,
745 value);
746
747 const bool ok = memcached_success(rt);
748 if (!ok) {
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);
753 }
754
755 MemcachedPrivate::setReturnType(returnType, rt);
756
757 return ok;
758}
759
761 uint32_t offset,
762 uint64_t *value,
763 ReturnType *returnType)
764{
765 if (!MemcachedPrivate::isRegistered(mcd, returnType)) {
766 return false;
767 }
768
769 const memcached_return_t rt =
770 memcached_decrement(mcd->d_ptr->memc, key.constData(), key.size(), offset, value);
771
772 const bool ok = memcached_success(rt);
773
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);
777 }
778
779 MemcachedPrivate::setReturnType(returnType, rt);
780
781 return ok;
782}
783
785 QByteArrayView key,
786 uint64_t offset,
787 uint64_t *value,
788 ReturnType *returnType)
789{
790 if (!MemcachedPrivate::isRegistered(mcd, returnType)) {
791 return false;
792 }
793
794 const memcached_return_t rt = memcached_decrement_by_key(mcd->d_ptr->memc,
795 groupKey.constData(),
796 groupKey.size(),
797 key.constData(),
798 key.size(),
799 offset,
800 value);
801
802 const bool ok = memcached_success(rt);
803
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);
808 }
809
810 MemcachedPrivate::setReturnType(returnType, rt);
811
812 return ok;
813}
814
816 uint64_t offset,
817 uint64_t initial,
818 time_t expiration,
819 uint64_t *value,
820 ReturnType *returnType)
821{
822 if (!MemcachedPrivate::isRegistered(mcd, returnType)) {
823 return false;
824 }
825
826 const memcached_return_t rt = memcached_decrement_with_initial(
827 mcd->d_ptr->memc, key.constData(), key.size(), offset, initial, expiration, value);
828
829 const bool ok = memcached_success(rt);
830
831 if (!ok) {
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);
835 }
836
837 MemcachedPrivate::setReturnType(returnType, rt);
838
839 return ok;
840}
841
843 QByteArrayView key,
844 uint64_t offset,
845 uint64_t initial,
846 time_t expiration,
847 uint64_t *value,
848 ReturnType *returnType)
849{
850 if (!MemcachedPrivate::isRegistered(mcd, returnType)) {
851 return false;
852 }
853
854 const memcached_return_t rt = memcached_decrement_with_initial_by_key(mcd->d_ptr->memc,
855 groupKey.constData(),
856 groupKey.size(),
857 key.constData(),
858 key.size(),
859 offset,
860 initial,
861 expiration,
862 value);
863
864 const bool ok = memcached_success(rt);
865 if (!ok) {
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);
870 }
871
872 MemcachedPrivate::setReturnType(returnType, rt);
873
874 return ok;
875}
876
878 const QByteArray &value,
879 time_t expiration,
880 uint64_t cas,
881 ReturnType *returnType)
882{
883 if (!MemcachedPrivate::isRegistered(mcd, returnType)) {
884 return false;
885 }
886
887 MemcachedPrivate::Flags flags;
888 const QByteArray _value = MemcachedPrivate::compressIfNeeded(value, flags);
889
890 const memcached_return_t rt = memcached_cas(mcd->d_ptr->memc,
891 key.constData(),
892 key.size(),
893 _value.constData(),
894 _value.size(),
895 expiration,
896 flags,
897 cas);
898
899 const bool ok = memcached_success(rt);
900
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);
904 }
905
906 MemcachedPrivate::setReturnType(returnType, rt);
907
908 return ok;
909}
910
912 QByteArrayView key,
913 const QByteArray &value,
914 time_t expiration,
915 uint64_t cas,
916 ReturnType *returnType)
917{
918 if (!MemcachedPrivate::isRegistered(mcd, returnType)) {
919 return false;
920 }
921
922 MemcachedPrivate::Flags flags;
923 const QByteArray _value = MemcachedPrivate::compressIfNeeded(value, flags);
924
925 const memcached_return_t rt = memcached_cas_by_key(mcd->d_ptr->memc,
926 groupKey.constData(),
927 groupKey.size(),
928 key.constData(),
929 key.size(),
930 _value.constData(),
931 _value.size(),
932 expiration,
933 flags,
934 cas);
935
936 const bool ok = memcached_success(rt);
937
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);
942 }
943
944 MemcachedPrivate::setReturnType(returnType, rt);
945
946 return ok;
947}
948
950{
951 if (!MemcachedPrivate::isRegistered(mcd, returnType)) {
952 return false;
953 }
954
955 const memcached_return_t rt = memcached_flush_buffers(mcd->d_ptr->memc);
956
957 const bool ok = memcached_success(rt);
958
959 if (!ok) {
960 qCWarning(C_MEMCACHED) << "Failed to flush buffers:"
961 << memcached_strerror(mcd->d_ptr->memc, rt);
962 }
963
964 MemcachedPrivate::setReturnType(returnType, rt);
965
966 return ok;
967}
968
969bool Memcached::flush(time_t expiration, ReturnType *returnType)
970{
971 if (!MemcachedPrivate::isRegistered(mcd, returnType)) {
972 return false;
973 }
974
975 const memcached_return_t rt = memcached_flush(mcd->d_ptr->memc, expiration);
976
977 const bool ok = memcached_success(rt);
978
979 if (!ok) {
980 qCWarning(C_MEMCACHED) << "Failed to wipe (flush) server content:"
981 << memcached_strerror(mcd->d_ptr->memc, rt);
982 }
983
984 MemcachedPrivate::setReturnType(returnType, rt);
985
986 return ok;
987}
988
991 ReturnType *returnType)
992{
994
995 if (!MemcachedPrivate::isRegistered(mcd, returnType)) {
996 return ret;
997 }
998
999 if (keys.empty()) {
1000 qCWarning(C_MEMCACHED) << "Can not get multiple values without a list of keys.";
1001 if (returnType) {
1002 *returnType = ReturnType::BadKeyProvided;
1003 }
1004 return ret;
1005 }
1006
1007 std::vector<const char *> _keys;
1008 _keys.reserve(keys.size());
1009 std::vector<size_t> _keysSizes;
1010 _keysSizes.reserve(keys.size());
1011
1012 for (const auto &key : keys) {
1013 _keys.push_back(key.data());
1014 _keysSizes.push_back(key.size());
1015 }
1016
1017 bool ok = false;
1018
1019 memcached_return_t rt =
1020 memcached_mget(mcd->d_ptr->memc, &_keys[0], &_keysSizes[0], _keys.size());
1021
1022 if (memcached_success(rt)) {
1023 ok = true;
1024 ret.reserve(keys.size());
1025 while ((rt != MEMCACHED_END) && (rt != MEMCACHED_NOTFOUND)) {
1026 memcached_result_st *result = memcached_fetch_result(mcd->d_ptr->memc, nullptr, &rt);
1027 if (result) {
1028 const QByteArray rk =
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)));
1033 if (casValues) {
1034 casValues->insert(rk, memcached_result_cas(result));
1035 }
1036 rd = MemcachedPrivate::uncompressIfNeeded(rd, result);
1037 ret.insert(rk, rd);
1038 }
1039 memcached_result_free(result);
1040 }
1041 }
1042
1043 if (!ok) {
1044 qCWarning(C_MEMCACHED) << "Failed to get values for multiple keys:"
1045 << memcached_strerror(mcd->d_ptr->memc, rt);
1046 }
1047
1048 MemcachedPrivate::setReturnType(returnType, rt);
1049
1050 return ret;
1051}
1052
1054 const QByteArrayList &keys,
1055 QHash<QByteArray, uint64_t> *casValues,
1056 ReturnType *returnType)
1057{
1059
1060 if (!MemcachedPrivate::isRegistered(mcd, returnType)) {
1061 return ret;
1062 }
1063
1064 if (groupKey.isEmpty()) {
1065 qCWarning(C_MEMCACHED)
1066 << "Can not get multiple values from specific server when groupKey is empty.";
1067 if (returnType) {
1068 *returnType = ReturnType::BadKeyProvided;
1069 }
1070 return ret;
1071 }
1072
1073 if (keys.empty()) {
1074 qCWarning(C_MEMCACHED) << "Can not get multiple values without a list of keys.";
1075 if (returnType) {
1076 *returnType = ReturnType::BadKeyProvided;
1077 }
1078 return ret;
1079 }
1080
1081 std::vector<const char *> _keys;
1082 _keys.reserve(keys.size());
1083 std::vector<size_t> _keysSizes;
1084 _keysSizes.reserve(keys.size());
1085
1086 for (const auto &key : keys) {
1087 _keys.push_back(key.data());
1088 _keysSizes.push_back(key.size());
1089 }
1090
1091 bool ok = false;
1092
1093 memcached_return_t rt = memcached_mget_by_key(mcd->d_ptr->memc,
1094 groupKey.constData(),
1095 groupKey.size(),
1096 &_keys[0],
1097 &_keysSizes[0],
1098 _keys.size());
1099
1100 if (memcached_success(rt)) {
1101 ok = true;
1102 ret.reserve(keys.size());
1103 while ((rt != MEMCACHED_END) && (rt != MEMCACHED_NOTFOUND)) {
1104 memcached_result_st *result = memcached_fetch_result(mcd->d_ptr->memc, nullptr, &rt);
1105 if (result) {
1106 const QByteArray rk =
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)));
1111 if (casValues) {
1112 casValues->insert(rk, memcached_result_cas(result));
1113 }
1114 rd = MemcachedPrivate::uncompressIfNeeded(rd, result);
1115 ret.insert(rk, rd);
1116 }
1117 memcached_result_free(result);
1118 }
1119 }
1120
1121 if (!ok) {
1122 qCWarning(C_MEMCACHED).nospace()
1123 << "Failed to get values for multiple keys in group " << groupKey << ": "
1124 << memcached_strerror(mcd->d_ptr->memc, rt);
1125 }
1126
1127 MemcachedPrivate::setReturnType(returnType, rt);
1128
1129 return ret;
1130}
1131
1132bool Memcached::touch(QByteArrayView key, time_t expiration, ReturnType *returnType)
1133{
1134 if (!MemcachedPrivate::isRegistered(mcd, returnType)) {
1135 return false;
1136 }
1137
1138 const memcached_return_t rt =
1139 memcached_touch(mcd->d_ptr->memc, key.constData(), key.size(), expiration);
1140
1141 const bool ok = memcached_success(rt);
1142
1143 if (!ok) {
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);
1147 }
1148
1149 MemcachedPrivate::setReturnType(returnType, rt);
1150
1151 return ok;
1152}
1153
1155 QByteArrayView key,
1156 time_t expiration,
1157 ReturnType *returnType)
1158{
1159 if (!MemcachedPrivate::isRegistered(mcd, returnType)) {
1160 return false;
1161 }
1162
1163 const memcached_return_t rt = memcached_touch_by_key(mcd->d_ptr->memc,
1164 groupKey.constData(),
1165 groupKey.size(),
1166 key.constData(),
1167 key.size(),
1168 expiration);
1169
1170 const bool ok = memcached_success(rt);
1171
1172 if (!ok) {
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);
1177 }
1178
1179 MemcachedPrivate::setReturnType(returnType, rt);
1180
1181 return ok;
1182}
1183
1185{
1186 switch (rt) {
1187 using enum Memcached::ReturnType;
1188 case Success:
1189 //% "The request was successfully executed."
1190 return c->qtTrId("cutelyst-memc-rt-success");
1191 case Failure:
1192 //% "An unknown failure has occurred in the Memcached server."
1193 return c->qtTrId("cutelyst-memc-rt-failure");
1194 case HostLookupFailure:
1195 //% "Failed to look up the hostname while trying to connect to a Memcached server."
1196 return c->qtTrId("cutelyst-memc-rt-hostlookupfailure");
1197 case ConnectionFailure:
1198 //% "An unknown error has occurred while trying to connect to a Memcached server."
1199 return c->qtTrId("cutelyst-memc-rt-connectionfailure");
1200 case WriteFailure:
1201 //% "An error has occurred while trying to write to a Memcached server."
1202 return c->qtTrId("cutelyst-memc-rt-writefailure");
1203 case ReadFailure:
1204 //% "An error has occurred while trying to read from a Memcached server."
1205 return c->qtTrId("cutelyst-memc-rt-readfailure");
1206 case UnknownReadFailure:
1207 //% "An unknown error has occurred while trying to read from a Memcached server. This "
1208 //% "only occures when either there is a bug in the server, or in rare cases where an "
1209 //% "ethernet NIC is reporting dubious information."
1210 return c->qtTrId("cutelyst-memc-rt-unknownreadfailure");
1211 case ProtocolError:
1212 //% "An unknown error has occurred in the Memcached protocol."
1213 return c->qtTrId("cutelyst-memc-rt-protocolerror");
1214 case ClientError:
1215 //% "An unknown Memcached client error has occurred internally."
1216 return c->qtTrId("cutelyst-memc-rt-clienterror");
1217 case ServerError:
1218 //% "An unknown error has occurred in the Memcached server."
1219 return c->qtTrId("cutelyst-memc-rt-servererror");
1220 case Error:
1221 //% "A general error occurred."
1222 return c->qtTrId("cutelyst-memc-rt-error");
1223 case DataExists:
1224 //% "The data for the given key alrey exists."
1225 return c->qtTrId("cutelyst-memc-rt-dataexists");
1226 case DataDoesNotExist:
1227 //% "The data requested with the key given was not found."
1228 return c->qtTrId("cutelyst-memc-rt-datadoesnotexist");
1229 case NotStored:
1230 //% "The request to store an object failed."
1231 return c->qtTrId("cutelyst-memc-rt-notstored");
1232 case Stored:
1233 //% "The requested object has been successfully stored on the server."
1234 return c->qtTrId("cutelyst-memc-rt-stored");
1235 case NotFound:
1236 //% "The object requested was not found."
1237 return c->qtTrId("cutelyst-memc-notfound");
1239 //% "An error has occurred while trying to allocate memory."
1240 return c->qtTrId("cutelyst-memc-rt-memallocfailure");
1241 case PartialRead:
1242 //% "The read operation was only partcially successful."
1243 return c->qtTrId("cutelyst-memc-rt-partread");
1244 case SomeErrors:
1245 //% "A multi request has been made, and some underterminate number of "
1246 //% "errors have occurred."
1247 return c->qtTrId("cutelyst-memc-rt-someerrors");
1248 case NoServers:
1249 //% "No servers have been added to the Memcached plugin."
1250 return c->qtTrId("cutelyst-memc-rt-noservers");
1251 case End:
1252 //% "The Memcached server has completed returning all of the objects requested."
1253 return c->qtTrId("cutelyst-memc-rt-end");
1254 case Deleted:
1255 //% "The object requested by the key has been deleted."
1256 return c->qtTrId("cutelyst-memc-rt-deleted");
1257 case Stat:
1258 //% "A “stat” command has been returned in the protocol."
1259 return c->qtTrId("cutelyst-memc-rt-stat");
1260 case Errno:
1261 //% "An error has occurred in the driver which has set errno."
1262 return qtTrId("cutelyst-memc-rt-errno");
1263 case NotSupported:
1264 //% "The given method is not supported in the Memcached server."
1265 return c->qtTrId("cutelyst-memc-rt-notsupported");
1266 case FetchNotFinished:
1267 //% "A request has been made, but the Memcached server has not finished "
1268 //% "the fetch of the last request."
1269 return c->qtTrId("cutelyst-memc-rt-fetchnotfinished");
1270 case Timeout:
1271 //% "The operation has timed out."
1272 return c->qtTrId("cutelyst-memc-rt-timeout");
1273 case Buffered:
1274 //% "The request has been buffered."
1275 return c->qtTrId("cutelyst-memc-rt-buffered");
1276 case BadKeyProvided:
1277 //% "The key provided is not a valid key."
1278 return c->qtTrId("cutelyst-memc-rt-badkeyprov");
1280 //% "The Memcached server you are connecting to has an invalid protocol. Most likely you "
1281 //% "are connecting to an older server that does not speak the binary protocol."
1282 return c->qtTrId("cutelyst-memc-rt-invalidhostprot");
1283 case ServerMarkedDead:
1284 //% "The requested Memcached server has been marked dead."
1285 return c->qtTrId("cutelyst-memc-rt-servermarkeddead");
1286 case UnknownStatKey:
1287 //% "The Memcached server you are communicating with has a stat key which "
1288 //% "has not be defined in the protocol."
1289 return c->qtTrId("cutelyst-memc-rt-unknownstatkey");
1290 case E2Big:
1291 //% "Item is too large for the Memcached server to store."
1292 return c->qtTrId("cutelyst-memc-rt-e2big");
1293 case InvalidArguments:
1294 //% "The arguments supplied to the given function were not valid."
1295 return c->qtTrId("cutelyst-memc-rt-invalidarg");
1296 case KeyTooBig:
1297 //% "The key that has been provided is too large for the given Memcached server."
1298 return c->qtTrId("cutelyst-memc-rt-key2big");
1299 case AuthProblem:
1300 //% "An unknown issue has occurred during SASL authentication."
1301 return c->qtTrId("cutelyst-memc-rt-authproblem");
1302 case AuthFailure:
1303 //% "The credentials provided are not valid for this Memcached server."
1304 return c->qtTrId("cutelyst-memc-rt-authfailure");
1305 case AuthContinue:
1306 //% "Authentication has been paused."
1307 return c->qtTrId("cutelyst-memc-rt-authcont");
1308 case ParseError:
1309 //% "An error has occurred while trying to parse the configuration string."
1310 return c->qtTrId("cutelyst-memc-rt-parseerr");
1311 case ParseUserError:
1312 //% "An error has occurred in parsing the configuration string."
1313 return c->qtTrId("cutelyst-memc-rt-parseusererr");
1314 case Deprecated:
1315 //% "The method that was requested has been deprecated."
1316 return c->qtTrId("cutelyst-memc-rt-deprecated");
1317 case PluginNotRegisterd:
1318 //% "The Cutelyst Memcached plugin has not been registered to the application."
1319 return c->qtTrId("cutelyst-memc-rt-pluginnotregistered");
1320 default:
1321 //% "An unknown error has occurred."
1322 return c->qtTrId("cutelyst-memc-rt-unknown-err");
1323 }
1324}
1325
1330
1331// clang-format off
1336Memcached::ReturnType MemcachedPrivate::returnTypeConvert(memcached_return_t rt)
1337{
1338 switch (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;
1387 }
1388}
1389// clang-format on
1390
1396void MemcachedPrivate::setReturnType(Memcached::ReturnType *rt1, memcached_return_t rt2)
1397{
1398 if (rt1) {
1399 *rt1 = MemcachedPrivate::returnTypeConvert(rt2);
1400 }
1401}
1402
1408bool MemcachedPrivate::isRegistered(Memcached *ptr, Memcached::ReturnType *rt)
1409{
1410 if (!ptr) {
1411 qCCritical(C_MEMCACHED) << "Memcached plugin not registered";
1412 if (rt) {
1414 }
1415 return false;
1416 }
1417 return true;
1418}
1419
1425QByteArray MemcachedPrivate::compressIfNeeded(const QByteArray &value, Flags &flags)
1426{
1427 if (mcd->d_ptr->compression && (value.size() > mcd->d_ptr->compressionThreshold)) {
1428 flags |= MemcachedPrivate::Compressed;
1429 return qCompress(value, mcd->d_ptr->compressionLevel);
1430 } else {
1431 return value;
1432 }
1433}
1434
1440QByteArray MemcachedPrivate::uncompressIfNeeded(const QByteArray &value,
1441 memcached_result_st *result)
1442{
1443 const MemcachedPrivate::Flags flags{memcached_result_flags(result)};
1444 if (flags.testFlag(MemcachedPrivate::Compressed)) {
1445 return qUncompress(value);
1446 } else {
1447 return value;
1448 }
1449}
1450
1458QVariant MemcachedPrivate::config(const QString &key, const QVariant &defaultValue) const
1459{
1460 return loadedConfig.value(key, defaultConfig.value(key, defaultValue));
1461}
1462
1463#include "moc_memcached.cpp"
The Cutelyst application.
Definition application.h:66
Engine * engine() const noexcept
void loadTranslations(const QString &filename, const QString &directory={}, const QString &prefix={}, const QString &suffix={})
void postForked(Cutelyst::Application *app)
The Cutelyst Context.
Definition context.h:42
QString qtTrId(const char *id, int n=-1) const
Definition context.h:656
QVariantMap config(const QString &entity) const
Definition engine.cpp:263
Cutelyst Memcached plugin.
Definition memcached.h:168
static bool exist(QByteArrayView key, ReturnType *returnType=nullptr)
static bool touch(QByteArrayView key, time_t expiration, ReturnType *returnType=nullptr)
static bool flush(time_t expiration, ReturnType *returnType=nullptr)
static bool touchByKey(QByteArrayView groupKey, QByteArrayView key, time_t expiration, ReturnType *returnType=nullptr)
static bool incrementByKey(QByteArrayView groupKey, QByteArrayView key, uint64_t offset, uint64_t *value=nullptr, ReturnType *returnType=nullptr)
static bool flushBuffers(ReturnType *returnType=nullptr)
static const std::chrono::seconds expirationNotAddDuration
Definition memcached.h:839
bool setup(Application *app) override
Definition memcached.cpp:45
static bool decrementWithInitial(QByteArrayView key, uint64_t offset, uint64_t initial, time_t expiration, uint64_t *value=nullptr, ReturnType *returnType=nullptr)
static bool removeByKey(QByteArrayView groupKey, QByteArrayView key, ReturnType *returnType=nullptr)
static bool incrementWithInitial(QByteArrayView key, uint64_t offset, uint64_t initial, time_t expiration, uint64_t *value=nullptr, ReturnType *returnType=nullptr)
static QHash< QByteArray, QByteArray > mgetByKey(QByteArrayView groupKey, const QByteArrayList &keys, QHash< QByteArray, uint64_t > *casValues=nullptr, ReturnType *returnType=nullptr)
static bool cas(QByteArrayView key, const QByteArray &value, time_t expiration, uint64_t cas, ReturnType *returnType=nullptr)
static bool replace(QByteArrayView key, const QByteArray &value, time_t expiration, ReturnType *returnType=nullptr)
static bool set(QByteArrayView key, const QByteArray &value, time_t expiration, ReturnType *returnType=nullptr)
static bool decrement(QByteArrayView key, uint32_t offset, uint64_t *value=nullptr, ReturnType *returnType=nullptr)
static bool replaceByKey(QByteArrayView groupKey, QByteArrayView key, const QByteArray &value, time_t expiration, ReturnType *returnType=nullptr)
static bool decrementByKey(QByteArrayView groupKey, QByteArrayView key, uint64_t offset, uint64_t *value=nullptr, ReturnType *returnType=nullptr)
static bool casByKey(QByteArrayView groupKey, QByteArrayView key, const QByteArray &value, time_t expiration, uint64_t cas, ReturnType *returnType=nullptr)
static QString errorString(Context *c, ReturnType rt)
~Memcached() override
static QHash< QByteArray, QByteArray > mget(const QByteArrayList &keys, QHash< QByteArray, uint64_t > *casValues=nullptr, ReturnType *returnType=nullptr)
static bool decrementWithInitialByKey(QByteArrayView groupKey, QByteArrayView key, uint64_t offset, uint64_t initial, time_t expiration, uint64_t *value=nullptr, ReturnType *returnType=nullptr)
static QByteArray getByKey(QByteArrayView groupKey, QByteArrayView key, uint64_t *cas=nullptr, ReturnType *returnType=nullptr)
static const time_t expirationNotAdd
Definition memcached.h:830
static bool addByKey(QByteArrayView groupKey, QByteArrayView key, const QByteArray &value, time_t expiration, ReturnType *returnType=nullptr)
static bool incrementWithInitialByKey(QByteArrayView groupKey, QByteArrayView key, uint64_t offset, uint64_t initial, time_t expiration, uint64_t *value=nullptr, ReturnType *returnType=nullptr)
static bool increment(QByteArrayView key, uint32_t offset, uint64_t *value=nullptr, ReturnType *returnType=nullptr)
static bool setByKey(QByteArrayView groupKey, QByteArrayView key, const QByteArray &value, time_t expiration, ReturnType *returnType=nullptr)
void setDefaultConfig(const QVariantMap &defaultConfig)
Definition memcached.cpp:39
static QByteArray get(QByteArrayView key, uint64_t *cas=nullptr, ReturnType *returnType=nullptr)
static bool existByKey(QByteArrayView groupKey, QByteArrayView key, ReturnType *returnType=nullptr)
Memcached(Application *parent)
Definition memcached.cpp:25
static QVersionNumber libMemcachedVersion()
Returns the version of the currently used libmemcached.
static bool remove(QByteArrayView key, ReturnType *returnType=nullptr)
static bool add(QByteArrayView key, const QByteArray &value, time_t expiration, ReturnType *returnType=nullptr)
Base class for Cutelyst Plugins.
Definition plugin.h:25
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
bool isEmpty() const const
qsizetype size() const const
QHash::iterator insert(const Key &key, const T &value)
void reserve(qsizetype size)
bool empty() const const
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
T value() const const
QVersionNumber fromString(QAnyStringView string, qsizetype *suffixIndex)