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