1 /* Copyright(C) 2004-2007 Brazil 2 3 This library is free software; you can redistribute it and/or 4 modify it under the terms of the GNU Lesser General Public 5 License as published by the Free Software Foundation; either 6 version 2.1 of the License, or (at your option) any later version. 7 8 This library is distributed in the hope that it will be useful, 9 but WITHOUT ANY WARRANTY; without even the implied warranty of 10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 11 Lesser General Public License for more details. 12 13 You should have received a copy of the GNU Lesser General Public 14 License along with this library; if not, write to the Free Software 15 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 16 */ 17 #ifndef SEN_CTX_H 18 #define SEN_CTX_H 19 20 #ifdef HAVE_ERRNO_H 21 #include <errno.h> 22 #endif /* HAVE_ERRNO_H */ 23 24 #ifndef SEN_COM_H 25 #include "com.h" 26 #endif /* SEN_COM_H */ 27 28 #ifdef __cplusplus 29 extern "C" { 30 #endif 31 32 /**** error handling ****/ 33 34 #define SEN_OP_T0LVL 0 35 #define SEN_OP_ERR0 1 36 37 enum { 38 SEN_EMERG = sen_log_emerg, 39 SEN_ALERT = sen_log_alert, 40 SEN_CRIT = sen_log_crit, 41 SEN_ERROR = sen_log_error, 42 SEN_WARN = sen_log_warning, 43 SEN_OK = sen_log_notice 44 }; 45 46 #define ERRCLR(ctx) do {\ 47 if (ctx) {\ 48 ((sen_ctx *)ctx)->errlvl = SEN_OK;\ 49 ((sen_ctx *)ctx)->rc = sen_success;\ 50 }\ 51 sen_gctx.errlvl = SEN_OK;\ 52 sen_gctx.rc = sen_success;\ 53 } while (0) 54 55 #define ERRSET(ctx,lvl,r,...) do {\ 56 ((sen_ctx *)ctx)->errlvl = (lvl);\ 57 ((sen_ctx *)ctx)->rc = (r);\ 58 ((sen_ctx *)ctx)->errfile = __FILE__;\ 59 ((sen_ctx *)ctx)->errline = __LINE__;\ 60 ((sen_ctx *)ctx)->errfunc = __FUNCTION__;\ 61 ((sen_ctx *)ctx)->cur = ((sen_ctx *)ctx)->str_end;\ 62 ((sen_ctx *)ctx)->op = SEN_OP_ERR0;\ 63 SEN_LOG(lvl, __VA_ARGS__);\ 64 sen_ctx_log((sen_ctx *)ctx, __VA_ARGS__);\ 65 } while (0) 66 67 #define ERRP(ctx,lvl) (((ctx) && ((sen_ctx *)(ctx))->errlvl <= (lvl)) || (sen_gctx.errlvl <= (lvl))) 68 69 #define QLERR(...) do {\ 70 ERRSET(ctx, SEN_WARN, sen_invalid_argument, __VA_ARGS__);\ 71 return F;\ 72 } while (0) 73 74 #define QLASSERT(expr) do {\ 75 if (!(expr)) { QLERR("syntax error"); }\ 76 } while (0) 77 78 #define ERR(rc,...) ERRSET(ctx, SEN_ERROR, (rc), __VA_ARGS__) 79 #define MERR(...) ERRSET(ctx, SEN_ALERT, sen_memory_exhausted, __VA_ARGS__) 80 #define SERR(str) ERR(sen_other_error, "syscall error '%s' (%s)", str, strerror(errno)) 81 82 #define GERR(rc,...) ERRSET(&sen_gctx, SEN_ERROR, (rc), __VA_ARGS__) 83 #define GMERR(...) ERRSET(&sen_gctx, SEN_ALERT, sen_memory_exhausted, __VA_ARGS__) 84 #define GSERR(str) GERR(sen_other_error, "syscall error '%s' (%s)", str, strerror(errno)) 85 86 #ifdef USE_FAIL_MALLOC 87 #define SEN_MALLOC(s) sen_fail_malloc(ctx,s,__FILE__,__LINE__,__FUNCTION__) 88 #define SEN_CALLOC(s) sen_fail_calloc(ctx,s,__FILE__,__LINE__,__FUNCTION__) 89 #define SEN_REALLOC(p,s) sen_fail_realloc(ctx,p,s,__FILE__,__LINE__,__FUNCTION__) 90 #define SEN_STRDUP(s) sen_fail_strdup(ctx,s,__FILE__,__LINE__,__FUNCTION__) 91 #define SEN_GMALLOC(s) sen_fail_malloc(&sen_gctx,s,__FILE__,__LINE__,__FUNCTION__) 92 #define SEN_GCALLOC(s) sen_fail_calloc(&sen_gctx,s,__FILE__,__LINE__,__FUNCTION__) 93 #define SEN_GREALLOC(p,s) sen_fail_realloc(&sen_gctx,p,s,__FILE__,__LINE__,__FUNCTION__) 94 #define SEN_GSTRDUP(s) sen_fail_strdup(&sen_gctx,s,__FILE__,__LINE__,__FUNTION__) 95 #else /* USE_FAIL_MALLOC */ 96 #define SEN_MALLOC(s) sen_malloc(ctx,s,__FILE__,__LINE__) 97 #define SEN_CALLOC(s) sen_calloc(ctx,s,__FILE__,__LINE__) 98 #define SEN_REALLOC(p,s) sen_realloc(ctx,p,s,__FILE__,__LINE__) 99 #define SEN_STRDUP(s) sen_strdup(ctx,s,__FILE__,__LINE__) 100 #define SEN_GMALLOC(s) sen_malloc(&sen_gctx,s,__FILE__,__LINE__) 101 #define SEN_GCALLOC(s) sen_calloc(&sen_gctx,s,__FILE__,__LINE__) 102 #define SEN_GREALLOC(p,s) sen_realloc(&sen_gctx,p,s,__FILE__,__LINE__) 103 #define SEN_GSTRDUP(s) sen_strdup(&sen_gctx,s,__FILE__,__LINE__) 104 #endif /* USE_FAIL_MALLOC */ 105 #define SEN_FREE(p) sen_free(ctx,p,__FILE__,__LINE__) 106 #define SEN_MALLOCN(t,n) ((t *)(SEN_MALLOC(sizeof(t) * (n)))) 107 #define SEN_GFREE(p) sen_free(&sen_gctx,p,__FILE__,__LINE__) 108 #define SEN_GMALLOCN(t,n) ((t *)(SEN_GMALLOC(sizeof(t) * (n)))) 109 110 #ifdef DEBUG 111 #define SEN_ASSERT(s) sen_assert((s),__FILE__,__LINE__,__FUNCTION__) 112 #else 113 #define SEN_ASSERT(s) 114 #endif 115 116 #ifdef USE_FAIL_MALLOC 117 int fail_malloc_check(size_t size, const char *file, int line, const char *func); 118 void *sen_fail_malloc(sen_ctx *ctx, size_t size, const char* file, int line, const char *func); 119 void *sen_fail_calloc(sen_ctx *ctx, size_t size, const char* file, int line, const char *func); 120 void *sen_fail_realloc(sen_ctx *ctx, void *ptr, size_t size, const char* file, int line, const char *func); 121 char *sen_fail_strdup(sen_ctx *ctx, const char *s, const char* file, int line, const char *func); 122 #endif /* USE_FAIL_MALLOC */ 123 void *sen_malloc(sen_ctx *ctx, size_t size, const char* file, int line); 124 void *sen_calloc(sen_ctx *ctx, size_t size, const char* file, int line); 125 void *sen_realloc(sen_ctx *ctx, void *ptr, size_t size, const char* file, int line); 126 char *sen_strdup(sen_ctx *ctx, const char *s, const char* file, int line); 127 void sen_free(sen_ctx *ctx, void *ptr, const char* file, int line); 128 129 void sen_assert(int cond, const char* file, int line, const char* func); 130 131 void sen_index_expire(void); 132 133 /**** sen_obj ****/ 134 135 typedef struct { 136 int32_t tv_sec; 137 int32_t tv_usec; 138 } sen_timeval; 139 140 typedef struct _sen_obj sen_obj; 141 typedef struct _sen_ql_co sen_ql_co; 142 typedef sen_obj *sen_ql_native_func(sen_ctx *, sen_obj *, sen_ql_co *); 143 144 struct _sen_obj { 145 uint8_t type; 146 uint8_t nrefs; 147 uint16_t flags; 148 sen_id class; 149 union { 150 struct { 151 sen_id self; 152 sen_ql_native_func *func; 153 } o; 154 struct { 155 void *value; 156 sen_ql_native_func *func; 157 } p; 158 struct { 159 char *value; 160 uint32_t size; 161 } b; 162 struct { 163 sen_obj *car; 164 sen_obj *cdr; 165 } l; 166 struct { 167 int64_t i; 168 } i; 169 struct { 170 double d; 171 } d; 172 struct { 173 int8_t op; 174 int8_t mode; 175 int16_t weight; 176 int32_t option; 177 } op; 178 sen_timeval tv; 179 } u; 180 }; 181 182 struct _sen_ql_co { 183 uint16_t mode; 184 uint16_t last; 185 sen_ql_native_func *func; 186 void *data; 187 }; 188 189 /**** sen_array ****/ 190 191 typedef struct _sen_array sen_array; 192 193 enum { 194 SEN_ARRAY_CLEAR = 1, 195 SEN_ARRAY_THREADSAFE = 2 196 }; 197 198 // #define SEN_ARRAY_W 2 199 #define SEN_ARRAY_W 0 200 #define SEN_ARRAY_R(i) (1<<((i)<<SEN_ARRAY_W)) 201 #define SEN_ARRAY_S (SEN_ARRAY_R(1)-1) 202 #define SEN_ARRAY_N (32>>SEN_ARRAY_W) 203 204 struct _sen_array { 205 sen_ctx *ctx; 206 sen_id max; 207 uint16_t element_size; 208 uint16_t flags; 209 sen_mutex lock; 210 void *elements[SEN_ARRAY_N]; 211 }; 212 213 #define SEN_ARRAY_EACH(a,head,tail,key,val,block) do {\ 214 int _ei;\ 215 const sen_id h = (head);\ 216 const sen_id t = (tail);\ 217 for (_ei = 0, (key) = (h); _ei < SEN_ARRAY_N && (key) <= (t); _ei++) {\ 218 int _ej = SEN_ARRAY_S * SEN_ARRAY_R(_ei);\ 219 if (((val) = (a)->elements[_ei])) {\ 220 for (; _ej-- && (key) <= (t); (key)++, (val) = (void *)((byte *)(val) + (a)->element_size)) block\ 221 } else {\ 222 (key) += _ej;\ 223 }\ 224 }\ 225 } while (0) 226 227 #define SEN_ARRAY_AT(a,id,e) do {\ 228 sen_id id_ = (id);\ 229 byte **e_;\ 230 size_t o_;\ 231 {\ 232 int l_, i_;\ 233 if (!id_) { e = NULL; break; }\ 234 SEN_BIT_SCAN_REV(id_, l_);\ 235 i_ = l_ >> SEN_ARRAY_W;\ 236 o_ = SEN_ARRAY_R(i_);\ 237 e_ = (byte **)&(a)->elements[i_];\ 238 }\ 239 if (!*e_) {\ 240 sen_ctx *ctx = (a)->ctx;\ 241 if ((a)->flags & SEN_ARRAY_THREADSAFE) { MUTEX_LOCK((a)->lock); }\ 242 if (!*e_) {\ 243 if ((a)->flags & SEN_ARRAY_CLEAR) {\ 244 *e_ = SEN_CALLOC(SEN_ARRAY_S * o_ * (a)->element_size);\ 245 } else {\ 246 *e_ = SEN_MALLOC(SEN_ARRAY_S * o_ * (a)->element_size);\ 247 }\ 248 }\ 249 if ((a)->flags & SEN_ARRAY_THREADSAFE) { MUTEX_UNLOCK((a)->lock); }\ 250 if (!*e_) { e = NULL; break; }\ 251 }\ 252 if (id_ > (a)->max) { (a)->max = id_; }\ 253 (e) = (void *)(*e_ + (id_ - o_) * (a)->element_size);\ 254 } while (0) 255 256 #define SEN_ARRAY_NEXT(a,e) SEN_ARRAY_AT((a), (a)->max + 1, e) 257 258 void sen_array_init(sen_array *a, sen_ctx *ctx, uint16_t element_size, uint16_t flags); 259 void sen_array_fin(sen_array *a); 260 void *sen_array_at(sen_array *a, sen_id id); 261 sen_id sen_array_id(sen_array *a, void *p); 262 263 /**** sen_ctx ****/ 264 265 #ifndef SEN_STORE_H 266 #include "store.h" 267 #endif /* SEN_STORE_H */ 268 269 #define SEN_CTX_MSGSIZE 128 270 271 // #define USE_SET_AS_OBJECTS 272 273 struct _sen_ctx { 274 sen_rc rc; 275 uint8_t errlvl; 276 const char *errfile; 277 int errline; 278 const char *errfunc; 279 char errbuf[SEN_CTX_MSGSIZE]; 280 281 uint32_t ncells; 282 uint32_t seqno; 283 uint32_t lseqno; 284 uint32_t nbinds; 285 uint32_t nunbinds; 286 uint8_t feed_mode; 287 uint8_t stat; 288 289 uint8_t batchmode; 290 uint8_t gc_verbose; 291 292 sen_encoding encoding; 293 294 int tok; 295 char *cur; 296 char *str_end; 297 298 sen_obj **pht; /* tail of placeholders */ 299 300 sen_obj arg; /* wait_data container (for coroutine) */ 301 sen_db *db; 302 uint32_t n_entries; 303 #ifdef USE_SET_AS_OBJECTS 304 sen_set *objects; /* object table */ 305 #else /* USE_SET_AS_OBJECTS */ 306 sen_array objects; /* object table */ 307 sen_obj *freelist; /* object free list */ 308 #endif /* USE_SET_AS_OBJECTS */ 309 sen_set *symbols; /* symbol table */ 310 sen_obj *phs; /* list of placeholders */ 311 sen_ql_co co; /* coroutine info */ 312 313 sen_obj *args; /* register for arguments of function */ 314 sen_obj *envir; /* stack register for current environment */ 315 sen_obj *code; /* register for current code */ 316 sen_obj *dump; /* stack register for next evaluation */ 317 sen_obj *value; /* evaluated value */ 318 sen_obj *global_env; /* global variables */ 319 320 uint8_t op; 321 322 char *inbuf; 323 sen_rbuf outbuf; 324 sen_rbuf subbuf; 325 unsigned int bufcur; 326 327 void (*output)(sen_ctx *, int, void *); 328 329 sen_com_sqtp *com; 330 unsigned int com_status; 331 unsigned int com_info; 332 333 void *currec; /* current recinfo (for slotexp) */ 334 sen_obj curobj; /* current record container (for slotexp) */ 335 336 union { 337 void *ptr; 338 int fd; 339 uint32_t u32; 340 uint64_t u64; 341 } data; 342 }; 343 344 extern sen_ctx sen_gctx; 345 346 sen_obj *sen_get(const char *key); 347 sen_obj *sen_at(const char *key); 348 sen_rc sen_del(const char *key); 349 350 #ifndef SEN_TIMEVAL_STR_SIZE 351 #define SEN_TIMEVAL_STR_SIZE 0x100 352 #endif /* SEN_TIMEVAL_STR_SIZE */ 353 #ifndef SEN_TIMEVAL_STR_FORMAT 354 #define SEN_TIMEVAL_STR_FORMAT "%04d-%02d-%02d %02d:%02d:%02d.%06d" 355 #endif /* SEN_TIMEVAL_STR_FORMAT */ 356 357 sen_rc sen_timeval_now(sen_timeval *tv); 358 sen_rc sen_timeval2str(sen_timeval *tv, char *buf); 359 sen_rc sen_str2timeval(const char *str, uint32_t str_len, sen_timeval *tv); 360 361 void sen_ctx_log(sen_ctx *ctx, char *fmt, ...); 362 363 /**** receive handler ****/ 364 365 void sen_ctx_recv_handler_set(sen_ctx *c, void (*func)(sen_ctx *, int, void *), 366 void *func_arg); 367 368 void sen_ctx_concat_func(sen_ctx *ctx, int flags, void *dummy); 369 void sen_ctx_stream_out_func(sen_ctx *c, int flags, void *stream); 370 371 #ifdef __cplusplus 372 } 373 #endif 374 375 #endif /* SEN_CTX_H */ 376