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