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