1 /*----------------------------------------------------------------------------
2 Name: QueueInterface.h
3 Project: xmlBlaster.org
4 Copyright: xmlBlaster.org, see xmlBlaster-LICENSE file
5 Author: "Marcel Ruff" <xmlBlaster@marcelruff.info>
6 Comment: Interface for transient or persistent queue implementations
7 with priority and time stamp sorting
8 Note: The gcc and icc (>=8) both define __GNUC__
9 See: http://www.xmlblaster.org/xmlBlaster/doc/requirements/client.c.queue.html
10 See: http://www.xmlblaster.org/xmlBlaster/doc/requirements/queue.html
11 -----------------------------------------------------------------------------*/
12 #ifndef I_QUEUE_QueueInterface_h
13 #define I_QUEUE_QueueInterface_h
14
15 #include "util/helper.h" /* BlobHolder. basicDefs.h: for int64_t (C99), Dll_Export, bool etc. */
16
17 #ifdef __cplusplus
18 #ifndef XMLBLASTER_C_COMPILE_AS_CPP /* 'g++ -DXMLBLASTER_C_COMPILE_AS_CPP ...' allows to compile the lib as C++ code */
19 extern "C" {
20 #endif
21 #endif
22
23 /*const int QUEUE_ENTRY_EMBEDDEDTYPE_LEN = 28; -> not supported with C90 to be used for array sizes */
24 #define QUEUE_ENTRY_EMBEDDEDTYPE_LEN 28
25
26 #define QUEUE_PREFIX_MAX 20
27 #define QUEUE_DBNAME_MAX 256
28 #define QUEUE_ID_MAX 256
29 /**
30 * The QueueProperty struct holds all configuration parameters of the queue to create.
31 * It is passed by the client code to create a queue.
32 */
33 typedef struct {
34 char dbName[QUEUE_DBNAME_MAX]; /**< The database name, for SQLite it is the file name on HD, "xmlBlaster.db" */
35 char queueName[QUEUE_ID_MAX]; /**< The name of the queue, "connection_client_joe" */
36 char tablePrefix[QUEUE_PREFIX_MAX]; /**< The table prefix to use, "XB_" */
37 int32_t maxNumOfEntries; /**< The max. accepted entries, 10000 */
38 int64_t maxNumOfBytes; /**< The max. capacity of the queue in bytes, 10000000LL */
39 XmlBlasterLogging logFp; /**< Your logging implementation or NULL if no logging callbacks are desired */
40 XMLBLASTER_LOG_LEVEL logLevel; /**< Set to LOG_TRACE to receive any logging */
41 void *userObject; /**< A pointer of your choice, is passed back when calling logFp in queueP->userObject */
42 } QueueProperties;
43
44 /**
45 * A struct holding the necessary queue entry informations used by I_Queue.
46 */
47 typedef struct {
48 int64_t uniqueId; /**< The unique key, used for sorting, usually a time stamp [nano sec]. Is assumed to be ascending over time. */
49 int16_t priority; /**< The priority of the queue entry, has higher sorting order than than the time stamp */
50 bool isPersistent; /**< Mark an entry to be persistent, needed for cache implementations, 'T' is true, 'F' is false. 'F' in persistent queue is a swapped transient entry */
51 int64_t sizeInBytes; /**< The size of this entry which is given by the client and used to sum up queue->numOfBytes, if 0 we use the size of the blob */
52 char embeddedType[QUEUE_ENTRY_EMBEDDEDTYPE_LEN]; /**< A string describing this entry, for example the format of the blob. */
53 BlobHolder embeddedBlob; /**< blob.data is allocated with malloc, you need to free() it yourself, is compressed if marked as such */
54 } QueueEntry;
55
56 /**
57 * Holds an array of Messages
58 */
59 typedef struct QueueEntryStructArr {
60 size_t len;
61 QueueEntry *queueEntryArr;
62 } QueueEntryArr;
63
64 struct I_QueueStruct;
65 typedef struct I_QueueStruct I_Queue;
66
67 /** Declare function pointers to use in struct to simulate object oriented access */
68 typedef bool ( * I_QueueInitialize)(I_Queue *queueP, const QueueProperties *queueProperties, ExceptionStruct *exception);
69 typedef void ( * I_QueueShutdown)(I_Queue **queuePP, ExceptionStruct *exception);
70 typedef bool ( * I_QueueDestroy)(I_Queue **queuePP, ExceptionStruct *exception);
71 typedef const QueueProperties *( * I_QueueGetProperties)(I_Queue *queueP);
72 typedef void ( * I_QueuePut)(I_Queue *queueP, const QueueEntry *queueEntry, ExceptionStruct *exception);
73 typedef QueueEntryArr *( * I_QueuePeekWithSamePriority)(I_Queue *queueP, int32_t maxNumOfEntries, int64_t maxNumOfBytes, ExceptionStruct *exception);
74 typedef int32_t ( * I_QueueRandomRemove)(I_Queue *queueP, const QueueEntryArr *queueEntryArr, ExceptionStruct *exception);
75 typedef bool ( * I_QueueClear)(I_Queue *queueP, ExceptionStruct *exception);
76 typedef bool ( * I_QueueEmpty)(I_Queue *queueP);
77 typedef int32_t ( * I_QueueNumOfEntries)(I_Queue *queueP);
78 typedef int32_t ( * I_QueueMaxNumOfEntries)(I_Queue *queueP);
79 typedef int64_t ( * I_QueueNumOfBytes)(I_Queue *queueP);
80 typedef int64_t ( * I_QueueMaxNumOfBytes)(I_Queue *queueP);
81
82 /**
83 * Interface for a queue implementation.
84 * See SQLiteQueue.c for a DB based persistent queue implementation.
85 * The 'I_' stands for 'interface'.
86 * @see <a href="http://www.xmlBlaster.org/xmlBlaster/doc/requirements/client.c.queue.html">The client.c.queue requirement</a>
87 */
88 struct I_QueueStruct {
89 /* public: */
90 void *userObject; /* A client can use this pointer to point to any client specific information */
91
92 /**
93 * Access the configuration properties (readonly).
94 * @param queueP The 'this' pointer (similar to the hidden C++ 'this' pointer)
95 * @return The queue configuration
96 */
97 I_QueueGetProperties getProperties;
98
99 /**
100 * Puts a new entry into the queue.
101 * Note that this method takes the entry pointed to by the argument
102 * and puts a reference to it into the queue. This means that you can not destroy the entry before the
103 * reference to it has been processed.
104 * @param queueP The 'this' pointer (similar to the hidden C++ 'this' pointer)
105 * @param queueEntry The data of type #QueueEntry to put into the queue
106 * Please initialize it with <code>memset(&queueEntry, 0, sizeof(QueueEntry));</code> before setting
107 * your values so we can add new fields without breaking your code
108 * @param exception Check *exception.errorCode!=0 for errors:
109 * "user.illegalArgument",
110 * "resource.db.unavailable", "resource.db.block", "resource.db.unknown"
111 * "resource.overflow.queue.entries", "resource.overflow.queue.bytes"
112 */
113 I_QueuePut put;
114
115 /**
116 * Returns maximum the first num element in the queue of highest priority
117 * but does not remove it from that queue (leaves it untouched).
118 * @param queueP The 'this' pointer (similar to the hidden C++ 'this' pointer)
119 * @param maxNumOfEntries Access num entries, if -1 access all entries currently found
120 * @param maxNumOfBytes so many entries are returned as not to exceed the amount specified. If the first
121 * entry is bigger than this amount, it is returned anyway. -1 is unlimited.
122 * @param exception *exception.errorCode!=0 if the underlying implementation gets an exception:
123 * "user.illegalArgument",
124 * "resource.db.unavailable", "resource.db.block", "resource.db.unknown"
125 * @return list with QueueEntry, the least elements with respect to the given time ordering
126 * or QueueEntryArr.len==0.
127 * Returned pointer is only NULL on exception
128 */
129 I_QueuePeekWithSamePriority peekWithSamePriority;
130
131 /**
132 * Removes the given entries from persistence.
133 * @param queueP The 'this' pointer (similar to the hidden C++ 'this' pointer)
134 * @param queueEntryArr The entries to remove
135 * Please initialize each entry with <code>memset(&queueEntry, 0, sizeof(QueueEntry));</code>
136 * (or use <code>calloc()</code>) before setting
137 * your values so we can add new fields without breaking your code
138 * @param exception Check *exception.errorCode!=0 for errors:
139 * "user.illegalArgument",
140 * "resource.db.unavailable", "resource.db.block", "resource.db.unknown"
141 * "resource.overflow.queue.entries", "resource.overflow.queue.bytes"
142 * @return The number of removed entries
143 */
144 I_QueueRandomRemove randomRemove;
145
146 /**
147 * Clears (removes all entries) this queue
148 * @param queueP The 'this' pointer (similar to the hidden C++ 'this' pointer)
149 * @param exception Check *exception.errorCode!=0 for errors:
150 * "user.illegalArgument",
151 * "resource.db.unavailable", "resource.db.block", "resource.db.unknown"
152 * @return true on success, if false *exception.errorCode is not 0
153 */
154 I_QueueClear clear;
155
156 /**
157 * Shutdown the queue and free memory resources, no persistent entries are destroyed.
158 * The backend store is closed and all memory allocation are freed and the queueP is set to NULL<br />
159 * NOTE: Your queueP is not usable anymore after this call.
160 * @param queuePP The pointer to your queue pointer, after freeing it is set to *queuePP=0
161 * @param exception *exception.errorCode!=0 if the underlying implementation gets an exception
162 */
163 I_QueueShutdown shutdown;
164
165 /**
166 * An administrative command to remove the backend store (e.g. clear all entries and the database files).
167 * @param queueP The 'this' pointer (similar to the hidden C++ 'this' pointer)
168 * @return true on success, if false *exception.errorCode is not 0
169 */
170 I_QueueDestroy destroy;
171
172 /**
173 * Access the current number of entries.
174 * @param queueP The 'this' pointer (similar to the hidden C++ 'this' pointer)
175 * @return The number of entries in the queue, returns -1 on error
176 */
177 I_QueueNumOfEntries getNumOfEntries;
178
179 /**
180 * Access the configured maximum number of elements for this queue.
181 * @param queueP The 'this' pointer (similar to the hidden C++ 'this' pointer)
182 * @return The maximum number of elements in the queue, returns -1 when passing a NULL pointer
183 */
184 I_QueueMaxNumOfEntries getMaxNumOfEntries;
185
186 /**
187 * Returns the amount of bytes currently in the queue
188 * If the implementation of this interface is not able to return the correct
189 * number of entries (for example if the implementation must make a remote
190 * call to a DB which is temporarly not available) it will return -1.
191 * @param queueP The 'this' pointer (similar to the hidden C++ 'this' pointer)
192 * @return The amount of bytes currently in the queue, returns -1 on error
193 */
194 I_QueueNumOfBytes getNumOfBytes;
195
196 /**
197 * Access the configured capacity (maximum bytes) for this queue.
198 * @param queueP The 'this' pointer (similar to the hidden C++ 'this' pointer)
199 * @return The maximum capacity for the queue in bytes, returns -1 when passing a NULL pointer
200 */
201 I_QueueMaxNumOfBytes getMaxNumOfBytes;
202
203 /**
204 * Check if queue is empty.
205 * @param queueP The 'this' pointer (similar to the hidden C++ 'this' pointer)
206 * returns true if the queue is empty, false otherwise
207 */
208 I_QueueEmpty empty;
209
210 /**
211 * Set the logLevel to LOG_TRACE to get logging output.
212 * Other levels are not supported
213 */
214 XMLBLASTER_LOG_LEVEL logLevel;
215
216 /**
217 * Assign your logging function pointer to receive logging output.
218 * @see xmlBlaster/demo/c/socket/LogRedirect.c for an example
219 */
220 XmlBlasterLogging log;
221
222 /* private: */
223
224 /**
225 * For internal use only.
226 * @return false on error
227 */
228 I_QueueInitialize initialize;
229 bool isInitialized; /** Hold current state of I_QueueStruct */
230 void *privateObject; /** Usually holds a pointer on the internal data structure (like a DB handle or a hashtable) */
231 };
232
233 /**
234 * Get an instance of a persistent queue and initialize it.
235 *
236 * Every call creates a new and independent instance which shall
237 * be destroyed by a call to freeQueue() when you are done
238 *
239 * @param queueProperties
240 * Configuration properties of the queue, always do a first
241 * <code>memset(&queueProperties, 0, sizeof(QueueProperties));</code>
242 * to initialize new, future members.<br />
243 * <pre>
244 * dbName The database name, for SQLite it is the file name on HD, "xmlBlasterClient.db"
245 * queueName The name of the queue, "connection_clientJoe"
246 * maxNumOfEntries The max. accepted entries, 10000000l
247 * maxNumOfBytes The max. accepted bytes, 1000000000ll
248 * logFp Your logging implementation or NULL if no logging callbacks are desired
249 * logLevel Set to LOG_TRACE to receive any logging
250 * userObject A pointer of your choice, is passed back when calling logFp in queueP->userObject
251 * </pre>
252 * @param exception
253 * @return queueP The 'this' pointer
254 */
255 Dll_Export extern I_Queue *createQueue(const QueueProperties *queueProperties, ExceptionStruct *exception);
256
257 /**
258 * Frees everything inside QueueEntryArr and the struct QueueEntryArr itself.
259 * @param queueEntryArr The struct to free, it is not usable anymore after this call.
260 * Passing NULL is OK
261 */
262 extern Dll_Export void freeQueueEntryArr(QueueEntryArr *queueEntryArr);
263
264 /**
265 * Frees everything inside QueueEntryArr but NOT the struct QueueEntryArr itself.
266 * @param queueEntryArr The struct internals to free.
267 * Passing NULL is OK
268 */
269 extern Dll_Export void freeQueueEntryArrInternal(QueueEntryArr *queueEntryArr);
270
271 /**
272 * Frees the internal blob and the queueEntry itself.
273 * @param queueEntry Its memory is freed, it is not usable anymore after this call.
274 * Passing NULL is OK
275 */
276 extern Dll_Export void freeQueueEntry(QueueEntry *queueEntry);
277
278 /**
279 * NOTE: You need to free the returned pointer with freeEntryDump() (which calls free())!
280 *
281 * @param maxContentDumpLen for -1 get the complete content, else limit the
282 * content to the given number of bytes
283 * @return A ASCII XML formatted entry or NULL if out of memory
284 */
285 extern Dll_Export char *queueEntryToXml(QueueEntry *queueEntry, int maxContentDumpLen);
286
287 /**
288 * Free the memory allocated by queueEntryToXml()
289 * @param queueDump NULL is OK
290 */
291 extern Dll_Export void freeEntryDump(char *queueDump);
292
293 #ifdef __cplusplus
294 #ifndef XMLBLASTER_C_COMPILE_AS_CPP
295 }
296 #endif
297 #endif
298
299 #endif /* I_QUEUE_QueueInterface_h */
syntax highlighted by Code2HTML, v. 0.9.1