summaryrefslogtreecommitdiff
path: root/examples/redis-unstable/src/rio.h
diff options
context:
space:
mode:
Diffstat (limited to 'examples/redis-unstable/src/rio.h')
-rw-r--r--examples/redis-unstable/src/rio.h188
1 files changed, 188 insertions, 0 deletions
diff --git a/examples/redis-unstable/src/rio.h b/examples/redis-unstable/src/rio.h
new file mode 100644
index 0000000..9cd24cd
--- /dev/null
+++ b/examples/redis-unstable/src/rio.h
@@ -0,0 +1,188 @@
1/*
2 * Copyright (c) 2009-Present, Redis Ltd.
3 * All rights reserved.
4 *
5 * Copyright (c) 2024-present, Valkey contributors.
6 * All rights reserved.
7 *
8 * Licensed under your choice of (a) the Redis Source Available License 2.0
9 * (RSALv2); or (b) the Server Side Public License v1 (SSPLv1); or (c) the
10 * GNU Affero General Public License v3 (AGPLv3).
11 *
12 * Portions of this file are available under BSD3 terms; see REDISCONTRIBUTIONS for more information.
13 */
14
15
16#ifndef __REDIS_RIO_H
17#define __REDIS_RIO_H
18
19#include <stdio.h>
20#include <stdint.h>
21#include "sds.h"
22#include "connection.h"
23
24#define RIO_FLAG_READ_ERROR (1<<0)
25#define RIO_FLAG_WRITE_ERROR (1<<1)
26
27#define RIO_TYPE_FILE (1<<0)
28#define RIO_TYPE_BUFFER (1<<1)
29#define RIO_TYPE_CONN (1<<2)
30#define RIO_TYPE_FD (1<<3)
31
32struct _rio {
33 /* Backend functions.
34 * Since this functions do not tolerate short writes or reads the return
35 * value is simplified to: zero on error, non zero on complete success. */
36 size_t (*read)(struct _rio *, void *buf, size_t len);
37 size_t (*write)(struct _rio *, const void *buf, size_t len);
38 off_t (*tell)(struct _rio *);
39 int (*flush)(struct _rio *);
40 /* The update_cksum method if not NULL is used to compute the checksum of
41 * all the data that was read or written so far. The method should be
42 * designed so that can be called with the current checksum, and the buf
43 * and len fields pointing to the new block of data to add to the checksum
44 * computation. */
45 void (*update_cksum)(struct _rio *, const void *buf, size_t len);
46
47 /* The current checksum and flags (see RIO_FLAG_*) */
48 uint64_t cksum, flags;
49
50 /* number of bytes read or written */
51 size_t processed_bytes;
52
53 /* maximum single read or write chunk size */
54 size_t max_processing_chunk;
55
56 /* Backend-specific vars. */
57 union {
58 /* In-memory buffer target. */
59 struct {
60 sds ptr;
61 off_t pos;
62 } buffer;
63 /* Stdio file pointer target. */
64 struct {
65 FILE *fp;
66 off_t buffered; /* Bytes written since last fsync. */
67 off_t autosync; /* fsync after 'autosync' bytes written. */
68 unsigned reclaim_cache:1; /* A flag to indicate reclaim cache after fsync */
69 } file;
70 /* Connection object (used to read from socket) */
71 struct {
72 connection *conn; /* Connection */
73 off_t pos; /* pos in buf that was returned */
74 sds buf; /* buffered data */
75 size_t read_limit; /* don't allow to buffer/read more than that */
76 size_t read_so_far; /* amount of data read from the rio (not buffered) */
77 } conn;
78 /* FD target (used to write to pipe). */
79 struct {
80 int fd; /* File descriptor. */
81 off_t pos;
82 sds buf;
83 } fd;
84 /* Multiple connections target (used to write to N sockets). */
85 struct {
86 struct {
87 connection *conn; /* Connection */
88 int failed; /* If write failed on this connection. */
89 } *dst;
90
91 size_t n_dst; /* Number of connections */
92 off_t pos; /* Number of sent bytes */
93 sds buf;
94 } connset;
95 } io;
96};
97
98typedef struct _rio rio;
99
100/* The following functions are our interface with the stream. They'll call the
101 * actual implementation of read / write / tell, and will update the checksum
102 * if needed. */
103
104static inline size_t rioWrite(rio *r, const void *buf, size_t len) {
105 if (r->flags & (RIO_FLAG_WRITE_ERROR)) return 0;
106 while (len) {
107 size_t bytes_to_write = (r->max_processing_chunk && r->max_processing_chunk < len) ? r->max_processing_chunk : len;
108 if (r->update_cksum) r->update_cksum(r,buf,bytes_to_write);
109 if (r->write(r,buf,bytes_to_write) == 0) {
110 r->flags |= RIO_FLAG_WRITE_ERROR;
111 return 0;
112 }
113 buf = (char*)buf + bytes_to_write;
114 len -= bytes_to_write;
115 r->processed_bytes += bytes_to_write;
116 }
117 return 1;
118}
119
120static inline size_t rioRead(rio *r, void *buf, size_t len) {
121 if (r->flags & (RIO_FLAG_READ_ERROR)) return 0;
122 while (len) {
123 size_t bytes_to_read = (r->max_processing_chunk && r->max_processing_chunk < len) ? r->max_processing_chunk : len;
124 if (r->read(r,buf,bytes_to_read) == 0) {
125 r->flags |= RIO_FLAG_READ_ERROR;
126 return 0;
127 }
128 if (r->update_cksum) r->update_cksum(r,buf,bytes_to_read);
129 buf = (char*)buf + bytes_to_read;
130 len -= bytes_to_read;
131 r->processed_bytes += bytes_to_read;
132 }
133 return 1;
134}
135
136static inline off_t rioTell(rio *r) {
137 return r->tell(r);
138}
139
140static inline int rioFlush(rio *r) {
141 return r->flush(r);
142}
143
144/* Abort RIO asynchronously by setting read and write error flags. Subsequent
145 * rioRead()/rioWrite() calls will fail, letting the caller terminate safely. */
146static inline void rioAbort(rio *r) {
147 r->flags |= (RIO_FLAG_READ_ERROR | RIO_FLAG_WRITE_ERROR);
148}
149
150/* This function allows to know if there was a read error in any past
151 * operation, since the rio stream was created or since the last call
152 * to rioClearError(). */
153static inline int rioGetReadError(rio *r) {
154 return (r->flags & RIO_FLAG_READ_ERROR) != 0;
155}
156
157/* Like rioGetReadError() but for write errors. */
158static inline int rioGetWriteError(rio *r) {
159 return (r->flags & RIO_FLAG_WRITE_ERROR) != 0;
160}
161
162static inline void rioClearErrors(rio *r) {
163 r->flags &= ~(RIO_FLAG_READ_ERROR|RIO_FLAG_WRITE_ERROR);
164}
165
166void rioInitWithFile(rio *r, FILE *fp);
167void rioInitWithBuffer(rio *r, sds s);
168void rioInitWithConn(rio *r, connection *conn, size_t read_limit);
169void rioInitWithFd(rio *r, int fd);
170void rioInitWithConnset(rio *r, connection **conns, size_t n_conns);
171
172void rioFreeFd(rio *r);
173void rioFreeConn(rio *r, sds* out_remainingBufferedData);
174void rioFreeConnset(rio *r);
175
176size_t rioWriteBulkCount(rio *r, char prefix, long count);
177size_t rioWriteBulkString(rio *r, const char *buf, size_t len);
178size_t rioWriteBulkLongLong(rio *r, long long l);
179size_t rioWriteBulkDouble(rio *r, double d);
180
181struct redisObject;
182int rioWriteBulkObject(rio *r, struct redisObject *obj);
183
184void rioGenericUpdateChecksum(rio *r, const void *buf, size_t len);
185void rioSetAutoSync(rio *r, off_t bytes);
186void rioSetReclaimCache(rio *r, int enabled);
187uint8_t rioCheckType(rio *r);
188#endif