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