--- libaitsess/inc/aitsess.h 2011/04/30 21:35:21 1.2 +++ libaitsess/inc/aitsess.h 2012/02/28 00:13:26 1.4.2.4 @@ -3,18 +3,58 @@ * by Michael Pounov * * $Author: misho $ -* $Id: aitsess.h,v 1.2 2011/04/30 21:35:21 misho Exp $ +* $Id: aitsess.h,v 1.4.2.4 2012/02/28 00:13:26 misho Exp $ * -*************************************************************************/ +************************************************************************** +The ELWIX and AITNET software is distributed under the following +terms: + +All of the documentation and software included in the ELWIX and AITNET +Releases is copyrighted by ELWIX - Sofia/Bulgaria + +Copyright 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012 + by Michael Pounov . All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. +3. All advertising materials mentioning features or use of this software + must display the following acknowledgement: +This product includes software developed by Michael Pounov +ELWIX - Embedded LightWeight unIX and its contributors. +4. Neither the name of AITNET nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY AITNET AND CONTRIBUTORS ``AS IS'' AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +SUCH DAMAGE. +*/ #ifndef __AITSESS_H #define __AITSESS_H +#include +#include #include -#include +#include -#define SHARED_IPC 1 -#define SHARED_MAP 2 +#define SHARED_UNKNOWN -1 +#define SHARED_IPC 0 +#define SHARED_MAP 1 #define IS_VAL 0x0 #define IS_ADD 0x40000000 @@ -23,13 +63,56 @@ #define ISNEW(x) (((x) & IS_ADD) == IS_ADD) #define ISDEF(x) (((x) & IS_DEF) == IS_DEF) -#define MAX_ATTRIBUTE 63 +#define MAX_ATTRIBUTE 64 #define MAX_SEMNAME 14 +/* Memory pool */ -typedef struct _tagSess { +#define MEM_BUCKETS 28 /* 32 bits - 4 bits = 28 items in bucket array */ + +struct tagAlloc { + char alloc_name[MAX_ATTRIBUTE]; + volatile unsigned int alloc_flags; + + unsigned int *alloc_mem; + + TAILQ_ENTRY(tagAlloc) alloc_node; +}; +typedef TAILQ_HEAD(, tagAlloc) mpool_bucket_t; + +typedef struct _tagMPool { + pthread_mutex_t pool_mtx; + + struct { + unsigned long alloc; + unsigned long free; + unsigned long cache; + } pool_calls; + struct { + unsigned long alloc; + unsigned long free; + unsigned long cache; + } pool_bytes; + struct { + unsigned long max; + unsigned long curr; + } pool_quota; + + /* pool buckets */ + mpool_bucket_t pool_active[MEM_BUCKETS]; + mpool_bucket_t pool_inactive[MEM_BUCKETS]; +} mpool_t; +#define mpool_lock(x) (assert((x)), pthread_mutex_lock(&(x)->pool_mtx)) +#define mpool_unlock(x) (assert((x)), pthread_mutex_unlock(&(x)->pool_mtx)) + +/* Shared memory session */ + +typedef struct tagSess { key_t key; - u_char type; + char type; + char zcpy; + + char name[BUFSIZ]; off_t eom; void *addr; off_t offset; @@ -41,276 +124,343 @@ typedef struct _tagSess { int semid; sem_t *sid; } id; -} tagSess; + struct { + int (*create)(int, long, void *, ...); + void (*destroy)(void *); + void *(*attach)(void *, void *); + void (*detach)(void *); + void (*notSem)(void *); + int (*isSemOK)(void *); + int (*incSem)(void *); + int (*decSem)(void *); + } sess; +} ait_sess_t; + // ------------------------------------------------------- // sess_GetErrno() Get error code of last operation inline int sess_GetErrno(); // sess_GetError() Get error text of last operation inline const char *sess_GetError(); +// sess_SetErr() Set error to variables for internal use!!! +inline void sess_SetErr(int eno, char *estr, ...); // ------------------------------------------------------- /* - * initSession() Initializing session structure, if session file not exists creating with specified tech - * @cnID = Technology using in session. SHARED_IPC IPC tech; SHARED_MAP BSD MemoryMap tech + * mpool_init() - Init memory pool + * + * return: =NULL error or !=NULL new allocated pool + */ +mpool_t *mpool_init(void); +/* + * mpool_destroy() - Destroy memory pool + * + * @mp = Memory pool + * return: none + */ +void mpool_destroy(mpool_t ** __restrict mp); +/* + * mpool_purge() - Purge memory block cache and release resources + * + * @mp = Memory pool + * @atmost = Free at most in buckets + * return: -1 error or 0 ok + */ +int mpool_purge(mpool_t * __restrict mp, unsigned int atmost); +/* + * mpool_malloc() - Memory allocation + * + * @mp = Memory pool + * @size = Size + * @memname = Optional memory block name + * return: NULL error or !=NULL ok allocated memory + */ +void *mpool_malloc(mpool_t * __restrict mp, unsigned int size, const char *memname); +/* + * mpool_free() Free allocated memory with mpool_alloc() + * + * @mp = Memory pool + * @data = Allocated memory data + * @purge = if !=0 force release memory block + * return: <0 error or 0 ok released memory block + */ +int mpool_free(mpool_t * __restrict mp, void * __restrict data, int purge); +/* + * mpool_free2() Free allocated memory with mpool_alloc() by size and memory name + * + * @mp = Memory pool + * @size = Allocated memory data size + * @memname = Memory name + * @purge = if !=0 force release memory block + * return: <0 error or 0 ok released memory block + */ +int mpool_free2(mpool_t * __restrict mp, unsigned int size, const char *memname, int purge); +/* + * mpool_getmembynam() Find allocated memory block by size and memory name + * + * @mp = Memory pool + * @size = Memory size + * @memname = Memory name + * return: NULL error or not found and !=NULL allocated memory + */ +inline struct tagAlloc *mpool_getmembynam(mpool_t * __restrict mp, unsigned int size, const char *memname); +/* + * mpool_getsizebyaddr() - Get size of allocated memory block by address + * + * @data = allocated memory from mpool_malloc() + * return: usable size of allocated memory block + */ +inline unsigned int mpool_getsizebyaddr(void * __restrict data); +/* + * mpool_chkaddr() - Check validity of given address + * + * @data = allocated memory from mpool_malloc() + * return: -1 bad address, 1 corrupted address or 0 ok + */ +inline int mpool_chkaddr(void * __restrict data); + + +/* + * sess_initSession() Initializing session structure, if session file not exists creating with specified tech + * + * @id = Technology using in session. SHARED_IPC IPC tech orSHARED_MAP BSD MemoryMap tech * @csFName = Session filename for build key and identified - * @Sess = Session item + * @Sess = Session item, if =NULL allocate memory for session after use must be free! * return: 0 OK new key created, -1 error: no memory or file not created, 1 OK key finded -*/ -inline int initSession(const int cnID, const char *csFName, tagSess ** __restrict Sess); + */ +int sess_initSession(int id, const char *csFName, ait_sess_t ** __restrict Sess); /* - * freeSession() Free allocated memory for session item and delete session file if present name - * @csFName = Session filename for delete, if NULL nothing delete + * sess_freeSession() Free allocated memory for session item and delete session file if present name + * * @Sess = Session item -*/ -inline void freeSession(const char *csFName, tagSess ** __restrict Sess); + * return: none + */ +void sess_freeSession(ait_sess_t ** __restrict Sess); + /* * map_createSession() MMAP Created session and allocated resources - * @csFName = Session name for identified - * @cnSeed = Seed for securing key - * @cnSize = Allocated shared memory size in bytes + * + * @nSeed = Seed for securing key, if =-1 must add ready for use key + * @nSize = Allocated shared memory size in bytes * @Sess = Session item + * @... = If nSeed == -1 add ready for use key value * return: 0 Ok successful, -1 error: not allocated resources -*/ -int map_createSession(const char *csFName, const int cnSeed, const u_int cnSize, tagSess ** __restrict Sess); + */ +int map_createSession(int nSeed, long nSize, ait_sess_t * __restrict Sess, ...); /* * map_destroySession() MMAP free shared resources - * @csFName = Session name for delete + * * @Sess = Session item -*/ -void map_destroySession(const char *csFName, tagSess ** __restrict Sess); + * return: none + */ +void map_destroySession(ait_sess_t * __restrict Sess); /* * ipc_createSession() IPC Created session and allocated resources - * @csFName = Session name for identified - * @cnSeed = Seed for securing key - * @cnSize = Allocated shared memory size in bytes + * + * @nSeed = Seed for securing key, if =-1 must add ready for use key + * @nSize = Allocated shared memory size in bytes * @Sess = Session item + * @... = If nSeed == -1 add ready for use key value * return: 0 Ok successful, -1 error: not allocated resources -*/ -int ipc_createSession(const char *csFName, const int cnSeed, const u_int cnSize, tagSess ** __restrict Sess); + */ +int ipc_createSession(int nSeed, long nSize, ait_sess_t * __restrict Sess, ...); /* * ipc_destroySession() IPC free shared resources - * @csFName = Session name for delete + * * @Sess = Session item -*/ -void ipc_destroySession(const char *csFName, tagSess ** __restrict Sess); + * return: none + */ +void ipc_destroySession(ait_sess_t * __restrict Sess); /* * map_attachSession() MMAP Attach to shared memory & return begin address + * * @s = Session item * @procMem = Custom start address (optionl) *default must be 0* * return: NULL failed attach, !=NULL begin address of memory -*/ -inline void *map_attachSession(tagSess * __restrict s, void *procMem); + */ +void *map_attachSession(ait_sess_t * __restrict s, void *procMem); /* * map_detachSession() MMAP Detach from shared memory + * * @s = Session item -*/ -inline void map_detachSession(tagSess * __restrict s); + * return: none + */ +void map_detachSession(ait_sess_t * __restrict s); /* * ipc_attachSession() IPC Attach to shared memory & return begin address + * * @s = Session item * @procMem = Custom start address (optionl) *default must be 0* * return: NULL failed attach, !=NULL begin address of memory -*/ -inline void *ipc_attachSession(tagSess * __restrict s, void *procMem); + */ +void *ipc_attachSession(ait_sess_t * __restrict s, void *procMem); /* * ipc_detachSession() IPC Detach from shared memory + * * @s = Session item -*/ -inline void ipc_detachSession(tagSess * __restrict s); + * return: none + */ +void ipc_detachSession(ait_sess_t * __restrict s); /* - * isAttached() Check for mapped/(attached) shared memory + * sess_isAttached() Check for attached shared memory + * * @s = Session item * return: -1 null session item, 0 not attached, 1 attached memory -*/ -inline int isAttached(tagSess * __restrict s); + */ +inline int sess_isAttached(ait_sess_t * __restrict s); /* * map_notSemaphore() MMAP negative block if semaphore isn`t signaled + * * @s = Session item -*/ -inline void map_notSemaphore(tagSess * __restrict s); + * return: none + */ +void map_notSemaphore(ait_sess_t * __restrict s); /* - * map_isSemaphored() MMAP Check semaphore + * map_isSemaphoreOK() MMAP Check semaphore + * * @s = Session item * return: -1 error: can`t return semaphore, 0 = false, 1 = true -*/ -inline int map_isSemaphored(tagSess * __restrict s); + */ +int map_isSemaphoreOK(ait_sess_t * __restrict s); /* - * map_addSemaphore() MMAP unblock semaphore, increment semaphore + * map_incSemaphore() MMAP unblock semaphore, increment semaphore + * * @s = Session item * return: 0 Ok, -1 error: can`t increment -*/ -inline int map_addSemaphore(tagSess * __restrict s); + */ +int map_incSemaphore(ait_sess_t * __restrict s); /* * map_decSemaphore() MMAP block semaphore, decrement semaphore + * * @s = Session item * return: 0 Ok, -1 error: can`t decrement -*/ -inline int map_decSemaphore(tagSess * __restrict s); + */ +int map_decSemaphore(ait_sess_t * __restrict s); /* * ipc_notSemaphore() IPC negative block if semaphore isn`t signaled + * * @s = Session item -*/ -inline void ipc_notSemaphore(tagSess * __restrict s); + * return: none + */ +void ipc_notSemaphore(ait_sess_t * __restrict s); /* - * ipc_isSemaphored() IPC Check semaphore + * ipc_isSemaphoreOK() IPC Check semaphore + * * @s = Session item * return: -1 error: can`t return semaphore, 0 = false, 1 = true -*/ -inline int ipc_isSemaphored(tagSess * __restrict s); + */ +int ipc_isSemaphoreOK(ait_sess_t * __restrict s); /* - * ipc_addSemaphore() IPC unblock semaphore, increment semaphore + * ipc_incSemaphore() IPC unblock semaphore, increment semaphore + * * @s = Session item * return: 0 Ok, -1 error: can`t increment -*/ -inline int ipc_addSemaphore(tagSess * __restrict s); + */ +int ipc_incSemaphore(ait_sess_t * __restrict s); /* * ipc_decSemaphore() IPC block semaphore, decrement semaphore + * * @s = Session item * return: 0 Ok, -1 error: can`t decrement -*/ -inline int ipc_decSemaphore(tagSess * __restrict s); + */ +int ipc_decSemaphore(ait_sess_t * __restrict s); -// --------------------------------------------------------- -// -// Lazy macros for lazy programmers :-) by Michael Pounov; Optimizing work with sessions! -// +/* --------------------------------------------------------- */ -#define DESTROY_SESSION(fname, s) do { \ - switch (((*s))->type) { \ - case SHARED_IPC: \ - ipc_destroySession((fname), (s)); \ - break; \ - case SHARED_MAP: \ - map_destroySession((fname), (s)); \ - break; \ - } \ - } while(0) +#define ALLOC_MEMORY(sd, siz, s, ...) (assert((s)), (s)->sess.create((sd), \ + (siz), (s), ## __VA_ARGS__)) +#define ATTACH_MEMORY(s) (assert((s)), (s)->sess.attach((s), NULL)) +#define DETACH_MEMORY(s) do { assert((s)); (s)->sess.detach((s)); } while(0) +#define FREE_MEMORY(s) do { assert((s)); (s)->sess.destroy((s)); } while(0) -#define ATTACH_MEMORY(s) do { \ - switch ((s)->type) { \ - case SHARED_IPC: \ - ipc_attachSession((s), 0); \ - break; \ - case SHARED_MAP: \ - map_attachSession((s), 0); \ - break; \ - } \ - } while(0) +#define IS_SEMOK(s) (assert((s)), (s)->sess.isSemOK((s))) +#define INC_SEM(s) (assert((s)), (s)->sess.incSem((s))) +#define DEC_SEM(s) (assert((s)), (s)->sess.decSem((s))) +#define NOT_SEM(s) do { assert((s)); (s)->sess.notSem((s)); } while(0) -#define DETACH_MEMORY(s) do { \ - switch ((s)->type) { \ - case SHARED_IPC: \ - ipc_detachSession((s)); \ - break; \ - case SHARED_MAP: \ - map_detachSession((s)); \ - break; \ - } \ - } while(0) +/* --------------------------------------------------------- */ -#define NOT_SEMAPHORE(s) do { \ - switch ((s)->type) { \ - case SHARED_IPC: \ - ipc_notSemaphore((s)); \ - break; \ - case SHARED_MAP: \ - map_notSemaphore((s)); \ - break; \ - } \ - } while(0) - -#define IS_SEMAPHORED(s, ret) do { \ - switch ((s)->type) { \ - case SHARED_IPC: \ - (ret) = ipc_isSemaphored((s)); \ - break; \ - case SHARED_MAP: \ - (ret) = map_isSemaphored((s)); \ - break; \ - default: \ - (ret) = -1; \ - } \ - } while(0) - -#define ADD_SEMAPHORE(s, ret) do { \ - switch ((s)->type) { \ - case SHARED_IPC: \ - (ret) = ipc_addSemaphore((s)); \ - break; \ - case SHARED_MAP: \ - (ret) = map_addSemaphore((s)); \ - break; \ - default: \ - (ret) = -1; \ - } \ - } while(0) - -#define DEC_SEMAPHORE(s, ret) do { \ - switch ((s)->type) { \ - case SHARED_IPC: \ - (ret) = ipc_decSemaphore((s)); \ - break; \ - case SHARED_MAP: \ - (ret) = map_decSemaphore((s)); \ - break; \ - default: \ - (ret) = -1; \ - } \ - } while(0) - -// --------------------------------------------------------- - /* * sess_FreeValues() Free all values from value array allocated from sess_GetValues() + * * @ppsVals = Array strings * return: none -*/ + */ inline void sess_FreeValues(char *** __restrict ppsVals); /* * sess_GetValues() Get all values from session shared memory + * * @s = Session item * @ppsVals = Return array strings * return: -1 error: in parameter, !=-1 count of returned strings in ppsVals (must be free after use!) -*/ -int sess_GetValues(tagSess * __restrict s, char ***ppsVals); + */ +int sess_GetValues(ait_sess_t * __restrict s, char ***ppsVals); /* * sess_GetValue() Get value from session shared memory from attribute + * * @s = Session item * @csAttr = Attribute for search * @psVal = Return string buffer * @pnLen = Length of return string buffer, // *{pnLen} input is max_size of buffer & output is really taken bytes * return: 0 not found, -1 error: in parameter, >0 get position, if define item merged with IS_DEF -*/ -int sess_GetValue(tagSess * __restrict s, const char *csAttr, char *psVal, int *pnLen); + */ +int sess_GetValue(ait_sess_t * __restrict s, const char *csAttr, char *psVal, int *pnLen); /* * sess_DelValue() Delete item from session shared memory + * * @s = Session item * @csAttr = Attribute for erasing * return: 0 Ok, -1 error: in parameter -*/ -int sess_DelValue(tagSess * __restrict s, const char *csAttr); + */ +int sess_DelValue(ait_sess_t * __restrict s, const char *csAttr); /* * sess_SetValue() Set item into session shared memory or update if find it + * * @s = Session item * @csAttr = Attribute * @psVal = Value * return: 0 nothing, -1 error: in parameter, >0 set position, if add item merged with IS_ADD and if define item merged with IS_DEF -*/ -int sess_SetValue(tagSess * __restrict s, const char *csAttr, const char *psVal); + */ +int sess_SetValue(ait_sess_t * __restrict s, const char *csAttr, const char *psVal); + +/* + * sess_prepareSession() Attach to shared memory and de-marshaling data + * + * @s = Session + * @useDirect = Use direct shared memory if !=0 or snapshot of data to array + * return: NULL error or no data, !=NULL array with variables, + * after use must free resources with sess_doneSession() + */ +array_t *sess_prepareSession(ait_sess_t * __restrict s, char useDirect); +/* + * sess_doneSession() Free resources allocated with sess_prepareSession() + * + * @s = Session + * @arr = Array with variables for free + * return: none + */ +void sess_doneSession(ait_sess_t * __restrict s, array_t ** __restrict arr); +/* + * sess_commitSession() Commit data to shared memory + * + * @s = Session + * @arr = Array with variables for save + * return -1 error or !=-1 size of stored variables into shared memory + */ +int sess_commitSession(ait_sess_t * __restrict s, array_t * __restrict arr); #endif