14#include "arcane/utils/FatalErrorException.h"
15#include "arcane/utils/UniqueArray.h"
16#include "arcane/utils/TraceAccessor.h"
19#include "arcane/std/internal/IRedisContext.h"
21#include "arcane_packages.h"
25#ifdef ARCANE_HAS_PACKAGE_HIREDIS
27#include <hiredis/hiredis.h>
47 void sendCommand(redisContext* c,
const char* format, ...)
52 va_start(arguments, format);
53 m_reply =
reinterpret_cast<redisReply*
>(redisvCommand(c, format, arguments));
56 if (m_reply ==
nullptr)
59 ARCANE_FATAL(
"Error during redis connection: %s\n", c->errstr);
61 bool isReplyString()
const
64 return m_reply->type == REDIS_REPLY_STRING;
66 size_t replyLength()
const
71 const char* replyData()
const
79 ::redisReply* m_reply =
nullptr;
84 freeReplyObject(m_reply);
99 HiredisContext(ITraceMng* tm)
105 ::redisFree(m_redis_context);
110 void open(
const String& machine,
Int32 port)
override
112 redisContext* c = ::redisConnect(machine.localstr(), port);
115 ARCANE_FATAL(
"Error during redis connection: can not allocate redis context");
117 ARCANE_FATAL(
"Error during redis connection: {0}", c->errstr);
122 void sendBuffer(
const String& key, Span<const std::byte> bytes)
override
125 auto key_bytes = key.bytes();
126 size_t key_len = key_bytes.size();
127 size_t buf_size = bytes.size();
128 HiredisCommand command;
129 command.sendCommand(m_redis_context,
"SET %b %b", key_bytes.data(), key_len, bytes.data(), buf_size);
132 void getBuffer(
const String& key, Array<std::byte>& bytes)
override
135 auto key_bytes = key.bytes();
136 size_t key_len = key_bytes.size();
137 HiredisCommand command;
138 command.sendCommand(m_redis_context,
"GET %b", key_bytes.data(), key_len);
139 if (!command.isReplyString())
141 Int64 reply_length = command.replyLength();
142 auto* data_as_bytes =
reinterpret_cast<const std::byte*
>(command.replyData());
143 bytes.copy(Span<const std::byte>(data_as_bytes, reply_length));
148 ::redisContext* m_redis_context =
nullptr;
154 if (!m_redis_context)
155 ARCANE_FATAL(
"No redis context. You have to call open() to create a context");
163:
public TraceAccessor
167 HiredisAdapter(ITraceMng* tm)
178 HiredisContext m_context;
187 m_context.open(
"127.0.0.1", 6379);
189 redisContext* c = m_context.m_redis_context;
192 HiredisCommand command;
194 constexpr const char* REDIS_VERSION_FIELD =
"redis_version:";
195 command.sendCommand(c,
"INFO");
196 if (!command.isReplyString())
198 if ((s = strstr((
char*)command.replyData(), REDIS_VERSION_FIELD)) == NULL)
201 s += strlen(REDIS_VERSION_FIELD);
204 if ((e = strstr(s,
"\r\n")) == NULL || (e - s) < 5)
206 info() <<
"VERSION=" << command.replyData();
208 UniqueArray<Int64> my_buffer(10000);
209 for (
Int64 i = 0, n = my_buffer.size(); i < n; ++i) {
210 my_buffer[i] = i + 1;
212 Span<const std::byte> send_buf(
asBytes(my_buffer));
213 Int64 send_size = send_buf.size();
214 info() <<
"SEND_SIZE=" << send_size;
216 m_context.sendBuffer(
"mytest", send_buf);
218 UniqueArray<std::byte> out_bytes;
219 m_context.getBuffer(
"mytest", out_bytes);
221 Int64 reply_length = out_bytes.largeSize();
222 info() <<
"REPLY_SIZE = " << reply_length;
223 if (reply_length != send_size)
224 ARCANE_FATAL(
"Bad reply v={0} expected={1}", reply_length, send_size);
226 Span<const Int64> receive_buf = Arccore::asSpan<Int64>(out_bytes.span());
227 if (receive_buf != my_buffer)
229 for (
Int64 x = 0, n = receive_buf.size(); x < n; ++x)
230 if (receive_buf[x] != my_buffer[x])
231 ARCANE_FATAL(
"Bad value i={0} v={1} expected={2}", x, receive_buf[x], my_buffer[x]);
253extern "C++" ARCANE_STD_EXPORT
void
254_testRedisAdapter([[maybe_unused]] ITraceMng* tm)
256#ifdef ARCANE_HAS_PACKAGE_HIREDIS
257 Redis::HiredisAdapter h{ tm };
265extern "C++" Ref<IRedisContext>
266createRedisContext([[maybe_unused]] ITraceMng* tm)
268#ifdef ARCANE_HAS_PACKAGE_HIREDIS
269 return makeRef<IRedisContext>(
new Redis::HiredisContext(tm));
271 ARCANE_FATAL(
"Can not create Redis context because Arcane is not "
272 "compiled with support for 'hiredis' library");
#define ARCANE_CHECK_POINTER(ptr)
Macro retournant le pointeur ptr s'il est non nul ou lancant une exception s'il est nul.
#define ARCANE_FATAL(...)
Macro envoyant une exception FatalErrorException.
Déclarations des types généraux de Arcane.
Lecteur des fichiers de maillage via la bibliothèque LIMA.
TraceMessage info() const
Flot pour un message d'information.
-*- tab-width: 2; indent-tabs-mode: nil; coding: utf-8-with-signature -*-
detail::SpanTypeFromSize< conststd::byte, SizeType >::SpanType asBytes(const SpanImpl< DataType, SizeType, Extent > &s)
Converti la vue en un tableau d'octets non modifiables.