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