--- libaitio/src/sess.c 2013/03/13 14:17:53 1.1 +++ libaitio/src/sess.c 2013/03/13 14:17:53 1.1.2.1 @@ -0,0 +1,437 @@ +/************************************************************************* +* (C) 2008 AITNET ltd - Sofia/Bulgaria - +* by Michael Pounov +* +* $Author: misho $ +* $Id: sess.c,v 1.1.2.1 2013/03/13 14:17:53 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, 2013 + 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. +*/ +#include "global.h" + + +/* + * sess_FreeValues() - Free all values from value array allocated from sess_GetValues() + * + * @ppsVals = Array strings + * return: none + */ +inline void +sess_FreeValues(char *** __restrict ppsVals) +{ + char **ptr; + + assert(ppsVals); + if (!ppsVals) + return; + + for (ptr = *ppsVals; *ptr; ptr++) + e_free(*ptr); + e_free(*ppsVals); + *ppsVals = NULL; +} + +/* + * 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 sess_FreeValues after use!) + */ +int +sess_GetValues(ait_sess_t * __restrict s, char ***ppsVals) +{ + register int i; + char **valz, *Shared = NULL; + char *peer, *p_brk; + + if (!s || !ppsVals) + return -1; + valz = e_malloc(sizeof(caddr_t)); + if (!valz) { + LOGERR; + return -1; + } else + *valz = NULL; + + /* allocated memory & mirrored shared memory into this */ + Shared = e_malloc(s->eom); + if (!Shared) { + LOGERR; + e_free(valz); + return -1; + } else + memcpy(Shared, s->addr, s->eom); + + for (i = 0, peer = strtok_r(Shared, MEM_DELIM"\r\n", &p_brk); peer; + peer = strtok_r(NULL, MEM_DELIM"\r\n", &p_brk)) { + if (!strchr(peer, '=')) + continue; + else + i++; + + valz = e_realloc(valz, (i + 1) * sizeof(caddr_t)); + if (!valz) { + LOGERR; + e_free(Shared); + return -1; + } else + valz[i] = NULL; + + valz[i - 1] = e_strdup(peer); + } + + e_free(Shared); + *ppsVals = valz; + return i; +} + +/* + * 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(ait_sess_t * __restrict s, const char *csAttr, char *psVal, int *pnLen) +{ + register int i; + int def = IS_VAL; + char *Shared = NULL; + char *peer, *p_brk, *a_brk, *attr, *val; + + if (!s || !csAttr || !*csAttr) + return -1; + if (psVal) { + if (pnLen && *pnLen > 0) + memset(psVal, 0, *pnLen); + else + return -1; + } + + /* allocated memory & mirrored shared memory into this */ + Shared = e_malloc(s->eom); + if (!Shared) { + LOGERR; + return -1; + } else + memcpy(Shared, s->addr, s->eom); + + for (i = 1, peer = strtok_r(Shared, MEM_DELIM"\r\n", &p_brk); peer; + i++, peer = strtok_r(NULL, MEM_DELIM"\r\n", &p_brk)) { + attr = strtok_r(peer, "=\r\n", &a_brk); + if (attr && !strncmp(attr, csAttr, MAX_ATTRIBUTE - 1)) { + val = strtok_r(NULL, "=\r\n", &a_brk); + if (val && strlen(val)) { + if (psVal) + strlcpy(psVal, val, *pnLen); + if (pnLen) + *pnLen = strlen(val); + } else + def = IS_DEF; + + e_free(Shared); + return i | def; + } + } + + e_free(Shared); + return 0; +} + +/* + * 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(ait_sess_t * __restrict s, const char *csAttr) +{ + register int i; + int attrlen; + char *Buffer, *Shared, szAttr[MAX_ATTRIBUTE]; + char *peer, *p_brk; + + if (!s || !csAttr || !*csAttr) + return -1; + else + attrlen = strlen(csAttr); + Buffer = Shared = NULL; + strlcpy(szAttr, csAttr, sizeof szAttr); + strlcat(szAttr, "=", sizeof szAttr); + + Buffer = e_malloc(s->eom); + if (!Buffer) { + LOGERR; + return -1; + } else + memset(Buffer, 0, s->eom); + Shared = e_malloc(s->eom); + if (!Shared) { + LOGERR; + e_free(Buffer); + return -1; + } else { + DEC_SEM(s); + memcpy(Shared, s->addr, s->eom); + } + + for (i = 1, peer = strtok_r(Shared, MEM_DELIM"\r\n", &p_brk); peer; + i++, peer = strtok_r(NULL, MEM_DELIM"\r\n", &p_brk)) { + if (!strncmp(peer, csAttr, attrlen)) + if (peer[attrlen] == '=' || peer[attrlen] == *MEM_DELIM || !peer[attrlen] || + peer[attrlen] == '\r' || peer[attrlen] == '\n') + continue; + + strlcat(Buffer, peer, s->eom); + strlcat(Buffer, MEM_DELIM, s->eom); + } + + memcpy(s->addr, Buffer, s->eom); + + if (s->type == SHARED_MAP) + msync(s->addr, 0, MS_SYNC | MS_INVALIDATE); + + INC_SEM(s); + e_free(Shared); + e_free(Buffer); + return 0; +} + +/* + * sess_SetValue() - Set item into session shared memory or update if exists + * + * @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(ait_sess_t * __restrict s, const char *csAttr, const char *psVal) +{ + register int i; + int upd, def = IS_VAL; + char *Buffer, *Shared, szAttr[MAX_ATTRIBUTE]; + char *peer, *p_brk; + + if (!s || !csAttr || !*csAttr) + return -1; + else + Buffer = Shared = NULL; + strlcpy(szAttr, csAttr, sizeof szAttr); + strlcat(szAttr, "=", sizeof szAttr); + + Buffer = e_malloc(s->eom); + if (!Buffer) { + LOGERR; + return -1; + } else + memset(Buffer, 0, s->eom); + Shared = e_malloc(s->eom); + if (!Shared) { + LOGERR; + e_free(Buffer); + return -1; + } else { + DEC_SEM(s); + memcpy(Shared, s->addr, s->eom); + } + + for (i = 1, upd = 0, peer = strtok_r(Shared, MEM_DELIM"\r\n", &p_brk); peer; + i++, peer = strtok_r(NULL, MEM_DELIM"\r\n", &p_brk)) { + if (!strncmp(peer, szAttr, strlen(szAttr))) { + upd++; + if (psVal) { + strlcat(Buffer, szAttr, s->eom); + strlcat(Buffer, psVal, s->eom); + strlcat(Buffer, MEM_DELIM, s->eom); + } else { + strlcat(Buffer, csAttr, s->eom); + strlcat(Buffer, MEM_DELIM, s->eom); + def = IS_DEF; + } + continue; + } + + strlcat(Buffer, peer, s->eom); + strlcat(Buffer, MEM_DELIM, s->eom); + } + + if (!upd) { + if (psVal) { + strlcat(Buffer, szAttr, s->eom); + strlcat(Buffer, psVal, s->eom); + strlcat(Buffer, MEM_DELIM, s->eom); + } else { + strlcat(Buffer, csAttr, s->eom); + strlcat(Buffer, MEM_DELIM, s->eom); + def = IS_DEF; + } + def |= IS_ADD; + } + + memcpy(s->addr, Buffer, s->eom); + + if (s->type == SHARED_MAP) + msync(s->addr, 0, MS_SYNC | MS_INVALIDATE); + + INC_SEM(s); + e_free(Shared); + e_free(Buffer); + return upd | def; +} + + +/* + * 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) +{ + array_t *arr = NULL; + sess_hdr_t *hdr; + + assert(s); + if (!s) { + sess_SetErr(EINVAL, "Invalid argument\n"); + return NULL; + } + if (s->addr) { + sess_SetErr(EINVAL, "Already attached memory\n"); + return NULL; + } + + ATTACH_MEMORY(s); + if (!s->addr) + return NULL; + else + hdr = (sess_hdr_t*) s->addr; + if (hdr->hdr_magic != SESS_AIT_MAGIC) { + DETACH_MEMORY(s); + + sess_SetErr(EINVAL, "Shared memory not contains values with proper format\n"); + return NULL; + } + + DEC_SEM(s); + s->zcpy = useDirect; + arr = ait_map2vars(s->addr + sizeof(sess_hdr_t), s->eom - sizeof(sess_hdr_t), + hdr->hdr_argc, useDirect); + INC_SEM(s); + + if (!s->zcpy) + DETACH_MEMORY(s); + return arr; +} + +/* + * 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) +{ + assert(s); + if (!s) { + sess_SetErr(EINVAL, "Invalid argument\n"); + return; + } + + if (!s->zcpy) + array_Free(*arr); + else + DETACH_MEMORY(s); + array_Destroy(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) +{ + sess_hdr_t *hdr; + int ret = 0; + + assert(s && arr); + if (!s || !arr) { + sess_SetErr(EINVAL, "Invalid argument\n"); + return -1; + } + + ATTACH_MEMORY(s); + if (!s->addr) { + DETACH_MEMORY(s); + return -1; + } else + hdr = (sess_hdr_t*) s->addr; + + DEC_SEM(s); + if ((ret = ait_vars2map(s->addr + sizeof(sess_hdr_t), + s->eom - sizeof(sess_hdr_t), arr)) != -1) { + hdr->hdr_magic = SESS_AIT_MAGIC; + hdr->hdr_argc = array_Size(arr); + ret += sizeof(sess_hdr_t); + } + INC_SEM(s); + + DETACH_MEMORY(s); + return ret; +}