From 5805ef4e92d4a531905fb6a0af22f47b5367f74d Mon Sep 17 00:00:00 2001 From: Liviu Chircu Date: Thu, 20 Mar 2014 22:22:27 +0200 Subject: [PATCH 01/44] f_malloc: undo fragment count change from commit 56b325be0a (cherry picked from commit 73999d46b5e5e7b26630588e7810ec643754f6bf) --- mem/f_malloc.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/mem/f_malloc.c b/mem/f_malloc.c index c9c8be1b55c..3e02e1f38f3 100644 --- a/mem/f_malloc.c +++ b/mem/f_malloc.c @@ -155,10 +155,7 @@ static inline void fm_insert_free(struct fm_block* qm, struct fm_frag* frag) (*f)->prev = &(frag->u.nxt_free); *f=frag; - - #if defined(DBG_F_MALLOC) || defined(STATISTICS) qm->free_hash[hash].no++; - #endif free_plus(qm, frag->size); } From ec75efb6be8f9e481d9f13388869ec469a28b435 Mon Sep 17 00:00:00 2001 From: Bogdan-Andrei Iancu Date: Fri, 21 Mar 2014 13:13:05 +0200 Subject: [PATCH 02/44] Fixed DH and EC compiling on openssl < 1.0.1 - credits go to Nick Altmann for reporting and testing the fix (cherry picked from commit aefe6c18319eaf6348695c5865aa2b2a5d451378) --- tls/tls_init.c | 54 ++++++++++++++++++++++++++++++-------------------- 1 file changed, 33 insertions(+), 21 deletions(-) diff --git a/tls/tls_init.c b/tls/tls_init.c index 8e8e6c32b93..21319aa42cf 100644 --- a/tls/tls_init.c +++ b/tls/tls_init.c @@ -43,8 +43,8 @@ #include #include -#define SER_SSL_SESS_ID ((unsigned char*)"opensips-tls-1.2.0") -#define SER_SSL_SESS_ID_LEN (sizeof(SER_SSL_SESS_ID)-1) +#define OS_SSL_SESS_ID ((unsigned char*)"opensips-tls-1.11.0") +#define OS_SSL_SESS_ID_LEN (sizeof(OS_SSL_SESS_ID)-1) #if OPENSSL_VERSION_NUMBER < 0x10001000L #warning "" @@ -55,7 +55,7 @@ #warning "" #endif -SSL_METHOD *ssl_methods[TLS_USE_SSLv23 + 1]; +SSL_METHOD *ssl_methods[TLS_USE_TLSv1_2 + 1]; #define VERIFY_DEPTH_S 3 @@ -336,6 +336,8 @@ load_ca_dir(SSL_CTX * ctx, char *directory) return 0; } + +#if (OPENSSL_VERSION_NUMBER > 0x10001000L) /* * Load and set DH params to be used in ephemeral key exchange from a file. */ @@ -366,6 +368,7 @@ set_dh_params(SSL_CTX * ctx, char *filename) return 0; } + /* * Set elliptic curve. */ @@ -393,6 +396,8 @@ static int set_ec_params(SSL_CTX * ctx, const char* curve_name) } return 0; } +#endif + /* * initialize ssl methods @@ -403,27 +408,27 @@ init_ssl_methods(void) LM_DBG("entered\n"); #ifndef OPENSSL_NO_SSL2 - ssl_methods[TLS_USE_SSLv2_cli - 1] = SSLv2_client_method(); - ssl_methods[TLS_USE_SSLv2_srv - 1] = SSLv2_server_method(); - ssl_methods[TLS_USE_SSLv2 - 1] = SSLv2_method(); + ssl_methods[TLS_USE_SSLv2_cli - 1] = (SSL_METHOD*)SSLv2_client_method(); + ssl_methods[TLS_USE_SSLv2_srv - 1] = (SSL_METHOD*)SSLv2_server_method(); + ssl_methods[TLS_USE_SSLv2 - 1] = (SSL_METHOD*)SSLv2_method(); #endif - ssl_methods[TLS_USE_SSLv3_cli - 1] = SSLv3_client_method(); - ssl_methods[TLS_USE_SSLv3_srv - 1] = SSLv3_server_method(); - ssl_methods[TLS_USE_SSLv3 - 1] = SSLv3_method(); + ssl_methods[TLS_USE_SSLv3_cli - 1] = (SSL_METHOD*)SSLv3_client_method(); + ssl_methods[TLS_USE_SSLv3_srv - 1] = (SSL_METHOD*)SSLv3_server_method(); + ssl_methods[TLS_USE_SSLv3 - 1] = (SSL_METHOD*)SSLv3_method(); - ssl_methods[TLS_USE_TLSv1_cli - 1] = TLSv1_client_method(); - ssl_methods[TLS_USE_TLSv1_srv - 1] = TLSv1_server_method(); - ssl_methods[TLS_USE_TLSv1 - 1] = TLSv1_method(); + ssl_methods[TLS_USE_TLSv1_cli - 1] = (SSL_METHOD*)TLSv1_client_method(); + ssl_methods[TLS_USE_TLSv1_srv - 1] = (SSL_METHOD*)TLSv1_server_method(); + ssl_methods[TLS_USE_TLSv1 - 1] = (SSL_METHOD*)TLSv1_method(); - ssl_methods[TLS_USE_SSLv23_cli - 1] = SSLv23_client_method(); - ssl_methods[TLS_USE_SSLv23_srv - 1] = SSLv23_server_method(); - ssl_methods[TLS_USE_SSLv23 - 1] = SSLv23_method(); + ssl_methods[TLS_USE_SSLv23_cli - 1] = (SSL_METHOD*)SSLv23_client_method(); + ssl_methods[TLS_USE_SSLv23_srv - 1] = (SSL_METHOD*)SSLv23_server_method(); + ssl_methods[TLS_USE_SSLv23 - 1] = (SSL_METHOD*)SSLv23_method(); #if OPENSSL_VERSION_NUMBER >= 0x10001000L - ssl_methods[TLS_USE_TLSv1_2_cli - 1] = TLSv1_2_client_method(); - ssl_methods[TLS_USE_TLSv1_2_srv - 1] = TLSv1_2_server_method(); - ssl_methods[TLS_USE_TLSv1_2 - 1] = TLSv1_2_method(); + ssl_methods[TLS_USE_TLSv1_2_cli - 1] = (SSL_METHOD*)TLSv1_2_client_method(); + ssl_methods[TLS_USE_TLSv1_2_srv - 1] = (SSL_METHOD*)TLSv1_2_server_method(); + ssl_methods[TLS_USE_TLSv1_2 - 1] = (SSL_METHOD*)TLSv1_2_method(); #endif } @@ -437,11 +442,12 @@ static int init_ssl_ctx_behavior( struct tls_domain *d ) { int verify_mode; +#if (OPENSSL_VERSION_NUMBER > 0x10001000L) /* * set dh params */ if (!d->tmp_dh_file) { - LM_NOTICE("no DH params file for tls[%s:%d] defined, " + LM_DBG("no DH params file for tls[%s:%d] defined, " "using default '%s'\n", ip_addr2a(&d->addr), d->port, tls_tmp_dh_file); d->tmp_dh_file = tls_tmp_dh_file; @@ -457,6 +463,12 @@ init_ssl_ctx_behavior( struct tls_domain *d ) { else { LM_NOTICE("No EC curve defined\n"); } +#else + if (d->tmp_dh_file || tls_tmp_dh_file) + LM_WARN("DH params file discarded as not supported by your openSSL version\n"); + if (d->tls_ec_curve) + LM_WARN("EC params file discarded as not supported by your openSSL version\n"); +#endif if( d->ciphers_list != 0 ) { if( SSL_CTX_set_cipher_list(d->ctx, d->ciphers_list) == 0 ) { @@ -564,8 +576,8 @@ init_ssl_ctx_behavior( struct tls_domain *d ) { SSL_CTX_set_verify_depth( d->ctx, VERIFY_DEPTH_S); SSL_CTX_set_session_cache_mode( d->ctx, SSL_SESS_CACHE_SERVER ); - SSL_CTX_set_session_id_context( d->ctx, SER_SSL_SESS_ID, - SER_SSL_SESS_ID_LEN ); + SSL_CTX_set_session_id_context( d->ctx, OS_SSL_SESS_ID, + OS_SSL_SESS_ID_LEN ); return 0; } From f7ab6ceccd28adbe2d0b738cde664f26bc4e3363 Mon Sep 17 00:00:00 2001 From: Liviu Chircu Date: Fri, 21 Mar 2014 14:05:45 +0200 Subject: [PATCH 03/44] hp malloc: rename functions, update headers, add some comments (cherry picked from commit d504e9fe6d531b2102133ac56337f17f60accbe8) --- mem/hp_malloc.c | 270 +++++++++++++++++++++++------------------------- mem/hp_malloc.h | 124 +++++++++++----------- mem/mem.c | 4 +- mem/mem.h | 32 +++--- mem/shm_mem.c | 10 +- mem/shm_mem.h | 34 +++--- 6 files changed, 230 insertions(+), 244 deletions(-) diff --git a/mem/hp_malloc.c b/mem/hp_malloc.c index 2ca1b06382e..583603668d6 100644 --- a/mem/hp_malloc.c +++ b/mem/hp_malloc.c @@ -1,5 +1,5 @@ /** - * truly parallel memory allocator for high-performance environments + * the truly parallel memory allocator * * Copyright (C) 2014 OpenSIPS Solutions * @@ -24,13 +24,6 @@ * 2014-01-19 initial version (liviu) */ -/** - * Note on coding style: - * - * although there is some duplicate code, it is the best way to go! - * (minimum number of parameters, no additional jmp instructions) --liviu - */ - #if !defined(q_malloc) && !(defined VQ_MALLOC) && !(defined F_MALLOC) && \ (defined HP_MALLOC) @@ -46,14 +39,13 @@ extern unsigned long *mem_hash_usage; -/*useful macros*/ #define max(a,b) ( (a)>(b)?(a):(b)) #define FRAG_NEXT(f) \ - ((struct fm_frag*)((char*)(f)+sizeof(struct fm_frag)+(f)->size )) + ((struct hp_frag*)((char*)(f)+sizeof(struct hp_frag)+(f)->size )) -#define FRAG_OVERHEAD (sizeof(struct fm_frag)) +#define FRAG_OVERHEAD (sizeof(struct hp_frag)) /* ROUNDTO= 2^k so the following works */ @@ -61,19 +53,14 @@ extern unsigned long *mem_hash_usage; #define ROUNDUP(s) (((s)+(ROUNDTO-1))&ROUNDTO_MASK) #define ROUNDDOWN(s) ((s)&ROUNDTO_MASK) -/* - #define ROUNDUP(s) (((s)%ROUNDTO)?((s)+ROUNDTO)/ROUNDTO*ROUNDTO:(s)) - #define ROUNDDOWN(s) (((s)%ROUNDTO)?((s)-ROUNDTO)/ROUNDTO*ROUNDTO:(s)) -*/ - #define SHM_LOCK(i) lock_get(&mem_lock[i]) #define SHM_UNLOCK(i) lock_release(&mem_lock[i]) #define MEM_FRAG_AVOIDANCE -#define F_MALLOC_LARGE_LIMIT F_MALLOC_OPTIMIZE -#define F_MALLOC_DEFRAG_LIMIT (F_MALLOC_LARGE_LIMIT * 5) -#define F_MALLOC_DEFRAG_PERCENT 5 +#define HP_MALLOC_LARGE_LIMIT HP_MALLOC_OPTIMIZE +#define HP_MALLOC_DEFRAG_LIMIT (HP_MALLOC_LARGE_LIMIT * 5) +#define HP_MALLOC_DEFRAG_PERCENT 5 /* computes hash number for big buckets*/ inline static unsigned long big_hash_idx(unsigned long s) @@ -95,15 +82,15 @@ inline static unsigned long big_hash_idx(unsigned long s) #define END_CHECK_PATTERN2 0xabcdefed #endif -static inline void fm_insert_free(struct fm_block* qm, struct fm_frag* frag) +static inline void hp_insert_free(struct hp_block* qm, struct hp_frag* frag) { - struct fm_frag** f; + struct hp_frag** f; unsigned int hash; hash=GET_HASH_RR(qm, frag->size); f=&(qm->free_hash[hash].first); - if (frag->size > F_MALLOC_OPTIMIZE){ /* because of '<=' in GET_HASH, + if (frag->size > HP_MALLOC_OPTIMIZE){ /* because of '<=' in GET_HASH, purpose --andrei ) */ for(; *f; f=&((*f)->u.nxt_free)){ if (frag->size <= (*f)->size) break; @@ -123,9 +110,9 @@ static inline void fm_insert_free(struct fm_block* qm, struct fm_frag* frag) #endif } -static inline void fm_remove_free(struct fm_block* qm, struct fm_frag* n) +static inline void hp_remove_free(struct hp_block* qm, struct hp_frag* n) { - struct fm_frag** pf; + struct hp_frag** pf; int hash; pf = n->prev; @@ -146,16 +133,16 @@ static inline void fm_remove_free(struct fm_block* qm, struct fm_frag* n) -void fm_split_frag_unsafe(struct fm_block* qm, struct fm_frag* frag, +void hp_split_frag_unsafe(struct hp_block* qm, struct hp_frag* frag, unsigned long size) { unsigned long rest; - struct fm_frag* n; + struct hp_frag* n; rest = frag->size - size; #ifdef MEM_FRAG_AVOIDANCE - if ((rest> (FRAG_OVERHEAD+F_MALLOC_OPTIMIZE))|| + if ((rest> (FRAG_OVERHEAD+HP_MALLOC_OPTIMIZE))|| (rest>=(FRAG_OVERHEAD+size))){ /* the residue fragm. is big enough*/ #else if (rest>(FRAG_OVERHEAD+MIN_FRAG_SIZE)){ @@ -179,12 +166,12 @@ void fm_split_frag_unsafe(struct fm_block* qm, struct fm_frag* frag, #ifdef DBG_F_MALLOC /* frag created by malloc, mark it*/ n->file=file; - n->func="frag. from fm_malloc"; + n->func="frag. from hp_malloc"; n->line=line; n->check=ST_CHECK_PATTERN; #endif - fm_insert_free(qm, n); + hp_insert_free(qm, n); } /* we cannot split this fragment any more => alloc all of it */ @@ -193,21 +180,21 @@ void fm_split_frag_unsafe(struct fm_block* qm, struct fm_frag* frag, /* size should be already rounded-up */ static inline #ifdef DBG_F_MALLOC -void fm_split_frag(struct fm_block* qm, struct fm_frag* frag, +void hp_split_frag(struct hp_block* qm, struct hp_frag* frag, unsigned long size, const char* file, const char* func, unsigned int line) #else -void fm_split_frag(struct fm_block* qm, struct fm_frag* frag, +void hp_split_frag(struct hp_block* qm, struct hp_frag* frag, unsigned long size, unsigned int old_hash) #endif { unsigned long rest, hash; - struct fm_frag* n; + struct hp_frag* n; rest = frag->size - size; #ifdef MEM_FRAG_AVOIDANCE - if ((rest> (FRAG_OVERHEAD+F_MALLOC_OPTIMIZE))|| + if ((rest> (FRAG_OVERHEAD+HP_MALLOC_OPTIMIZE))|| (rest>=(FRAG_OVERHEAD+size))){ /* the residue fragm. is big enough*/ #else if (rest>(FRAG_OVERHEAD+MIN_FRAG_SIZE)){ @@ -231,18 +218,18 @@ void fm_split_frag(struct fm_block* qm, struct fm_frag* frag, #ifdef DBG_F_MALLOC /* frag created by malloc, mark it*/ n->file=file; - n->func="frag. from fm_malloc"; + n->func="frag. from hp_malloc"; n->line=line; n->check=ST_CHECK_PATTERN; #endif - /* insert the newly obtained fm_frag in its free list */ + /* insert the newly obtained hp_frag in its free list */ hash = PEEK_HASH_RR(qm, n->size); if (hash != old_hash) SHM_LOCK(hash); - fm_insert_free(qm, n); + hp_insert_free(qm, n); if (hash != old_hash) SHM_UNLOCK(hash); @@ -251,7 +238,10 @@ void fm_split_frag(struct fm_block* qm, struct fm_frag* frag, /* we cannot split this fragment any more => alloc all of it */ } -void fm_update_mem_pattern_file(void) +/** + * dumps the current memory allocation pattern of OpenSIPS into a pattern file + */ +void hp_update_mem_pattern_file(void) { int i; FILE *f; @@ -265,17 +255,17 @@ void fm_update_mem_pattern_file(void) return; } - if (fprintf(f, "%lu %lu\n", ROUNDTO, F_HASH_SIZE) < 0) + if (fprintf(f, "%lu %lu\n", ROUNDTO, HP_HASH_SIZE) < 0) goto write_error; /* first compute sum of all malloc requests since startup */ - for (i = 0; i < F_MALLOC_OPTIMIZE / ROUNDTO; i++) + for (i = 0; i < HP_MALLOC_OPTIMIZE / ROUNDTO; i++) sum += mem_hash_usage[i] * (i * ROUNDTO + FRAG_OVERHEAD); LM_DBG("mem warming hash sum: %llu\n", sum); /* save the usage rate of each bucket to the memory pattern file */ - for (i = 0; i < F_MALLOC_OPTIMIZE / ROUNDTO; i++) { + for (i = 0; i < HP_MALLOC_OPTIMIZE / ROUNDTO; i++) { LM_DBG("[%d] %lf %.8lf\n", i, (double)mem_hash_usage[i], (double)mem_hash_usage[i] / sum * (i * ROUNDTO + FRAG_OVERHEAD)); verification += (double)mem_hash_usage[i] / sum * (i * ROUNDTO + FRAG_OVERHEAD); @@ -298,9 +288,9 @@ void fm_update_mem_pattern_file(void) } /** - * TODO: comments + * on-demand memory fragmentation, based on an input pattern file */ -int fm_mem_warming(struct fm_block *qm) +int hp_mem_warming(struct hp_block *qm) { struct size_fraction { int hash_index; @@ -318,7 +308,7 @@ int fm_mem_warming(struct fm_block *qm) long long bucket_mem; int i, c = 0; unsigned int current_frag_size; - struct fm_frag *big_frag; + struct hp_frag *big_frag; unsigned int optimized_buckets; f = fopen(mem_warming_pattern_file, "r"); @@ -336,15 +326,15 @@ int fm_mem_warming(struct fm_block *qm) } rc = 0; - if (roundto != ROUNDTO || hash_size != F_HASH_SIZE) { - LM_ERR("incompatible pattern file data: [F_HASH_SIZE: %lu-%lu] " - "[ROUNDTO: %lu-%lu]\n", hash_size, F_HASH_SIZE, roundto, ROUNDTO); + if (roundto != ROUNDTO || hash_size != HP_HASH_SIZE) { + LM_ERR("incompatible pattern file data: [HP_HASH_SIZE: %lu-%lu] " + "[ROUNDTO: %lu-%lu]\n", hash_size, HP_HASH_SIZE, roundto, ROUNDTO); rc = -1; goto out; } /* read bucket usage percentages and sort them by number of fragments */ - for (i = 0; i < LINEAR_HASH_SIZE; i++) { + for (i = 0; i < HP_LINEAR_HASH_SIZE; i++) { sf = malloc(sizeof *sf); if (!sf) { @@ -387,10 +377,10 @@ int fm_mem_warming(struct fm_block *qm) } /* only optimize the configured number of buckets */ - optimized_buckets = (float)shm_hash_split_percentage / 100 * LINEAR_HASH_SIZE; + optimized_buckets = (float)shm_hash_split_percentage / 100 * HP_LINEAR_HASH_SIZE; LM_INFO("Optimizing %u / %lu mem buckets\n", optimized_buckets, - LINEAR_HASH_SIZE); + HP_LINEAR_HASH_SIZE); sf = sorted_sf; for (i = 0; i < optimized_buckets; i++) { @@ -412,17 +402,17 @@ int fm_mem_warming(struct fm_block *qm) /* create free fragments worth of 'bucket_mem' memory */ while (bucket_mem >= FRAG_OVERHEAD + current_frag_size) { - fm_remove_free(qm, big_frag); + hp_remove_free(qm, big_frag); /* trim-insert operation on the big free fragment */ - fm_split_frag(qm, big_frag, current_frag_size, -1); + hp_split_frag(qm, big_frag, current_frag_size, -1); /* * "big_frag" now points to a smaller, free and detached frag. * * With optimized buckets, inserts will be automagically * balanced within their dedicated hashes */ - fm_insert_free(qm, big_frag); + hp_insert_free(qm, big_frag); big_frag = FRAG_NEXT(big_frag); @@ -447,20 +437,20 @@ int fm_mem_warming(struct fm_block *qm) return rc; } -/* init malloc and return a fm_block*/ -struct fm_block* fm_malloc_init(char* address, unsigned long size) +/* init malloc and return a hp_block*/ +struct hp_block* hp_malloc_init(char* address, unsigned long size) { char* start; char* end; - struct fm_block* qm; + struct hp_block* qm; unsigned long init_overhead; /* make address and size multiple of 8*/ start=(char*)ROUNDUP((unsigned long) address); LM_DBG("F_OPTIMIZE=%lu, /ROUNDTO=%lu\n", - F_MALLOC_OPTIMIZE, F_MALLOC_OPTIMIZE/ROUNDTO); - LM_DBG("F_HASH_SIZE=%lu, fm_block size=%lu\n", - F_HASH_SIZE, (long)sizeof(struct fm_block)); + HP_MALLOC_OPTIMIZE, HP_MALLOC_OPTIMIZE/ROUNDTO); + LM_DBG("HP_HASH_SIZE=%lu, hp_block size=%lu\n", + HP_HASH_SIZE, (long)sizeof(struct hp_block)); LM_DBG("params (%p, %lu), start=%p\n", address, size, start); if (size<(unsigned long)(start-address)) return 0; @@ -468,17 +458,19 @@ struct fm_block* fm_malloc_init(char* address, unsigned long size) if (size <(MIN_FRAG_SIZE+FRAG_OVERHEAD)) return 0; size=ROUNDDOWN(size); - init_overhead=(ROUNDUP(sizeof(struct fm_block))+ 2 * FRAG_OVERHEAD); + init_overhead=(ROUNDUP(sizeof(struct hp_block))+ 2 * FRAG_OVERHEAD); if (size < init_overhead) { + LM_ERR("not enough memory for the basic structures! " + "need %lu bytes\n", init_overhead); /* not enough mem to create our control structures !!!*/ return 0; } end=start+size; - qm=(struct fm_block*)start; - memset(qm, 0, sizeof(struct fm_block)); + qm=(struct hp_block*)start; + memset(qm, 0, sizeof(struct hp_block)); qm->size=size; #if defined(DBG_F_MALLOC) || defined(STATISTICS) @@ -488,8 +480,8 @@ struct fm_block* fm_malloc_init(char* address, unsigned long size) qm->max_real_used=init_overhead; #endif - qm->first_frag=(struct fm_frag*)(start+ROUNDUP(sizeof(struct fm_block))); - qm->last_frag=(struct fm_frag*)(end-sizeof(struct fm_frag)); + qm->first_frag=(struct hp_frag*)(start+ROUNDUP(sizeof(struct hp_block))); + qm->last_frag=(struct hp_frag*)(end-sizeof(struct hp_frag)); /* init initial fragment*/ qm->first_frag->size=size-init_overhead; qm->last_frag->size=0; @@ -505,20 +497,20 @@ struct fm_block* fm_malloc_init(char* address, unsigned long size) /* link initial fragment into the free list*/ qm->large_space = 0; - qm->large_limit = qm->size / 100 * F_MALLOC_DEFRAG_PERCENT; + qm->large_limit = qm->size / 100 * HP_MALLOC_DEFRAG_PERCENT; - if( qm->large_limit < F_MALLOC_DEFRAG_LIMIT ) - qm->large_limit = F_MALLOC_DEFRAG_LIMIT; + if( qm->large_limit < HP_MALLOC_DEFRAG_LIMIT ) + qm->large_limit = HP_MALLOC_DEFRAG_LIMIT; - fm_insert_free(qm, qm->first_frag); + hp_insert_free(qm, qm->first_frag); return qm; } -void* fm_malloc_unsafe(struct fm_block* qm, unsigned long size) +void* hp_malloc_unsafe(struct hp_block* qm, unsigned long size) { - struct fm_frag* frag; + struct hp_frag* frag; unsigned int hash; #ifdef DBG_F_MALLOC @@ -531,7 +523,7 @@ void* fm_malloc_unsafe(struct fm_block* qm, unsigned long size) /*search for a suitable free frag*/ - for(hash=GET_HASH(size);hashfree_hash[hash].first; for( ; frag; frag = frag->u.nxt_free ) if ( frag->size >= size ) goto found; @@ -545,35 +537,35 @@ void* fm_malloc_unsafe(struct fm_block* qm, unsigned long size) found: /* we found it!*/ - fm_remove_free(qm,frag); + hp_remove_free(qm,frag); /*see if we'll use full frag, or we'll split it in 2*/ #ifdef DBG_F_MALLOC - fm_split_frag_unsafe(qm, frag, size, file, func, line); + hp_split_frag_unsafe(qm, frag, size, file, func, line); frag->file=file; frag->func=func; frag->line=line; frag->check=ST_CHECK_PATTERN; LM_DBG("params(%p, %lu), returns address %p \n", qm, size, - (char*)frag+sizeof(struct fm_frag)); + (char*)frag+sizeof(struct hp_frag)); #else - fm_split_frag_unsafe(qm, frag, size); + hp_split_frag_unsafe(qm, frag, size); #endif pkg_threshold_check(); - return (char*)frag+sizeof(struct fm_frag); + return (char*)frag+sizeof(struct hp_frag); } #ifdef DBG_F_MALLOC -void* fm_malloc(struct fm_block* qm, unsigned long size, +void* hp_malloc(struct hp_block* qm, unsigned long size, const char* file, const char* func, unsigned int line) #else -void* fm_malloc(struct fm_block* qm, unsigned long size) +void* hp_malloc(struct hp_block* qm, unsigned long size) #endif { - struct fm_frag* frag; + struct hp_frag* frag; unsigned int init_hash, hash, sec_hash; int i; @@ -587,7 +579,7 @@ void* fm_malloc(struct fm_block* qm, unsigned long size) /*search for a suitable free frag*/ - for (hash = GET_HASH(size), init_hash = hash; hash < F_HASH_SIZE; hash++) { + for (hash = GET_HASH(size), init_hash = hash; hash < HP_HASH_SIZE; hash++) { if (!qm->free_hash[hash].is_optimized) { SHM_LOCK(hash); frag = qm->free_hash[hash].first; @@ -599,7 +591,7 @@ void* fm_malloc(struct fm_block* qm, unsigned long size) SHM_UNLOCK(hash); } else { /* optimized size. search through its own hash! */ - for (i = 0, sec_hash = F_HASH_SIZE + + for (i = 0, sec_hash = HP_HASH_SIZE + hash * shm_secondary_hash_size + optimized_get_indexes[hash]; i < shm_secondary_hash_size; @@ -631,11 +623,11 @@ void* fm_malloc(struct fm_block* qm, unsigned long size) found: /* we found it!*/ - fm_remove_free(qm,frag); + hp_remove_free(qm,frag); /*see if we'll use full frag, or we'll split it in 2*/ - fm_split_frag(qm, frag, size, hash); + hp_split_frag(qm, frag, size, hash); SHM_UNLOCK(hash); @@ -643,13 +635,13 @@ void* fm_malloc(struct fm_block* qm, unsigned long size) mem_hash_usage[init_hash]++; pkg_threshold_check(); - return (char*)frag+sizeof(struct fm_frag); + return (char*)frag+sizeof(struct hp_frag); } -void fm_free_unsafe(struct fm_block* qm, void* p) +void hp_free_unsafe(struct hp_block* qm, void* p) { - struct fm_frag* f,*n; + struct hp_frag* f,*n; #ifdef DBG_F_MALLOC LM_DBG("params(%p, %p), called from %s: %s(%d)\n", qm, p, file, func, line); @@ -662,7 +654,7 @@ void fm_free_unsafe(struct fm_block* qm, void* p) LM_WARN("free(0) called\n"); return; } - f=(struct fm_frag*) ((char*)p-sizeof(struct fm_frag)); + f=(struct hp_frag*) ((char*)p-sizeof(struct hp_frag)); #ifdef DBG_F_MALLOC LM_DBG("freeing block alloc'ed from %s: %s(%ld)\n", f->file, f->func, @@ -682,7 +674,7 @@ void fm_free_unsafe(struct fm_block* qm, void* p) if (((char*)n < (char*)qm->last_frag) && n->prev ) { - fm_remove_free(qm, n); + hp_remove_free(qm, n); /* join */ f->size += n->size + FRAG_OVERHEAD; @@ -695,19 +687,19 @@ void fm_free_unsafe(struct fm_block* qm, void* p) no_join: - fm_insert_free(qm, f); + hp_insert_free(qm, f); pkg_threshold_check(); } #ifdef DBG_F_MALLOC -void fm_free(struct fm_block* qm, void* p, const char* file, const char* func, +void hp_free(struct hp_block* qm, void* p, const char* file, const char* func, unsigned int line) #else -void fm_free(struct fm_block* qm, void* p) +void hp_free(struct hp_block* qm, void* p) #endif { - struct fm_frag* f,*n; + struct hp_frag* f,*n; unsigned int hash; #ifdef DBG_F_MALLOC @@ -721,7 +713,7 @@ void fm_free(struct fm_block* qm, void* p) LM_WARN("free(0) called\n"); return; } - f=(struct fm_frag*) ((char*)p-sizeof(struct fm_frag)); + f=(struct hp_frag*) ((char*)p-sizeof(struct hp_frag)); hash = PEEK_HASH_RR(qm, f->size); #ifdef DBG_F_MALLOC @@ -743,7 +735,7 @@ void fm_free(struct fm_block* qm, void* p) if (((char*)n < (char*)qm->last_frag) && n->prev ) { - fm_remove_free(qm, n); + hp_remove_free(qm, n); /* join */ f->size += n->size + FRAG_OVERHEAD; @@ -756,7 +748,7 @@ void fm_free(struct fm_block* qm, void* p) no_join: - fm_insert_free(qm, f); + hp_insert_free(qm, f); SHM_UNLOCK(hash); @@ -764,12 +756,12 @@ void fm_free(struct fm_block* qm, void* p) } -void* fm_realloc_unsafe(struct fm_block* qm, void* p, unsigned long size) +void* hp_realloc_unsafe(struct hp_block* qm, void* p, unsigned long size) { - struct fm_frag *f; + struct hp_frag *f; unsigned long diff; unsigned long orig_size; - struct fm_frag *n; + struct hp_frag *n; void *ptr; #ifdef DBG_F_MALLOC @@ -783,20 +775,20 @@ void* fm_realloc_unsafe(struct fm_block* qm, void* p, unsigned long size) if (size==0) { if (p) #ifdef DBG_F_MALLOC - fm_free(qm, p, file, func, line); + hp_free(qm, p, file, func, line); #else - fm_free(qm, p); + hp_free(qm, p); #endif pkg_threshold_check(); return 0; } if (p==0) #ifdef DBG_F_MALLOC - return fm_malloc(qm, size, file, func, line); + return hp_malloc(qm, size, file, func, line); #else - return fm_malloc(qm, size); + return hp_malloc(qm, size); #endif - f=(struct fm_frag*) ((char*)p-sizeof(struct fm_frag)); + f=(struct hp_frag*) ((char*)p-sizeof(struct hp_frag)); #ifdef DBG_F_MALLOC LM_DBG("realloc'ing frag %p alloc'ed from %s: %s(%ld)\n", f, f->file, f->func, f->line); @@ -807,9 +799,9 @@ void* fm_realloc_unsafe(struct fm_block* qm, void* p, unsigned long size) /* shrink */ #ifdef DBG_F_MALLOC LM_DBG("shrinking from %lu to %lu\n", f->size, size); - fm_split_frag_unsafe(qm, f, size, file, "frag. from fm_realloc", line); + hp_split_frag_unsafe(qm, f, size, file, "frag. from hp_realloc", line); #else - fm_split_frag_unsafe(qm, f, size); + hp_split_frag_unsafe(qm, f, size); #endif }else if (f->sizelast_frag) && n->prev && ((n->size+FRAG_OVERHEAD)>=diff)){ - fm_remove_free(qm,n); + hp_remove_free(qm,n); /* join */ f->size += n->size + FRAG_OVERHEAD; @@ -836,26 +828,26 @@ void* fm_realloc_unsafe(struct fm_block* qm, void* p, unsigned long size) /* split it if necessary */ if (f->size > size){ #ifdef DBG_F_MALLOC - fm_split_frag_unsafe(qm, f, size, file, "fragm. from fm_realloc", + hp_split_frag_unsafe(qm, f, size, file, "fragm. from hp_realloc", line); #else - fm_split_frag_unsafe(qm, f, size); + hp_split_frag_unsafe(qm, f, size); #endif } }else{ /* could not join => realloc */ #ifdef DBG_F_MALLOC - ptr=fm_malloc(qm, size, file, func, line); + ptr=hp_malloc(qm, size, file, func, line); #else - ptr = fm_malloc(qm, size); + ptr = hp_malloc(qm, size); #endif if (ptr) { /* copy, need by libssl */ memcpy(ptr, p, orig_size); #ifdef DBG_F_MALLOC - fm_free(qm, p, file, func, line); + hp_free(qm, p, file, func, line); #else - fm_free(qm, p); + hp_free(qm, p); #endif } p = ptr; @@ -875,17 +867,17 @@ void* fm_realloc_unsafe(struct fm_block* qm, void* p, unsigned long size) } #ifdef DBG_F_MALLOC -void* fm_realloc(struct fm_block* qm, void* p, unsigned long size, +void* hp_realloc(struct hp_block* qm, void* p, unsigned long size, const char* file, const char* func, unsigned int line) #else -void* fm_realloc(struct fm_block* qm, void* p, unsigned long size) +void* hp_realloc(struct hp_block* qm, void* p, unsigned long size) #endif { - struct fm_frag *f; + struct hp_frag *f; unsigned long diff; unsigned long orig_size; unsigned int hash_next; - struct fm_frag *n; + struct hp_frag *n; void *ptr; #ifdef DBG_F_MALLOC @@ -899,20 +891,20 @@ void* fm_realloc(struct fm_block* qm, void* p, unsigned long size) if (size==0) { if (p) #ifdef DBG_F_MALLOC - fm_free(qm, p, file, func, line); + hp_free(qm, p, file, func, line); #else - fm_free(qm, p); + hp_free(qm, p); #endif pkg_threshold_check(); return 0; } if (p==0) #ifdef DBG_F_MALLOC - return fm_malloc(qm, size, file, func, line); + return hp_malloc(qm, size, file, func, line); #else - return fm_malloc(qm, size); + return hp_malloc(qm, size); #endif - f=(struct fm_frag*) ((char*)p-sizeof(struct fm_frag)); + f=(struct hp_frag*) ((char*)p-sizeof(struct hp_frag)); #ifdef DBG_F_MALLOC LM_DBG("realloc'ing frag %p alloc'ed from %s: %s(%ld)\n", f, f->file, f->func, f->line); @@ -926,9 +918,9 @@ void* fm_realloc(struct fm_block* qm, void* p, unsigned long size) /* shrink */ #ifdef DBG_F_MALLOC LM_DBG("shrinking from %lu to %lu\n", f->size, size); - fm_split_frag(qm, f, size, file, "frag. from fm_realloc", line); + hp_split_frag(qm, f, size, file, "frag. from hp_realloc", line); #else - fm_split_frag(qm, f, size, 0); + hp_split_frag(qm, f, size, 0); #endif }else if (f->sizelast_frag) && n->prev && ((n->size+FRAG_OVERHEAD)>=diff)){ - fm_remove_free(qm,n); + hp_remove_free(qm,n); if (0 != hash_next) SHM_UNLOCK(hash_next); @@ -964,10 +956,10 @@ void* fm_realloc(struct fm_block* qm, void* p, unsigned long size) /* split it if necessary */ if (f->size > size){ #ifdef DBG_F_MALLOC - fm_split_frag(qm, f, size, file, "fragm. from fm_realloc", + hp_split_frag(qm, f, size, file, "fragm. from hp_realloc", line); #else - fm_split_frag(qm, f, size, 0); + hp_split_frag(qm, f, size, 0); #endif } }else{ @@ -976,17 +968,17 @@ void* fm_realloc(struct fm_block* qm, void* p, unsigned long size) /* could not join => realloc */ #ifdef DBG_F_MALLOC - ptr=fm_malloc(qm, size, file, func, line); + ptr=hp_malloc(qm, size, file, func, line); #else - ptr=fm_malloc(qm, size); + ptr=hp_malloc(qm, size); #endif if (ptr) { /* copy, need by libssl */ memcpy(ptr, p, orig_size); #ifdef DBG_F_MALLOC - fm_free_unsafe(qm, p, file, func, line); + hp_free_unsafe(qm, p, file, func, line); #else - fm_free_unsafe(qm, p); + hp_free_unsafe(qm, p); #endif } p = ptr; @@ -1010,15 +1002,15 @@ void* fm_realloc(struct fm_block* qm, void* p, unsigned long size) -void fm_status(struct fm_block* qm) +void hp_status(struct hp_block* qm) { - struct fm_frag* f; + struct hp_frag* f; unsigned int i,j; unsigned int h; int unused; unsigned long size; - LM_GEN1(memdump, "fm_status (%p):\n", qm); + LM_GEN1(memdump, "hp_status (%p):\n", qm); if (!qm) return; LM_GEN1(memdump, " heap size= %ld\n", qm->size); @@ -1029,14 +1021,14 @@ void fm_status(struct fm_block* qm) #endif LM_GEN1(memdump, "dumping free list:\n"); - for(h=0,i=0,size=0;hfree_hash[h].first,j=0; f; size+=f->size,f=f->u.nxt_free,i++,j++){ } if (j) LM_GEN1(memdump,"hash = %3d fragments no.: %5d, unused: %5d\n\t\t" " bucket size: %9lu - %9lu (first %9lu)\n", h, j, unused, UN_HASH(h), - ((h<=F_MALLOC_OPTIMIZE/ROUNDTO)?1:2)* UN_HASH(h), + ((h<=HP_MALLOC_OPTIMIZE/ROUNDTO)?1:2)* UN_HASH(h), qm->free_hash[h].first->size ); if (j!=qm->free_hash[h].no){ @@ -1055,12 +1047,12 @@ void fm_status(struct fm_block* qm) /* fills a malloc info structure with info about the block * if a parameter is not supported, it will be filled with 0 */ -void fm_info(struct fm_block* qm, struct mem_info* info) +void hp_info(struct hp_block* qm, struct mem_info* info) { unsigned int r; long total_frags; #if !defined(DBG_F_MALLOC) && !defined(STATISTICS) - struct fm_frag* f; + struct hp_frag* f; #endif memset(info,0, sizeof(*info)); @@ -1071,16 +1063,16 @@ void fm_info(struct fm_block* qm, struct mem_info* info) info->free=qm->size-qm->real_used; info->used=qm->used; info->real_used=qm->real_used; - for(r=0;rfree_hash[r].no; } #else /* we'll have to compute it all */ - for (r=0; r<=F_MALLOC_OPTIMIZE/ROUNDTO; r++){ + for (r=0; r<=HP_MALLOC_OPTIMIZE/ROUNDTO; r++){ info->free+=qm->free_hash[r].no*UN_HASH(r); total_frags+=qm->free_hash[r].no; } - for(;rfree_hash[r].no; for(f=qm->free_hash[r].first;f;f=f->u.nxt_free){ info->free+=f->size; diff --git a/mem/hp_malloc.h b/mem/hp_malloc.h index fdd6a828ef2..2de7f15e910 100644 --- a/mem/hp_malloc.h +++ b/mem/hp_malloc.h @@ -1,8 +1,7 @@ -/* $Id$ +/** + * the truly parallel memory allocator * - * simple, very fast, malloc library - * - * Copyright (C) 2001-2003 FhG Fokus + * Copyright (C) 2014 OpenSIPS Solutions * * This file is part of opensips, a free SIP server. * @@ -22,14 +21,9 @@ * * History: * -------- - * 2003-05-21 on sparc64 roundto 8 even in debugging mode (so malloc'ed - * long longs will be 64 bit aligned) (andrei) - * 2004-07-19 support for 64 bit (2^64 mem. block) and more info - * for the future de-fragmentation support (andrei) - * 2004-11-10 support for > 4Gb mem., switched to long (andrei) + * 2014-01-19 initial version (liviu) */ - #if !defined(f_malloc_h) && !defined(VQ_MALLOC) && !defined(hp_malloc_h) #define hp_malloc_h @@ -48,7 +42,7 @@ #define ROUNDTO sizeof(long long) #else #define ROUNDTO sizeof(void*) /* size we round to, must be = 2^n, and - sizeof(fm_frag) must be multiple of ROUNDTO !*/ + sizeof(hp_frag) must be multiple of ROUNDTO !*/ #endif #else /* DBG_F_MALLOC */ #define ROUNDTO 8UL @@ -57,21 +51,21 @@ -#define F_MALLOC_OPTIMIZE_FACTOR 14UL /*used below */ -#define F_MALLOC_OPTIMIZE (1UL<free_hash[___hash].is_optimized ? \ ___hash : \ - F_HASH_SIZE + ___hash * shm_secondary_hash_size + \ + HP_HASH_SIZE + ___hash * shm_secondary_hash_size + \ optimized_put_indexes[___hash]; \ }) : \ - LINEAR_HASH_SIZE + big_hash_idx((s)) - F_MALLOC_OPTIMIZE_FACTOR + 1) + HP_LINEAR_HASH_SIZE + big_hash_idx((s)) - HP_MALLOC_OPTIMIZE_FACTOR + 1) -#define UN_HASH(h) (((unsigned long)(h) <= (F_MALLOC_OPTIMIZE/ROUNDTO)) ?\ +#define UN_HASH(h) (((unsigned long)(h) <= (HP_MALLOC_OPTIMIZE/ROUNDTO)) ?\ (unsigned long)(h)*ROUNDTO: \ - 1UL<<((unsigned long)(h)-F_MALLOC_OPTIMIZE/ROUNDTO+\ - F_MALLOC_OPTIMIZE_FACTOR-1)\ + 1UL<<((unsigned long)(h)-HP_MALLOC_OPTIMIZE/ROUNDTO+\ + HP_MALLOC_OPTIMIZE_FACTOR-1)\ ) -struct fm_frag{ +struct hp_frag{ unsigned long size; union{ - struct fm_frag* nxt_free; + struct hp_frag* nxt_free; long reserved; }u; - struct fm_frag ** prev; + struct hp_frag ** prev; #ifdef DBG_F_MALLOC const char* file; const char* func; @@ -156,15 +150,15 @@ struct fm_frag{ #endif }; -struct fm_frag_lnk{ +struct hp_frag_lnk{ /* optimized buckets are further split into X buckets */ char is_optimized; - struct fm_frag* first; + struct hp_frag* first; unsigned long no; }; -struct fm_block{ +struct hp_block{ unsigned long size; /* total size */ unsigned long large_space; unsigned long large_limit; @@ -175,77 +169,77 @@ struct fm_block{ unsigned long max_real_used; #endif - struct fm_frag* first_frag; - struct fm_frag* last_frag; + struct hp_frag* first_frag; + struct hp_frag* last_frag; /* * the extra hash further divides the heavily used buckets * in order to achieve an even finer-grained locking */ - struct fm_frag_lnk free_hash[F_HASH_SIZE + F_EXTRA_HASH_SIZE]; + struct hp_frag_lnk free_hash[HP_HASH_SIZE + HP_EXTRA_HASH_SIZE]; }; -struct fm_block* fm_malloc_init(char* address, unsigned long size); -int fm_mem_warming(struct fm_block *fmb); -void fm_update_mem_pattern_file(void); +struct hp_block* hp_malloc_init(char* address, unsigned long size); +int hp_mem_warming(struct hp_block *fmb); +void hp_update_mem_pattern_file(void); #ifdef DBG_F_MALLOC -void* fm_malloc(struct fm_block*, unsigned long size, +void* hp_malloc(struct hp_block*, unsigned long size, const char* file, const char* func, unsigned int line); #else -void* fm_malloc(struct fm_block*, unsigned long size); +void* hp_malloc(struct hp_block*, unsigned long size); #endif -void* fm_malloc_unsafe(struct fm_block*, unsigned long size); -void* fm_malloc_raw(struct fm_block*, unsigned long size); +void* hp_malloc_unsafe(struct hp_block*, unsigned long size); +void* hp_malloc_raw(struct hp_block*, unsigned long size); #ifdef DBG_F_MALLOC -void fm_free(struct fm_block*, void* p, const char* file, const char* func, +void hp_free(struct hp_block*, void* p, const char* file, const char* func, unsigned int line); #else -void fm_free(struct fm_block*, void* p); +void hp_free(struct hp_block*, void* p); #endif -void fm_free_unsafe(struct fm_block *qm, void *p); -void fm_free_raw(struct fm_block *qm, void *p); +void hp_free_unsafe(struct hp_block *qm, void *p); +void hp_free_raw(struct hp_block *qm, void *p); #ifdef DBG_F_MALLOC -void* fm_realloc(struct fm_block*, void* p, unsigned long size, +void* hp_realloc(struct hp_block*, void* p, unsigned long size, const char* file, const char* func, unsigned int line); #else -void *fm_realloc(struct fm_block*, void* p, unsigned long size); +void *hp_realloc(struct hp_block*, void* p, unsigned long size); #endif -void *fm_realloc_unsafe(struct fm_block *qm, void *p, unsigned long size); -void *fm_realloc_raw(struct fm_block *qm, void *p, unsigned long size); +void *hp_realloc_unsafe(struct hp_block *qm, void *p, unsigned long size); +void *hp_realloc_raw(struct hp_block *qm, void *p, unsigned long size); -void fm_status(struct fm_block*); -void fm_info(struct fm_block*, struct mem_info*); +void hp_status(struct hp_block*); +void hp_info(struct hp_block*, struct mem_info*); #ifdef STATISTICS -static inline unsigned long fm_get_size(struct fm_block* qm) +static inline unsigned long hp_get_size(struct hp_block* qm) { return qm->size; } -static inline unsigned long fm_get_used(struct fm_block* qm) +static inline unsigned long hp_get_used(struct hp_block* qm) { return qm->used; } -static inline unsigned long fm_get_free(struct fm_block* qm) +static inline unsigned long hp_get_free(struct hp_block* qm) { return qm->size-qm->real_used; } -static inline unsigned long fm_get_real_used(struct fm_block* qm) +static inline unsigned long hp_get_real_used(struct hp_block* qm) { return qm->real_used; } -static inline unsigned long fm_get_max_real_used(struct fm_block* qm) +static inline unsigned long hp_get_max_real_used(struct hp_block* qm) { return qm->max_real_used; } -static inline unsigned long fm_get_frags(struct fm_block* qm) +static inline unsigned long hp_get_frags(struct hp_block* qm) { unsigned long frags; unsigned int r; - for(r=0,frags=0;rfree_hash[r].no; } return frags; diff --git a/mem/mem.c b/mem/mem.c index cf66d73bb07..272733451e1 100644 --- a/mem/mem.c +++ b/mem/mem.c @@ -53,7 +53,7 @@ #elif defined F_MALLOC struct fm_block* mem_block; #elif defined HP_MALLOC - struct fm_block* mem_block; + struct hp_block* mem_block; #else struct qm_block* mem_block; #endif @@ -75,7 +75,7 @@ int init_pkg_mallocs(void) #elif F_MALLOC mem_block=fm_malloc_init(mem_pool, pkg_mem_size); #elif HP_MALLOC - mem_block=fm_malloc_init(mem_pool, pkg_mem_size); + mem_block=hp_malloc_init(mem_pool, pkg_mem_size); #else mem_block=qm_malloc_init(mem_pool, pkg_mem_size); #endif diff --git a/mem/mem.h b/mem/mem.h index bafd6c3ae82..3b4c5111366 100644 --- a/mem/mem.h +++ b/mem/mem.h @@ -55,7 +55,7 @@ extern struct fm_block* mem_block; # elif defined HP_MALLOC # include "hp_malloc.h" - extern struct fm_block* mem_block; + extern struct hp_block* mem_block; # else # include "q_malloc.h" extern struct qm_block* mem_block; @@ -99,13 +99,13 @@ void set_pkg_stats(pkg_status_holder*); __FUNCTION__, __LINE__) # define pkg_info(i) fm_info(mem_block,i) # elif defined HP_MALLOC -# define pkg_malloc(s) fm_malloc_unsafe(mem_block, (s),__FILE__, \ +# define pkg_malloc(s) hp_malloc_unsafe(mem_block, (s),__FILE__, \ __FUNCTION__, __LINE__) -# define pkg_free(p) fm_free_unsafe(mem_block, (p), __FILE__, \ +# define pkg_free(p) hp_free_unsafe(mem_block, (p), __FILE__, \ __FUNCTION__, __LINE__) -# define pkg_realloc(p, s) fm_realloc_unsafe(mem_block, (p), (s),__FILE__, \ +# define pkg_realloc(p, s) hp_realloc_unsafe(mem_block, (p), (s),__FILE__, \ __FUNCTION__, __LINE__) -# define pkg_info(i) fm_info(mem_block,i) +# define pkg_info(i) hp_info(mem_block,i) # else # define pkg_malloc(s) qm_malloc(mem_block, (s),__FILE__, \ __FUNCTION__, __LINE__) @@ -125,10 +125,10 @@ void set_pkg_stats(pkg_status_holder*); # define pkg_free(p) fm_free(mem_block, (p)) # define pkg_info(i) fm_info(mem_block,i) # elif defined HP_MALLOC -# define pkg_malloc(s) fm_malloc_unsafe(mem_block, (s)) -# define pkg_realloc(p, s) fm_realloc_unsafe(mem_block, (p), (s)) -# define pkg_free(p) fm_free_unsafe(mem_block, (p)) -# define pkg_info(i) fm_info(mem_block,i) +# define pkg_malloc(s) hp_malloc_unsafe(mem_block, (s)) +# define pkg_realloc(p, s) hp_realloc_unsafe(mem_block, (p), (s)) +# define pkg_free(p) hp_free_unsafe(mem_block, (p)) +# define pkg_info(i) hp_info(mem_block,i) # else # define pkg_malloc(s) qm_malloc(mem_block, (s)) # define pkg_realloc(p, s) qm_realloc(mem_block, (p), (s)) @@ -147,13 +147,13 @@ void set_pkg_stats(pkg_status_holder*); # define MY_PKG_GET_FREE() fm_get_free(mem_block) # define MY_PKG_GET_FRAGS() fm_get_frags(mem_block) # elif defined HP_MALLOC -# define pkg_status() fm_status(mem_block) -# define MY_PKG_GET_SIZE() fm_get_size(mem_block) -# define MY_PKG_GET_USED() fm_get_used(mem_block) -# define MY_PKG_GET_RUSED() fm_get_real_used(mem_block) -# define MY_PKG_GET_MUSED() fm_get_max_real_used(mem_block) -# define MY_PKG_GET_FREE() fm_get_free(mem_block) -# define MY_PKG_GET_FRAGS() fm_get_frags(mem_block) +# define pkg_status() hp_status(mem_block) +# define MY_PKG_GET_SIZE() hp_get_size(mem_block) +# define MY_PKG_GET_USED() hp_get_used(mem_block) +# define MY_PKG_GET_RUSED() hp_get_real_used(mem_block) +# define MY_PKG_GET_MUSED() hp_get_max_real_used(mem_block) +# define MY_PKG_GET_FREE() hp_get_free(mem_block) +# define MY_PKG_GET_FRAGS() hp_get_frags(mem_block) # else # define pkg_status() qm_status(mem_block) # define MY_PKG_GET_SIZE() qm_get_size(mem_block) diff --git a/mem/shm_mem.c b/mem/shm_mem.c index a149f97d957..8b9b3a88118 100644 --- a/mem/shm_mem.c +++ b/mem/shm_mem.c @@ -73,7 +73,7 @@ static void* shm_mempool=(void*)-1; #elif F_MALLOC struct fm_block* shm_block; #elif HP_MALLOC - struct fm_block* shm_block; + struct hp_block* shm_block; #else struct qm_block* shm_block; #endif @@ -289,23 +289,23 @@ int shm_mem_init_mallocs(void* mempool, unsigned long pool_size) LM_INFO("skipped memory warming\n"); } - mem_hash_usage = shm_malloc_unsafe(F_HASH_SIZE * sizeof *mem_hash_usage); + mem_hash_usage = shm_malloc_unsafe(HP_HASH_SIZE * sizeof *mem_hash_usage); if (!mem_hash_usage) { LM_ERR("failed to allocate statistics array\n"); return -1; } - memset(mem_hash_usage, 0, F_HASH_SIZE * sizeof *mem_hash_usage); + memset(mem_hash_usage, 0, HP_HASH_SIZE * sizeof *mem_hash_usage); /* lock_alloc cannot be used yet! */ - mem_lock = shm_malloc_unsafe(F_HASH_SIZE * sizeof *mem_lock); + mem_lock = shm_malloc_unsafe(HP_HASH_SIZE * sizeof *mem_lock); if (!mem_lock) { LM_CRIT("could not allocate shm lock array\n"); shm_mem_destroy(); return -1; } - for (i = 0; i < F_HASH_SIZE; i++) + for (i = 0; i < HP_HASH_SIZE; i++) if (!lock_init(&mem_lock[i])) { LM_CRIT("could not initialize lock\n"); shm_mem_destroy(); diff --git a/mem/shm_mem.h b/mem/shm_mem.h index 94c7e9b1fc7..9f731b972a4 100644 --- a/mem/shm_mem.h +++ b/mem/shm_mem.h @@ -96,25 +96,25 @@ # define shm_malloc_init fm_malloc_init #elif defined HP_MALLOC # include "hp_malloc.h" - extern struct fm_block* shm_block; -# define MY_MALLOC_UNSAFE fm_malloc_unsafe -# define MY_MALLOC fm_malloc -# define MY_FREE_UNSAFE fm_free_unsafe -# define MY_FREE fm_free -# define MY_REALLOC fm_realloc -# define MY_STATUS fm_status -# define MY_MEMINFO fm_info + extern struct hp_block* shm_block; +# define MY_MALLOC_UNSAFE hp_malloc_unsafe +# define MY_MALLOC hp_malloc +# define MY_FREE_UNSAFE hp_free_unsafe +# define MY_FREE hp_free +# define MY_REALLOC hp_realloc +# define MY_STATUS hp_status +# define MY_MEMINFO hp_info # ifdef STATISTICS -# define MY_SHM_GET_SIZE fm_get_size -# define MY_SHM_GET_USED fm_get_used -# define MY_SHM_GET_RUSED fm_get_real_used -# define MY_SHM_GET_MUSED fm_get_max_real_used -# define MY_SHM_GET_FREE fm_get_free -# define MY_SHM_GET_FRAGS fm_get_frags +# define MY_SHM_GET_SIZE hp_get_size +# define MY_SHM_GET_USED hp_get_used +# define MY_SHM_GET_RUSED hp_get_real_used +# define MY_SHM_GET_MUSED hp_get_max_real_used +# define MY_SHM_GET_FREE hp_get_free +# define MY_SHM_GET_FRAGS hp_get_frags # endif -# define shm_malloc_init fm_malloc_init -# define shm_mem_warming fm_mem_warming -# define update_mem_pattern_file fm_update_mem_pattern_file +# define shm_malloc_init hp_malloc_init +# define shm_mem_warming hp_mem_warming +# define update_mem_pattern_file hp_update_mem_pattern_file #else # include "q_malloc.h" extern struct qm_block* shm_block; From 3da4c5d7a1a6247d50700e3962ac114e618ececc Mon Sep 17 00:00:00 2001 From: Liviu Chircu Date: Fri, 21 Mar 2014 14:10:40 +0200 Subject: [PATCH 04/44] hp malloc: increase built-in PKG mem size to match the larger hash * otherwise, "opensips -V" would fail (cherry picked from commit 6246df172cede302e33bb63e667a4786e2a47c17) --- config.h | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/config.h b/config.h index 7381a668a05..61502367995 100644 --- a/config.h +++ b/config.h @@ -42,7 +42,7 @@ #define CFG_FILE CFG_DIR "opensips.cfg" #define MEM_WARMING_DEFAULT_PATTERN_FILE CFG_DIR "mem_warming_pattern" -#define MEM_WARMING_DEFAULT_PERCENTAGE 85 +#define MEM_WARMING_DEFAULT_PERCENTAGE 75 #define TLS_PKEY_FILE CFG_DIR "tls/cert.pem" #define TLS_CERT_FILE CFG_DIR "tls/cert.pem" @@ -119,7 +119,11 @@ #define SRV_MAX_PREFIX_LEN SRV_TLS_PREFIX_LEN +#ifdef HP_MALLOC +#define PKG_MEM_SIZE 16 /*!< Used only if PKG_MALLOC is defined*/ +#else #define PKG_MEM_SIZE 2 /*!< Used only if PKG_MALLOC is defined*/ +#endif #define SHM_MEM_SIZE 32 /*!< Used if SH_MEM is defined*/ #define SHM_MAX_SECONDARY_HASH_SIZE 100 #define DEFAULT_SHM_HASH_SPLIT_PERCENTAGE 1 /*!< Used if SH_MEM is defined*/ From 5973c96de7e469f291418e1fb5f3abbb8fb015cc Mon Sep 17 00:00:00 2001 From: Liviu Chircu Date: Fri, 21 Mar 2014 14:27:40 +0200 Subject: [PATCH 05/44] hp malloc: expose memory warming parameters in the script (cherry picked from commit 83c97e8a6f9a3c14dd393722467d701c7d03f87b) --- cfg.lex | 6 ++++++ cfg.y | 9 +++++++++ main.c | 14 +++++++++++--- mem/hp_malloc.c | 2 +- 4 files changed, 27 insertions(+), 4 deletions(-) diff --git a/cfg.lex b/cfg.lex index bc34bbf561d..3f69baf37ba 100644 --- a/cfg.lex +++ b/cfg.lex @@ -304,6 +304,9 @@ CHILDREN children CHECK_VIA check_via SHM_HASH_SPLIT_PERCENTAGE "shm_hash_split_percentage" SHM_SECONDARY_HASH_SIZE "shm_secondary_hash_size" +MEM_WARMING_ENABLED "mem_warming"|"mem_warming_enabled" +MEM_WARMING_PATTERN_FILE "mem_warming_pattern_file" +MEM_WARMING_PERCENTAGE "mem_warming_percentage" MEMLOG "memlog"|"mem_log" MEMDUMP "memdump"|"mem_dump" EXECMSGTHRESHOLD "execmsgthreshold"|"exec_msg_threshold" @@ -611,6 +614,9 @@ IMPORTFILE "import_file" {CHECK_VIA} { count(); yylval.strval=yytext; return CHECK_VIA; } {SHM_HASH_SPLIT_PERCENTAGE} { count(); yylval.strval=yytext; return SHM_HASH_SPLIT_PERCENTAGE; } {SHM_SECONDARY_HASH_SIZE} { count(); yylval.strval=yytext; return SHM_SECONDARY_HASH_SIZE; } +{MEM_WARMING_ENABLED} { count(); yylval.strval=yytext; return MEM_WARMING_ENABLED; } +{MEM_WARMING_PATTERN_FILE} { count(); yylval.strval=yytext; return MEM_WARMING_PATTERN_FILE; } +{MEM_WARMING_PERCENTAGE} { count(); yylval.strval=yytext; return MEM_WARMING_PERCENTAGE; } {MEMLOG} { count(); yylval.strval=yytext; return MEMLOG; } {MEMDUMP} { count(); yylval.strval=yytext; return MEMDUMP; } {EXECMSGTHRESHOLD} { count(); yylval.strval=yytext; return EXECMSGTHRESHOLD; } diff --git a/cfg.y b/cfg.y index 7d34d44bd97..71aded70a11 100644 --- a/cfg.y +++ b/cfg.y @@ -329,6 +329,9 @@ extern int line; %token CHECK_VIA %token SHM_HASH_SPLIT_PERCENTAGE %token SHM_SECONDARY_HASH_SIZE +%token MEM_WARMING_ENABLED +%token MEM_WARMING_PATTERN_FILE +%token MEM_WARMING_PERCENTAGE %token MEMLOG %token MEMDUMP %token EXECMSGTHRESHOLD @@ -695,6 +698,12 @@ assign_stm: DEBUG EQUAL snumber { | SHM_HASH_SPLIT_PERCENTAGE EQUAL error { yyerror("number expected"); } | SHM_SECONDARY_HASH_SIZE EQUAL NUMBER { shm_secondary_hash_size=$3; } | SHM_SECONDARY_HASH_SIZE EQUAL error { yyerror("number expected"); } + | MEM_WARMING_ENABLED EQUAL NUMBER { mem_warming_enabled = $3; } + | MEM_WARMING_ENABLED EQUAL error { yyerror("number expected"); } + | MEM_WARMING_PATTERN_FILE EQUAL STRING { mem_warming_pattern_file = $3; } + | MEM_WARMING_PATTERN_FILE EQUAL error { yyerror("string expected"); } + | MEM_WARMING_PERCENTAGE EQUAL NUMBER { mem_warming_percentage = $3; } + | MEM_WARMING_PERCENTAGE EQUAL error { yyerror("number expected"); } | MEMLOG EQUAL NUMBER { memlog=$3; memdump=$3; } | MEMLOG EQUAL error { yyerror("int value expected"); } | MEMDUMP EQUAL NUMBER { memdump=$3; } diff --git a/main.c b/main.c index b45e351ba8e..83eb52dfdea 100644 --- a/main.c +++ b/main.c @@ -347,11 +347,11 @@ unsigned long pkg_mem_size=PKG_MEM_SIZE * 1024 * 1024; * used to fragment the shared memory pool at daemon startup */ char *mem_warming_pattern_file; -int mem_warming_enabled = 1; +int mem_warming_enabled; /* * percentage of shared memory which will be fragmented at startup - * values between [0, 75] + * common values are between [0, 75] */ int mem_warming_percentage = -1; @@ -387,7 +387,7 @@ void cleanup(int show_status) { int i; - for (i = 0; i < F_HASH_SIZE; i++) + for (i = 0; i < HP_HASH_SIZE; i++) shm_unlock(i); } #else @@ -1455,6 +1455,14 @@ int main(int argc, char** argv) time(&startup_time); + if (mem_warming_enabled) { + if (!mem_warming_pattern_file) + mem_warming_pattern_file = MEM_WARMING_DEFAULT_PATTERN_FILE; + + if (mem_warming_percentage == -1) + mem_warming_percentage = MEM_WARMING_DEFAULT_PERCENTAGE; + } + /*init shm mallocs * this must be here * -to allow setting shm mem size from the command line diff --git a/mem/hp_malloc.c b/mem/hp_malloc.c index 583603668d6..74ee30c57e2 100644 --- a/mem/hp_malloc.c +++ b/mem/hp_malloc.c @@ -447,7 +447,7 @@ struct hp_block* hp_malloc_init(char* address, unsigned long size) /* make address and size multiple of 8*/ start=(char*)ROUNDUP((unsigned long) address); - LM_DBG("F_OPTIMIZE=%lu, /ROUNDTO=%lu\n", + LM_DBG("HP_OPTIMIZE=%lu, /ROUNDTO=%lu\n", HP_MALLOC_OPTIMIZE, HP_MALLOC_OPTIMIZE/ROUNDTO); LM_DBG("HP_HASH_SIZE=%lu, hp_block size=%lu\n", HP_HASH_SIZE, (long)sizeof(struct hp_block)); From ea6ab4d87ce03d2501896038b4d7e234130f0c47 Mon Sep 17 00:00:00 2001 From: Liviu Chircu Date: Fri, 21 Mar 2014 19:37:24 +0200 Subject: [PATCH 06/44] tm: fix fr_inv_timeout bug from commit d244686dc5f * also improve code readability with a couple of macros (cherry picked from commit 2535935327f30a2c004c3f2619c1cc9f0ed0e26c) --- modules/tm/t_funcs.c | 2 +- modules/tm/t_funcs.h | 3 +++ modules/tm/t_reply.c | 5 ++++- modules/tm/tm.c | 4 ++-- 4 files changed, 10 insertions(+), 4 deletions(-) diff --git a/modules/tm/t_funcs.c b/modules/tm/t_funcs.c index 28836db6216..8a9e5bed4fc 100644 --- a/modules/tm/t_funcs.c +++ b/modules/tm/t_funcs.c @@ -271,7 +271,7 @@ inline void _set_fr_retr( struct retr_buf *rb, int retr ) set_timer( &rb->retr_timer, RT_T1_TO_1, NULL ); } - if (!rb->my_T || rb->my_T->fr_timeout==0) + if (!rb->my_T || !is_timeout_set(rb->my_T->fr_timeout)) set_1timer(&rb->fr_timer, FR_TIMER_LIST, NULL); else { timer = rb->my_T->fr_timeout; diff --git a/modules/tm/t_funcs.h b/modules/tm/t_funcs.h index 99435c7c1da..78c902f2abe 100644 --- a/modules/tm/t_funcs.h +++ b/modules/tm/t_funcs.h @@ -121,6 +121,9 @@ int send_pr_buffer( struct retr_buf *rb, void *buf, int len); #define INIT_REF_UNSAFE(_T_cell) ((_T_cell)->ref_count=1) #define IS_REFFED_UNSAFE(_T_cell) ((_T_cell)->ref_count!=0) +#define unset_timeout(timeout) ((timeout) = 0) +#define is_timeout_set(timeout) ((timeout) != 0) + inline void set_fr_retr(struct retr_buf *rb, int retr ); inline void start_retr(struct retr_buf *rb); inline void force_retr(struct retr_buf *rb); diff --git a/modules/tm/t_reply.c b/modules/tm/t_reply.c index 94e955ca3cc..ee07b2c33df 100644 --- a/modules/tm/t_reply.c +++ b/modules/tm/t_reply.c @@ -1609,7 +1609,10 @@ int reply_received( struct sip_msg *p_msg ) * attempt to restart retransmission any more */ backup_list = set_avp_list(&t->user_avps); - timer = t->fr_inv_timeout; + timer = is_timeout_set(t->fr_inv_timeout) ? + t->fr_inv_timeout : + timer_id2timeout[FR_INV_TIMER_LIST]; + LM_DBG("FR_INV_TIMER = %lld\n", timer); set_timer(&uac->request.fr_timer, FR_INV_TIMER_LIST, &timer); set_avp_list(backup_list); diff --git a/modules/tm/tm.c b/modules/tm/tm.c index 542ca55c288..d7b2c8bc048 100644 --- a/modules/tm/tm.c +++ b/modules/tm/tm.c @@ -683,8 +683,8 @@ static int script_init( struct sip_msg *foo, void *bar) set_t(T_UNDEFINED); reset_cancelled_t(); reset_e2eack_t(); - fr_timeout = 0; - fr_inv_timeout = 0; + unset_timeout(fr_timeout); + unset_timeout(fr_inv_timeout); /* reset the kill reason status */ reset_kr(); From eb2dee68e72c01c80a76816bbee89acffa06d862 Mon Sep 17 00:00:00 2001 From: Nick Altmann Date: Sat, 22 Mar 2014 10:15:15 +0400 Subject: [PATCH 07/44] Update rpm specs for 1.11 --- packaging/fedora/opensips.spec | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/packaging/fedora/opensips.spec b/packaging/fedora/opensips.spec index 4f4e1553588..99aba3cafaa 100644 --- a/packaging/fedora/opensips.spec +++ b/packaging/fedora/opensips.spec @@ -878,6 +878,7 @@ chown -R %{name}:%{name} %{_sysconfdir}/%{name} %{_libdir}/opensips/modules/mi_fifo.so %{_libdir}/opensips/modules/mi_datagram.so %{_libdir}/opensips/modules/mi_http.so +%{_libdir}/opensips/modules/mi_json.so %{_libdir}/opensips/modules/msilo.so %{_libdir}/opensips/modules/nathelper.so %{_libdir}/opensips/modules/nat_traversal.so @@ -891,6 +892,7 @@ chown -R %{name}:%{name} %{_sysconfdir}/%{name} %{_libdir}/opensips/modules/ratelimit.so %{_libdir}/opensips/modules/registrar.so %{_libdir}/opensips/modules/rr.so +%{_libdir}/opensips/modules/script_helper.so %{_libdir}/opensips/modules/signaling.so %{_libdir}/opensips/modules/sipcapture.so %{_libdir}/opensips/modules/sipmsgops.so @@ -947,6 +949,7 @@ chown -R %{name}:%{name} %{_sysconfdir}/%{name} %doc docdir/README.mi_datagram %doc docdir/README.mi_fifo %doc docdir/README.mi_http +%doc docdir/README.mi_json %doc docdir/README.msilo %doc docdir/README.nat_traversal %doc docdir/README.nathelper @@ -960,6 +963,7 @@ chown -R %{name}:%{name} %{_sysconfdir}/%{name} %doc docdir/README.registrar %doc docdir/README.rr %doc docdir/README.rtpproxy +%doc docdir/README.script_helper %doc docdir/README.signaling %doc docdir/README.sipcapture %doc docdir/README.sipmsgops @@ -999,8 +1003,12 @@ chown -R %{name}:%{name} %{_sysconfdir}/%{name} %files b2bua %{_libdir}/opensips/modules/b2b_entities.so %{_libdir}/opensips/modules/b2b_logic.so +%{_libdir}/opensips/modules/b2b_sca.so +%{_libdir}/opensips/modules/call_center.so %doc docdir/README.b2b_entities %doc docdir/README.b2b_logic +%doc docdir/README.b2b_sca +%doc docdir/README.call_center %files carrierroute %{_libdir}/opensips/modules/carrierroute.so @@ -1257,7 +1265,7 @@ chown -R %{name}:%{name} %{_sysconfdir}/%{name} %doc docdir/README.xmpp %changelog -* Tue Aug 13 2013 Nick Altmann - 1.11.0-1 +* Fri Mar 21 2014 Nick Altmann - 1.11.0-1 - Update to 1.11.0 * Tue Jul 30 2013 Nick Altmann - 1.10.0-1 From bb3c2df52ac5786330bc283fa974e4967bf80d8a Mon Sep 17 00:00:00 2001 From: fabriziopicconi Date: Sat, 22 Mar 2014 15:58:14 +0100 Subject: [PATCH 08/44] New modules included Some new rpm optional modules are added: b2b_sca,call_center,mi_json,script_helper --- packaging/rpm/opensips.spec.CentOS | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/packaging/rpm/opensips.spec.CentOS b/packaging/rpm/opensips.spec.CentOS index 55d33261a85..5b9e1f8f8f2 100644 --- a/packaging/rpm/opensips.spec.CentOS +++ b/packaging/rpm/opensips.spec.CentOS @@ -426,6 +426,7 @@ fi %doc %{_docdir}/opensips/README.benchmark %doc %{_docdir}/opensips/README.cachedb_local %doc %{_docdir}/opensips/README.cachedb_sql +%doc %{_docdir}/opensips/README.call_center %doc %{_docdir}/opensips/README.call_control %doc %{_docdir}/opensips/README.cfgutils %doc %{_docdir}/opensips/README.closeddial @@ -466,8 +467,6 @@ fi %doc %{_docdir}/opensips/README.peering %doc %{_docdir}/opensips/README.permissions %doc %{_docdir}/opensips/README.pike -%doc %{_docdir}/opensips/README.presence_callinfo -%doc %{_docdir}/opensips/README.presence_xcapdiff %doc %{_docdir}/opensips/README.qos %doc %{_docdir}/opensips/README.ratelimit %doc %{_docdir}/opensips/README.registrar @@ -475,6 +474,7 @@ fi %doc %{_docdir}/opensips/README.rr %doc %{_docdir}/opensips/README.rtpproxy %doc %{_docdir}/opensips/README.seas +%doc %{_docdir}/opensips/README.script_helper %doc %{_docdir}/opensips/README.signaling %doc %{_docdir}/opensips/README.sipcapture %doc %{_docdir}/opensips/README.sipmsgops @@ -514,6 +514,7 @@ fi %{_libdir}/opensips/modules/benchmark.so %{_libdir}/opensips/modules/cachedb_local.so %{_libdir}/opensips/modules/cachedb_sql.so +%{_libdir}/opensips/modules/call_center.so %{_libdir}/opensips/modules/call_control.so %{_libdir}/opensips/modules/cfgutils.so %{_libdir}/opensips/modules/closeddial.so @@ -554,8 +555,6 @@ fi %{_libdir}/opensips/modules/peering.so %{_libdir}/opensips/modules/permissions.so %{_libdir}/opensips/modules/pike.so -%{_libdir}/opensips/modules/presence_callinfo.so -%{_libdir}/opensips/modules/presence_xcapdiff.so %{_libdir}/opensips/modules/python.so %{_libdir}/opensips/modules/qos.so %{_libdir}/opensips/modules/ratelimit.so @@ -564,6 +563,7 @@ fi %{_libdir}/opensips/modules/rr.so %{_libdir}/opensips/modules/rtpproxy.so %{_libdir}/opensips/modules/seas.so +%{_libdir}/opensips/modules/script_helper.so %{_libdir}/opensips/modules/signaling.so %{_libdir}/opensips/modules/sipcapture.so %{_libdir}/opensips/modules/sipmsgops.so @@ -652,6 +652,7 @@ fi %defattr(-,root,root) %doc %{_docdir}/opensips/README.presence %doc %{_docdir}/opensips/README.presence_callinfo +%doc %{_docdir}/opensips/README.b2b_sca %doc %{_docdir}/opensips/README.presence_dialoginfo %doc %{_docdir}/opensips/README.presence_mwi %doc %{_docdir}/opensips/README.presence_xcapdiff @@ -668,6 +669,7 @@ fi %{_libdir}/opensips/modules/presence.so %{_libdir}/opensips/modules/presence_callinfo.so +%{_libdir}/opensips/modules/b2b_sca.so %{_libdir}/opensips/modules/presence_dialoginfo.so %{_libdir}/opensips/modules/presence_mwi.so %{_libdir}/opensips/modules/presence_xcapdiff.so @@ -748,8 +750,10 @@ fi %files json %defattr(-,root,root) %doc %{_docdir}/opensips/README.json +%doc %{_docdir}/opensips/README.mi_json %{_libdir}/opensips/modules/json.so +%{_libdir}/opensips/modules/mi_json.so %files carrierroute @@ -903,6 +907,10 @@ fi %{_libdir}/opensips/modules/tlsops.so +%changelog +* Tue Mar 22 2014 Fabrizio Picconi +- Some new rpm optional modules are added: + b2b_sca,call_center,mi_json,script_helper %changelog * Tue Aug 06 2013 Fabrizio Picconi - Some new rpm optional modules are added: From 5508a27bd2c3ccff9a6a793877f07141d6d214f6 Mon Sep 17 00:00:00 2001 From: Nick Altmann Date: Mon, 24 Mar 2014 15:33:23 +0400 Subject: [PATCH 09/44] Update centos spec file: fixed b2b submodule and removed some odd files from main module --- packaging/rpm/opensips.spec.CentOS | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/packaging/rpm/opensips.spec.CentOS b/packaging/rpm/opensips.spec.CentOS index 5b9e1f8f8f2..8553f7249bb 100644 --- a/packaging/rpm/opensips.spec.CentOS +++ b/packaging/rpm/opensips.spec.CentOS @@ -422,7 +422,6 @@ fi %doc %{_docdir}/opensips/README.auth_db %doc %{_docdir}/opensips/README.auth_diameter %doc %{_docdir}/opensips/README.avpops -%doc %{_docdir}/opensips/README.b2b_entities %doc %{_docdir}/opensips/README.benchmark %doc %{_docdir}/opensips/README.cachedb_local %doc %{_docdir}/opensips/README.cachedb_sql @@ -464,7 +463,6 @@ fi %doc %{_docdir}/opensips/README.options %doc %{_docdir}/opensips/README.path %doc %{_docdir}/opensips/README.pdt -%doc %{_docdir}/opensips/README.peering %doc %{_docdir}/opensips/README.permissions %doc %{_docdir}/opensips/README.pike %doc %{_docdir}/opensips/README.qos @@ -510,7 +508,6 @@ fi %{_libdir}/opensips/modules/auth_db.so %{_libdir}/opensips/modules/auth_diameter.so %{_libdir}/opensips/modules/avpops.so -%{_libdir}/opensips/modules/b2b_entities.so %{_libdir}/opensips/modules/benchmark.so %{_libdir}/opensips/modules/cachedb_local.so %{_libdir}/opensips/modules/cachedb_sql.so @@ -552,7 +549,6 @@ fi %{_libdir}/opensips/modules/options.so %{_libdir}/opensips/modules/path.so %{_libdir}/opensips/modules/pdt.so -%{_libdir}/opensips/modules/peering.so %{_libdir}/opensips/modules/permissions.so %{_libdir}/opensips/modules/pike.so %{_libdir}/opensips/modules/python.so @@ -652,7 +648,6 @@ fi %defattr(-,root,root) %doc %{_docdir}/opensips/README.presence %doc %{_docdir}/opensips/README.presence_callinfo -%doc %{_docdir}/opensips/README.b2b_sca %doc %{_docdir}/opensips/README.presence_dialoginfo %doc %{_docdir}/opensips/README.presence_mwi %doc %{_docdir}/opensips/README.presence_xcapdiff @@ -669,7 +664,6 @@ fi %{_libdir}/opensips/modules/presence.so %{_libdir}/opensips/modules/presence_callinfo.so -%{_libdir}/opensips/modules/b2b_sca.so %{_libdir}/opensips/modules/presence_dialoginfo.so %{_libdir}/opensips/modules/presence_mwi.so %{_libdir}/opensips/modules/presence_xcapdiff.so @@ -710,9 +704,11 @@ fi %defattr(-,root,root) %doc %{_docdir}/opensips/README.b2b_entities %doc %{_docdir}/opensips/README.b2b_logic +%doc %{_docdir}/opensips/README.b2b_sca %{_libdir}/opensips/modules/b2b_entities.so %{_libdir}/opensips/modules/b2b_logic.so +%{_libdir}/opensips/modules/b2b_sca.so %files ldap From 3285be4892b10aadef3a234630bcd05a778a6f08 Mon Sep 17 00:00:00 2001 From: Liviu Chircu Date: Mon, 24 Mar 2014 14:55:58 +0200 Subject: [PATCH 10/44] sipmsgops: Fix trailing whitespaces when doing "codec_delete_re" * deleting the last payload attribute led to trailing whitespaces * some UAs would return "488 Not Acceptable Here" in this case (cherry picked from commit c9657d4154ebc3ee271e981db036a10d9b9a7922) --- modules/sipmsgops/codecs.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/modules/sipmsgops/codecs.c b/modules/sipmsgops/codecs.c index 63679d5967d..3d3ff31cd6a 100644 --- a/modules/sipmsgops/codecs.c +++ b/modules/sipmsgops/codecs.c @@ -561,6 +561,15 @@ static int stream_process(struct sip_msg * msg, struct sdp_stream_cell *cell, found.len++; } + /* when trimming the very last payload, avoid trailing ws */ + if (cur == lmp->u.value + lmp->len) { + tmp = found.s; + while (*(--tmp) == ' ') { + found.s--; + found.len++; + } + } + /* delete the string and update iterators */ for(tmp=found.s ; tmp< lmp->u.value + lmp->len ; tmp++ ) *tmp = *(tmp+found.len); From a345f50dae2eca10be798b3806cb9d06f71203fb Mon Sep 17 00:00:00 2001 From: Nick Altmann Date: Mon, 24 Mar 2014 18:45:52 +0400 Subject: [PATCH 11/44] Update CentOS and RHEL/Fedora specs: fixed b2b submodule, added additional dependencies --- packaging/fedora/opensips.spec | 1 + packaging/rpm/opensips.spec.CentOS | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/packaging/fedora/opensips.spec b/packaging/fedora/opensips.spec index 99aba3cafaa..a767881e999 100644 --- a/packaging/fedora/opensips.spec +++ b/packaging/fedora/opensips.spec @@ -124,6 +124,7 @@ server, namely DIameter Server Client (DISC). Summary: Back-2-Back User Agent Group: System Environment/Daemons Requires: %{name} = %{version}-%{release} +Requires: %{name}-pua %description b2bua B2BUA is an implementation of the behavior of a B2BUA as defined in RFC 3261 diff --git a/packaging/rpm/opensips.spec.CentOS b/packaging/rpm/opensips.spec.CentOS index 8553f7249bb..b8c3ab30318 100644 --- a/packaging/rpm/opensips.spec.CentOS +++ b/packaging/rpm/opensips.spec.CentOS @@ -425,7 +425,6 @@ fi %doc %{_docdir}/opensips/README.benchmark %doc %{_docdir}/opensips/README.cachedb_local %doc %{_docdir}/opensips/README.cachedb_sql -%doc %{_docdir}/opensips/README.call_center %doc %{_docdir}/opensips/README.call_control %doc %{_docdir}/opensips/README.cfgutils %doc %{_docdir}/opensips/README.closeddial @@ -511,7 +510,6 @@ fi %{_libdir}/opensips/modules/benchmark.so %{_libdir}/opensips/modules/cachedb_local.so %{_libdir}/opensips/modules/cachedb_sql.so -%{_libdir}/opensips/modules/call_center.so %{_libdir}/opensips/modules/call_control.so %{_libdir}/opensips/modules/cfgutils.so %{_libdir}/opensips/modules/closeddial.so @@ -705,10 +703,12 @@ fi %doc %{_docdir}/opensips/README.b2b_entities %doc %{_docdir}/opensips/README.b2b_logic %doc %{_docdir}/opensips/README.b2b_sca +%doc %{_docdir}/opensips/README.call_center %{_libdir}/opensips/modules/b2b_entities.so %{_libdir}/opensips/modules/b2b_logic.so %{_libdir}/opensips/modules/b2b_sca.so +%{_libdir}/opensips/modules/call_center.so %files ldap From 0bc24b510a946e349c9eeb8b048cee5bc0c2ca80 Mon Sep 17 00:00:00 2001 From: Ovidiu Sas Date: Mon, 24 Mar 2014 15:04:41 -0400 Subject: [PATCH 12/44] mi: declare/move MI_DATE_BUF_LEN into the mi headers (cherry picked from commit 8925239f47bec295e1b0188c5b8c0deb2903a4ca) --- mi/tree.h | 2 ++ modules/dialog/dlg_hash.c | 2 -- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/mi/tree.h b/mi/tree.h index a92a22a3854..6bc5ec8bef1 100644 --- a/mi/tree.h +++ b/mi/tree.h @@ -65,6 +65,8 @@ struct mi_handler; #define MI_MISSING_PARM MI_MISSING_PARM_S #define MI_BAD_PARM MI_BAD_PARM_S +#define MI_DATE_BUF_LEN 21 + struct mi_node { str value; str name; diff --git a/modules/dialog/dlg_hash.c b/modules/dialog/dlg_hash.c index a63d65d0c6f..808b1f599a7 100644 --- a/modules/dialog/dlg_hash.c +++ b/modules/dialog/dlg_hash.c @@ -63,8 +63,6 @@ #define MAX_LDG_LOCKS 2048 #define MIN_LDG_LOCKS 2 -#define MI_DATE_BUF_LEN 21 - extern struct tm_binds d_tmb; extern int last_dst_leg; From d84ffc8eda5af6cfba407e7c4a1f7658b81baddb Mon Sep 17 00:00:00 2001 From: Ovidiu Sas Date: Mon, 24 Mar 2014 15:26:44 -0400 Subject: [PATCH 13/44] httpd: fix compiler warning (cherry picked from commit 4e703a579d74587fe8f82fa040e3b39fe4b93b2d) --- modules/httpd/httpd_proc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/httpd/httpd_proc.c b/modules/httpd/httpd_proc.c index f6375d973fe..f9f1888693c 100644 --- a/modules/httpd/httpd_proc.c +++ b/modules/httpd/httpd_proc.c @@ -212,7 +212,7 @@ static int post_iterator (void *cls, " value=[%p]->'%s' off=%ld size=%ld\n", cls, kind, key, key, filename, content_type, transfer_encoding, - value, value, off, size); + value, value, (long long unsigned int)off, size); pr = (struct post_request*)cls; From 4b90882cc890599d11e4399359c85616faba8257 Mon Sep 17 00:00:00 2001 From: Ovidiu Sas Date: Tue, 25 Mar 2014 10:48:10 -0400 Subject: [PATCH 14/44] presence: subs_phtable_list - print expires attr in human readable format (cherry picked from commit ddaf00470e4f376a572483a3d1e8bf8c2bc98c4e) --- modules/presence/presence.c | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/modules/presence/presence.c b/modules/presence/presence.c index de849f46a0b..fbb78daf7dc 100644 --- a/modules/presence/presence.c +++ b/modules/presence/presence.c @@ -690,6 +690,9 @@ static inline int mi_print_shtable_record(struct mi_node *rpl, subs_t* s) { struct mi_node *node, *node1; struct mi_attr *attr; + time_t _ts; + char date_buf[MI_DATE_BUF_LEN]; + int date_buf_len; char *p; int len; @@ -701,11 +704,16 @@ static inline int mi_print_shtable_record(struct mi_node *rpl, subs_t* s) attr = add_mi_attr(node, MI_DUP_VALUE, "event_id", 8, s->event_id.s, s->event_id.len); if (attr==NULL) goto error; */ - p= int2str((unsigned long)s->status, &len); - attr = add_mi_attr(node, MI_DUP_VALUE, "status", 6, p, len); if (attr==NULL) goto error; - p= int2str((unsigned long)s->expires, &len); - attr = add_mi_attr(node, MI_DUP_VALUE, "expires", 7, p, len); + _ts = (time_t)s->expires; + date_buf_len = strftime(date_buf, MI_DATE_BUF_LEN - 1, + "%Y-%m-%d %H:%M:%S", localtime(&_ts)); + if (date_buf_len != 0) { + attr = add_mi_attr(node, MI_DUP_VALUE, "expires", 7, date_buf, date_buf_len); + } else { + p= int2str((unsigned long)s->expires, &len); + attr = add_mi_attr(node, MI_DUP_VALUE, "expires", 7, p, len); + } if (attr==NULL) goto error; p= int2str((unsigned long)s->db_flag, &len); attr = add_mi_attr(node, MI_DUP_VALUE, "db_flag", 7, p, len); From 22ca1a66d4811c620d32a1058e95f605a57ebfb3 Mon Sep 17 00:00:00 2001 From: Liviu Chircu Date: Tue, 25 Mar 2014 16:45:20 +0200 Subject: [PATCH 15/44] hp malloc: fix the hash size macros * the old ones actually led to bad memory accesses within hp_malloc() (cherry picked from commit faaca742a06d5a1e5f8925a1e95cfafcdd85c709) --- mem/hp_malloc.c | 6 +++--- mem/hp_malloc.h | 7 ++++--- mem/shm_mem.c | 8 ++++---- 3 files changed, 11 insertions(+), 10 deletions(-) diff --git a/mem/hp_malloc.c b/mem/hp_malloc.c index 74ee30c57e2..8be681ca8cd 100644 --- a/mem/hp_malloc.c +++ b/mem/hp_malloc.c @@ -405,7 +405,7 @@ int hp_mem_warming(struct hp_block *qm) hp_remove_free(qm, big_frag); /* trim-insert operation on the big free fragment */ - hp_split_frag(qm, big_frag, current_frag_size, -1); + hp_split_frag_unsafe(qm, big_frag, current_frag_size); /* * "big_frag" now points to a smaller, free and detached frag. @@ -449,8 +449,8 @@ struct hp_block* hp_malloc_init(char* address, unsigned long size) start=(char*)ROUNDUP((unsigned long) address); LM_DBG("HP_OPTIMIZE=%lu, /ROUNDTO=%lu\n", HP_MALLOC_OPTIMIZE, HP_MALLOC_OPTIMIZE/ROUNDTO); - LM_DBG("HP_HASH_SIZE=%lu, hp_block size=%lu\n", - HP_HASH_SIZE, (long)sizeof(struct hp_block)); + LM_DBG("HP_HASH_SIZE=%lu, HP_EXTRA_HASH_SIZE=%lu, hp_block size=%lu\n", + HP_HASH_SIZE, HP_EXTRA_HASH_SIZE, (long)sizeof(struct hp_block)); LM_DBG("params (%p, %lu), start=%p\n", address, size, start); if (size<(unsigned long)(start-address)) return 0; diff --git a/mem/hp_malloc.h b/mem/hp_malloc.h index 2de7f15e910..0a318b34681 100644 --- a/mem/hp_malloc.h +++ b/mem/hp_malloc.h @@ -60,9 +60,10 @@ #define HP_LINEAR_HASH_SIZE (HP_MALLOC_OPTIMIZE/ROUNDTO) #define HP_EXPONENTIAL_HASH_SIZE ((sizeof(long)*8-HP_MALLOC_OPTIMIZE_FACTOR)+1) -#define HP_HASH_SIZE (HP_LINEAR_HASH_SIZE + HP_EXPONENTIAL_HASH_SIZE + \ - HP_LINEAR_HASH_SIZE * SHM_MAX_SECONDARY_HASH_SIZE) -#define HP_EXTRA_HASH_SIZE (HP_LINEAR_HASH_SIZE * SHM_MAX_SECONDARY_HASH_SIZE) +#define HP_HASH_SIZE (HP_LINEAR_HASH_SIZE + HP_EXPONENTIAL_HASH_SIZE) +#define HP_EXTRA_HASH_SIZE (HP_LINEAR_HASH_SIZE * SHM_MAX_SECONDARY_HASH_SIZE) + +#define HP_TOTAL_HASH_SIZE (HP_HASH_SIZE + HP_EXTRA_HASH_SIZE) /* hash structure: * 0 .... HP_MALLOC_OPTIMIZE/ROUNDTO - small buckets, size increases with diff --git a/mem/shm_mem.c b/mem/shm_mem.c index 8b9b3a88118..6ab7b261324 100644 --- a/mem/shm_mem.c +++ b/mem/shm_mem.c @@ -289,23 +289,23 @@ int shm_mem_init_mallocs(void* mempool, unsigned long pool_size) LM_INFO("skipped memory warming\n"); } - mem_hash_usage = shm_malloc_unsafe(HP_HASH_SIZE * sizeof *mem_hash_usage); + mem_hash_usage = shm_malloc_unsafe(HP_TOTAL_HASH_SIZE * sizeof *mem_hash_usage); if (!mem_hash_usage) { LM_ERR("failed to allocate statistics array\n"); return -1; } - memset(mem_hash_usage, 0, HP_HASH_SIZE * sizeof *mem_hash_usage); + memset(mem_hash_usage, 0, HP_TOTAL_HASH_SIZE * sizeof *mem_hash_usage); /* lock_alloc cannot be used yet! */ - mem_lock = shm_malloc_unsafe(HP_HASH_SIZE * sizeof *mem_lock); + mem_lock = shm_malloc_unsafe(HP_TOTAL_HASH_SIZE * sizeof *mem_lock); if (!mem_lock) { LM_CRIT("could not allocate shm lock array\n"); shm_mem_destroy(); return -1; } - for (i = 0; i < HP_HASH_SIZE; i++) + for (i = 0; i < HP_TOTAL_HASH_SIZE; i++) if (!lock_init(&mem_lock[i])) { LM_CRIT("could not initialize lock\n"); shm_mem_destroy(); From eaea7ff2fb6c38c82a0580001416cea9686fb68f Mon Sep 17 00:00:00 2001 From: Liviu Chircu Date: Tue, 25 Mar 2014 16:48:33 +0200 Subject: [PATCH 16/44] hp malloc: reduce the built-in maximum split factor * dividing the list into too many smaller ones may actually hurt performance * this also reduces the minimum pkg and shm consumption by 3.4MB when enabling HP_MALLOC (cherry picked from commit 7d302c18fbd6c4c4d7af64aeddb1e9c65b6c9fc3) --- config.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config.h b/config.h index 61502367995..65743673e0d 100644 --- a/config.h +++ b/config.h @@ -125,7 +125,7 @@ #define PKG_MEM_SIZE 2 /*!< Used only if PKG_MALLOC is defined*/ #endif #define SHM_MEM_SIZE 32 /*!< Used if SH_MEM is defined*/ -#define SHM_MAX_SECONDARY_HASH_SIZE 100 +#define SHM_MAX_SECONDARY_HASH_SIZE 32 #define DEFAULT_SHM_HASH_SPLIT_PERCENTAGE 1 /*!< Used if SH_MEM is defined*/ #define DEFAULT_SHM_SECONDARY_HASH_SIZE 8 From 24353c63454f7002e9d5a8055e597264c6b0fdee Mon Sep 17 00:00:00 2001 From: Ovidiu Sas Date: Mon, 24 Mar 2014 21:31:33 -0400 Subject: [PATCH 17/44] core: list_tcp_conns: print Timeout attr in human readable format (cherry picked from commit 6ac1dc8251c597b60f0787026d65d95158d00a77) --- tcp_main.c | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/tcp_main.c b/tcp_main.c index 66efe1d990c..fe2533db8aa 100644 --- a/tcp_main.c +++ b/tcp_main.c @@ -2372,6 +2372,9 @@ struct mi_root *mi_list_tcp_conns(struct mi_root *cmd, void *param) struct mi_node* node; struct mi_attr *attr; struct tcp_connection *conn; + time_t _ts; + char date_buf[MI_DATE_BUF_LEN]; + int date_buf_len; unsigned long ctime; unsigned int i,n; char proto[4]; @@ -2429,8 +2432,16 @@ struct mi_root *mi_list_tcp_conns(struct mi_root *cmd, void *param) goto error; /* add timeout */ - p = int2str((unsigned long)conn->timeout+ctime, &len); - attr = add_mi_attr( node, MI_DUP_VALUE, MI_SSTR("Timeout"), p,len); + _ts = (time_t)conn->timeout+ctime; + date_buf_len = strftime(date_buf, MI_DATE_BUF_LEN - 1, + "%Y-%m-%d %H:%M:%S", localtime(&_ts)); + if (date_buf_len != 0) { + attr = add_mi_attr( node, MI_DUP_VALUE, MI_SSTR("Timeout"), + date_buf, date_buf_len); + } else { + p = int2str((unsigned long)_ts, &len); + attr = add_mi_attr( node, MI_DUP_VALUE, MI_SSTR("Timeout"), p,len); + } if (attr==0) goto error; From 74c5b3e4a2532835f59b5b95e3ad9f769b314a12 Mon Sep 17 00:00:00 2001 From: Bogdan-Andrei Iancu Date: Tue, 25 Mar 2014 16:59:10 -0400 Subject: [PATCH 18/44] core: list_tcp_conns: compute properly the tmeout attr (cherry picked from commit 344cd96ca6e9cef70525b92cd824f44e38476d55) --- tcp_main.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/tcp_main.c b/tcp_main.c index fe2533db8aa..1a2b660b87c 100644 --- a/tcp_main.c +++ b/tcp_main.c @@ -2375,7 +2375,6 @@ struct mi_root *mi_list_tcp_conns(struct mi_root *cmd, void *param) time_t _ts; char date_buf[MI_DATE_BUF_LEN]; int date_buf_len; - unsigned long ctime; unsigned int i,n; char proto[4]; char *p; @@ -2388,8 +2387,6 @@ struct mi_root *mi_list_tcp_conns(struct mi_root *cmd, void *param) if (rpl_tree==NULL) return 0; - ctime = (long)time(NULL); - TCPCONN_LOCK; for( i=0,n=0 ; itimeout+ctime; + _ts = (time_t)conn->timeout + startup_time; date_buf_len = strftime(date_buf, MI_DATE_BUF_LEN - 1, "%Y-%m-%d %H:%M:%S", localtime(&_ts)); if (date_buf_len != 0) { From 16bdc3aa85cca1b07a8cbe01be252ec82c43e586 Mon Sep 17 00:00:00 2001 From: Ovidiu Sas Date: Tue, 25 Mar 2014 19:17:23 -0400 Subject: [PATCH 19/44] pi_http: update pi_framework_mod.xsl to generate new pi_http samples - add link_cmd to the primary key for DB_UPDATE commands (cherry picked from commit d0ced797fce24c00502a008ab12e88eeeea85b0f) --- doc/dbschema/xsl/pi_framework_mod.xsl | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/doc/dbschema/xsl/pi_framework_mod.xsl b/doc/dbschema/xsl/pi_framework_mod.xsl index 7d6fb7825f0..ab53f5ce5bc 100644 --- a/doc/dbschema/xsl/pi_framework_mod.xsl +++ b/doc/dbschema/xsl/pi_framework_mod.xsl @@ -55,9 +55,18 @@ <cmd_type>DB_QUERY</cmd_type> <query_cols> - <col><field> - - </field></col> + + + <col><field> + + </field><link_cmd>update</link_cmd></col> + + + <col><field> + + </field></col> + + </query_cols> </cmd> From d5871e27742ad98de5ecc79d90770e4188b50c5f Mon Sep 17 00:00:00 2001 From: Ovidiu Sas Date: Tue, 25 Mar 2014 19:20:49 -0400 Subject: [PATCH 20/44] pi_http: samples regenerated (cherry picked from commit cbf2f118c407aa6549cce43fc6e9b6bcf9ae09fc) --- scripts/pi_http/acc-mod | 4 +- scripts/pi_http/alias_db-mod | 2 +- scripts/pi_http/auth_db-mod | 2 +- scripts/pi_http/avpops-mod | 2 +- scripts/pi_http/b2b-mod | 4 +- scripts/pi_http/b2b_sca-mod | 2 +- scripts/pi_http/call_center-mod | 6 +- scripts/pi_http/carrierroute-mod | 6 +- scripts/pi_http/closeddial-mod | 2 +- scripts/pi_http/cpl-mod | 2 +- scripts/pi_http/dialog-mod | 2 +- scripts/pi_http/dialplan-mod | 2 +- scripts/pi_http/dispatcher-mod | 2 +- scripts/pi_http/domain-mod | 2 +- scripts/pi_http/domainpolicy-mod | 2 +- scripts/pi_http/drouting-mod | 8 +-- scripts/pi_http/group-mod | 4 +- scripts/pi_http/imc-mod | 4 +- scripts/pi_http/load_balancer-mod | 2 +- scripts/pi_http/msilo-mod | 2 +- scripts/pi_http/pdt-mod | 2 +- scripts/pi_http/permissions-mod | 2 +- scripts/pi_http/pi_framework-01 | 2 + scripts/pi_http/pi_framework.xml | 100 +++++++++++++++--------------- scripts/pi_http/presence-mod | 10 +-- scripts/pi_http/registrant-mod | 2 +- scripts/pi_http/registrar-mod | 2 +- scripts/pi_http/rls-mod | 4 +- scripts/pi_http/rtpproxy-mod | 2 +- scripts/pi_http/siptrace-mod | 2 +- scripts/pi_http/speeddial-mod | 2 +- scripts/pi_http/uri_db-mod | 2 +- scripts/pi_http/userblacklist-mod | 4 +- scripts/pi_http/usrloc-mod | 2 +- 34 files changed, 102 insertions(+), 98 deletions(-) diff --git a/scripts/pi_http/acc-mod b/scripts/pi_http/acc-mod index 585f2eda999..726d38a5802 100644 --- a/scripts/pi_http/acc-mod +++ b/scripts/pi_http/acc-mod @@ -4,7 +4,7 @@ acc DB_QUERY - id + idupdate method from_tag to_tag @@ -66,7 +66,7 @@ missed_calls DB_QUERY - id + idupdate method from_tag to_tag diff --git a/scripts/pi_http/alias_db-mod b/scripts/pi_http/alias_db-mod index 0550768cf3d..1f00902d16e 100644 --- a/scripts/pi_http/alias_db-mod +++ b/scripts/pi_http/alias_db-mod @@ -4,7 +4,7 @@ dbaliases DB_QUERY - id + idupdate alias_username alias_domain username diff --git a/scripts/pi_http/auth_db-mod b/scripts/pi_http/auth_db-mod index 8f9e5996110..7890f97bb69 100644 --- a/scripts/pi_http/auth_db-mod +++ b/scripts/pi_http/auth_db-mod @@ -4,7 +4,7 @@ subscriber DB_QUERY - id + idupdate username domain password diff --git a/scripts/pi_http/avpops-mod b/scripts/pi_http/avpops-mod index a17b79c3703..a11a2732eef 100644 --- a/scripts/pi_http/avpops-mod +++ b/scripts/pi_http/avpops-mod @@ -4,7 +4,7 @@ usr_preferences DB_QUERY - id + idupdate uuid username domain diff --git a/scripts/pi_http/b2b-mod b/scripts/pi_http/b2b-mod index 0d9b4582f70..245e8eb1eaa 100644 --- a/scripts/pi_http/b2b-mod +++ b/scripts/pi_http/b2b-mod @@ -4,7 +4,7 @@ b2b_entities DB_QUERY - id + idupdate type state ruri @@ -114,7 +114,7 @@ b2b_logic DB_QUERY - id + idupdate si_key scenario sstate diff --git a/scripts/pi_http/b2b_sca-mod b/scripts/pi_http/b2b_sca-mod index b8bb04244fd..b31a28d6397 100644 --- a/scripts/pi_http/b2b_sca-mod +++ b/scripts/pi_http/b2b_sca-mod @@ -4,7 +4,7 @@ b2b_sca DB_QUERY - id + idupdate shared_line watchers app1_shared_entity diff --git a/scripts/pi_http/call_center-mod b/scripts/pi_http/call_center-mod index b98c0eda62d..36d3b81595b 100644 --- a/scripts/pi_http/call_center-mod +++ b/scripts/pi_http/call_center-mod @@ -5,7 +5,7 @@ DB_QUERY id - flowid + flowidupdate priority skill prependcid @@ -55,7 +55,7 @@ DB_QUERY id - agentid + agentidupdate location logstate skills @@ -98,7 +98,7 @@ cc_cdrs DB_QUERY - id + idupdate caller received_timestamp wait_time diff --git a/scripts/pi_http/carrierroute-mod b/scripts/pi_http/carrierroute-mod index 6aa40e9a07e..d5c28417f91 100644 --- a/scripts/pi_http/carrierroute-mod +++ b/scripts/pi_http/carrierroute-mod @@ -4,7 +4,7 @@ carrierroute DB_QUERY - id + idupdate carrier domain scan_prefix @@ -69,7 +69,7 @@ carrierfailureroute DB_QUERY - id + idupdate carrier domain scan_prefix @@ -128,7 +128,7 @@ route_tree DB_QUERY - id + idupdate carrier diff --git a/scripts/pi_http/closeddial-mod b/scripts/pi_http/closeddial-mod index 11bd07b9c29..3107740110d 100644 --- a/scripts/pi_http/closeddial-mod +++ b/scripts/pi_http/closeddial-mod @@ -4,7 +4,7 @@ closeddial DB_QUERY - id + idupdate username domain cd_username diff --git a/scripts/pi_http/cpl-mod b/scripts/pi_http/cpl-mod index 77c4736129c..1e2479a188c 100644 --- a/scripts/pi_http/cpl-mod +++ b/scripts/pi_http/cpl-mod @@ -4,7 +4,7 @@ cpl DB_QUERY - id + idupdate username domain cpl_xml diff --git a/scripts/pi_http/dialog-mod b/scripts/pi_http/dialog-mod index 89cc09638d9..4ed45806f0c 100644 --- a/scripts/pi_http/dialog-mod +++ b/scripts/pi_http/dialog-mod @@ -4,7 +4,7 @@ dialog DB_QUERY - dlg_id + dlg_idupdate callid from_uri from_tag diff --git a/scripts/pi_http/dialplan-mod b/scripts/pi_http/dialplan-mod index ba2b734e74d..ad624de15bf 100644 --- a/scripts/pi_http/dialplan-mod +++ b/scripts/pi_http/dialplan-mod @@ -4,7 +4,7 @@ dialplan DB_QUERY - id + idupdate dpid pr match_op diff --git a/scripts/pi_http/dispatcher-mod b/scripts/pi_http/dispatcher-mod index 2af4d5c8c85..f2ab6d32ba2 100644 --- a/scripts/pi_http/dispatcher-mod +++ b/scripts/pi_http/dispatcher-mod @@ -4,7 +4,7 @@ dispatcher DB_QUERY - id + idupdate setid destination socket diff --git a/scripts/pi_http/domain-mod b/scripts/pi_http/domain-mod index 4326fd6f74a..df216548a2b 100644 --- a/scripts/pi_http/domain-mod +++ b/scripts/pi_http/domain-mod @@ -4,7 +4,7 @@ domain DB_QUERY - id + idupdate domain last_modified diff --git a/scripts/pi_http/domainpolicy-mod b/scripts/pi_http/domainpolicy-mod index 72d04104504..802dfff7a33 100644 --- a/scripts/pi_http/domainpolicy-mod +++ b/scripts/pi_http/domainpolicy-mod @@ -4,7 +4,7 @@ domainpolicy DB_QUERY - id + idupdate rule type att diff --git a/scripts/pi_http/drouting-mod b/scripts/pi_http/drouting-mod index da710a3236a..c71ba444a87 100644 --- a/scripts/pi_http/drouting-mod +++ b/scripts/pi_http/drouting-mod @@ -4,7 +4,7 @@ dr_gateways DB_QUERY - id + idupdate gwid type address @@ -66,7 +66,7 @@ dr_rules DB_QUERY - ruleid + ruleidupdate groupid prefix timerec @@ -122,7 +122,7 @@ dr_carriers DB_QUERY - id + idupdate carrierid gwlist flags @@ -172,7 +172,7 @@ dr_groups DB_QUERY - id + idupdate username domain groupid diff --git a/scripts/pi_http/group-mod b/scripts/pi_http/group-mod index 4856476292e..65ebdf1285f 100644 --- a/scripts/pi_http/group-mod +++ b/scripts/pi_http/group-mod @@ -4,7 +4,7 @@ grp DB_QUERY - id + idupdate username domain grp @@ -48,7 +48,7 @@ re_grp DB_QUERY - id + idupdate reg_exp group_id diff --git a/scripts/pi_http/imc-mod b/scripts/pi_http/imc-mod index 79ba46d01f2..b640fd6d2c0 100644 --- a/scripts/pi_http/imc-mod +++ b/scripts/pi_http/imc-mod @@ -4,7 +4,7 @@ imc_rooms DB_QUERY - id + idupdate name domain flag @@ -45,7 +45,7 @@ imc_members DB_QUERY - id + idupdate username domain room diff --git a/scripts/pi_http/load_balancer-mod b/scripts/pi_http/load_balancer-mod index fd98048a451..224f15e8fed 100644 --- a/scripts/pi_http/load_balancer-mod +++ b/scripts/pi_http/load_balancer-mod @@ -4,7 +4,7 @@ load_balancer DB_QUERY - id + idupdate group_id dst_uri resources diff --git a/scripts/pi_http/msilo-mod b/scripts/pi_http/msilo-mod index 32c06651373..99466350823 100644 --- a/scripts/pi_http/msilo-mod +++ b/scripts/pi_http/msilo-mod @@ -4,7 +4,7 @@ silo DB_QUERY - id + idupdate src_addr dst_addr username diff --git a/scripts/pi_http/pdt-mod b/scripts/pi_http/pdt-mod index 7626bd5b075..8581c4292a5 100644 --- a/scripts/pi_http/pdt-mod +++ b/scripts/pi_http/pdt-mod @@ -4,7 +4,7 @@ pdt DB_QUERY - id + idupdate sdomain prefix domain diff --git a/scripts/pi_http/permissions-mod b/scripts/pi_http/permissions-mod index e2ce778d14c..85e98e2f8a5 100644 --- a/scripts/pi_http/permissions-mod +++ b/scripts/pi_http/permissions-mod @@ -4,7 +4,7 @@ address DB_QUERY - id + idupdate grp ip mask diff --git a/scripts/pi_http/pi_framework-01 b/scripts/pi_http/pi_framework-01 index 08e15432a35..8bda6ebad63 100644 --- a/scripts/pi_http/pi_framework-01 +++ b/scripts/pi_http/pi_framework-01 @@ -14,6 +14,8 @@ Each col will have: - a mandatory 'field' identifying the name of the field - an optional 'value' identifing the given value + - an optional 'link_cmd' identifing the update cmd with prepared values + * only for query_cols for DB_QUERY commands - a mandatory 'operator' only for 'clause_cols' The [clause|query|order_by]_cols can be: - ov : optional with multiple 'col' with optional 'value' diff --git a/scripts/pi_http/pi_framework.xml b/scripts/pi_http/pi_framework.xml index a9c514d6318..d8fc2fb05e9 100644 --- a/scripts/pi_http/pi_framework.xml +++ b/scripts/pi_http/pi_framework.xml @@ -823,6 +823,8 @@ Each col will have: - a mandatory 'field' identifying the name of the field - an optional 'value' identifing the given value + - an optional 'link_cmd' identifing the update cmd with prepared values + * only for query_cols for DB_QUERY commands - a mandatory 'operator' only for 'clause_cols' The [clause|query|order_by]_cols can be: - ov : optional with multiple 'col' with optional 'value' @@ -851,7 +853,7 @@ acc DB_QUERY - id + idupdate method from_tag to_tag @@ -913,7 +915,7 @@ missed_calls DB_QUERY - id + idupdate method from_tag to_tag @@ -966,7 +968,7 @@ dbaliases DB_QUERY - id + idupdate alias_username alias_domain username @@ -1010,7 +1012,7 @@ subscriber DB_QUERY - id + idupdate username domain password @@ -1063,7 +1065,7 @@ usr_preferences DB_QUERY - id + idupdate uuid username domain @@ -1116,7 +1118,7 @@ b2b_entities DB_QUERY - id + idupdate type state ruri @@ -1226,7 +1228,7 @@ b2b_logic DB_QUERY - id + idupdate si_key scenario sstate @@ -1336,7 +1338,7 @@ b2b_sca DB_QUERY - id + idupdate shared_line watchers app1_shared_entity @@ -1548,7 +1550,7 @@ DB_QUERY id - flowid + flowidupdate priority skill prependcid @@ -1598,7 +1600,7 @@ DB_QUERY id - agentid + agentidupdate location logstate skills @@ -1641,7 +1643,7 @@ cc_cdrs DB_QUERY - id + idupdate caller received_timestamp wait_time @@ -1706,7 +1708,7 @@ carrierroute DB_QUERY - id + idupdate carrier domain scan_prefix @@ -1771,7 +1773,7 @@ carrierfailureroute DB_QUERY - id + idupdate carrier domain scan_prefix @@ -1830,7 +1832,7 @@ route_tree DB_QUERY - id + idupdate carrier @@ -1865,7 +1867,7 @@ closeddial DB_QUERY - id + idupdate username domain cd_username @@ -1915,7 +1917,7 @@ cpl DB_QUERY - id + idupdate username domain cpl_xml @@ -1959,7 +1961,7 @@ dialog DB_QUERY - dlg_id + dlg_idupdate callid from_uri from_tag @@ -2064,7 +2066,7 @@ dialplan DB_QUERY - id + idupdate dpid pr match_op @@ -2123,7 +2125,7 @@ dispatcher DB_QUERY - id + idupdate setid destination socket @@ -2176,7 +2178,7 @@ domain DB_QUERY - id + idupdate domain last_modified @@ -2214,7 +2216,7 @@ domainpolicy DB_QUERY - id + idupdate rule type att @@ -2261,7 +2263,7 @@ dr_gateways DB_QUERY - id + idupdate gwid type address @@ -2323,7 +2325,7 @@ dr_rules DB_QUERY - ruleid + ruleidupdate groupid prefix timerec @@ -2379,7 +2381,7 @@ dr_carriers DB_QUERY - id + idupdate carrierid gwlist flags @@ -2429,7 +2431,7 @@ dr_groups DB_QUERY - id + idupdate username domain groupid @@ -2473,7 +2475,7 @@ grp DB_QUERY - id + idupdate username domain grp @@ -2517,7 +2519,7 @@ re_grp DB_QUERY - id + idupdate reg_exp group_id @@ -2555,7 +2557,7 @@ imc_rooms DB_QUERY - id + idupdate name domain flag @@ -2596,7 +2598,7 @@ imc_members DB_QUERY - id + idupdate username domain room @@ -2640,7 +2642,7 @@ load_balancer DB_QUERY - id + idupdate group_id dst_uri resources @@ -2687,7 +2689,7 @@ silo DB_QUERY - id + idupdate src_addr dst_addr username @@ -2746,7 +2748,7 @@ pdt DB_QUERY - id + idupdate sdomain prefix domain @@ -2787,7 +2789,7 @@ address DB_QUERY - id + idupdate grp ip mask @@ -2840,7 +2842,7 @@ presentity DB_QUERY - id + idupdate username domain event @@ -2899,7 +2901,7 @@ active_watchers DB_QUERY - id + idupdate presentity_uri watcher_username watcher_domain @@ -2991,7 +2993,7 @@ watchers DB_QUERY - id + idupdate presentity_uri watcher_username watcher_domain @@ -3044,7 +3046,7 @@ xcap DB_QUERY - id + idupdate username domain doc @@ -3100,7 +3102,7 @@ pua DB_QUERY - id + idupdate pres_uri pres_id event @@ -3189,7 +3191,7 @@ registrant DB_QUERY - id + idupdate registrar proxy aor @@ -3251,7 +3253,7 @@ aliases DB_QUERY - id + idupdate username domain contact @@ -3331,7 +3333,7 @@ rls_presentity DB_QUERY - id + idupdate rlsubs_did resource_uri content_type @@ -3387,7 +3389,7 @@ rls_watchers DB_QUERY - id + idupdate presentity_uri to_user to_domain @@ -3479,7 +3481,7 @@ rtpproxy_sockets DB_QUERY - id + idupdate rtpproxy_sock set_id @@ -3517,7 +3519,7 @@ sip_trace DB_QUERY - id + idupdate time_stamp callid traced_user @@ -3579,7 +3581,7 @@ speed_dial DB_QUERY - id + idupdate username domain sd_username @@ -3654,7 +3656,7 @@ uri DB_QUERY - id + idupdate username domain uri_user @@ -3698,7 +3700,7 @@ userblacklist DB_QUERY - id + idupdate username domain prefix @@ -3742,7 +3744,7 @@ globalblacklist DB_QUERY - id + idupdate prefix whitelist description @@ -3783,7 +3785,7 @@ location DB_QUERY - id + idupdate username domain contact diff --git a/scripts/pi_http/presence-mod b/scripts/pi_http/presence-mod index 2838d5cb9e6..d535b78d927 100644 --- a/scripts/pi_http/presence-mod +++ b/scripts/pi_http/presence-mod @@ -4,7 +4,7 @@ presentity DB_QUERY - id + idupdate username domain event @@ -63,7 +63,7 @@ active_watchers DB_QUERY - id + idupdate presentity_uri watcher_username watcher_domain @@ -155,7 +155,7 @@ watchers DB_QUERY - id + idupdate presentity_uri watcher_username watcher_domain @@ -208,7 +208,7 @@ xcap DB_QUERY - id + idupdate username domain doc @@ -264,7 +264,7 @@ pua DB_QUERY - id + idupdate pres_uri pres_id event diff --git a/scripts/pi_http/registrant-mod b/scripts/pi_http/registrant-mod index 7aa72236778..5d226cf6108 100644 --- a/scripts/pi_http/registrant-mod +++ b/scripts/pi_http/registrant-mod @@ -4,7 +4,7 @@ registrant DB_QUERY - id + idupdate registrar proxy aor diff --git a/scripts/pi_http/registrar-mod b/scripts/pi_http/registrar-mod index 6e551e95a5d..c889d96bb68 100644 --- a/scripts/pi_http/registrar-mod +++ b/scripts/pi_http/registrar-mod @@ -4,7 +4,7 @@ aliases DB_QUERY - id + idupdate username domain contact diff --git a/scripts/pi_http/rls-mod b/scripts/pi_http/rls-mod index fde473f6924..2a6c5f23267 100644 --- a/scripts/pi_http/rls-mod +++ b/scripts/pi_http/rls-mod @@ -4,7 +4,7 @@ rls_presentity DB_QUERY - id + idupdate rlsubs_did resource_uri content_type @@ -60,7 +60,7 @@ rls_watchers DB_QUERY - id + idupdate presentity_uri to_user to_domain diff --git a/scripts/pi_http/rtpproxy-mod b/scripts/pi_http/rtpproxy-mod index 53c3be86b84..592fd09ec26 100644 --- a/scripts/pi_http/rtpproxy-mod +++ b/scripts/pi_http/rtpproxy-mod @@ -4,7 +4,7 @@ rtpproxy_sockets DB_QUERY - id + idupdate rtpproxy_sock set_id diff --git a/scripts/pi_http/siptrace-mod b/scripts/pi_http/siptrace-mod index 2ce3378af14..f58a03be046 100644 --- a/scripts/pi_http/siptrace-mod +++ b/scripts/pi_http/siptrace-mod @@ -4,7 +4,7 @@ sip_trace DB_QUERY - id + idupdate time_stamp callid traced_user diff --git a/scripts/pi_http/speeddial-mod b/scripts/pi_http/speeddial-mod index 81d395445c3..34a45d3719c 100644 --- a/scripts/pi_http/speeddial-mod +++ b/scripts/pi_http/speeddial-mod @@ -4,7 +4,7 @@ speed_dial DB_QUERY - id + idupdate username domain sd_username diff --git a/scripts/pi_http/uri_db-mod b/scripts/pi_http/uri_db-mod index b85325792e2..f9449d3d58e 100644 --- a/scripts/pi_http/uri_db-mod +++ b/scripts/pi_http/uri_db-mod @@ -4,7 +4,7 @@ uri DB_QUERY - id + idupdate username domain uri_user diff --git a/scripts/pi_http/userblacklist-mod b/scripts/pi_http/userblacklist-mod index 244a0acb447..d97a1c9f460 100644 --- a/scripts/pi_http/userblacklist-mod +++ b/scripts/pi_http/userblacklist-mod @@ -4,7 +4,7 @@ userblacklist DB_QUERY - id + idupdate username domain prefix @@ -48,7 +48,7 @@ globalblacklist DB_QUERY - id + idupdate prefix whitelist description diff --git a/scripts/pi_http/usrloc-mod b/scripts/pi_http/usrloc-mod index 1344a553a51..9ea3e6bf788 100644 --- a/scripts/pi_http/usrloc-mod +++ b/scripts/pi_http/usrloc-mod @@ -4,7 +4,7 @@ location DB_QUERY - id + idupdate username domain contact From 096160848f7fb3afc6025a5ccf0e2f0cc718ca29 Mon Sep 17 00:00:00 2001 From: Ovidiu Sas Date: Tue, 25 Mar 2014 19:38:18 -0400 Subject: [PATCH 21/44] pi_http: fix html output (cherry picked from commit a1f454bcc6e9eb45249eafe1f49726121b792a67) --- modules/pi_http/http_fnc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/pi_http/http_fnc.c b/modules/pi_http/http_fnc.c index 73fe6d9336e..80e19b8c10d 100644 --- a/modules/pi_http/http_fnc.c +++ b/modules/pi_http/http_fnc.c @@ -3141,7 +3141,7 @@ int ph_run_pi_cmd(int mod, int cmd, command->q_keys[j]->len, command->q_keys[j]->s); } - PI_HTTP_COPY(p,PI_HTTP_HREF_3); + if(link_on) PI_HTTP_COPY(p,PI_HTTP_HREF_3); PI_HTTP_COPY(p,PI_HTTP_Response_Menu_Cmd_td_4d); } PI_HTTP_COPY(p,PI_HTTP_Response_Menu_Cmd_tr_2); From 23dd8e710b4eec26bdc4803bf20cf85daf8bbd88 Mon Sep 17 00:00:00 2001 From: Ovidiu Sas Date: Tue, 25 Mar 2014 21:07:55 -0400 Subject: [PATCH 22/44] pi_http: fix HTTP escaping (cherry picked from commit 980dfc853c411730e07db74242188bc6190aafdf) --- modules/pi_http/http_fnc.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/modules/pi_http/http_fnc.c b/modules/pi_http/http_fnc.c index 80e19b8c10d..aedd7cc6e88 100644 --- a/modules/pi_http/http_fnc.c +++ b/modules/pi_http/http_fnc.c @@ -261,31 +261,31 @@ do{ \ case '<': \ (temp_holder).len = (temp_counter) - (temp_holder).len; \ PI_HTTP_COPY_2(p, (temp_holder), PI_HTTP_ESC_LT); \ - (temp_holder).s += (temp_counter) + 1; \ + (temp_holder).s = (str).s + (temp_counter) + 1; \ (temp_holder).len = (temp_counter) + 1; \ break; \ case '>': \ (temp_holder).len = (temp_counter) - (temp_holder).len; \ PI_HTTP_COPY_2(p, (temp_holder), PI_HTTP_ESC_GT); \ - (temp_holder).s += (temp_counter) + 1; \ + (temp_holder).s = (str).s + (temp_counter) + 1; \ (temp_holder).len = (temp_counter) + 1; \ break; \ case '&': \ (temp_holder).len = (temp_counter) - (temp_holder).len; \ PI_HTTP_COPY_2(p, (temp_holder), PI_HTTP_ESC_AMP); \ - (temp_holder).s += (temp_counter) + 1; \ + (temp_holder).s = (str).s + (temp_counter) + 1; \ (temp_holder).len = (temp_counter) + 1; \ break; \ case '"': \ (temp_holder).len = (temp_counter) - (temp_holder).len; \ PI_HTTP_COPY_2(p, (temp_holder), PI_HTTP_ESC_QUOT); \ - (temp_holder).s += (temp_counter) + 1; \ + (temp_holder).s = (str).s + (temp_counter) + 1; \ (temp_holder).len = (temp_counter) + 1; \ break; \ case '\'': \ (temp_holder).len = (temp_counter) - (temp_holder).len; \ PI_HTTP_COPY_2(p, (temp_holder), PI_HTTP_ESC_SQUOT); \ - (temp_holder).s += (temp_counter) + 1; \ + (temp_holder).s = (str).s + (temp_counter) + 1; \ (temp_holder).len = (temp_counter) + 1; \ break; \ } \ From 5cb96e4e966292050a1463e4ac1d6ee8d6308878 Mon Sep 17 00:00:00 2001 From: Bogdan-Andrei Iancu Date: Wed, 26 Mar 2014 19:52:26 +0200 Subject: [PATCH 23/44] Fixed detection of the module functions used in script - we need to look also into the logical expressions (like IF and WHILE conditions) Credits for reportind and helping with the troubleshooting go to Justin Zondagh (cherry picked from commit ab22467a2ed8af97ba89ce53144d4414dbcd5a52) --- route_struct.c | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/route_struct.c b/route_struct.c index e71406fc8a8..d3a5c5fbed3 100644 --- a/route_struct.c +++ b/route_struct.c @@ -635,6 +635,22 @@ void print_actions(struct action* a) } +static int is_mod_func_in_expr(struct expr *e, char *name, int param_no) +{ + if (e->type==ELEM_T) { + if (e->left.type==ACTION_O) + if (is_mod_func_used((struct action*)e->right.v.data,name,param_no)==1) + return 1; + } else if (e->type==EXP_T) { + if (e->left.v.expr && is_mod_func_in_expr(e->left.v.expr,name,param_no)==1) + return 1; + if (e->right.v.expr && is_mod_func_in_expr(e->right.v.expr,name,param_no)==1) + return 1; + } + return 0; +} + + int is_mod_func_used(struct action *a, char *name, int param_no) { cmd_export_t *cmd; @@ -642,11 +658,16 @@ int is_mod_func_used(struct action *a, char *name, int param_no) if (a->type==MODULE_T) { /* first param is the name of the function */ cmd = (cmd_export_t*)a->elem[0].u.data; + LM_DBG("checking %s against %s\n",name,cmd->name); if (strcasecmp(cmd->name, name)==0 && (param_no==cmd->param_no || param_no==-1) ) return 1; } + if (a->type==IF_T || a->type==WHILE_T) + if (is_mod_func_in_expr((struct expr*)a->elem[0].u.data,name,param_no)==1) + return 1; + /* follow all leads from actions than may have sub-blocks of instructions */ if (a->elem[0].type==ACTIONS_ST) if (is_mod_func_used((struct action*)a->elem[0].u.data,name,param_no)==1) From fad349183d6271b8c6e7a40869b42383fe784fd9 Mon Sep 17 00:00:00 2001 From: Walter Doekes Date: Wed, 12 Mar 2014 10:26:54 +0100 Subject: [PATCH 24/44] presence_dialoginfo: Fix bounds checking by using a helper function. Reported by: dsandras > About the bound checking error, the code was cut&pasted from another > place in the same file where the same error is still present: > ... Also I replaced a heap str with a stack one in build_dialoginfo. This one wasn't freed either unless an error condition was hit. (cherry picked from commit 6d058ec495c2faa015b24f412e2fe1b55526657e) --- modules/presence_dialoginfo/notify_body.c | 75 +++++++++-------------- 1 file changed, 28 insertions(+), 47 deletions(-) diff --git a/modules/presence_dialoginfo/notify_body.c b/modules/presence_dialoginfo/notify_body.c index 15d065ca56f..8e1e92e5349 100644 --- a/modules/presence_dialoginfo/notify_body.c +++ b/modules/presence_dialoginfo/notify_body.c @@ -57,22 +57,28 @@ void free_xml_body(char* body) xmlFree(body); } +/* Joins user and domain into "sip:USER@DOMAIN". + * dst must fit at least MAX_URI_SIZE+1 characters! */ +static inline int sipuri_cat(char* dst, const str* user, const str* domain) { + if ((4 + user->len + 1 + domain->len) > MAX_URI_SIZE) { + LM_ERR("entity URI too long, maximum=%d\n", MAX_URI_SIZE); + return -1; + } + memcpy(dst, "sip:", 4); + memcpy(dst + 4, user->s, user->len); + dst[user->len + 4] = '@'; + memcpy(dst + user->len + 5, domain->s, domain->len); + dst[user->len + 5 + domain->len] = '\0'; + return 0; +} str* dlginfo_agg_nbody(str* pres_user, str* pres_domain, str** body_array, int n, int off_index) { str* n_body= NULL; char pres_uri_char[MAX_URI_SIZE+1]; - if ((pres_user->len + pres_domain->len + 5) > MAX_URI_SIZE) { - LM_ERR("entity URI too long, maximum=%d\n", MAX_URI_SIZE); + if (sipuri_cat(pres_uri_char, pres_user, pres_domain) != 0) return NULL; - } - memcpy(pres_uri_char, "sip:", 4); - memcpy(pres_uri_char + 4, pres_user->s, pres_user->len); - pres_uri_char[pres_user->len + 4] = '@'; - memcpy(pres_uri_char + pres_user->len + 5, pres_domain->s, pres_domain->len); - pres_uri_char[pres_user->len + 5 + pres_domain->len] = '\0'; - LM_DBG("[pres_uri] %s (%d), [n]=%d\n", pres_uri_char, pres_user->len + 5 + pres_domain->len, n); @@ -117,7 +123,7 @@ str* agregate_xmls(str* pres_user, str* pres_domain, str** body_array, int n, in int winner_priority = -1, priority ; xmlNodePtr winner_dialog_node = NULL ; str *body= NULL; - char buf[MAX_URI_SIZE+1]; + char buf[MAX_URI_SIZE+1]; LM_DBG("[pres_user]=%.*s [pres_domain]= %.*s, [n]=%d\n", pres_user->len, pres_user->s, pres_domain->len, pres_domain->s, n); @@ -163,15 +169,8 @@ str* agregate_xmls(str* pres_user, str* pres_domain, str** body_array, int n, in /* LM_DBG("number of bodies in total [n]=%d, number of useful bodies [j]=%d\n", n, j ); */ /* create the new NOTIFY body */ - if ( (pres_user->len + pres_domain->len + 1) > MAX_URI_SIZE) { - LM_ERR("entity URI too long, maximum=%d\n", MAX_URI_SIZE); - return NULL; - } - memcpy(buf, "sip:", 4); - memcpy(buf+4, pres_user->s, pres_user->len); - buf[pres_user->len+4] = '@'; - memcpy(buf + pres_user->len + 5, pres_domain->s, pres_domain->len); - buf[pres_user->len + 5 + pres_domain->len]= '\0'; + if (sipuri_cat(buf, pres_user, pres_domain) != 0) + goto error; doc = xmlNewDoc(BAD_CAST "1.0"); if(doc==0) @@ -360,37 +359,21 @@ str* build_dialoginfo(str* pres_user, str* pres_domain) xmlNodePtr state_node = NULL; str *body= NULL; - str *pres_uri= NULL; + str pres_uri; char buf[MAX_URI_SIZE+1]; - if ( (pres_user->len + pres_domain->len + 1) > MAX_URI_SIZE) { - LM_ERR("entity URI too long, maximum=%d\n", MAX_URI_SIZE); + if (sipuri_cat(buf, pres_user, pres_domain) != 0) return NULL; - } - memcpy(buf, "sip:", 4); - memcpy(buf+4, pres_user->s, pres_user->len); - buf[pres_user->len+4] = '@'; - memcpy(buf + pres_user->len + 5, pres_domain->s, pres_domain->len); - buf[pres_user->len + 5 + pres_domain->len]= '\0'; - - pres_uri = (str*)pkg_malloc(sizeof(str)); - if(pres_uri == NULL) - { - LM_ERR("while allocating memory\n"); - return NULL; - } - memset(pres_uri, 0, sizeof(str)); - pres_uri->s = buf; - pres_uri->len = pres_user->len + 5 + pres_domain->len; + pres_uri.s = buf; + pres_uri.len = 4 + pres_user->len + 1 + pres_domain->len; + LM_DBG("[pres_uri] %.*s\n", pres_uri.len, pres_uri.s); - LM_DBG("[pres_uri] %.*s\n", pres_uri->len, pres_uri->s); - - if ( pres_contains_presence(pres_uri)<0 ) { + if (pres_contains_presence(&pres_uri) < 0) { LM_DBG("No record exists in hash_table\n"); goto error; } - /* create the Publish body */ + /* create the Publish body */ doc = xmlNewDoc(BAD_CAST "1.0"); if(doc==0) goto error; @@ -415,8 +398,10 @@ str* build_dialoginfo(str* pres_user, str* pres_domain) LM_ERR("while adding child [dialog]\n"); goto error; } + + /* reuse buf for user-part only */ memcpy(buf, pres_user->s, pres_user->len); - buf[pres_user->len]= '\0'; + buf[pres_user->len] = '\0'; xmlNewProp(dialog_node, BAD_CAST "id", BAD_CAST buf); @@ -444,10 +429,6 @@ str* build_dialoginfo(str* pres_user, str* pres_domain) xmlCleanupParser(); return body; error: - if ( pres_uri ) - { - pkg_free(pres_uri); - } if(body) { if(body->s) From 5c82191fb401b80ccee2ea576fc6f8179d0f9e5b Mon Sep 17 00:00:00 2001 From: Liviu Chircu Date: Thu, 27 Mar 2014 13:58:19 +0200 Subject: [PATCH 25/44] dispatcher init: initialize the old_data pointer * otherwise, the code will dereference a random pointer (cherry picked from commit dbf1b4bfe98e0d18debaca9c33fc0adc2a1809fe) --- modules/dispatcher/dispatch.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/modules/dispatcher/dispatch.c b/modules/dispatcher/dispatch.c index 0deb6d32cd9..d6c2e3b4faa 100644 --- a/modules/dispatcher/dispatch.c +++ b/modules/dispatcher/dispatch.c @@ -96,6 +96,8 @@ int init_ds_data(void) return -1; } + *ds_data = NULL; + /* create & init lock */ if ((ds_lock = lock_init_rw()) == NULL) { LM_CRIT("failed to init reader/writer lock\n"); From 5663e4129bb2a6aced49715a57d50406e0968a6f Mon Sep 17 00:00:00 2001 From: Liviu Chircu Date: Thu, 27 Mar 2014 16:30:24 +0200 Subject: [PATCH 26/44] hp malloc: fix shm statistics * processes now update fragment statistics for each bucket * the MI workers iterate and aggregate all memory information * the built-in maximum sampling rate is 200ms - repeating a fetch in < 200ms will return the same results * this patch also corrects a rare deadlock in hp_realloc - hp_realloc "growth" may deadlock with hp_malloc "shrink" - the best solution is to drop the "growth" realloc operation - this also merges well with the allocator fragmentation requirements (cherry picked from commit 9ad2947eed7add4510b1fa388004524cc50d5bab) --- mem/hp_malloc.c | 727 ++++++++++++------------------------------ mem/hp_malloc.h | 160 ++++------ mem/hp_malloc_stats.c | 144 +++++++++ mem/hp_malloc_stats.h | 49 +++ mem/shm_mem.c | 10 +- 5 files changed, 466 insertions(+), 624 deletions(-) create mode 100644 mem/hp_malloc_stats.c create mode 100644 mem/hp_malloc_stats.h diff --git a/mem/hp_malloc.c b/mem/hp_malloc.c index 8be681ca8cd..2ebac8c3218 100644 --- a/mem/hp_malloc.c +++ b/mem/hp_malloc.c @@ -31,22 +31,17 @@ #include #include -#include "hp_malloc.h" +#include "sys/time.h" + #include "../dprint.h" #include "../globals.h" #include "../statistics.h" #include "../locking.h" -extern unsigned long *mem_hash_usage; - - -#define max(a,b) ( (a)>(b)?(a):(b)) - -#define FRAG_NEXT(f) \ - ((struct hp_frag*)((char*)(f)+sizeof(struct hp_frag)+(f)->size )) - -#define FRAG_OVERHEAD (sizeof(struct hp_frag)) +#include "hp_malloc.h" +#include "hp_malloc_stats.h" +extern unsigned long *mem_hash_usage; /* ROUNDTO= 2^k so the following works */ #define ROUNDTO_MASK (~((unsigned long)ROUNDTO-1)) @@ -62,33 +57,57 @@ extern unsigned long *mem_hash_usage; #define HP_MALLOC_DEFRAG_LIMIT (HP_MALLOC_LARGE_LIMIT * 5) #define HP_MALLOC_DEFRAG_PERCENT 5 -/* computes hash number for big buckets*/ +#define can_split_frag(frag, wanted_size) \ + ((frag)->size - wanted_size > (FRAG_OVERHEAD + MIN_FRAG_SIZE)) + +/* + * tries to split a frag, in an attempt to optimize memory usage + * + * Note: the memory lock on "hash" must be acquired when this is called + */ +#define hp_frag_split(blk, frag, sz, hash) \ + do { \ + if (can_split_frag(frag, sz)) { \ + blk->free_hash[PEEK_HASH_RR(blk, frag->size)].total_no--; \ + blk->free_hash[PEEK_HASH_RR(blk, sz)].total_no++; \ + __hp_frag_split(blk, frag, sz, hash); \ + } \ + } while (0) + +/* tries to split a frag, in an attempt to optimize memory usage */ +#define hp_frag_split_unsafe(blk, frag, sz) \ + do { \ + if ((frag)->size - (sz) > (FRAG_OVERHEAD + MIN_FRAG_SIZE)) { \ + blk->free_hash[PEEK_HASH_RR(blk, frag->size)].total_no--; \ + blk->free_hash[PEEK_HASH_RR(blk, sz)].total_no++; \ + __hp_frag_split_unsafe(blk, frag, sz); \ + } \ + } while (0) + +/* computes hash number for big buckets */ inline static unsigned long big_hash_idx(unsigned long s) { unsigned long idx; + /* s is rounded => s = k*2^n (ROUNDTO=2^n) * index= i such that 2^i > s >= 2^(i-1) * * => index = number of the first non null bit in s*/ - idx=sizeof(long)*8-1; - for (; !(s&(1UL<<(sizeof(long)*8-1))) ; s<<=1, idx--); - return idx; -} + idx = 8 * sizeof(long) - 1; + for (; !(s & (1UL << (8 * sizeof(long) - 1))); s <<= 1, idx--) + ; -#ifdef DBG_F_MALLOC -#define ST_CHECK_PATTERN 0xf0f0f0f0 -#define END_CHECK_PATTERN1 0xc0c0c0c0 -#define END_CHECK_PATTERN2 0xabcdefed -#endif + return idx; +} -static inline void hp_insert_free(struct hp_block* qm, struct hp_frag* frag) +static inline void hp_frag_attach(struct hp_block *qm, struct hp_frag *frag) { - struct hp_frag** f; + struct hp_frag **f; unsigned int hash; - hash=GET_HASH_RR(qm, frag->size); - f=&(qm->free_hash[hash].first); + hash = GET_HASH_RR(qm, frag->size); + f = &(qm->free_hash[hash].first); if (frag->size > HP_MALLOC_OPTIMIZE){ /* because of '<=' in GET_HASH, purpose --andrei ) */ @@ -100,142 +119,76 @@ static inline void hp_insert_free(struct hp_block* qm, struct hp_frag* frag) /*insert it here*/ frag->prev = f; frag->u.nxt_free=*f; - if( *f ) + if (*f) (*f)->prev = &(frag->u.nxt_free); - *f=frag; + *f = frag; - #if defined(DBG_F_MALLOC) || defined(STATISTICS) qm->free_hash[hash].no++; - #endif } -static inline void hp_remove_free(struct hp_block* qm, struct hp_frag* n) +static inline void hp_frag_detach(struct hp_block *qm, struct hp_frag *n) { - struct hp_frag** pf; - int hash; + struct hp_frag **pf; + unsigned int hash; + + hash = GET_HASH_RR(qm, n->size); pf = n->prev; - hash = GET_HASH( n->size ); /* detach */ - *pf=n->u.nxt_free; + *pf = n->u.nxt_free; - if( n->u.nxt_free ) + if (n->u.nxt_free) n->u.nxt_free->prev = pf; n->prev = NULL; - #if defined(DBG_F_MALLOC) || defined(STATISTICS) qm->free_hash[hash].no--; - #endif }; - - -void hp_split_frag_unsafe(struct hp_block* qm, struct hp_frag* frag, - unsigned long size) +void __hp_frag_split_unsafe(struct hp_block *qm, struct hp_frag *frag, + unsigned long size) { unsigned long rest; - struct hp_frag* n; + struct hp_frag *n; rest = frag->size - size; + frag->size = size; - #ifdef MEM_FRAG_AVOIDANCE - if ((rest> (FRAG_OVERHEAD+HP_MALLOC_OPTIMIZE))|| - (rest>=(FRAG_OVERHEAD+size))){ /* the residue fragm. is big enough*/ - #else - if (rest>(FRAG_OVERHEAD+MIN_FRAG_SIZE)){ - #endif - frag->size=size; - /*split the fragment*/ - n=FRAG_NEXT(frag); - n->size=rest-FRAG_OVERHEAD; - - /* - * The real used memory does not increase, as the frag memory is not - * freed from real_used. On the other hand, the used size should - * decrease, because the new fragment is not "useful data" - razvanc - - #if defined(DBG_F_MALLOC) || defined(STATISTICS) - qm->real_used+=FRAG_OVERHEAD; - #endif - - */ - - #ifdef DBG_F_MALLOC - /* frag created by malloc, mark it*/ - n->file=file; - n->func="frag. from hp_malloc"; - n->line=line; - n->check=ST_CHECK_PATTERN; - #endif - - hp_insert_free(qm, n); - } + /* split the fragment */ + n = FRAG_NEXT(frag); + n->size = rest - FRAG_OVERHEAD; - /* we cannot split this fragment any more => alloc all of it */ + qm->free_hash[PEEK_HASH_RR(qm, n->size)].total_no++; + hp_frag_attach(qm, n); } - /* size should be already rounded-up */ -static inline -#ifdef DBG_F_MALLOC -void hp_split_frag(struct hp_block* qm, struct hp_frag* frag, - unsigned long size, - const char* file, const char* func, unsigned int line) -#else -void hp_split_frag(struct hp_block* qm, struct hp_frag* frag, - unsigned long size, unsigned int old_hash) -#endif + /* size should already be rounded-up */ +void __hp_frag_split(struct hp_block *qm, struct hp_frag *frag, + unsigned long size, unsigned int old_hash) { unsigned long rest, hash; - struct hp_frag* n; + struct hp_frag *n; rest = frag->size - size; + frag->size = size; - #ifdef MEM_FRAG_AVOIDANCE - if ((rest> (FRAG_OVERHEAD+HP_MALLOC_OPTIMIZE))|| - (rest>=(FRAG_OVERHEAD+size))){ /* the residue fragm. is big enough*/ - #else - if (rest>(FRAG_OVERHEAD+MIN_FRAG_SIZE)){ - #endif - frag->size=size; - /*split the fragment*/ - n=FRAG_NEXT(frag); - n->size=rest-FRAG_OVERHEAD; - - /* - * The real used memory does not increase, as the frag memory is not - * freed from real_used. On the other hand, the used size should - * decrease, because the new fragment is not "useful data" - razvanc - - #if defined(DBG_F_MALLOC) || defined(STATISTICS) - qm->real_used+=FRAG_OVERHEAD; - #endif - - */ - - #ifdef DBG_F_MALLOC - /* frag created by malloc, mark it*/ - n->file=file; - n->func="frag. from hp_malloc"; - n->line=line; - n->check=ST_CHECK_PATTERN; - #endif - - /* insert the newly obtained hp_frag in its free list */ - hash = PEEK_HASH_RR(qm, n->size); - - if (hash != old_hash) - SHM_LOCK(hash); + /* split the fragment */ + n = FRAG_NEXT(frag); + n->size = rest - FRAG_OVERHEAD; - hp_insert_free(qm, n); + /* insert the newly obtained hp_frag in its free list */ + hash = PEEK_HASH_RR(qm, n->size); - if (hash != old_hash) - SHM_UNLOCK(hash); - } + if (hash != old_hash) + SHM_LOCK(hash); + + hp_frag_attach(qm, n); + qm->free_hash[hash].total_no++; - /* we cannot split this fragment any more => alloc all of it */ + if (hash != old_hash) + SHM_UNLOCK(hash); } /** @@ -351,7 +304,6 @@ int hp_mem_warming(struct hp_block *qm) mem_warming_pattern_file); abort(); } - if (i == 0) sf->fragments = 0; @@ -402,17 +354,18 @@ int hp_mem_warming(struct hp_block *qm) /* create free fragments worth of 'bucket_mem' memory */ while (bucket_mem >= FRAG_OVERHEAD + current_frag_size) { - hp_remove_free(qm, big_frag); + hp_frag_detach(qm, big_frag); /* trim-insert operation on the big free fragment */ - hp_split_frag_unsafe(qm, big_frag, current_frag_size); + hp_frag_split_unsafe(qm, big_frag, current_frag_size); /* * "big_frag" now points to a smaller, free and detached frag. * * With optimized buckets, inserts will be automagically - * balanced within their dedicated hashes */ - hp_insert_free(qm, big_frag); + * balanced within their dedicated hashes + */ + hp_frag_attach(qm, big_frag); big_frag = FRAG_NEXT(big_frag); @@ -437,73 +390,82 @@ int hp_mem_warming(struct hp_block *qm) return rc; } -/* init malloc and return a hp_block*/ -struct hp_block* hp_malloc_init(char* address, unsigned long size) +/* initialise the allocator and return its main block */ +struct hp_block *hp_malloc_init(char *address, unsigned long size) { - char* start; - char* end; - struct hp_block* qm; + char *start; + char *end; + struct hp_block *qm; unsigned long init_overhead; /* make address and size multiple of 8*/ - start=(char*)ROUNDUP((unsigned long) address); - LM_DBG("HP_OPTIMIZE=%lu, /ROUNDTO=%lu\n", + start = (char *)ROUNDUP((unsigned long) address); + LM_DBG("HP_OPTIMIZE=%lu, ROUNDTO=%lu\n", HP_MALLOC_OPTIMIZE, HP_MALLOC_OPTIMIZE/ROUNDTO); - LM_DBG("HP_HASH_SIZE=%lu, HP_EXTRA_HASH_SIZE=%lu, hp_block size=%lu\n", - HP_HASH_SIZE, HP_EXTRA_HASH_SIZE, (long)sizeof(struct hp_block)); + LM_DBG("HP_HASH_SIZE=%lu, HP_EXTRA_HASH_SIZE=%lu, hp_block size=%zu\n", + HP_HASH_SIZE, HP_EXTRA_HASH_SIZE, sizeof(struct hp_block)); LM_DBG("params (%p, %lu), start=%p\n", address, size, start); - if (size<(unsigned long)(start-address)) return 0; - size-=(start-address); - if (size <(MIN_FRAG_SIZE+FRAG_OVERHEAD)) return 0; - size=ROUNDDOWN(size); + if (size < (unsigned long)(start - address)) + return NULL; + + size -= start - address; + + if (size < (MIN_FRAG_SIZE+FRAG_OVERHEAD)) + return NULL; - init_overhead=(ROUNDUP(sizeof(struct hp_block))+ 2 * FRAG_OVERHEAD); + size = ROUNDDOWN(size); + init_overhead = (ROUNDUP(sizeof(struct hp_block)) + 2 * FRAG_OVERHEAD); if (size < init_overhead) { LM_ERR("not enough memory for the basic structures! " "need %lu bytes\n", init_overhead); /* not enough mem to create our control structures !!!*/ - return 0; + return NULL; } - end=start+size; - qm=(struct hp_block*)start; - memset(qm, 0, sizeof(struct hp_block)); - qm->size=size; - #if defined(DBG_F_MALLOC) || defined(STATISTICS) + end = start + size; + qm = (struct hp_block *)start; + memset(qm, 0, sizeof(struct hp_block)); + qm->size = size; - qm->used=size-init_overhead; - qm->real_used=size; - qm->max_real_used=init_overhead; - #endif + qm->used = size - init_overhead; + qm->real_used = size; + qm->max_real_used = init_overhead; + gettimeofday(&qm->last_updated, NULL); - qm->first_frag=(struct hp_frag*)(start+ROUNDUP(sizeof(struct hp_block))); - qm->last_frag=(struct hp_frag*)(end-sizeof(struct hp_frag)); + qm->first_frag = (struct hp_frag *)(start + ROUNDUP(sizeof(struct hp_block))); + qm->last_frag = (struct hp_frag *)(end - sizeof(struct hp_frag)); /* init initial fragment*/ - qm->first_frag->size=size-init_overhead; - qm->last_frag->size=0; - - qm->last_frag->prev=NULL; - qm->first_frag->prev=NULL; + qm->first_frag->size = size - init_overhead; + qm->last_frag->size = 0; - #ifdef DBG_F_MALLOC - qm->first_frag->check=ST_CHECK_PATTERN; - qm->last_frag->check=END_CHECK_PATTERN1; - #endif + qm->last_frag->prev = NULL; + qm->first_frag->prev = NULL; /* link initial fragment into the free list*/ qm->large_space = 0; qm->large_limit = qm->size / 100 * HP_MALLOC_DEFRAG_PERCENT; - if( qm->large_limit < HP_MALLOC_DEFRAG_LIMIT ) + if (qm->large_limit < HP_MALLOC_DEFRAG_LIMIT) qm->large_limit = HP_MALLOC_DEFRAG_LIMIT; - hp_insert_free(qm, qm->first_frag); + qm->free_hash[PEEK_HASH_RR(qm, qm->first_frag->size)].total_no++; + hp_frag_attach(qm, qm->first_frag); + hp_stats_lock = hp_malloc_unsafe(qm, sizeof *hp_stats_lock); + if (!hp_stats_lock) { + LM_ERR("failed to alloc hp statistics lock\n"); + return NULL; + } + + if (!lock_init(hp_stats_lock)) { + LM_CRIT("could not initialize hp statistics lock\n"); + return NULL; + } return qm; } @@ -513,11 +475,6 @@ void* hp_malloc_unsafe(struct hp_block* qm, unsigned long size) struct hp_frag* frag; unsigned int hash; - #ifdef DBG_F_MALLOC - LM_DBG("params (%p, %lu), called from %s: %s(%d)\n", qm, size, file, func, - line); - #endif - /*size must be a multiple of 8*/ size=ROUNDUP(size); @@ -536,46 +493,26 @@ void* hp_malloc_unsafe(struct hp_block* qm, unsigned long size) found: /* we found it!*/ - - hp_remove_free(qm,frag); - + + hp_frag_detach(qm, frag); + /*see if we'll use full frag, or we'll split it in 2*/ - - #ifdef DBG_F_MALLOC - hp_split_frag_unsafe(qm, frag, size, file, func, line); - - frag->file=file; - frag->func=func; - frag->line=line; - frag->check=ST_CHECK_PATTERN; - LM_DBG("params(%p, %lu), returns address %p \n", qm, size, - (char*)frag+sizeof(struct hp_frag)); - #else - hp_split_frag_unsafe(qm, frag, size); - #endif + + hp_frag_split_unsafe(qm, frag, size); pkg_threshold_check(); - return (char*)frag+sizeof(struct hp_frag); + + return (char *)frag + sizeof *frag; } -#ifdef DBG_F_MALLOC -void* hp_malloc(struct hp_block* qm, unsigned long size, - const char* file, const char* func, unsigned int line) -#else -void* hp_malloc(struct hp_block* qm, unsigned long size) -#endif +void *hp_malloc(struct hp_block *qm, unsigned long size) { - struct hp_frag* frag; + struct hp_frag *frag; unsigned int init_hash, hash, sec_hash; int i; - #ifdef DBG_F_MALLOC - LM_DBG("params (%p, %lu), called from %s: %s(%d)\n", qm, size, file, func, - line); - #endif - - /*size must be a multiple of 8*/ - size=ROUNDUP(size); + /* size must be a multiple of ROUNDTO */ + size = ROUNDUP(size); /*search for a suitable free frag*/ @@ -616,143 +553,59 @@ void* hp_malloc(struct hp_block* qm, unsigned long size) /* try in a bigger bucket */ } - /* not found, bad! */ - LM_CRIT("not enough memory, please increase the \"-m\" parameter!\n"); + /* out of memory... we have to shut down */ + LM_CRIT("not enough shared memory, please increase the \"-m\" parameter!\n"); abort(); found: - /* we found it!*/ - - hp_remove_free(qm,frag); - - /*see if we'll use full frag, or we'll split it in 2*/ - - hp_split_frag(qm, frag, size, hash); + + hp_frag_detach(qm, frag); + + /* split the fragment if possible */ + hp_frag_split(qm, frag, size, hash); SHM_UNLOCK(hash); /* ignore concurrency issues, simply obtaining an estimate is enough */ mem_hash_usage[init_hash]++; - pkg_threshold_check(); - return (char*)frag+sizeof(struct hp_frag); + return (char *)frag + sizeof *frag; } void hp_free_unsafe(struct hp_block* qm, void* p) { - struct hp_frag* f,*n; - - #ifdef DBG_F_MALLOC - LM_DBG("params(%p, %p), called from %s: %s(%d)\n", qm, p, file, func, line); - if (p>(void*)qm->last_frag || p<(void*)qm->first_frag){ - LM_CRIT("bad pointer %p (out of memory block!) - aborting\n", p); - abort(); - } - #endif - if (p==0) { + struct hp_frag *f; + + if (!p) { LM_WARN("free(0) called\n"); return; } - f=(struct hp_frag*) ((char*)p-sizeof(struct hp_frag)); - - #ifdef DBG_F_MALLOC - LM_DBG("freeing block alloc'ed from %s: %s(%ld)\n", f->file, f->func, - f->line); - f->file=file; - f->func=func; - f->line=line; - #endif - -join: - - if( qm->large_limit < qm->large_space ) - goto no_join; - n = FRAG_NEXT(f); - - if (((char*)n < (char*)qm->last_frag) && n->prev ) - { - - hp_remove_free(qm, n); - /* join */ - f->size += n->size + FRAG_OVERHEAD; - - #if defined(DBG_F_MALLOC) || defined(STATISTICS) - qm->real_used -= FRAG_OVERHEAD; - #endif - - goto join; - } + f = FRAG_OF(p); -no_join: + hp_frag_attach(qm, f); - hp_insert_free(qm, f); pkg_threshold_check(); } -#ifdef DBG_F_MALLOC -void hp_free(struct hp_block* qm, void* p, const char* file, const char* func, - unsigned int line) -#else -void hp_free(struct hp_block* qm, void* p) -#endif +void hp_free(struct hp_block *qm, void *p) { - struct hp_frag* f,*n; + struct hp_frag *f; unsigned int hash; - #ifdef DBG_F_MALLOC - LM_DBG("params(%p, %p), called from %s: %s(%d)\n", qm, p, file, func, line); - if (p>(void*)qm->last_frag || p<(void*)qm->first_frag){ - LM_CRIT("bad pointer %p (out of memory block!) - aborting\n", p); - abort(); - } - #endif - if (p==0) { + if (!p) { LM_WARN("free(0) called\n"); return; } - f=(struct hp_frag*) ((char*)p-sizeof(struct hp_frag)); - hash = PEEK_HASH_RR(qm, f->size); - #ifdef DBG_F_MALLOC - LM_DBG("freeing block alloc'ed from %s: %s(%ld)\n", f->file, f->func, - f->line); - f->file=file; - f->func=func; - f->line=line; - #endif + f = FRAG_OF(p); + hash = PEEK_HASH_RR(qm, f->size); SHM_LOCK(hash); - -join: - if( qm->large_limit < qm->large_space ) - goto no_join; - - n = FRAG_NEXT(f); - - if (((char*)n < (char*)qm->last_frag) && n->prev ) - { - - hp_remove_free(qm, n); - /* join */ - f->size += n->size + FRAG_OVERHEAD; - - #if defined(DBG_F_MALLOC) || defined(STATISTICS) - qm->real_used -= FRAG_OVERHEAD; - #endif - - goto join; - } - -no_join: - - hp_insert_free(qm, f); - + hp_frag_attach(qm, f); SHM_UNLOCK(hash); - - pkg_threshold_check(); } @@ -764,245 +617,106 @@ void* hp_realloc_unsafe(struct hp_block* qm, void* p, unsigned long size) struct hp_frag *n; void *ptr; - #ifdef DBG_F_MALLOC - LM_DBG("params(%p, %p, %lu), called from %s: %s(%d)\n", qm, p, size, - file, func, line); - if ((p)&&(p>(void*)qm->last_frag || p<(void*)qm->first_frag)){ - LM_CRIT("bad pointer %p (out of memory block!) - aborting\n", p); - abort(); - } - #endif if (size==0) { if (p) - #ifdef DBG_F_MALLOC - hp_free(qm, p, file, func, line); - #else hp_free(qm, p); - #endif + pkg_threshold_check(); return 0; } if (p==0) - #ifdef DBG_F_MALLOC - return hp_malloc(qm, size, file, func, line); - #else return hp_malloc(qm, size); - #endif - f=(struct hp_frag*) ((char*)p-sizeof(struct hp_frag)); - #ifdef DBG_F_MALLOC - LM_DBG("realloc'ing frag %p alloc'ed from %s: %s(%ld)\n", - f, f->file, f->func, f->line); - #endif + + f = FRAG_OF(p); + size=ROUNDUP(size); orig_size=f->size; if (f->size > size){ /* shrink */ - #ifdef DBG_F_MALLOC - LM_DBG("shrinking from %lu to %lu\n", f->size, size); - hp_split_frag_unsafe(qm, f, size, file, "frag. from hp_realloc", line); - #else - hp_split_frag_unsafe(qm, f, size); - #endif + hp_frag_split_unsafe(qm, f, size); }else if (f->sizesize, size); - #endif - diff=size-f->size; n=FRAG_NEXT(f); if (((char*)n < (char*)qm->last_frag) && n->prev && ((n->size+FRAG_OVERHEAD)>=diff)){ - hp_remove_free(qm,n); + hp_frag_detach(qm,n); /* join */ f->size += n->size + FRAG_OVERHEAD; - #if defined(DBG_F_MALLOC) || defined(STATISTICS) - qm->real_used -= FRAG_OVERHEAD; - #endif - /* split it if necessary */ - if (f->size > size){ - #ifdef DBG_F_MALLOC - hp_split_frag_unsafe(qm, f, size, file, "fragm. from hp_realloc", - line); - #else - hp_split_frag_unsafe(qm, f, size); - #endif - } + if (f->size > size) + hp_frag_split_unsafe(qm, f, size); }else{ /* could not join => realloc */ - #ifdef DBG_F_MALLOC - ptr=hp_malloc(qm, size, file, func, line); - #else ptr = hp_malloc(qm, size); - #endif if (ptr) { /* copy, need by libssl */ memcpy(ptr, p, orig_size); - #ifdef DBG_F_MALLOC - hp_free(qm, p, file, func, line); - #else hp_free(qm, p); - #endif } p = ptr; } - }else{ - /* do nothing */ - #ifdef DBG_F_MALLOC - LM_DBG("doing nothing, same size: %lu - %lu\n", f->size, size); - #endif } - #ifdef DBG_F_MALLOC - LM_DBG("returning %p\n", p); - #endif pkg_threshold_check(); return p; } -#ifdef DBG_F_MALLOC -void* hp_realloc(struct hp_block* qm, void* p, unsigned long size, - const char* file, const char* func, unsigned int line) -#else -void* hp_realloc(struct hp_block* qm, void* p, unsigned long size) -#endif +void *hp_realloc(struct hp_block *qm, void *p, unsigned long size) { struct hp_frag *f; - unsigned long diff; unsigned long orig_size; - unsigned int hash_next; - struct hp_frag *n; + unsigned int hash; void *ptr; - #ifdef DBG_F_MALLOC - LM_DBG("params(%p, %p, %lu), called from %s: %s(%d)\n", qm, p, size, - file, func, line); - if ((p)&&(p>(void*)qm->last_frag || p<(void*)qm->first_frag)){ - LM_CRIT("bad pointer %p (out of memory block!) - aborting\n", p); - abort(); - } - #endif - if (size==0) { + if (size == 0) { if (p) - #ifdef DBG_F_MALLOC - hp_free(qm, p, file, func, line); - #else hp_free(qm, p); - #endif + pkg_threshold_check(); - return 0; + return NULL; } - if (p==0) - #ifdef DBG_F_MALLOC - return hp_malloc(qm, size, file, func, line); - #else - return hp_malloc(qm, size); - #endif - f=(struct hp_frag*) ((char*)p-sizeof(struct hp_frag)); - #ifdef DBG_F_MALLOC - LM_DBG("realloc'ing frag %p alloc'ed from %s: %s(%ld)\n", - f, f->file, f->func, f->line); - #endif - size=ROUNDUP(size); - - SHM_LOCK(0); - - orig_size=f->size; - if (f->size > size){ - /* shrink */ - #ifdef DBG_F_MALLOC - LM_DBG("shrinking from %lu to %lu\n", f->size, size); - hp_split_frag(qm, f, size, file, "frag. from hp_realloc", line); - #else - hp_split_frag(qm, f, size, 0); - #endif - - }else if (f->sizesize, size); - #endif - - diff=size-f->size; - n=FRAG_NEXT(f); - - hash_next = GET_HASH(n->size); - - if (0 != hash_next) - SHM_LOCK(hash_next); - - if (((char*)n < (char*)qm->last_frag) && n->prev && - ((n->size+FRAG_OVERHEAD)>=diff)){ + if (!p) + return hp_malloc(qm, size); - hp_remove_free(qm,n); + f = FRAG_OF(p); + size = ROUNDUP(size); - if (0 != hash_next) - SHM_UNLOCK(hash_next); + hash = PEEK_HASH_RR(qm, f->size); + SHM_LOCK(hash); - /* join */ - f->size += n->size + FRAG_OVERHEAD; + orig_size = f->size; - #if defined(DBG_F_MALLOC) || defined(STATISTICS) - qm->real_used -= FRAG_OVERHEAD; - #endif + if (f->size > size) { + /* shrink */ + hp_frag_split_unsafe(qm, f, size); + SHM_UNLOCK(hash); - /* split it if necessary */ - if (f->size > size){ - #ifdef DBG_F_MALLOC - hp_split_frag(qm, f, size, file, "fragm. from hp_realloc", - line); - #else - hp_split_frag(qm, f, size, 0); - #endif - } - }else{ - if (0 != hash_next) - SHM_UNLOCK(hash_next); + } else { + SHM_UNLOCK(hash); - /* could not join => realloc */ - #ifdef DBG_F_MALLOC - ptr=hp_malloc(qm, size, file, func, line); - #else - ptr=hp_malloc(qm, size); - #endif - if (ptr) { - /* copy, need by libssl */ - memcpy(ptr, p, orig_size); - #ifdef DBG_F_MALLOC - hp_free_unsafe(qm, p, file, func, line); - #else - hp_free_unsafe(qm, p); - #endif - } - p = ptr; + ptr = hp_malloc(qm, size); + if (ptr) { + /* copy, need by libssl */ + memcpy(ptr, p, orig_size); + hp_free(qm, p); } - }else{ - /* do nothing */ - #ifdef DBG_F_MALLOC - LM_DBG("doing nothing, same size: %lu - %lu\n", f->size, size); - #endif - } - SHM_UNLOCK(0); - - #ifdef DBG_F_MALLOC - LM_DBG("returning %p\n", p); - #endif + p = ptr; + } - pkg_threshold_check(); return p; } -void hp_status(struct hp_block* qm) +void hp_status(struct hp_block *qm) { struct hp_frag* f; unsigned int i,j; @@ -1014,7 +728,8 @@ void hp_status(struct hp_block* qm) if (!qm) return; LM_GEN1(memdump, " heap size= %ld\n", qm->size); -#if defined(DBG_F_MALLOC) || defined(STATISTICS) + +#ifdef STATISTICS LM_GEN1(memdump, " used= %lu, used+overhead=%lu, free=%lu\n", qm->used, qm->real_used, qm->size-qm->used); LM_GEN1(memdump, " max used (+overhead)= %lu\n", qm->max_real_used); @@ -1045,45 +760,25 @@ void hp_status(struct hp_block* qm) -/* fills a malloc info structure with info about the block - * if a parameter is not supported, it will be filled with 0 */ -void hp_info(struct hp_block* qm, struct mem_info* info) +/* fills a malloc info structure with info about the memory block */ +void hp_info(struct hp_block *qm, struct mem_info *info) { - unsigned int r; - long total_frags; -#if !defined(DBG_F_MALLOC) && !defined(STATISTICS) - struct hp_frag* f; -#endif + memset(info, 0, sizeof *info); - memset(info,0, sizeof(*info)); - total_frags=0; - info->total_size=qm->size; - info->min_frag=MIN_FRAG_SIZE; -#if defined(DBG_F_MALLOC) || defined(STATISTICS) - info->free=qm->size-qm->real_used; - info->used=qm->used; - info->real_used=qm->real_used; - for(r=0;rfree_hash[r].no; - } -#else - /* we'll have to compute it all */ - for (r=0; r<=HP_MALLOC_OPTIMIZE/ROUNDTO; r++){ - info->free+=qm->free_hash[r].no*UN_HASH(r); - total_frags+=qm->free_hash[r].no; - } - for(;rfree_hash[r].no; - for(f=qm->free_hash[r].first;f;f=f->u.nxt_free){ - info->free+=f->size; - } - } - info->real_used=info->total_size-info->free; - info->used=0; /* we don't really now */ -#endif - info->total_frags=total_frags; -} + info->total_size = qm->size; + info->min_frag = MIN_FRAG_SIZE; + if (stats_are_expired(qm)) + update_shm_stats(qm); + info->used = qm->used; + info->real_used = qm->real_used; + info->free = qm->size - qm->real_used; + info->total_frags = qm->total_fragments; + + LM_DBG("mem_info: (sz: %ld | us: %ld | rus: %ld | free: %ld | frags: %ld)\n", + info->total_size, info->used, info->real_used, info->free, + info->total_frags); +} #endif diff --git a/mem/hp_malloc.h b/mem/hp_malloc.h index 0a318b34681..191035bddae 100644 --- a/mem/hp_malloc.h +++ b/mem/hp_malloc.h @@ -24,32 +24,31 @@ * 2014-01-19 initial version (liviu) */ -#if !defined(f_malloc_h) && !defined(VQ_MALLOC) && !defined(hp_malloc_h) -#define hp_malloc_h +#if !defined(HP_MALLOC_H) && !defined(f_malloc_h) && !defined(VQ_MALLOC) +#define HP_MALLOC_H + +struct hp_frag; +struct hp_frag_lnk; +struct hp_block; -#include "meminfo.h" #include "../statistics.h" #include "../config.h" #include "../globals.h" -/* defs*/ - -#ifdef DBG_F_MALLOC -#if defined(__CPU_sparc64) || defined(__CPU_sparc) -/* tricky, on sun in 32 bits mode long long must be 64 bits aligned - * but long can be 32 bits aligned => malloc should return long long - * aligned memory */ - #define ROUNDTO sizeof(long long) -#else - #define ROUNDTO sizeof(void*) /* size we round to, must be = 2^n, and - sizeof(hp_frag) must be multiple of ROUNDTO !*/ -#endif -#else /* DBG_F_MALLOC */ - #define ROUNDTO 8UL -#endif +#include "hp_malloc_stats.h" +#include "meminfo.h" + +#define ROUNDTO 8UL #define MIN_FRAG_SIZE ROUNDTO +#define FRAG_NEXT(f) ((struct hp_frag *) \ + ((char *)(f) + sizeof(struct hp_frag) + ((struct hp_frag *)(f))->size)) + +/* get the fragment which corresponds to a pointer */ +#define FRAG_OF(p) \ + ((struct hp_frag *)((char *)(p) - sizeof(struct hp_frag))) +#define FRAG_OVERHEAD (sizeof(struct hp_frag)) #define HP_MALLOC_OPTIMIZE_FACTOR 14UL /*used below */ #define HP_MALLOC_OPTIMIZE (1UL << HP_MALLOC_OPTIMIZE_FACTOR) @@ -133,45 +132,49 @@ unsigned int optimized_put_indexes[HP_HASH_SIZE]; #define UN_HASH(h) (((unsigned long)(h) <= (HP_MALLOC_OPTIMIZE/ROUNDTO)) ?\ (unsigned long)(h)*ROUNDTO: \ 1UL<<((unsigned long)(h)-HP_MALLOC_OPTIMIZE/ROUNDTO+\ - HP_MALLOC_OPTIMIZE_FACTOR-1)\ + HP_MALLOC_OPTIMIZE_FACTOR - 1)\ ) -struct hp_frag{ +struct hp_frag { unsigned long size; - union{ - struct hp_frag* nxt_free; + union { + struct hp_frag *nxt_free; long reserved; - }u; - struct hp_frag ** prev; -#ifdef DBG_F_MALLOC - const char* file; - const char* func; - unsigned long line; - unsigned long check; -#endif + } u; + struct hp_frag **prev; }; -struct hp_frag_lnk{ - /* optimized buckets are further split into X buckets */ +struct hp_frag_lnk { + /* + * optimized buckets are further split into + * "shm_secondary_hash_size" buckets + */ char is_optimized; - struct hp_frag* first; - unsigned long no; + struct hp_frag *first; + + /* + * no - current number of free fragments in this bucket + * total_no - (no + allocated) free fragments in this bucket + */ + long no; + long total_no; }; -struct hp_block{ +struct hp_block { unsigned long size; /* total size */ - unsigned long large_space; - unsigned long large_limit; + unsigned long large_space; + unsigned long large_limit; -#if defined(DBG_F_MALLOC) || defined(STATISTICS) - unsigned long used; /* alloc'ed size*/ - unsigned long real_used; /* used+malloc overhead*/ + unsigned long used; /* alloc'ed size */ + unsigned long real_used; /* used+malloc overhead */ unsigned long max_real_used; -#endif + unsigned long total_fragments; + + struct timeval last_updated; - struct hp_frag* first_frag; - struct hp_frag* last_frag; + struct hp_frag *first_frag; + struct hp_frag *last_frag; /* * the extra hash further divides the heavily used buckets @@ -180,72 +183,23 @@ struct hp_block{ struct hp_frag_lnk free_hash[HP_HASH_SIZE + HP_EXTRA_HASH_SIZE]; }; -struct hp_block* hp_malloc_init(char* address, unsigned long size); +struct hp_block *hp_malloc_init(char *address, unsigned long size); int hp_mem_warming(struct hp_block *fmb); void hp_update_mem_pattern_file(void); -#ifdef DBG_F_MALLOC -void* hp_malloc(struct hp_block*, unsigned long size, - const char* file, const char* func, unsigned int line); -#else -void* hp_malloc(struct hp_block*, unsigned long size); -#endif -void* hp_malloc_unsafe(struct hp_block*, unsigned long size); -void* hp_malloc_raw(struct hp_block*, unsigned long size); - -#ifdef DBG_F_MALLOC -void hp_free(struct hp_block*, void* p, const char* file, const char* func, - unsigned int line); -#else -void hp_free(struct hp_block*, void* p); -#endif +void *hp_malloc(struct hp_block *, unsigned long size); +void *hp_malloc_unsafe(struct hp_block *, unsigned long size); +void *hp_malloc_raw(struct hp_block *, unsigned long size); + +void hp_free(struct hp_block *, void *p); void hp_free_unsafe(struct hp_block *qm, void *p); void hp_free_raw(struct hp_block *qm, void *p); -#ifdef DBG_F_MALLOC -void* hp_realloc(struct hp_block*, void* p, unsigned long size, - const char* file, const char* func, unsigned int line); -#else -void *hp_realloc(struct hp_block*, void* p, unsigned long size); -#endif +void *hp_realloc(struct hp_block *, void *p, unsigned long size); void *hp_realloc_unsafe(struct hp_block *qm, void *p, unsigned long size); void *hp_realloc_raw(struct hp_block *qm, void *p, unsigned long size); -void hp_status(struct hp_block*); -void hp_info(struct hp_block*, struct mem_info*); - - -#ifdef STATISTICS -static inline unsigned long hp_get_size(struct hp_block* qm) -{ - return qm->size; -} -static inline unsigned long hp_get_used(struct hp_block* qm) -{ - return qm->used; -} -static inline unsigned long hp_get_free(struct hp_block* qm) -{ - return qm->size-qm->real_used; -} -static inline unsigned long hp_get_real_used(struct hp_block* qm) -{ - return qm->real_used; -} -static inline unsigned long hp_get_max_real_used(struct hp_block* qm) -{ - return qm->max_real_used; -} -static inline unsigned long hp_get_frags(struct hp_block* qm) -{ - unsigned long frags; - unsigned int r; - for(r=0,frags=0;rfree_hash[r].no; - } - return frags; -} -#endif /*STATISTICS*/ - - -#endif +void hp_status(struct hp_block *); +void hp_info(struct hp_block *, struct mem_info *); + +#endif /* HP_MALLOC_H */ diff --git a/mem/hp_malloc_stats.c b/mem/hp_malloc_stats.c new file mode 100644 index 00000000000..715d0d6cee2 --- /dev/null +++ b/mem/hp_malloc_stats.c @@ -0,0 +1,144 @@ +/** + * the truly parallel memory allocator + * + * Copyright (C) 2014 OpenSIPS Solutions + * + * This file is part of opensips, a free SIP server. + * + * opensips is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version + * + * opensips is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * History: + * -------- + * 2014-01-19 initial version (liviu) + */ + +#include +#include +#include + +#include "sys/time.h" + +#include "../lock_ops.h" +#include "hp_malloc.h" +#include "hp_malloc_stats.h" + +gen_lock_t *hp_stats_lock; + +int stats_are_expired(struct hp_block *qm) +{ + struct timeval now; + + gettimeofday(&now, NULL); + + return (now.tv_sec * 1000000L + now.tv_usec) - + (qm->last_updated.tv_sec * 1000000L + qm->last_updated.tv_usec) + + > SHM_STATS_SAMPLING_PERIOD; +} + +void update_shm_stats(struct hp_block *qm) +{ + struct hp_frag_lnk *bucket, *it; + int i, j, used_mem; + unsigned long in_use_frags; + long size = 0; + + lock_get(hp_stats_lock); + + qm->used = qm->real_used = qm->total_fragments = 0; + + for (i = 0, bucket = qm->free_hash; + bucket < &qm->free_hash[HP_HASH_SIZE]; + i++, bucket++) { + + size = UN_HASH(i); + + if (!bucket->is_optimized) { + in_use_frags = bucket->total_no - bucket->no; + used_mem = in_use_frags * size; + + qm->used += used_mem; + qm->real_used += used_mem + bucket->total_no * FRAG_OVERHEAD; + qm->total_fragments += bucket->total_no; + } else { + for (j = 0, it = &qm->free_hash[HP_HASH_SIZE + i * shm_secondary_hash_size]; + j < shm_secondary_hash_size; + j++, it++) { + + in_use_frags = it->total_no - it->no; + used_mem = in_use_frags * size; + + qm->used += used_mem; + qm->real_used += used_mem + bucket->total_no * FRAG_OVERHEAD; + qm->total_fragments += bucket->total_no; + } + } + } + + if (qm->real_used > qm->max_real_used) + qm->max_real_used = qm->real_used; + + LM_DBG("updated shm statistics: [ us: %ld | rus: %ld | frags: %ld ]\n", + qm->used, qm->real_used, qm->total_fragments); + + gettimeofday(&qm->last_updated, NULL); + + lock_release(hp_stats_lock); +} + +unsigned long hp_get_size(struct hp_block *qm) +{ + return qm->size; +} + +unsigned long hp_get_used(struct hp_block *qm) +{ + if (stats_are_expired(qm)) + update_shm_stats(qm); + + return qm->used; +} + +unsigned long hp_get_free(struct hp_block *qm) +{ + if (stats_are_expired(qm)) + update_shm_stats(qm); + + return qm->size - qm->real_used; +} + +unsigned long hp_get_real_used(struct hp_block *qm) +{ + if (stats_are_expired(qm)) + update_shm_stats(qm); + + return qm->real_used; +} + +unsigned long hp_get_max_real_used(struct hp_block *qm) +{ + if (stats_are_expired(qm)) + update_shm_stats(qm); + + return qm->max_real_used; +} + +unsigned long hp_get_frags(struct hp_block *qm) +{ + if (stats_are_expired(qm)) + update_shm_stats(qm); + + return qm->total_fragments; +} diff --git a/mem/hp_malloc_stats.h b/mem/hp_malloc_stats.h new file mode 100644 index 00000000000..f0d9bef4402 --- /dev/null +++ b/mem/hp_malloc_stats.h @@ -0,0 +1,49 @@ +/** + * the truly parallel memory allocator + * + * Copyright (C) 2014 OpenSIPS Solutions + * + * This file is part of opensips, a free SIP server. + * + * opensips is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version + * + * opensips is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * History: + * -------- + * 2014-01-19 initial version (liviu) + */ + +#ifndef HP_MALLOC_STATS_H +#define HP_MALLOC_STATS_H + +#include "../lock_ops.h" + +/* specified in microseconds */ +#define SHM_STATS_SAMPLING_PERIOD 200000L + +extern gen_lock_t *hp_stats_lock; + +int stats_are_expired(struct hp_block *qm); +void update_shm_stats(struct hp_block *qm); + +#ifdef STATISTICS +unsigned long hp_get_size(struct hp_block *qm); +unsigned long hp_get_used(struct hp_block *qm); +unsigned long hp_get_free(struct hp_block *qm); +unsigned long hp_get_real_used(struct hp_block *qm); +unsigned long hp_get_max_real_used(struct hp_block *qm); +unsigned long hp_get_frags(struct hp_block *qm); +#endif /* STATISTICS */ + +#endif /* HP_MALLOC_STATS_H */ diff --git a/mem/shm_mem.c b/mem/shm_mem.c index 6ab7b261324..933e4c79bd0 100644 --- a/mem/shm_mem.c +++ b/mem/shm_mem.c @@ -275,8 +275,8 @@ int shm_mem_init_mallocs(void* mempool, unsigned long pool_size) #endif /* init it for malloc*/ - shm_block=shm_malloc_init(mempool, pool_size); - if (shm_block==0){ + shm_block = shm_malloc_init(mempool, pool_size); + if (!shm_block){ LM_CRIT("could not initialize shared malloc\n"); shm_mem_destroy(); return -1; @@ -300,7 +300,7 @@ int shm_mem_init_mallocs(void* mempool, unsigned long pool_size) /* lock_alloc cannot be used yet! */ mem_lock = shm_malloc_unsafe(HP_TOTAL_HASH_SIZE * sizeof *mem_lock); if (!mem_lock) { - LM_CRIT("could not allocate shm lock array\n"); + LM_CRIT("could not allocate the shm lock array\n"); shm_mem_destroy(); return -1; } @@ -314,7 +314,7 @@ int shm_mem_init_mallocs(void* mempool, unsigned long pool_size) #else mem_lock = shm_malloc_unsafe(sizeof *mem_lock); if (!mem_lock) { - LM_CRIT("could not allocate shm lock array\n"); + LM_CRIT("could not allocate the shm lock\n"); shm_mem_destroy(); return -1; } @@ -337,7 +337,7 @@ int shm_mem_init_mallocs(void* mempool, unsigned long pool_size) *event_shm_last=0; event_shm_pending=shm_malloc_unsafe(sizeof(int)); if (event_shm_pending==0){ - LM_CRIT("could not allocate shm peinding flags\n"); + LM_CRIT("could not allocate shm pending flags\n"); shm_mem_destroy(); return -1; } From 8b8ab79a19d90c173a682ff373003ec2d32b41c3 Mon Sep 17 00:00:00 2001 From: Liviu Chircu Date: Thu, 27 Mar 2014 17:38:41 +0200 Subject: [PATCH 27/44] hp malloc: reorder some initializing operations * hp_mem_warming() fails if anything is allocated before (it cannot access the big fragment anymore) (cherry picked from commit 9f710642b9da0d091d67b79b95b4a89cac954315) --- mem/hp_malloc.c | 6 ++++++ mem/shm_mem.c | 23 +++++++++-------------- 2 files changed, 15 insertions(+), 14 deletions(-) diff --git a/mem/hp_malloc.c b/mem/hp_malloc.c index 2ebac8c3218..cf5c5a3395e 100644 --- a/mem/hp_malloc.c +++ b/mem/hp_malloc.c @@ -456,6 +456,12 @@ struct hp_block *hp_malloc_init(char *address, unsigned long size) qm->free_hash[PEEK_HASH_RR(qm, qm->first_frag->size)].total_no++; hp_frag_attach(qm, qm->first_frag); + /* if memory warming is on, pre-populate the hash with free fragments */ + if (mem_warming_enabled) { + if (shm_mem_warming(qm) != 0) + LM_INFO("skipped memory warming\n"); + } + hp_stats_lock = hp_malloc_unsafe(qm, sizeof *hp_stats_lock); if (!hp_stats_lock) { LM_ERR("failed to alloc hp statistics lock\n"); diff --git a/mem/shm_mem.c b/mem/shm_mem.c index 933e4c79bd0..14a3d6c6edc 100644 --- a/mem/shm_mem.c +++ b/mem/shm_mem.c @@ -283,20 +283,6 @@ int shm_mem_init_mallocs(void* mempool, unsigned long pool_size) } #ifdef HP_MALLOC - /* if memory warming is on, pre-populate the hash with free fragments */ - if (mem_warming_enabled) { - if (shm_mem_warming(shm_block) != 0) - LM_INFO("skipped memory warming\n"); - } - - mem_hash_usage = shm_malloc_unsafe(HP_TOTAL_HASH_SIZE * sizeof *mem_hash_usage); - if (!mem_hash_usage) { - LM_ERR("failed to allocate statistics array\n"); - return -1; - } - - memset(mem_hash_usage, 0, HP_TOTAL_HASH_SIZE * sizeof *mem_hash_usage); - /* lock_alloc cannot be used yet! */ mem_lock = shm_malloc_unsafe(HP_TOTAL_HASH_SIZE * sizeof *mem_lock); if (!mem_lock) { @@ -311,6 +297,15 @@ int shm_mem_init_mallocs(void* mempool, unsigned long pool_size) shm_mem_destroy(); return -1; } + + mem_hash_usage = shm_malloc_unsafe(HP_TOTAL_HASH_SIZE * sizeof *mem_hash_usage); + if (!mem_hash_usage) { + LM_ERR("failed to allocate statistics array\n"); + return -1; + } + + memset(mem_hash_usage, 0, HP_TOTAL_HASH_SIZE * sizeof *mem_hash_usage); + #else mem_lock = shm_malloc_unsafe(sizeof *mem_lock); if (!mem_lock) { From 51c1518be82cea753caa72d49e57f7a641e2eab1 Mon Sep 17 00:00:00 2001 From: Liviu Chircu Date: Thu, 27 Mar 2014 19:10:14 +0200 Subject: [PATCH 28/44] call_center: fix some db schema errors * reduce the cc_agents skills column size * fix some primary key issues in cc_flows and cc_agents * fix a couple of bad column names in cc_cdrs (cherry picked from commit edd872182882536f3cf37bd5c4be633075f265d4) --- db/schema/cc_agents.xml | 12 +- db/schema/cc_cdrs.xml | 6 +- db/schema/cc_flows.xml | 10 +- scripts/db_berkeley/opensips/cc_agents | 2 +- scripts/db_berkeley/opensips/cc_cdrs | 2 +- scripts/db_berkeley/opensips/cc_flows | 2 +- scripts/dbtext/opensips/cc_cdrs | 2 +- scripts/mysql/call_center-create.sql | 20 +-- scripts/oracle/call_center-create.sql | 18 +-- scripts/pi_http/call_center-mod | 32 ++--- scripts/pi_http/call_center-table | 4 +- scripts/pi_http/pi_framework.xml | 168 ++++++++++++------------ scripts/postgres/call_center-create.sql | 18 +-- 13 files changed, 155 insertions(+), 141 deletions(-) diff --git a/db/schema/cc_agents.xml b/db/schema/cc_agents.xml index bba3d26a7aa..7e18849589d 100644 --- a/db/schema/cc_agents.xml +++ b/db/schema/cc_agents.xml @@ -23,8 +23,7 @@ unsigned int &table_id_len; - - + int,auto Agent unique ID in DB @@ -34,7 +33,6 @@ agentid string 128 - The unique ID of the agent in the Call Center module - to be used to identify the agent in the module and from outside the module; @@ -65,7 +63,7 @@ skills string - 512 + 255 Comma separated list of skills offered by the agent; these skills must match the skills used in the queues/flows definition; In order to receive @@ -74,4 +72,10 @@ + + unique_agentid + + + + diff --git a/db/schema/cc_cdrs.xml b/db/schema/cc_cdrs.xml index 275a84580e4..7c3db14f551 100644 --- a/db/schema/cc_cdrs.xml +++ b/db/schema/cc_cdrs.xml @@ -96,7 +96,7 @@ call_type - unsigned int + int 11 -1 Type of call: -2 - call rejected by agent; @@ -107,7 +107,7 @@ - call_type + rejected unsigned int 11 0 @@ -117,7 +117,7 @@ - call_type + fstats unsigned int 11 0 diff --git a/db/schema/cc_flows.xml b/db/schema/cc_flows.xml index 39a61bb77c5..6854642bd86 100644 --- a/db/schema/cc_flows.xml +++ b/db/schema/cc_flows.xml @@ -23,8 +23,7 @@ unsigned int &table_id_len; - - + int,auto Flow unique ID in DB @@ -34,7 +33,6 @@ flowid string 64 - The unique ID of the flow in the Call Center module - to be used to identify the flow/queue in the module and from outside the module; @@ -94,4 +92,10 @@ server must never hung up on it. + + unique_flowid + + + + diff --git a/scripts/db_berkeley/opensips/cc_agents b/scripts/db_berkeley/opensips/cc_agents index 6955640549e..6cfcb1e4034 100644 --- a/scripts/db_berkeley/opensips/cc_agents +++ b/scripts/db_berkeley/opensips/cc_agents @@ -1,7 +1,7 @@ METADATA_COLUMNS id(int) agentid(str) location(str) logstate(int) skills(str) METADATA_KEY -0 + METADATA_READONLY 0 METADATA_LOGFLAGS diff --git a/scripts/db_berkeley/opensips/cc_cdrs b/scripts/db_berkeley/opensips/cc_cdrs index 4f023e3e325..c2586ab1db7 100644 --- a/scripts/db_berkeley/opensips/cc_cdrs +++ b/scripts/db_berkeley/opensips/cc_cdrs @@ -1,5 +1,5 @@ METADATA_COLUMNS -id(int) caller(str) received_timestamp(datetime) wait_time(int) pickup_time(int) talk_time(int) flow_id(str) agent_id(str) call_type(int) call_type(int) call_type(int) cid(int) +id(int) caller(str) received_timestamp(datetime) wait_time(int) pickup_time(int) talk_time(int) flow_id(str) agent_id(str) call_type(int) rejected(int) fstats(int) cid(int) METADATA_KEY 0 METADATA_READONLY diff --git a/scripts/db_berkeley/opensips/cc_flows b/scripts/db_berkeley/opensips/cc_flows index 4e5bc62b4ee..55ed0ff5cfb 100644 --- a/scripts/db_berkeley/opensips/cc_flows +++ b/scripts/db_berkeley/opensips/cc_flows @@ -1,7 +1,7 @@ METADATA_COLUMNS id(int) flowid(str) priority(int) skill(str) prependcid(str) message_welcome(str) message_queue(str) METADATA_KEY -0 + METADATA_READONLY 0 METADATA_LOGFLAGS diff --git a/scripts/dbtext/opensips/cc_cdrs b/scripts/dbtext/opensips/cc_cdrs index ffa8dff3f3a..41f73add6b5 100644 --- a/scripts/dbtext/opensips/cc_cdrs +++ b/scripts/dbtext/opensips/cc_cdrs @@ -1 +1 @@ -id(int,auto) caller(string) received_timestamp(int) wait_time(int) pickup_time(int) talk_time(int) flow_id(string) agent_id(string,null) call_type(int) call_type(int) call_type(int) cid(int,null) +id(int,auto) caller(string) received_timestamp(int) wait_time(int) pickup_time(int) talk_time(int) flow_id(string) agent_id(string,null) call_type(int) rejected(int) fstats(int) cid(int,null) diff --git a/scripts/mysql/call_center-create.sql b/scripts/mysql/call_center-create.sql index f409c5cc5b5..840e0db0f2d 100644 --- a/scripts/mysql/call_center-create.sql +++ b/scripts/mysql/call_center-create.sql @@ -1,21 +1,23 @@ INSERT INTO version (table_name, table_version) values ('cc_flows','1'); CREATE TABLE cc_flows ( - id INT(10) UNSIGNED AUTO_INCREMENT NOT NULL, - flowid CHAR(64) PRIMARY KEY NOT NULL, + id INT(10) UNSIGNED AUTO_INCREMENT PRIMARY KEY NOT NULL, + flowid CHAR(64) NOT NULL, priority INT(11) UNSIGNED DEFAULT 256 NOT NULL, skill CHAR(64) NOT NULL, prependcid CHAR(32) NOT NULL, message_welcome CHAR(128) DEFAULT NULL, - message_queue CHAR(128) NOT NULL + message_queue CHAR(128) NOT NULL, + CONSTRAINT unique_flowid UNIQUE (flowid) ) ENGINE=MyISAM; INSERT INTO version (table_name, table_version) values ('cc_agents','1'); CREATE TABLE cc_agents ( - id INT(10) UNSIGNED AUTO_INCREMENT NOT NULL, - agentid CHAR(128) PRIMARY KEY NOT NULL, + id INT(10) UNSIGNED AUTO_INCREMENT PRIMARY KEY NOT NULL, + agentid CHAR(128) NOT NULL, location CHAR(128) NOT NULL, logstate INT(10) UNSIGNED DEFAULT 0 NOT NULL, - skills CHAR(512) NOT NULL + skills CHAR(255) NOT NULL, + CONSTRAINT unique_agentid UNIQUE (agentid) ) ENGINE=MyISAM; INSERT INTO version (table_name, table_version) values ('cc_cdrs','1'); @@ -28,9 +30,9 @@ CREATE TABLE cc_cdrs ( talk_time INT(11) UNSIGNED DEFAULT 0 NOT NULL, flow_id CHAR(128) NOT NULL, agent_id CHAR(128) DEFAULT NULL, - call_type INT(11) UNSIGNED DEFAULT -1 NOT NULL, - call_type INT(11) UNSIGNED DEFAULT 0 NOT NULL, - call_type INT(11) UNSIGNED DEFAULT 0 NOT NULL, + call_type INT(11) DEFAULT -1 NOT NULL, + rejected INT(11) UNSIGNED DEFAULT 0 NOT NULL, + fstats INT(11) UNSIGNED DEFAULT 0 NOT NULL, cid INT(11) UNSIGNED DEFAULT 0 ) ENGINE=MyISAM; diff --git a/scripts/oracle/call_center-create.sql b/scripts/oracle/call_center-create.sql index 3f2dda67e8f..a362fdf885c 100644 --- a/scripts/oracle/call_center-create.sql +++ b/scripts/oracle/call_center-create.sql @@ -1,12 +1,13 @@ INSERT INTO version (table_name, table_version) values ('cc_flows','1'); CREATE TABLE cc_flows ( - id NUMBER(10), - flowid VARCHAR2(64) PRIMARY KEY, + id NUMBER(10) PRIMARY KEY, + flowid VARCHAR2(64), priority NUMBER(10) DEFAULT 256 NOT NULL, skill VARCHAR2(64), prependcid VARCHAR2(32), message_welcome VARCHAR2(128) DEFAULT NULL, - message_queue VARCHAR2(128) + message_queue VARCHAR2(128), + CONSTRAINT cc_flows_unique_flowid UNIQUE (flowid) ); CREATE OR REPLACE TRIGGER cc_flows_tr @@ -19,11 +20,12 @@ BEGIN map2users('cc_flows'); END; / INSERT INTO version (table_name, table_version) values ('cc_agents','1'); CREATE TABLE cc_agents ( - id NUMBER(10), - agentid VARCHAR2(128) PRIMARY KEY, + id NUMBER(10) PRIMARY KEY, + agentid VARCHAR2(128), location VARCHAR2(128), logstate NUMBER(10) DEFAULT 0 NOT NULL, - skills VARCHAR2(512) + skills VARCHAR2(255), + CONSTRAINT cc_agents_unique_agentid UNIQUE (agentid) ); CREATE OR REPLACE TRIGGER cc_agents_tr @@ -45,8 +47,8 @@ CREATE TABLE cc_cdrs ( flow_id VARCHAR2(128), agent_id VARCHAR2(128) DEFAULT NULL, call_type NUMBER(10) DEFAULT -1 NOT NULL, - call_type NUMBER(10) DEFAULT 0 NOT NULL, - call_type NUMBER(10) DEFAULT 0 NOT NULL, + rejected NUMBER(10) DEFAULT 0 NOT NULL, + fstats NUMBER(10) DEFAULT 0 NOT NULL, cid NUMBER(10) DEFAULT 0 ); diff --git a/scripts/pi_http/call_center-mod b/scripts/pi_http/call_center-mod index 36d3b81595b..5d8c0a9cbbd 100644 --- a/scripts/pi_http/call_center-mod +++ b/scripts/pi_http/call_center-mod @@ -4,8 +4,8 @@ cc_flows DB_QUERY - id - flowidupdate + idupdate + flowid priority skill prependcid @@ -29,10 +29,10 @@ cc_flows DB_UPDATE - flowid= + id= - id + flowid priority skill prependcid @@ -44,7 +44,7 @@ cc_flows DB_DELETE - flowid= + id= @@ -54,8 +54,8 @@ cc_agents DB_QUERY - id - agentidupdate + idupdate + agentid location logstate skills @@ -75,10 +75,10 @@ cc_agents DB_UPDATE - agentid= + id= - id + agentid location logstate skills @@ -88,7 +88,7 @@ cc_agents DB_DELETE - agentid= + id= @@ -107,8 +107,8 @@ flow_id agent_id call_type - call_type - call_type + rejected + fstats cid @@ -124,8 +124,8 @@ flow_id agent_id call_type - call_type - call_type + rejected + fstats cid @@ -144,8 +144,8 @@ flow_id agent_id call_type - call_type - call_type + rejected + fstats cid diff --git a/scripts/pi_http/call_center-table b/scripts/pi_http/call_center-table index 9b9c82dcdbe..00f4fe27b92 100644 --- a/scripts/pi_http/call_center-table +++ b/scripts/pi_http/call_center-table @@ -33,7 +33,7 @@ flow_idDB_STR agent_idDB_STR call_typeDB_INT - call_typeDB_INT - call_typeDB_INT + rejectedDB_INT + fstatsDB_INT cidDB_INT diff --git a/scripts/pi_http/pi_framework.xml b/scripts/pi_http/pi_framework.xml index d8fc2fb05e9..a01e5a85933 100644 --- a/scripts/pi_http/pi_framework.xml +++ b/scripts/pi_http/pi_framework.xml @@ -94,6 +94,64 @@ valueDB_STR last_modifiedDB_DATETIME + + + b2b_sca + mysql + idDB_INT + shared_lineDB_STR + watchersDB_STR + app1_shared_entityDB_INT + app1_call_stateDB_INT + app1_call_info_uriDB_STR + app1_call_info_appearance_uriDB_STR + app1_b2bl_keyDB_STR + app2_shared_entityDB_INT + app2_call_stateDB_INT + app2_call_info_uriDB_STR + app2_call_info_appearance_uriDB_STR + app2_b2bl_keyDB_STR + app3_shared_entityDB_INT + app3_call_stateDB_INT + app3_call_info_uriDB_STR + app3_call_info_appearance_uriDB_STR + app3_b2bl_keyDB_STR + app4_shared_entityDB_INT + app4_call_stateDB_INT + app4_call_info_uriDB_STR + app4_call_info_appearance_uriDB_STR + app4_b2bl_keyDB_STR + app5_shared_entityDB_INT + app5_call_stateDB_INT + app5_call_info_uriDB_STR + app5_call_info_appearance_uriDB_STR + app5_b2bl_keyDB_STR + app6_shared_entityDB_INT + app6_call_stateDB_INT + app6_call_info_uriDB_STR + app6_call_info_appearance_uriDB_STR + app6_b2bl_keyDB_STR + app7_shared_entityDB_INT + app7_call_stateDB_INT + app7_call_info_uriDB_STR + app7_call_info_appearance_uriDB_STR + app7_b2bl_keyDB_STR + app8_shared_entityDB_INT + app8_call_stateDB_INT + app8_call_info_uriDB_STR + app8_call_info_appearance_uriDB_STR + app8_b2bl_keyDB_STR + app9_shared_entityDB_INT + app9_call_stateDB_INT + app9_call_info_uriDB_STR + app9_call_info_appearance_uriDB_STR + app9_b2bl_keyDB_STR + app10_shared_entityDB_INT + app10_call_stateDB_INT + app10_call_info_uriDB_STR + app10_call_info_appearance_uriDB_STR + app10_b2bl_keyDB_STR + b2b_entities @@ -158,64 +216,6 @@ e3_toDB_STR e3_keyDB_STR - - - b2b_sca - mysql - idDB_INT - shared_lineDB_STR - watchersDB_STR - app1_shared_entityDB_INT - app1_call_stateDB_INT - app1_call_info_uriDB_STR - app1_call_info_appearance_uriDB_STR - app1_b2bl_keyDB_STR - app2_shared_entityDB_INT - app2_call_stateDB_INT - app2_call_info_uriDB_STR - app2_call_info_appearance_uriDB_STR - app2_b2bl_keyDB_STR - app3_shared_entityDB_INT - app3_call_stateDB_INT - app3_call_info_uriDB_STR - app3_call_info_appearance_uriDB_STR - app3_b2bl_keyDB_STR - app4_shared_entityDB_INT - app4_call_stateDB_INT - app4_call_info_uriDB_STR - app4_call_info_appearance_uriDB_STR - app4_b2bl_keyDB_STR - app5_shared_entityDB_INT - app5_call_stateDB_INT - app5_call_info_uriDB_STR - app5_call_info_appearance_uriDB_STR - app5_b2bl_keyDB_STR - app6_shared_entityDB_INT - app6_call_stateDB_INT - app6_call_info_uriDB_STR - app6_call_info_appearance_uriDB_STR - app6_b2bl_keyDB_STR - app7_shared_entityDB_INT - app7_call_stateDB_INT - app7_call_info_uriDB_STR - app7_call_info_appearance_uriDB_STR - app7_b2bl_keyDB_STR - app8_shared_entityDB_INT - app8_call_stateDB_INT - app8_call_info_uriDB_STR - app8_call_info_appearance_uriDB_STR - app8_b2bl_keyDB_STR - app9_shared_entityDB_INT - app9_call_stateDB_INT - app9_call_info_uriDB_STR - app9_call_info_appearance_uriDB_STR - app9_b2bl_keyDB_STR - app10_shared_entityDB_INT - app10_call_stateDB_INT - app10_call_info_uriDB_STR - app10_call_info_appearance_uriDB_STR - app10_b2bl_keyDB_STR - cachedb @@ -260,8 +260,8 @@ flow_idDB_STR agent_idDB_STR call_typeDB_INT - call_typeDB_INT - call_typeDB_INT + rejectedDB_INT + fstatsDB_INT cidDB_INT @@ -383,14 +383,6 @@ attrsDB_STR descriptionDB_STR - - - domain - mysql - idDB_INT - domainDB_STR - last_modifiedDB_DATETIME - domainpolicy @@ -402,6 +394,14 @@ valDB_STR descriptionDB_STR + + + domain + mysql + idDB_INT + domainDB_STR + last_modifiedDB_DATETIME + dr_gateways @@ -1549,8 +1549,8 @@ cc_flows DB_QUERY - id - flowidupdate + idupdate + flowid priority skill prependcid @@ -1574,10 +1574,10 @@ cc_flows DB_UPDATE - flowid= + id= - id + flowid priority skill prependcid @@ -1589,7 +1589,7 @@ cc_flows DB_DELETE - flowid= + id= @@ -1599,8 +1599,8 @@ cc_agents DB_QUERY - id - agentidupdate + idupdate + agentid location logstate skills @@ -1620,10 +1620,10 @@ cc_agents DB_UPDATE - agentid= + id= - id + agentid location logstate skills @@ -1633,7 +1633,7 @@ cc_agents DB_DELETE - agentid= + id= @@ -1652,8 +1652,8 @@ flow_id agent_id call_type - call_type - call_type + rejected + fstats cid @@ -1669,8 +1669,8 @@ flow_id agent_id call_type - call_type - call_type + rejected + fstats cid @@ -1689,8 +1689,8 @@ flow_id agent_id call_type - call_type - call_type + rejected + fstats cid diff --git a/scripts/postgres/call_center-create.sql b/scripts/postgres/call_center-create.sql index 918fd5b8511..1e62629839d 100644 --- a/scripts/postgres/call_center-create.sql +++ b/scripts/postgres/call_center-create.sql @@ -1,21 +1,23 @@ INSERT INTO version (table_name, table_version) values ('cc_flows','1'); CREATE TABLE cc_flows ( - id SERIAL NOT NULL, - flowid VARCHAR(64) PRIMARY KEY NOT NULL, + id SERIAL PRIMARY KEY NOT NULL, + flowid VARCHAR(64) NOT NULL, priority INTEGER DEFAULT 256 NOT NULL, skill VARCHAR(64) NOT NULL, prependcid VARCHAR(32) NOT NULL, message_welcome VARCHAR(128) DEFAULT NULL, - message_queue VARCHAR(128) NOT NULL + message_queue VARCHAR(128) NOT NULL, + CONSTRAINT cc_flows_unique_flowid UNIQUE (flowid) ); INSERT INTO version (table_name, table_version) values ('cc_agents','1'); CREATE TABLE cc_agents ( - id SERIAL NOT NULL, - agentid VARCHAR(128) PRIMARY KEY NOT NULL, + id SERIAL PRIMARY KEY NOT NULL, + agentid VARCHAR(128) NOT NULL, location VARCHAR(128) NOT NULL, logstate INTEGER DEFAULT 0 NOT NULL, - skills VARCHAR(512) NOT NULL + skills VARCHAR(255) NOT NULL, + CONSTRAINT cc_agents_unique_agentid UNIQUE (agentid) ); INSERT INTO version (table_name, table_version) values ('cc_cdrs','1'); @@ -29,8 +31,8 @@ CREATE TABLE cc_cdrs ( flow_id VARCHAR(128) NOT NULL, agent_id VARCHAR(128) DEFAULT NULL, call_type INTEGER DEFAULT -1 NOT NULL, - call_type INTEGER DEFAULT 0 NOT NULL, - call_type INTEGER DEFAULT 0 NOT NULL, + rejected INTEGER DEFAULT 0 NOT NULL, + fstats INTEGER DEFAULT 0 NOT NULL, cid INTEGER DEFAULT 0 ); From 30654e5ba3f41ee71e134a7a23251eae24d8f902 Mon Sep 17 00:00:00 2001 From: Bogdan-Andrei Iancu Date: Fri, 28 Mar 2014 14:27:45 +0200 Subject: [PATCH 29/44] Fix recalculation of sending socket after local route Take into consideration the "force_send_socket" setting in local route. (cherry picked from commit d37ae664dcfd9a5f83de62a493628ba12d495e75) --- modules/tm/uac.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/modules/tm/uac.c b/modules/tm/uac.c index 5293f1fc04b..f334ac5fa54 100644 --- a/modules/tm/uac.c +++ b/modules/tm/uac.c @@ -182,6 +182,7 @@ int t_uac(str* method, str* headers, str* body, dlg_t* dialog, struct socket_info *send_sock, *new_send_sock; str h_to, h_from, h_cseq, h_callid; struct proxy_l *proxy, *new_proxy; + unsigned short dst_changed; ret=-1; @@ -306,13 +307,15 @@ int t_uac(str* method, str* headers, str* body, dlg_t* dialog, set_avp_list( backup ); /* check for changes - if none, do not regenerate the buffer */ - if (req->new_uri.s || req->add_rm || req->body_lumps || + dst_changed = 1; + if (req->new_uri.s || req->force_send_socket!=dialog->send_sock || req->dst_uri.len != dialog->hooks.next_hop->len || - memcmp(req->dst_uri.s,dialog->hooks.next_hop->s,req->dst_uri.len)){ + memcmp(req->dst_uri.s,dialog->hooks.next_hop->s,req->dst_uri.len) || + (dst_changed=0)==0 || req->add_rm || req->body_lumps){ new_send_sock = NULL; /* do we also need to change the destination? */ - if (req->dst_uri.s || req->new_uri.s) { + if (dst_changed) { /* calculate the socket corresponding to next hop */ new_proxy = uri2proxy( req->dst_uri.s ? &(req->dst_uri) : &req->new_uri, From a09410ac2d7fb3b51f80987245901d9916be4c53 Mon Sep 17 00:00:00 2001 From: Liviu Chircu Date: Fri, 28 Mar 2014 18:53:26 +0200 Subject: [PATCH 30/44] hp malloc statistics: fix incorrect stats when configuring split buckets (cherry picked from commit b68cfbab2716efe9bdcc3bfd1724b228ce84bda2) --- mem/hp_malloc.c | 1 - mem/hp_malloc_stats.c | 4 ++-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/mem/hp_malloc.c b/mem/hp_malloc.c index cf5c5a3395e..868e1f31596 100644 --- a/mem/hp_malloc.c +++ b/mem/hp_malloc.c @@ -39,7 +39,6 @@ #include "../locking.h" #include "hp_malloc.h" -#include "hp_malloc_stats.h" extern unsigned long *mem_hash_usage; diff --git a/mem/hp_malloc_stats.c b/mem/hp_malloc_stats.c index 715d0d6cee2..2c95f678329 100644 --- a/mem/hp_malloc_stats.c +++ b/mem/hp_malloc_stats.c @@ -81,8 +81,8 @@ void update_shm_stats(struct hp_block *qm) used_mem = in_use_frags * size; qm->used += used_mem; - qm->real_used += used_mem + bucket->total_no * FRAG_OVERHEAD; - qm->total_fragments += bucket->total_no; + qm->real_used += used_mem + it->total_no * FRAG_OVERHEAD; + qm->total_fragments += it->total_no; } } } From 87cc1ea11c54d8457c64db0735cdd03bba9540ee Mon Sep 17 00:00:00 2001 From: Liviu Chircu Date: Tue, 1 Apr 2014 17:15:58 +0300 Subject: [PATCH 31/44] core statistics: export a initialization checking function * this allows statistics-dependent code to test initialization * change all "shm_malloc" calls to "shm_malloc_unsafe" * ultimately, memory allocators are now able to make use of core stats (cherry picked from commit 42c3d383b1449af42a1ddfb91f4891f28fcbf50b) --- statistics.c | 33 +++++++++++++++++++++------------ statistics.h | 2 ++ 2 files changed, 23 insertions(+), 12 deletions(-) diff --git a/statistics.c b/statistics.c index 1c3a1ee638e..0d5124d1d3e 100644 --- a/statistics.c +++ b/statistics.c @@ -53,6 +53,7 @@ #ifdef STATISTICS static stats_collector *collector = NULL; +static int stats_ready; static struct mi_root *mi_get_stats(struct mi_root *cmd, void *param); static struct mi_root *mi_reset_stats(struct mi_root *cmd, void *param); @@ -228,7 +229,7 @@ static inline module_stats* add_stat_module( char *module) if ( (module==0) || ((len = strlen(module))==0 ) ) return 0; - amods = (module_stats*)shm_realloc( collector->amodules, + amods = (module_stats*)shm_realloc_unsafe( collector->amodules, (collector->mod_no+1)*sizeof(module_stats) ); if (amods==0) { LM_ERR("no more shm memory\n"); @@ -296,7 +297,7 @@ int init_stats_collector(void) char *s; /* init the collector */ - collector = (stats_collector*)shm_malloc(sizeof(stats_collector)); + collector = (stats_collector*)shm_malloc_unsafe(sizeof(stats_collector)); if (collector==0) { LM_ERR("no more shm mem\n"); goto error; @@ -307,7 +308,7 @@ int init_stats_collector(void) for ( psn=pending_name_list ; psn ; psn=next ) { next = psn->next; - s = (char*)shm_malloc( psn->name->len ); + s = (char*)shm_malloc_unsafe( psn->name->len ); if (s==NULL) { LM_ERR("no more shm mem (%d)\n", psn->name->len); goto error; @@ -318,6 +319,12 @@ int init_stats_collector(void) pkg_free(psn); } + /* register sh_mem statistics */ + if (register_module_stats( "shmem", shm_stats)!=0 ) { + LM_ERR("failed to register sh_mem statistics\n"); + goto error; + } + #ifdef NO_ATOMIC_OPS /* init BIG (really BIG) lock */ stat_lock = lock_alloc(); @@ -344,11 +351,7 @@ int init_stats_collector(void) LM_ERR("failed to register core statistics\n"); goto error; } - /* register sh_mem statistics */ - if (register_module_stats( "shmem", shm_stats)!=0 ) { - LM_ERR("failed to register sh_mem statistics\n"); - goto error; - } + /* register sh_mem statistics */ if (register_module_stats( "net", net_stats)!=0 ) { LM_ERR("failed to register network statistics\n"); @@ -364,6 +367,7 @@ int init_stats_collector(void) /* mark it as dynamic, so it will require locking */ dy_mod->is_dyn = 1 ; + stats_ready = 1; LM_DBG("statistics manager successfully initialized\n"); return 0; @@ -424,6 +428,10 @@ void destroy_stats_collector(void) return; } +int stats_are_ready(void) +{ + return stats_ready; +} /********************* Create/Register STATS functions ***********************/ @@ -445,7 +453,8 @@ int register_stat2( char *module, char *name, stat_var **pvar, } name_len = strlen(name); - stat = (stat_var*)shm_malloc(sizeof(stat_var) + ((flags&STAT_SHM_NAME)==0)*name_len); + stat = (stat_var*)shm_malloc_unsafe(sizeof(stat_var) + + ((flags&STAT_SHM_NAME)==0)*name_len); if (stat==0) { LM_ERR("no more shm memory\n"); goto error; @@ -453,7 +462,7 @@ int register_stat2( char *module, char *name, stat_var **pvar, memset( stat, 0, sizeof(stat_var) ); if ( (flags&STAT_IS_FUNC)==0 ) { - stat->u.val = (stat_val*)shm_malloc(sizeof(stat_val)); + stat->u.val = (stat_val*)shm_malloc_unsafe(sizeof(stat_val)); if (stat->u.val==0) { LM_ERR("no more shm memory\n"); goto error1; @@ -507,8 +516,8 @@ int register_stat2( char *module, char *name, stat_var **pvar, /* duplicate found -> drop current stat and return the * found one */ lock_stop_write((rw_lock_t *)collector->rwl); - if (flags&STAT_SHM_NAME) shm_free(stat->name.s); - if ((flags&STAT_IS_FUNC)==0) shm_free(stat->u.val); + if (flags&STAT_SHM_NAME) shm_free_unsafe(stat->name.s); + if ((flags&STAT_IS_FUNC)==0) shm_free_unsafe(stat->u.val); shm_free(stat); *pvar = it; return 0; diff --git a/statistics.h b/statistics.h index 3a21bccae45..55a2f850a1d 100644 --- a/statistics.h +++ b/statistics.h @@ -103,6 +103,7 @@ typedef struct stat_export_ { char *build_stat_name( str* prefix, char *var_name); int init_stats_collector(); +int stats_are_ready(); /* for code which is statistics-dependent */ int register_udp_load_stat(str *name, stat_var **ctx, int children); int register_tcp_load_stat(stat_var **ctx); @@ -153,6 +154,7 @@ extern gen_lock_t *stat_lock; #define get_stat_var_from_num_code( _n_code, _in_code) NULL #define register_udp_load_stat( _a, _b, _c) 0 #define register_tcp_load_stat( _a) 0 + #define stats_are_ready() 0 #define clone_pv_stat_name( _name, _clone) 0 #endif From 84d919faf0b84316db8a0870d85e4d45e4b0d5fd Mon Sep 17 00:00:00 2001 From: Liviu Chircu Date: Tue, 1 Apr 2014 18:42:07 +0300 Subject: [PATCH 32/44] hp malloc: differentiate the pkg and shm statistics code When HP_MALLOC is defined: * shm statistics are based on 32/64-bit atomic counters - the former logic is still available with HP_MALLOC_FAST_STATS - however, stat aggregation and the shm threshold checks should be done by a single process * pkg statistics are implemented similarly to the other allocators * also re-introduce fragment coalescing for pkg memory (cherry-picked from commit 268955ba5af0306e849877aecc87967a0b6c7c3e) --- main.c | 2 + mem/hp_malloc.c | 496 +++++++++++++++++++++++++++++++++--------- mem/hp_malloc.h | 36 +-- mem/hp_malloc_stats.c | 102 ++++++++- mem/hp_malloc_stats.h | 86 +++++++- mem/mem.c | 2 +- mem/mem.h | 26 +-- mem/shm_mem.c | 58 +++-- mem/shm_mem.h | 116 +++++++--- 9 files changed, 736 insertions(+), 188 deletions(-) diff --git a/main.c b/main.c index 83eb52dfdea..7ca07d15700 100644 --- a/main.c +++ b/main.c @@ -1481,6 +1481,8 @@ int main(int argc, char** argv) goto error; } + init_shm_statistics(); + /*init timer, before parsing the cfg!*/ if (init_timer()<0){ LM_CRIT("could not initialize timer, exiting...\n"); diff --git a/mem/hp_malloc.c b/mem/hp_malloc.c index 868e1f31596..b62caf197c8 100644 --- a/mem/hp_malloc.c +++ b/mem/hp_malloc.c @@ -42,6 +42,12 @@ extern unsigned long *mem_hash_usage; +#if defined(HP_MALLOC) && !defined(HP_MALLOC_FAST_STATS) +stat_var *shm_used; +stat_var *shm_rused; +stat_var *shm_frags; +#endif + /* ROUNDTO= 2^k so the following works */ #define ROUNDTO_MASK (~((unsigned long)ROUNDTO-1)) #define ROUNDUP(s) (((s)+(ROUNDTO-1))&ROUNDTO_MASK) @@ -60,26 +66,36 @@ extern unsigned long *mem_hash_usage; ((frag)->size - wanted_size > (FRAG_OVERHEAD + MIN_FRAG_SIZE)) /* - * tries to split a frag, in an attempt to optimize memory usage - * - * Note: the memory lock on "hash" must be acquired when this is called + * the *_split functions try to split a fragment in an attempt + * to minimize memory usage */ -#define hp_frag_split(blk, frag, sz, hash) \ +#define pkg_frag_split(blk, frag, sz) \ do { \ if (can_split_frag(frag, sz)) { \ - blk->free_hash[PEEK_HASH_RR(blk, frag->size)].total_no--; \ - blk->free_hash[PEEK_HASH_RR(blk, sz)].total_no++; \ - __hp_frag_split(blk, frag, sz, hash); \ + __pkg_frag_split(blk, frag, sz); \ + update_stats_pkg_frag_split(blk); \ } \ } while (0) -/* tries to split a frag, in an attempt to optimize memory usage */ -#define hp_frag_split_unsafe(blk, frag, sz) \ +#define shm_frag_split_unsafe(blk, frag, sz) \ do { \ - if ((frag)->size - (sz) > (FRAG_OVERHEAD + MIN_FRAG_SIZE)) { \ - blk->free_hash[PEEK_HASH_RR(blk, frag->size)].total_no--; \ - blk->free_hash[PEEK_HASH_RR(blk, sz)].total_no++; \ - __hp_frag_split_unsafe(blk, frag, sz); \ + if (can_split_frag(frag, sz)) { \ + __shm_frag_split_unsafe(blk, frag, sz); \ + if (stats_are_ready()) { \ + update_stats_shm_frag_split(); \ + } else { \ + (blk)->real_used += FRAG_OVERHEAD; \ + (blk)->total_fragments++; \ + } \ + } \ + } while (0) + +/* Note: the shm lock on "hash" must be acquired when this is called */ +#define shm_frag_split(blk, frag, sz, hash) \ + do { \ + if (can_split_frag(frag, sz)) { \ + __shm_frag_split(blk, frag, sz, hash); \ + update_stats_shm_frag_split(); \ } \ } while (0) @@ -123,35 +139,61 @@ static inline void hp_frag_attach(struct hp_block *qm, struct hp_frag *frag) *f = frag; +#ifdef HP_MALLOC_FAST_STATS qm->free_hash[hash].no++; +#endif } -static inline void hp_frag_detach(struct hp_block *qm, struct hp_frag *n) +static inline void hp_frag_detach(struct hp_block *qm, struct hp_frag *frag) { struct hp_frag **pf; - unsigned int hash; - - hash = GET_HASH_RR(qm, n->size); - pf = n->prev; + pf = frag->prev; /* detach */ - *pf = n->u.nxt_free; + *pf = frag->u.nxt_free; + + if (frag->u.nxt_free) + frag->u.nxt_free->prev = pf; - if (n->u.nxt_free) - n->u.nxt_free->prev = pf; + frag->prev = NULL; - n->prev = NULL; +#ifdef HP_MALLOC_FAST_STATS + unsigned int hash; + hash = GET_HASH_RR(qm, frag->size); qm->free_hash[hash].no--; +#endif }; -void __hp_frag_split_unsafe(struct hp_block *qm, struct hp_frag *frag, +void __pkg_frag_split(struct hp_block *qm, struct hp_frag *frag, + unsigned long size) +{ + unsigned long rest; + struct hp_frag *n; + + rest = frag->size - size; + frag->size = size; + + /* split the fragment */ + n = FRAG_NEXT(frag); + n->size = rest - FRAG_OVERHEAD; + + hp_frag_attach(qm, n); + update_stats_pkg_frag_attach(qm, n); +} + +void __shm_frag_split_unsafe(struct hp_block *qm, struct hp_frag *frag, unsigned long size) { unsigned long rest; struct hp_frag *n; +#ifdef HP_MALLOC_FAST_STATS + qm->free_hash[PEEK_HASH_RR(qm, frag->size)].total_no--; + qm->free_hash[PEEK_HASH_RR(qm, size)].total_no++; +#endif + rest = frag->size - size; frag->size = size; @@ -159,17 +201,32 @@ void __hp_frag_split_unsafe(struct hp_block *qm, struct hp_frag *frag, n = FRAG_NEXT(frag); n->size = rest - FRAG_OVERHEAD; +#ifdef HP_MALLOC_FAST_STATS qm->free_hash[PEEK_HASH_RR(qm, n->size)].total_no++; +#endif + hp_frag_attach(qm, n); + + if (stats_are_ready()) + update_stats_shm_frag_attach(n); + else { + qm->used -= n->size; + qm->real_used -= n->size; + } } /* size should already be rounded-up */ -void __hp_frag_split(struct hp_block *qm, struct hp_frag *frag, +void __shm_frag_split(struct hp_block *qm, struct hp_frag *frag, unsigned long size, unsigned int old_hash) { unsigned long rest, hash; struct hp_frag *n; +#ifdef HP_MALLOC_FAST_STATS + qm->free_hash[PEEK_HASH_RR(qm, frag->size)].total_no--; + qm->free_hash[PEEK_HASH_RR(qm, size)].total_no++; +#endif + rest = frag->size - size; frag->size = size; @@ -184,7 +241,10 @@ void __hp_frag_split(struct hp_block *qm, struct hp_frag *frag, SHM_LOCK(hash); hp_frag_attach(qm, n); + +#ifdef HP_MALLOC_FAST_STATS qm->free_hash[hash].total_no++; +#endif if (hash != old_hash) SHM_UNLOCK(hash); @@ -218,8 +278,11 @@ void hp_update_mem_pattern_file(void) /* save the usage rate of each bucket to the memory pattern file */ for (i = 0; i < HP_MALLOC_OPTIMIZE / ROUNDTO; i++) { - LM_DBG("[%d] %lf %.8lf\n", i, (double)mem_hash_usage[i], (double)mem_hash_usage[i] / sum * (i * ROUNDTO + FRAG_OVERHEAD)); - verification += (double)mem_hash_usage[i] / sum * (i * ROUNDTO + FRAG_OVERHEAD); + LM_DBG("[%d] %lf %.8lf\n", i, (double)mem_hash_usage[i], + (double)mem_hash_usage[i] / sum * (i * ROUNDTO + FRAG_OVERHEAD)); + + verification += (double)mem_hash_usage[i] / + sum * (i * ROUNDTO + FRAG_OVERHEAD); if (fprintf(f, "%.12lf ", (double)mem_hash_usage[i] / sum * (i * ROUNDTO + FRAG_OVERHEAD)) < 0) @@ -343,8 +406,9 @@ int hp_mem_warming(struct hp_block *qm) /* populate each free hash bucket with proper number of fragments */ for (sf = sorted_sf; sf; sf = sf->next) { - LM_INFO("[%d] fraction: %.12lf total mem: %llu, %lu\n", sf->hash_index, - sf->amount, (unsigned long long) (sf->amount * + LM_INFO("[%d][%s] fraction: %.12lf total mem: %llu, %lu\n", sf->hash_index, + qm->free_hash[sf->hash_index].is_optimized ? "X" : " ", + sf->amount, (unsigned long long) (sf->amount * qm->size * mem_warming_percentage / 100), ROUNDTO * sf->hash_index); @@ -354,9 +418,15 @@ int hp_mem_warming(struct hp_block *qm) /* create free fragments worth of 'bucket_mem' memory */ while (bucket_mem >= FRAG_OVERHEAD + current_frag_size) { hp_frag_detach(qm, big_frag); + if (stats_are_ready()) + update_stats_shm_frag_detach(big_frag); + else { + qm->used += big_frag->size; + qm->real_used += big_frag->size + FRAG_OVERHEAD; + } /* trim-insert operation on the big free fragment */ - hp_frag_split_unsafe(qm, big_frag, current_frag_size); + shm_frag_split_unsafe(qm, big_frag, current_frag_size); /* * "big_frag" now points to a smaller, free and detached frag. @@ -365,6 +435,12 @@ int hp_mem_warming(struct hp_block *qm) * balanced within their dedicated hashes */ hp_frag_attach(qm, big_frag); + if (stats_are_ready()) + update_stats_shm_frag_attach(big_frag); + else { + qm->used -= big_frag->size; + qm->real_used -= big_frag->size + FRAG_OVERHEAD; + } big_frag = FRAG_NEXT(big_frag); @@ -390,7 +466,7 @@ int hp_mem_warming(struct hp_block *qm) } /* initialise the allocator and return its main block */ -struct hp_block *hp_malloc_init(char *address, unsigned long size) +static struct hp_block *hp_malloc_init(char *address, unsigned long size) { char *start; char *end; @@ -399,8 +475,8 @@ struct hp_block *hp_malloc_init(char *address, unsigned long size) /* make address and size multiple of 8*/ start = (char *)ROUNDUP((unsigned long) address); - LM_DBG("HP_OPTIMIZE=%lu, ROUNDTO=%lu\n", - HP_MALLOC_OPTIMIZE, HP_MALLOC_OPTIMIZE/ROUNDTO); + LM_DBG("HP_OPTIMIZE=%lu, HP_LINEAR_HASH_SIZE=%lu\n", + HP_MALLOC_OPTIMIZE, HP_LINEAR_HASH_SIZE); LM_DBG("HP_HASH_SIZE=%lu, HP_EXTRA_HASH_SIZE=%lu, hp_block size=%zu\n", HP_HASH_SIZE, HP_EXTRA_HASH_SIZE, sizeof(struct hp_block)); LM_DBG("params (%p, %lu), start=%p\n", address, size, start); @@ -430,8 +506,8 @@ struct hp_block *hp_malloc_init(char *address, unsigned long size) memset(qm, 0, sizeof(struct hp_block)); qm->size = size; - qm->used = size - init_overhead; - qm->real_used = size; + qm->used = 0; + qm->real_used = init_overhead; qm->max_real_used = init_overhead; gettimeofday(&qm->last_updated, NULL); @@ -452,16 +528,58 @@ struct hp_block *hp_malloc_init(char *address, unsigned long size) if (qm->large_limit < HP_MALLOC_DEFRAG_LIMIT) qm->large_limit = HP_MALLOC_DEFRAG_LIMIT; - qm->free_hash[PEEK_HASH_RR(qm, qm->first_frag->size)].total_no++; - hp_frag_attach(qm, qm->first_frag); + return qm; +} + +struct hp_block *hp_pkg_malloc_init(char *address, unsigned long size) +{ + struct hp_block *hpb; + + hpb = hp_malloc_init(address, size); + if (!hpb) { + LM_ERR("failed to initialize shm block\n"); + return NULL; + } + + hp_frag_attach(hpb, hpb->first_frag); + + /* first fragment attach is the equivalent of a split */ + update_stats_pkg_frag_split(hpb, hpb->first_frag); + + return hpb; +} + +struct hp_block *hp_shm_malloc_init(char *address, unsigned long size) +{ + struct hp_block *hpb; + + hpb = hp_malloc_init(address, size); + if (!hpb) { + LM_ERR("failed to initialize shm block\n"); + return NULL; + } + +#ifdef HP_MALLOC_FAST_STATS + hpb->free_hash[PEEK_HASH_RR(hpb, hpb->first_frag->size)].total_no++; +#endif + + hp_frag_attach(hpb, hpb->first_frag); + + /* first fragment attach is the equivalent of a split */ + if (stats_are_ready()) + update_stats_shm_frag_split(hpb, hpb->first_frag); + else { + hpb->real_used += FRAG_OVERHEAD; + hpb->total_fragments++; + } /* if memory warming is on, pre-populate the hash with free fragments */ if (mem_warming_enabled) { - if (shm_mem_warming(qm) != 0) + if (hp_mem_warming(hpb) != 0) LM_INFO("skipped memory warming\n"); } - hp_stats_lock = hp_malloc_unsafe(qm, sizeof *hp_stats_lock); + hp_stats_lock = hp_shm_malloc_unsafe(hpb, sizeof *hp_stats_lock); if (!hp_stats_lock) { LM_ERR("failed to alloc hp statistics lock\n"); return NULL; @@ -472,45 +590,136 @@ struct hp_block *hp_malloc_init(char *address, unsigned long size) return NULL; } - return qm; + return hpb; } -void* hp_malloc_unsafe(struct hp_block* qm, unsigned long size) + +void *hp_pkg_malloc(struct hp_block *qm, unsigned long size) { - struct hp_frag* frag; + struct hp_frag *frag; unsigned int hash; - /*size must be a multiple of 8*/ - size=ROUNDUP(size); + /* size must be a multiple of ROUNDTO */ + size = ROUNDUP(size); - /*search for a suitable free frag*/ + /* search for a suitable free frag */ + for (hash = GET_HASH(size); hash < HP_HASH_SIZE; hash++) { + frag = qm->free_hash[hash].first; + + for (; frag; frag = frag->u.nxt_free) + if (frag->size >= size) + goto found; - for(hash=GET_HASH(size);hashfree_hash[hash].first; - for( ; frag; frag = frag->u.nxt_free ) - if ( frag->size >= size ) goto found; /* try in a bigger bucket */ } - /* not found, bad! */ - LM_CRIT("not enough memory, please increase the \"-m\" parameter!\n"); + /* out of memory... we have to shut down */ + LM_CRIT("not enough memory, please increase the \"-M\" parameter!\n"); abort(); found: - /* we found it!*/ - hp_frag_detach(qm, frag); + update_stats_pkg_frag_detach(qm, frag); - /*see if we'll use full frag, or we'll split it in 2*/ + /* split the fragment if possible */ + pkg_frag_split(qm, frag, size); - hp_frag_split_unsafe(qm, frag, size); + if (qm->real_used > qm->max_real_used) + qm->max_real_used = qm->real_used; pkg_threshold_check(); return (char *)frag + sizeof *frag; } -void *hp_malloc(struct hp_block *qm, unsigned long size) +/* + * although there is a lot of duplicate code, we get the best performance: + * + * - the _unsafe version will not be used too much anyway (usually at startup) + * - hp_shm_malloc is faster (no 3rd parameter, no extra if blocks) + */ +void *hp_shm_malloc_unsafe(struct hp_block *qm, unsigned long size) +{ + struct hp_frag *frag; + unsigned int init_hash, hash, sec_hash; + int i; + + /* size must be a multiple of ROUNDTO */ + size = ROUNDUP(size); + + /*search for a suitable free frag*/ + + for (hash = GET_HASH(size), init_hash = hash; hash < HP_HASH_SIZE; hash++) { + if (!qm->free_hash[hash].is_optimized) { + frag = qm->free_hash[hash].first; + + for (; frag; frag = frag->u.nxt_free) + if (frag->size >= size) + goto found; + + } else { + /* optimized size. search through its own hash! */ + for (i = 0, sec_hash = HP_HASH_SIZE + + hash * shm_secondary_hash_size + + optimized_get_indexes[hash]; + i < shm_secondary_hash_size; + i++, sec_hash = (sec_hash + 1) % shm_secondary_hash_size) { + + frag = qm->free_hash[sec_hash].first; + for (; frag; frag = frag->u.nxt_free) + if (frag->size >= size) { + /* free fragments are detached in a simple round-robin manner */ + optimized_get_indexes[hash] = + (optimized_get_indexes[hash] + i + 1) + % shm_secondary_hash_size; + hash = sec_hash; + goto found; + } + } + } + + /* try in a bigger bucket */ + } + + /* out of memory... we have to shut down */ + LM_CRIT("not enough shared memory, please increase the \"-m\" parameter!\n"); + abort(); + +found: + hp_frag_detach(qm, frag); + if (stats_are_ready()) + update_stats_shm_frag_detach(frag); + else { + qm->used += frag->size; + qm->real_used += frag->size + FRAG_OVERHEAD; + } + + /* split the fragment if possible */ + shm_frag_split_unsafe(qm, frag, size); + +#ifndef HP_MALLOC_FAST_STATS + if (stats_are_ready()) { + unsigned long real_used; + + real_used = get_stat_val(shm_rused); + if (real_used > qm->max_real_used) + qm->max_real_used = real_used; + } else + if (qm->real_used > qm->max_real_used) + qm->max_real_used = qm->real_used; +#endif + + if (mem_hash_usage) + mem_hash_usage[init_hash]++; + + return (char *)frag + sizeof *frag; +} + +/* + * Note: as opposed to hp_shm_malloc_unsafe(), + * hp_shm_malloc() assumes that the core statistics are initialized + */ +void *hp_shm_malloc(struct hp_block *qm, unsigned long size) { struct hp_frag *frag; unsigned int init_hash, hash, sec_hash; @@ -563,22 +772,63 @@ void *hp_malloc(struct hp_block *qm, unsigned long size) abort(); found: - hp_frag_detach(qm, frag); /* split the fragment if possible */ - hp_frag_split(qm, frag, size, hash); + shm_frag_split(qm, frag, size, hash); SHM_UNLOCK(hash); + update_stats_shm_frag_detach(frag); + +#ifndef HP_MALLOC_FAST_STATS + unsigned long real_used; + + real_used = get_stat_val(shm_rused); + if (real_used > qm->max_real_used) + qm->max_real_used = real_used; +#endif + /* ignore concurrency issues, simply obtaining an estimate is enough */ mem_hash_usage[init_hash]++; return (char *)frag + sizeof *frag; } +void hp_pkg_free(struct hp_block *qm, void *p) +{ + struct hp_frag *f, *next; -void hp_free_unsafe(struct hp_block* qm, void* p) + if (!p) { + LM_WARN("free(0) called\n"); + return; + } + + f = FRAG_OF(p); + + /* + * for private memory, coalesce as many consecutive fragments as possible + * The same operation is not performed for shared memory, because: + * - performance penalties introduced by additional locking logic + * - the allocator itself actually favours fragmentation and reusage + */ + for (;;) { + next = FRAG_NEXT(f); + if (next >= qm->last_frag || !next->prev) + break; + + hp_frag_detach(qm, next); + update_stats_pkg_frag_detach(qm, next); + + f->size += next->size + FRAG_OVERHEAD; + update_stats_pkg_frag_merge(qm); + } + + hp_frag_attach(qm, f); + update_stats_pkg_frag_attach(qm, f); +} + +void hp_shm_free_unsafe(struct hp_block *qm, void *p) { struct hp_frag *f; @@ -590,16 +840,14 @@ void hp_free_unsafe(struct hp_block* qm, void* p) f = FRAG_OF(p); hp_frag_attach(qm, f); - - pkg_threshold_check(); + update_stats_shm_frag_attach(f); } - -void hp_free(struct hp_block *qm, void *p) +void hp_shm_free(struct hp_block *qm, void *p) { struct hp_frag *f; unsigned int hash; - + if (!p) { LM_WARN("free(0) called\n"); return; @@ -611,84 +859,130 @@ void hp_free(struct hp_block *qm, void *p) SHM_LOCK(hash); hp_frag_attach(qm, f); SHM_UNLOCK(hash); + + update_stats_shm_frag_attach(f); } -void* hp_realloc_unsafe(struct hp_block* qm, void* p, unsigned long size) +void *hp_pkg_realloc(struct hp_block *qm, void *p, unsigned long size) { struct hp_frag *f; unsigned long diff; unsigned long orig_size; - struct hp_frag *n; + struct hp_frag *next; void *ptr; - if (size==0) { + if (size == 0) { if (p) - hp_free(qm, p); + hp_pkg_free(qm, p); - pkg_threshold_check(); - return 0; + return NULL; } - if (p==0) - return hp_malloc(qm, size); + + if (!p) + return hp_pkg_malloc(qm, size); f = FRAG_OF(p); - size=ROUNDUP(size); - orig_size=f->size; - if (f->size > size){ - /* shrink */ - hp_frag_split_unsafe(qm, f, size); + size = ROUNDUP(size); + orig_size = f->size; - }else if (f->sizesize; - n=FRAG_NEXT(f); + /* shrink operation */ + if (orig_size > size) { + pkg_frag_split(qm, f, size); + + /* grow operation */ + } else if (orig_size < size) { - if (((char*)n < (char*)qm->last_frag) && n->prev && - ((n->size+FRAG_OVERHEAD)>=diff)){ + diff = size - orig_size; + next = FRAG_NEXT(f); + + /* try to join with a large enough adjacent free fragment */ + if (next < qm->last_frag && next->prev && + (next->size + FRAG_OVERHEAD) >= diff) { + + hp_frag_detach(qm, next); + update_stats_pkg_frag_detach(qm, next); - hp_frag_detach(qm,n); - /* join */ - f->size += n->size + FRAG_OVERHEAD; + f->size += next->size + FRAG_OVERHEAD; - /* split it if necessary */ + /* split the result if necessary */ if (f->size > size) - hp_frag_split_unsafe(qm, f, size); - }else{ + pkg_frag_split(qm, f, size); + + } else { /* could not join => realloc */ - ptr = hp_malloc(qm, size); + ptr = hp_pkg_malloc(qm, size); if (ptr) { /* copy, need by libssl */ memcpy(ptr, p, orig_size); - hp_free(qm, p); + hp_pkg_free(qm, p); } p = ptr; } + + if (qm->real_used > qm->max_real_used) + qm->max_real_used = qm->real_used; } pkg_threshold_check(); return p; } -void *hp_realloc(struct hp_block *qm, void *p, unsigned long size) +void *hp_shm_realloc_unsafe(struct hp_block *qm, void *p, unsigned long size) { struct hp_frag *f; unsigned long orig_size; - unsigned int hash; void *ptr; if (size == 0) { if (p) - hp_free(qm, p); + hp_shm_free_unsafe(qm, p); + + return NULL; + } + + if (!p) + return hp_shm_malloc_unsafe(qm, size); + + f = FRAG_OF(p); + size = ROUNDUP(size); + + orig_size = f->size; + + /* shrink operation? */ + if (orig_size > size) + shm_frag_split_unsafe(qm, f, size); + else if (orig_size < size) { + ptr = hp_shm_malloc_unsafe(qm, size); + if (ptr) { + /* copy, need by libssl */ + memcpy(ptr, p, orig_size); + hp_shm_free_unsafe(qm, p); + } + + p = ptr; + } + + return p; +} + +void *hp_shm_realloc(struct hp_block *qm, void *p, unsigned long size) +{ + struct hp_frag *f; + unsigned long orig_size; + unsigned int hash; + void *ptr; + + if (size == 0) { + if (p) + hp_shm_free(qm, p); - pkg_threshold_check(); return NULL; } if (!p) - return hp_malloc(qm, size); + return hp_shm_malloc(qm, size); f = FRAG_OF(p); size = ROUNDUP(size); @@ -698,19 +992,19 @@ void *hp_realloc(struct hp_block *qm, void *p, unsigned long size) orig_size = f->size; - if (f->size > size) { + if (orig_size > size) { /* shrink */ - hp_frag_split_unsafe(qm, f, size); + shm_frag_split_unsafe(qm, f, size); SHM_UNLOCK(hash); - } else { + } else if (orig_size < size) { SHM_UNLOCK(hash); - ptr = hp_malloc(qm, size); + ptr = hp_shm_malloc(qm, size); if (ptr) { /* copy, need by libssl */ memcpy(ptr, p, orig_size); - hp_free(qm, p); + hp_shm_free(qm, p); } p = ptr; diff --git a/mem/hp_malloc.h b/mem/hp_malloc.h index 191035bddae..7f939013486 100644 --- a/mem/hp_malloc.h +++ b/mem/hp_malloc.h @@ -27,13 +27,19 @@ #if !defined(HP_MALLOC_H) && !defined(f_malloc_h) && !defined(VQ_MALLOC) #define HP_MALLOC_H +#include "../statistics.h" +#include "../config.h" +#include "../globals.h" + struct hp_frag; struct hp_frag_lnk; struct hp_block; -#include "../statistics.h" -#include "../config.h" -#include "../globals.h" +#ifndef HP_MALLOC_FAST_STATS +extern stat_var *shm_used; +extern stat_var *shm_rused; +extern stat_var *shm_frags; +#endif #include "hp_malloc_stats.h" #include "meminfo.h" @@ -183,21 +189,23 @@ struct hp_block { struct hp_frag_lnk free_hash[HP_HASH_SIZE + HP_EXTRA_HASH_SIZE]; }; -struct hp_block *hp_malloc_init(char *address, unsigned long size); -int hp_mem_warming(struct hp_block *fmb); +struct hp_block *hp_pkg_malloc_init(char *addr, unsigned long size); +struct hp_block *hp_shm_malloc_init(char *addr, unsigned long size); + +int hp_mem_warming(struct hp_block *); void hp_update_mem_pattern_file(void); -void *hp_malloc(struct hp_block *, unsigned long size); -void *hp_malloc_unsafe(struct hp_block *, unsigned long size); -void *hp_malloc_raw(struct hp_block *, unsigned long size); +void *hp_shm_malloc(struct hp_block *, unsigned long size); +void *hp_shm_malloc_unsafe(struct hp_block *, unsigned long size); +void *hp_pkg_malloc(struct hp_block *, unsigned long size); -void hp_free(struct hp_block *, void *p); -void hp_free_unsafe(struct hp_block *qm, void *p); -void hp_free_raw(struct hp_block *qm, void *p); +void hp_shm_free(struct hp_block *, void *p); +void hp_shm_free_unsafe(struct hp_block *qm, void *p); +void hp_pkg_free(struct hp_block *, void *p); -void *hp_realloc(struct hp_block *, void *p, unsigned long size); -void *hp_realloc_unsafe(struct hp_block *qm, void *p, unsigned long size); -void *hp_realloc_raw(struct hp_block *qm, void *p, unsigned long size); +void *hp_shm_realloc(struct hp_block *, void *p, unsigned long size); +void *hp_shm_realloc_unsafe(struct hp_block *qm, void *p, unsigned long size); +void *hp_pkg_realloc(struct hp_block *, void *p, unsigned long size); void hp_status(struct hp_block *); void hp_info(struct hp_block *, struct mem_info *); diff --git a/mem/hp_malloc_stats.c b/mem/hp_malloc_stats.c index 2c95f678329..ce2ae1f8962 100644 --- a/mem/hp_malloc_stats.c +++ b/mem/hp_malloc_stats.c @@ -24,6 +24,9 @@ * 2014-01-19 initial version (liviu) */ +#if !defined(q_malloc) && !(defined VQ_MALLOC) && !(defined F_MALLOC) && \ + (defined HP_MALLOC) + #include #include #include @@ -36,6 +39,8 @@ gen_lock_t *hp_stats_lock; +#ifdef STATISTICS + int stats_are_expired(struct hp_block *qm) { struct timeval now; @@ -98,12 +103,13 @@ void update_shm_stats(struct hp_block *qm) lock_release(hp_stats_lock); } -unsigned long hp_get_size(struct hp_block *qm) +unsigned long hp_shm_get_size(struct hp_block *qm) { return qm->size; } -unsigned long hp_get_used(struct hp_block *qm) +#ifdef HP_MALLOC_FAST_STATS +unsigned long hp_shm_get_used(struct hp_block *qm) { if (stats_are_expired(qm)) update_shm_stats(qm); @@ -111,34 +117,112 @@ unsigned long hp_get_used(struct hp_block *qm) return qm->used; } -unsigned long hp_get_free(struct hp_block *qm) +unsigned long hp_shm_get_real_used(struct hp_block *qm) { if (stats_are_expired(qm)) update_shm_stats(qm); - return qm->size - qm->real_used; + return qm->real_used; } -unsigned long hp_get_real_used(struct hp_block *qm) +unsigned long hp_shm_get_max_real_used(struct hp_block *qm) { if (stats_are_expired(qm)) update_shm_stats(qm); - return qm->real_used; + return qm->max_real_used; } -unsigned long hp_get_max_real_used(struct hp_block *qm) +unsigned long hp_shm_get_free(struct hp_block *qm) { if (stats_are_expired(qm)) update_shm_stats(qm); - return qm->max_real_used; + return qm->size - qm->real_used; } -unsigned long hp_get_frags(struct hp_block *qm) +unsigned long hp_shm_get_frags(struct hp_block *qm) { if (stats_are_expired(qm)) update_shm_stats(qm); return qm->total_fragments; } + +void hp_init_shm_statistics(struct hp_block *qm) +{ + update_shm_stats(qm); +} + +#else /* HP_MALLOC_FAST_STATS */ + +void hp_init_shm_statistics(struct hp_block *qm) +{ + update_stat(shm_used, qm->used); + update_stat(shm_rused, qm->real_used); + update_stat(shm_frags, qm->total_fragments); + + LM_DBG("initializing atomic shm statistics: " + "[ us: %ld | rus: %ld | frags: %ld ]\n", qm->used, qm->real_used, qm->total_fragments); +} + +unsigned long hp_shm_get_used(struct hp_block *qm) +{ + return get_stat_val(shm_used); +} + +unsigned long hp_shm_get_real_used(struct hp_block *qm) +{ + return get_stat_val(shm_rused); +} + +unsigned long hp_shm_get_max_real_used(struct hp_block *qm) +{ + return qm->max_real_used; +} + +unsigned long hp_shm_get_free(struct hp_block *qm) +{ + return qm->size - get_stat_val(shm_rused); +} + +unsigned long hp_shm_get_frags(struct hp_block *qm) +{ + return get_stat_val(shm_frags); +} +#endif /* HP_MALLOC_FAST_STATS */ + + +unsigned long hp_pkg_get_size(struct hp_block *qm) +{ + return qm->size; +} + +unsigned long hp_pkg_get_used(struct hp_block *qm) +{ + return qm->used; +} + +unsigned long hp_pkg_get_real_used(struct hp_block *qm) +{ + return qm->real_used; +} + +unsigned long hp_pkg_get_max_real_used(struct hp_block *qm) +{ + return qm->max_real_used; +} + +unsigned long hp_pkg_get_free(struct hp_block *qm) +{ + return qm->size - qm->real_used; +} + +unsigned long hp_pkg_get_frags(struct hp_block *qm) +{ + return qm->total_fragments; +} + +#endif /* STATISTICS */ + +#endif diff --git a/mem/hp_malloc_stats.h b/mem/hp_malloc_stats.h index f0d9bef4402..778c8c9dc56 100644 --- a/mem/hp_malloc_stats.h +++ b/mem/hp_malloc_stats.h @@ -34,16 +34,86 @@ extern gen_lock_t *hp_stats_lock; +#ifdef STATISTICS int stats_are_expired(struct hp_block *qm); void update_shm_stats(struct hp_block *qm); +void hp_init_shm_statistics(struct hp_block *qm); -#ifdef STATISTICS -unsigned long hp_get_size(struct hp_block *qm); -unsigned long hp_get_used(struct hp_block *qm); -unsigned long hp_get_free(struct hp_block *qm); -unsigned long hp_get_real_used(struct hp_block *qm); -unsigned long hp_get_max_real_used(struct hp_block *qm); -unsigned long hp_get_frags(struct hp_block *qm); -#endif /* STATISTICS */ +unsigned long hp_shm_get_size(struct hp_block *qm); +unsigned long hp_shm_get_used(struct hp_block *qm); +unsigned long hp_shm_get_free(struct hp_block *qm); +unsigned long hp_shm_get_real_used(struct hp_block *qm); +unsigned long hp_shm_get_max_real_used(struct hp_block *qm); +unsigned long hp_shm_get_frags(struct hp_block *qm); + +unsigned long hp_pkg_get_size(struct hp_block *qm); +unsigned long hp_pkg_get_used(struct hp_block *qm); +unsigned long hp_pkg_get_free(struct hp_block *qm); +unsigned long hp_pkg_get_real_used(struct hp_block *qm); +unsigned long hp_pkg_get_max_real_used(struct hp_block *qm); +unsigned long hp_pkg_get_frags(struct hp_block *qm); + +#define update_stats_pkg_frag_attach(blk, frag) \ + do { \ + (blk)->used -= (frag)->size; \ + (blk)->real_used -= (frag)->size + FRAG_OVERHEAD; \ + } while (0) + +#define update_stats_pkg_frag_detach(blk, frag) \ + do { \ + (blk)->used += (frag)->size; \ + (blk)->real_used += (frag)->size + FRAG_OVERHEAD; \ + } while (0) + +#define update_stats_pkg_frag_split(blk, ...) \ + do { \ + (blk)->real_used += FRAG_OVERHEAD; \ + (blk)->total_fragments++; \ + } while (0) + +#define update_stats_pkg_frag_merge(blk, ...) \ + do { \ + (blk)->real_used -= FRAG_OVERHEAD; \ + (blk)->total_fragments--; \ + } while (0) + +#ifdef HP_MALLOC_FAST_STATS + #define update_stats_shm_frag_attach(frag) + #define update_stats_shm_frag_detach(frag) + #define update_stats_shm_frag_split() + +#else /* HP_MALLOC_FAST_STATS */ + #define update_stats_shm_frag_attach(frag) \ + do { \ + update_stat(shm_used, -(frag)->size); \ + update_stat(shm_rused, -((frag)->size + FRAG_OVERHEAD)); \ + } while (0) + + #define update_stats_shm_frag_detach(frag) \ + do { \ + update_stat(shm_used, (frag)->size); \ + update_stat(shm_rused, (frag)->size + FRAG_OVERHEAD); \ + } while (0) + + #define update_stats_shm_frag_split(...) \ + do { \ + update_stat(shm_rused, FRAG_OVERHEAD); \ + update_stat(shm_frags, 1); \ + } while (0) +#endif /* HP_MALLOC_FAST_STATS */ + +#else /* STATISTICS */ + #define stats_are_expired(...) 0 + #define update_shm_stats(...) + + #define hp_init_shm_statistics(...) + #define update_stats_pkg_frag_attach(blk, frag) + #define update_stats_pkg_frag_detach(blk, frag) + #define update_stats_pkg_frag_split(blk, ...) + #define update_stats_pkg_frag_merge(blk, ...) + #define update_stats_shm_frag_attach(frag) + #define update_stats_shm_frag_detach(frag) + #define update_stats_shm_frag_split(...) +#endif #endif /* HP_MALLOC_STATS_H */ diff --git a/mem/mem.c b/mem/mem.c index 272733451e1..3b90dac8006 100644 --- a/mem/mem.c +++ b/mem/mem.c @@ -75,7 +75,7 @@ int init_pkg_mallocs(void) #elif F_MALLOC mem_block=fm_malloc_init(mem_pool, pkg_mem_size); #elif HP_MALLOC - mem_block=hp_malloc_init(mem_pool, pkg_mem_size); + mem_block=hp_pkg_malloc_init(mem_pool, pkg_mem_size); #else mem_block=qm_malloc_init(mem_pool, pkg_mem_size); #endif diff --git a/mem/mem.h b/mem/mem.h index 3b4c5111366..1ce5a7e5f32 100644 --- a/mem/mem.h +++ b/mem/mem.h @@ -98,14 +98,6 @@ void set_pkg_stats(pkg_status_holder*); # define pkg_realloc(p, s) fm_realloc(mem_block, (p), (s),__FILE__, \ __FUNCTION__, __LINE__) # define pkg_info(i) fm_info(mem_block,i) -# elif defined HP_MALLOC -# define pkg_malloc(s) hp_malloc_unsafe(mem_block, (s),__FILE__, \ - __FUNCTION__, __LINE__) -# define pkg_free(p) hp_free_unsafe(mem_block, (p), __FILE__, \ - __FUNCTION__, __LINE__) -# define pkg_realloc(p, s) hp_realloc_unsafe(mem_block, (p), (s),__FILE__, \ - __FUNCTION__, __LINE__) -# define pkg_info(i) hp_info(mem_block,i) # else # define pkg_malloc(s) qm_malloc(mem_block, (s),__FILE__, \ __FUNCTION__, __LINE__) @@ -125,9 +117,9 @@ void set_pkg_stats(pkg_status_holder*); # define pkg_free(p) fm_free(mem_block, (p)) # define pkg_info(i) fm_info(mem_block,i) # elif defined HP_MALLOC -# define pkg_malloc(s) hp_malloc_unsafe(mem_block, (s)) -# define pkg_realloc(p, s) hp_realloc_unsafe(mem_block, (p), (s)) -# define pkg_free(p) hp_free_unsafe(mem_block, (p)) +# define pkg_malloc(s) hp_pkg_malloc(mem_block, (s)) +# define pkg_realloc(p, s) hp_pkg_realloc(mem_block, (p), (s)) +# define pkg_free(p) hp_pkg_free(mem_block, (p)) # define pkg_info(i) hp_info(mem_block,i) # else # define pkg_malloc(s) qm_malloc(mem_block, (s)) @@ -148,12 +140,12 @@ void set_pkg_stats(pkg_status_holder*); # define MY_PKG_GET_FRAGS() fm_get_frags(mem_block) # elif defined HP_MALLOC # define pkg_status() hp_status(mem_block) -# define MY_PKG_GET_SIZE() hp_get_size(mem_block) -# define MY_PKG_GET_USED() hp_get_used(mem_block) -# define MY_PKG_GET_RUSED() hp_get_real_used(mem_block) -# define MY_PKG_GET_MUSED() hp_get_max_real_used(mem_block) -# define MY_PKG_GET_FREE() hp_get_free(mem_block) -# define MY_PKG_GET_FRAGS() hp_get_frags(mem_block) +# define MY_PKG_GET_SIZE() hp_pkg_get_size(mem_block) +# define MY_PKG_GET_USED() hp_pkg_get_used(mem_block) +# define MY_PKG_GET_RUSED() hp_pkg_get_real_used(mem_block) +# define MY_PKG_GET_MUSED() hp_pkg_get_max_real_used(mem_block) +# define MY_PKG_GET_FREE() hp_pkg_get_free(mem_block) +# define MY_PKG_GET_FRAGS() hp_pkg_get_frags(mem_block) # else # define pkg_status() qm_status(mem_block) # define MY_PKG_GET_SIZE() qm_get_size(mem_block) diff --git a/mem/shm_mem.c b/mem/shm_mem.c index 14a3d6c6edc..d05ef7d951d 100644 --- a/mem/shm_mem.c +++ b/mem/shm_mem.c @@ -50,12 +50,25 @@ #ifdef STATISTICS stat_export_t shm_stats[] = { - {"total_size" , STAT_IS_FUNC, (stat_var**)shm_get_size }, - {"used_size" , STAT_IS_FUNC, (stat_var**)shm_get_used }, - {"real_used_size" , STAT_IS_FUNC, (stat_var**)shm_get_rused }, - {"max_used_size" , STAT_IS_FUNC, (stat_var**)shm_get_mused }, - {"free_size" , STAT_IS_FUNC, (stat_var**)shm_get_free }, - {"fragments" , STAT_IS_FUNC, (stat_var**)shm_get_frags }, + {"total_size" , STAT_IS_FUNC, (stat_var**)shm_get_size }, + +#if defined(HP_MALLOC) && !defined(HP_MALLOC_FAST_STATS) + {"used_size" , 0, &shm_used }, + {"real_used_size" , 0, &shm_rused }, +#else + {"used_size" , STAT_IS_FUNC, (stat_var**)shm_get_used }, + {"real_used_size" , STAT_IS_FUNC, (stat_var**)shm_get_rused }, +#endif + + {"max_used_size" , STAT_IS_FUNC, (stat_var**)shm_get_mused }, + {"free_size" , STAT_IS_FUNC, (stat_var**)shm_get_free }, + +#if defined(HP_MALLOC) && !defined(HP_MALLOC_FAST_STATS) + {"fragments" , 0, &shm_frags }, +#else + {"fragments" , STAT_IS_FUNC, (stat_var**)shm_get_frags }, +#endif + {0,0,0} }; #endif @@ -78,9 +91,11 @@ static void* shm_mempool=(void*)-1; struct qm_block* shm_block; #endif -/* - * holds the total number of shm_mallocs requested for each - * bucket of the memory hash since daemon startup (useful for memory warming) +/* + * - the memory fragmentation pattern of OpenSIPS + * - holds the total number of shm_mallocs requested for each + * different possible size since daemon startup + * - allows memory warming (preserving the fragmentation pattern on restarts) */ unsigned long long *mem_hash_usage; @@ -148,7 +163,7 @@ void shm_event_raise(long used, long size, long perc) #ifdef HP_MALLOC shm_lock(0); #else - shm_unlock(); + shm_lock(); #endif list = 0; @@ -164,11 +179,22 @@ void shm_event_raise(long used, long size, long perc) inline static void* sh_realloc(void* p, unsigned int size) { void *r; - //shm_lock(0); + +#ifndef HP_MALLOC + shm_lock(); + shm_free_unsafe(p); + r = shm_malloc_unsafe(size); +#else shm_free(p); - r=shm_malloc(size); + r = shm_malloc(size); +#endif + shm_threshold_check(); - //shm_unlock(0); + +#ifndef HP_MALLOC + shm_unlock(); +#endif + return r; } @@ -360,6 +386,12 @@ int shm_mem_init(void) return shm_mem_init_mallocs(shm_mempool, shm_mem_size); } +void init_shm_statistics(void) +{ + #if defined(SHM_MEM) && defined(HP_MALLOC) + hp_init_shm_statistics(shm_block); + #endif +} void shm_mem_destroy(void) { diff --git a/mem/shm_mem.h b/mem/shm_mem.h index 9f731b972a4..45b84496151 100644 --- a/mem/shm_mem.h +++ b/mem/shm_mem.h @@ -63,7 +63,6 @@ #endif #endif - #include "../dprint.h" #include "../lock_ops.h" /* we don't include locking.h on purpose */ @@ -78,9 +77,7 @@ #elif defined F_MALLOC # include "f_malloc.h" extern struct fm_block* shm_block; -# define MY_MALLOC_UNSAFE fm_malloc # define MY_MALLOC fm_malloc -# define MY_FREE_UNSAFE fm_free # define MY_FREE fm_free # define MY_REALLOC fm_realloc # define MY_STATUS fm_status @@ -94,25 +91,29 @@ # define MY_SHM_GET_FRAGS fm_get_frags # endif # define shm_malloc_init fm_malloc_init +# define MY_MALLOC_UNSAFE MY_MALLOC +# define MY_FREE_UNSAFE MY_FREE +# define MY_REALLOC_UNSAFE MY_REALLOC #elif defined HP_MALLOC # include "hp_malloc.h" extern struct hp_block* shm_block; -# define MY_MALLOC_UNSAFE hp_malloc_unsafe -# define MY_MALLOC hp_malloc -# define MY_FREE_UNSAFE hp_free_unsafe -# define MY_FREE hp_free -# define MY_REALLOC hp_realloc +# define MY_MALLOC hp_shm_malloc +# define MY_MALLOC_UNSAFE hp_shm_malloc_unsafe +# define MY_FREE hp_shm_free +# define MY_FREE_UNSAFE hp_shm_free_unsafe +# define MY_REALLOC hp_shm_realloc +# define MY_REALLOC_UNSAFE hp_shm_realloc_unsafe # define MY_STATUS hp_status # define MY_MEMINFO hp_info # ifdef STATISTICS -# define MY_SHM_GET_SIZE hp_get_size -# define MY_SHM_GET_USED hp_get_used -# define MY_SHM_GET_RUSED hp_get_real_used -# define MY_SHM_GET_MUSED hp_get_max_real_used -# define MY_SHM_GET_FREE hp_get_free -# define MY_SHM_GET_FRAGS hp_get_frags +# define MY_SHM_GET_SIZE hp_shm_get_size +# define MY_SHM_GET_USED hp_shm_get_used +# define MY_SHM_GET_RUSED hp_shm_get_real_used +# define MY_SHM_GET_MUSED hp_shm_get_max_real_used +# define MY_SHM_GET_FREE hp_shm_get_free +# define MY_SHM_GET_FRAGS hp_shm_get_frags # endif -# define shm_malloc_init hp_malloc_init +# define shm_malloc_init hp_shm_malloc_init # define shm_mem_warming hp_mem_warming # define update_mem_pattern_file hp_update_mem_pattern_file #else @@ -123,6 +124,9 @@ # define MY_REALLOC qm_realloc # define MY_STATUS qm_status # define MY_MEMINFO qm_info +# define MY_MALLOC_UNSAFE MY_MALLOC +# define MY_FREE_UNSAFE MY_FREE +# define MY_REALLOC_UNSAFE MY_REALLOC # ifdef STATISTICS # define MY_SHM_GET_SIZE qm_get_size # define MY_SHM_GET_USED qm_get_used @@ -139,7 +143,13 @@ extern gen_lock_t* mem_lock; int shm_mem_init(); /* calls shm_getmem & shm_mem_init_mallocs */ -void update_shm_statistics(void); + +/* + * should be called after the statistics engine is initialized + * updates the atomic shm statistics with proper values + */ +void init_shm_statistics(void); + int shm_getmem(); /* allocates the memory (mmap or sysv shmap) */ int shm_mem_init_mallocs(void* mempool, unsigned long size); /* initialize the mallocs @@ -208,8 +218,9 @@ inline static void* _shm_malloc_unsafe(unsigned int size, const char *file, const char *function, int line ) { void *p; - - p = MY_MALLOC(shm_block, size, file, function, line); + + p = MY_MALLOC_UNSAFE(shm_block, size, file, function, line); + shm_threshold_check(); return p; @@ -220,9 +231,17 @@ inline static void* _shm_malloc(unsigned int size, { void *p; +#ifndef HP_MALLOC + shm_lock(); +#endif + p = MY_MALLOC(shm_block, size, file, function, line); shm_threshold_check(); +#ifndef HP_MALLOC + shm_unlock(); +#endif + return p; } @@ -232,9 +251,28 @@ inline static void* _shm_realloc(void *ptr, unsigned int size, { void *p; +#ifndef HP_MALLOC + shm_lock(); +#endif + p = MY_REALLOC(shm_block, ptr, size, file, function, line); shm_threshold_check(); +#ifndef HP_MALLOC + shm_unlock(); +#endif + + return p; +} + +inline static void* _shm_realloc_unsafe(void *ptr, unsigned int size, + const char* file, const char* function, int line ) +{ + void *p; + + p = MY_REALLOC_UNSAFE(shm_block, ptr, size, file, function, line); + shm_threshold_check(); + return p; } @@ -247,6 +285,9 @@ inline static void* _shm_realloc(void *ptr, unsigned int size, #define shm_realloc( _ptr, _size ) _shm_realloc( (_ptr), (_size), \ __FILE__, __FUNCTION__, __LINE__ ) +#define shm_realloc_unsafe( _ptr, _size ) _shm_realloc_unsafe( (_ptr), (_size), \ + __FILE__, __FUNCTION__, __LINE__ ) + #define shm_free_unsafe( _p ) \ @@ -280,6 +321,7 @@ inline static void* shm_malloc_unsafe(unsigned int size) void *p; p = MY_MALLOC_UNSAFE(shm_block, size); + shm_threshold_check(); return p; @@ -289,24 +331,51 @@ inline static void* shm_malloc(unsigned long size) { void *p; +#ifndef HP_MALLOC + shm_lock(); +#endif + p = MY_MALLOC(shm_block, size); shm_threshold_check(); +#ifndef HP_MALLOC + shm_unlock(); +#endif + return p; } inline static void* shm_realloc(void *ptr, unsigned int size) { void *p; + +#ifndef HP_MALLOC + shm_lock(); +#endif + p = MY_REALLOC(shm_block, ptr, size); shm_threshold_check(); +#ifndef HP_MALLOC + shm_unlock(); +#endif + + return p; +} + +inline static void* shm_realloc_unsafe(void *ptr, unsigned int size) +{ + void *p; + + p = MY_REALLOC_UNSAFE(shm_block, ptr, size); + shm_threshold_check(); + return p; } #define shm_free_unsafe( _p ) \ do { \ - MY_FREE(shm_block, (_p)); \ + MY_FREE_UNSAFE(shm_block, (_p)); \ shm_threshold_check(); \ } while(0) @@ -341,16 +410,13 @@ void* _shm_resize(void* ptr, unsigned int size); inline static void shm_status(void) { -#ifdef HP_MALLOC - shm_lock(0); -#else +#ifndef HP_MALLOC shm_lock(); #endif + MY_STATUS(shm_block); -#ifdef HP_MALLOC - shm_unlock(0); -#else +#ifndef HP_MALLOC shm_unlock(); #endif } From bead0160c0ee63a674d02e213bae05bc9384e02f Mon Sep 17 00:00:00 2001 From: Razvan Crainea Date: Thu, 3 Apr 2014 11:54:25 +0300 Subject: [PATCH 33/44] fixed acc to raise the proper event when using acc_evi_request() Credits go to Brett Nemeroff for reporting and testing (cherry picked from commit 24bd3a843f382860a917dc7da0c8af52afb4c9b8) --- modules/acc/acc.c | 12 ++++-------- modules/acc/acc.h | 4 ++++ modules/acc/acc_logic.c | 12 ++++++++++-- modules/acc/acc_logic.h | 1 + 4 files changed, 19 insertions(+), 10 deletions(-) diff --git a/modules/acc/acc.c b/modules/acc/acc.c index 1b046d9dc8a..80d8d58cb49 100644 --- a/modules/acc/acc.c +++ b/modules/acc/acc.c @@ -1417,22 +1417,18 @@ int acc_evi_request( struct sip_msg *rq, struct sip_msg *rpl) int n; int i; int backup_idx = -1, ret = -1; - event_id_t event = EVI_ERROR; /* * if the code is not set, choose the missed calls event * otherwise, check if the code is negative */ - event = (!acc_env.code || acc_env.code > 300) ? - acc_missed_event : acc_event; - - if (event == EVI_ERROR) { + if (acc_env.event == EVI_ERROR) { LM_ERR("event not registered %d\n", acc_event); return -1; } /* check if someone is interested in this event */ - if (!evi_probe_event(event)) + if (!evi_probe_event(acc_env.event)) return 1; m = core2strar( rq, val_arr ); @@ -1466,7 +1462,7 @@ int acc_evi_request( struct sip_msg *rq, struct sip_msg *rpl) backup_idx = m - 1; evi_params[backup_idx]->next = NULL; - if (evi_raise_event(event, acc_event_params) < 0) { + if (evi_raise_event(acc_env.event, acc_event_params) < 0) { LM_ERR("cannot raise ACC event\n"); goto end; } @@ -1482,7 +1478,7 @@ int acc_evi_request( struct sip_msg *rq, struct sip_msg *rpl) backup_idx = i - 1; evi_params[backup_idx]->next = NULL; - if (evi_raise_event(event, acc_event_params) < 0) { + if (evi_raise_event(acc_env.event, acc_event_params) < 0) { LM_ERR("cannot raise ACC event\n"); goto end; } diff --git a/modules/acc/acc.h b/modules/acc/acc.h index 500427e88ca..b52a9082adf 100644 --- a/modules/acc/acc.h +++ b/modules/acc/acc.h @@ -112,6 +112,9 @@ int acc_evi_request( struct sip_msg *req, struct sip_msg *rpl); int acc_evi_cdrs(struct dlg_cell *dlg, struct sip_msg *msg); int store_evi_extra_values(struct dlg_cell *dlg, struct sip_msg *req, struct sip_msg *reply); +extern event_id_t acc_cdr_event; +extern event_id_t acc_event; +extern event_id_t acc_missed_event; @@ -120,4 +123,5 @@ int acc_diam_init(); int acc_diam_request( struct sip_msg *req, struct sip_msg *rpl); #endif + #endif diff --git a/modules/acc/acc_logic.c b/modules/acc/acc_logic.c index 7a9b483ebe2..4b29fca025b 100644 --- a/modules/acc/acc_logic.c +++ b/modules/acc/acc_logic.c @@ -158,6 +158,11 @@ static inline void env_set_comment(struct acc_param *accp) acc_env.reason = accp->reason; } +static inline void env_set_event(event_id_t ev) +{ + acc_env.event = ev; +} + static inline int acc_preparse_req(struct sip_msg *req) { @@ -422,6 +427,7 @@ static inline void on_missed(struct cell *t, struct sip_msg *req, */ if (is_evi_mc_on(req)) { + env_set_event(acc_missed_event); acc_evi_request( req, reply ); flags_to_reset |= evi_missed_flag; } @@ -589,8 +595,10 @@ static inline void acc_onreply( struct cell* t, struct sip_msg *req, } } else { /* do old accounting */ - if ( is_evi_acc_on(req) ) + if ( is_evi_acc_on(req) ) { + env_set_event(acc_cdr_event); acc_evi_request( req, reply ); + } if ( is_log_acc_on(req) ) { env_set_text( ACC_ANSWERED, ACC_ANSWERED_LEN); @@ -631,7 +639,7 @@ static void acc_dlg_callback(struct dlg_cell *dlg, int type, flags = (unsigned int)(long)(*_params->param); if (flags & evi_flag) { - + env_set_event(acc_cdr_event); if (acc_evi_cdrs(dlg, _params->msg) < 0) { LM_ERR("cannot send accounting events\n"); return; diff --git a/modules/acc/acc_logic.h b/modules/acc/acc_logic.h index e2393d075d4..50f42a783d7 100644 --- a/modules/acc/acc_logic.h +++ b/modules/acc/acc_logic.h @@ -43,6 +43,7 @@ struct acc_enviroment { struct hdr_field *to; str text; time_t ts; + event_id_t event; }; /* param trasnporter*/ From 4b22509fe88bca0017b5b4785a7e56b634a30124 Mon Sep 17 00:00:00 2001 From: Liviu Chircu Date: Thu, 3 Apr 2014 16:51:35 +0300 Subject: [PATCH 34/44] mi_xmlrpc: fix crash when flushing complex MI trees as strings * crash was replicated with "ul_dump" command at 51+ contacts - "reply_option" must be disabled This patch solves a couple of other issues: * properly mark completed nodes when "reply_option" = 0 * a rare memory leak when flushing empty "mi_node"s (cherry picked from commit f5da89d27099f405e1242347bdf9e3cb6368423c) --- modules/mi_xmlrpc/xr_server.c | 2 ++ modules/mi_xmlrpc/xr_writer.c | 44 ++++++++++++++++++++++------------- modules/mi_xmlrpc/xr_writer.h | 1 + 3 files changed, 31 insertions(+), 16 deletions(-) diff --git a/modules/mi_xmlrpc/xr_server.c b/modules/mi_xmlrpc/xr_server.c index be0937059e7..5926c48526a 100644 --- a/modules/mi_xmlrpc/xr_server.c +++ b/modules/mi_xmlrpc/xr_server.c @@ -177,6 +177,8 @@ xmlrpc_value* default_method (xmlrpc_env* env, LM_DBG("starting up.....\n"); + xr_writer_reset(); + f = lookup_mi_cmd((char*)methodName, strlen(methodName)); if ( f == 0 ) { diff --git a/modules/mi_xmlrpc/xr_writer.c b/modules/mi_xmlrpc/xr_writer.c index b139f238deb..551b8277710 100644 --- a/modules/mi_xmlrpc/xr_writer.c +++ b/modules/mi_xmlrpc/xr_writer.c @@ -49,6 +49,11 @@ int xr_writer_init( unsigned int size ) return 0; } +void xr_writer_reset(void) +{ + *reply_buffer = '\0'; +} + #ifndef XMLRPC_HAS_FORCE_CHARS #define XMLRPC_NONXML_CHAR 0x7F @@ -217,10 +222,7 @@ static int recur_flush_response_array(xmlrpc_env * env, struct mi_node *tree, kid = kid->next; tree->kids = kid; - if(!tmp->kids){ - /* this node does not have any kids */ - free_mi_node(tmp); - } + free_mi_node(tmp); } else{ /* the node will have more kids => to keep the tree shape, do not @@ -286,11 +288,11 @@ static int recur_build_response( xmlrpc_env * env, struct mi_node * tree, LM_ERR("failed to get MI node data!\n"); return -1; } - - /* we are sure that this node has been written - * => avoid writing it again */ - tree->flags |= MI_WRITTEN; } + + /* we are sure that this node has been written + * => avoid writing it again */ + tree->flags |= MI_WRITTEN; } if ( tree->kids ) { @@ -305,9 +307,11 @@ static int recur_build_response( xmlrpc_env * env, struct mi_node * tree, char* xr_build_response( xmlrpc_env * env, struct mi_root * tree ) { str buf; + int len; - buf.s = reply_buffer; - buf.len = reply_buffer_len; + len = strlen(reply_buffer); + buf.s = reply_buffer + len; + buf.len = reply_buffer_len - len; if ( tree->code<200 || tree->code>=300 ){ LM_DBG("command processing failure: %s\n", tree->reason.s); @@ -335,6 +339,15 @@ static int recur_flush_response(xmlrpc_env * env, struct mi_node *tree, str *buf struct mi_node *kid, *tmp; int ret; + if (!rpl_opt) { + if (recur_build_response(env, tree, buf) != 0) { + LM_ERR("failed to read from the MI tree!\n"); + return -1; + } + + return 0; + } + for(kid = tree->kids ; kid ; ){ /* write the current kid */ if (!(kid->flags & MI_WRITTEN)){ @@ -371,10 +384,7 @@ static int recur_flush_response(xmlrpc_env * env, struct mi_node *tree, str *buf kid = kid->next; tree->kids = kid; - if(!tmp->kids){ - /* this node does not have any kids */ - free_mi_node(tmp); - } + free_mi_node(tmp); } else{ /* the node will have more kids => to keep the tree shape, do not @@ -389,9 +399,11 @@ static int recur_flush_response(xmlrpc_env * env, struct mi_node *tree, str *buf char* xr_flush_response( xmlrpc_env * env, struct mi_root * tree ) { str buf; + int len; - buf.s = reply_buffer; - buf.len = reply_buffer_len; + len = strlen(reply_buffer); + buf.s = reply_buffer + len; + buf.len = reply_buffer_len - len; if ( tree->code<200 || tree->code>=300 ){ LM_DBG("command processing failure: %s\n", tree->reason.s); diff --git a/modules/mi_xmlrpc/xr_writer.h b/modules/mi_xmlrpc/xr_writer.h index 5ad208fa443..aef9e393dbf 100644 --- a/modules/mi_xmlrpc/xr_writer.h +++ b/modules/mi_xmlrpc/xr_writer.h @@ -34,6 +34,7 @@ #include "../../mi/tree.h" int xr_writer_init( unsigned int size ); +void xr_writer_reset(void); char * xr_build_response( xmlrpc_env * env, struct mi_root * tree ); char * xr_flush_response( xmlrpc_env * env, struct mi_root * tree ); int xr_build_response_array( xmlrpc_env * env, struct mi_root * tree ); From ca11afbbea75d6475e15cb4bfdd459a2280f1f22 Mon Sep 17 00:00:00 2001 From: Razvan Crainea Date: Thu, 3 Apr 2014 17:49:53 +0300 Subject: [PATCH 35/44] opensipsctl: change trapping logging method the operator '&>>' does not exist for all shells, used '2>&1 >>' instead --- scripts/opensipsctl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/opensipsctl b/scripts/opensipsctl index ce8812274c7..932e16c3c3e 100755 --- a/scripts/opensipsctl +++ b/scripts/opensipsctl @@ -2636,7 +2636,7 @@ opensips_trap() { PID=`echo $pid | cut -d '-' -f 1` echo "" >> $LOG_FILE echo "---start $PID -----------------------------------------------------" >> $LOG_FILE - $GDB opensips $PID -batch --eval-command="bt full" &>> $LOG_FILE + $GDB opensips $PID -batch --eval-command="bt full" 2>&1 >> $LOG_FILE echo "---end $PID -------------------------------------------------------" >> $LOG_FILE done echo "." From 3155d871b80b10eab4b6b5db5a882c2f36ba0940 Mon Sep 17 00:00:00 2001 From: Liviu Chircu Date: Thu, 3 Apr 2014 18:11:27 +0300 Subject: [PATCH 36/44] hp malloc: do not write the pattern file when "mem_warming" = 0 * also improve the logging at shutdown (cherry picked from commit 19832c6a24a8a3f291b744e739d8c3e3c0670267) --- mem/hp_malloc.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/mem/hp_malloc.c b/mem/hp_malloc.c index b62caf197c8..805441757b1 100644 --- a/mem/hp_malloc.c +++ b/mem/hp_malloc.c @@ -260,6 +260,9 @@ void hp_update_mem_pattern_file(void) unsigned long long sum = 0; double verification = 0; + if (!mem_warming_enabled) + return; + f = fopen(mem_warming_pattern_file, "w+"); if (!f) { LM_ERR("failed to open pattern file %s for writing: %d - %s\n", @@ -292,13 +295,16 @@ void hp_update_mem_pattern_file(void) fprintf(f, "\n"); } - LM_INFO("verification: %lf\n", verification); + if (verification < 0.99 || verification > 1.01) + LM_INFO("memory pattern file appears to be incorrect: %lf\n", verification); + + LM_INFO("updated memory pattern file %s\n", mem_warming_pattern_file); fclose(f); return; write_error: - LM_ERR("failed to write to pattern file\n"); + LM_ERR("failed to update pattern file %s\n", mem_warming_pattern_file); fclose(f); } From 8c1f51df5c61d2c05936a2a6e3dab859e4f38c72 Mon Sep 17 00:00:00 2001 From: Liviu Chircu Date: Fri, 4 Apr 2014 17:11:54 +0300 Subject: [PATCH 37/44] hp malloc: fix pkg max_real_used computation in hp_info() * update_shm_stats() should not be called at all (cherry picked from commit e56f327aea403aae6982bbb404b2c9f6f4c146a3) --- mem/hp_malloc.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/mem/hp_malloc.c b/mem/hp_malloc.c index 805441757b1..5230e693c22 100644 --- a/mem/hp_malloc.c +++ b/mem/hp_malloc.c @@ -1073,8 +1073,10 @@ void hp_info(struct hp_block *qm, struct mem_info *info) info->total_size = qm->size; info->min_frag = MIN_FRAG_SIZE; +#ifdef HP_MALLOC_FAST_STATS if (stats_are_expired(qm)) update_shm_stats(qm); +#endif info->used = qm->used; info->real_used = qm->real_used; From 47e1f90d102fa19174c9bb9dbc563acf9c844562 Mon Sep 17 00:00:00 2001 From: Liviu Chircu Date: Fri, 4 Apr 2014 17:17:54 +0300 Subject: [PATCH 38/44] hp malloc: properly release the hash lock on redundant shm_reallocs * e.g. shm_realloc(shm_malloc(16), 16); (cherry picked from commit 4148c3f19d99919bb06aff3d7370cbfb96c40374) --- mem/hp_malloc.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/mem/hp_malloc.c b/mem/hp_malloc.c index 5230e693c22..4256b9b4a20 100644 --- a/mem/hp_malloc.c +++ b/mem/hp_malloc.c @@ -994,14 +994,13 @@ void *hp_shm_realloc(struct hp_block *qm, void *p, unsigned long size) size = ROUNDUP(size); hash = PEEK_HASH_RR(qm, f->size); - SHM_LOCK(hash); + SHM_LOCK(hash); orig_size = f->size; if (orig_size > size) { /* shrink */ shm_frag_split_unsafe(qm, f, size); - SHM_UNLOCK(hash); } else if (orig_size < size) { SHM_UNLOCK(hash); @@ -1013,9 +1012,10 @@ void *hp_shm_realloc(struct hp_block *qm, void *p, unsigned long size) hp_shm_free(qm, p); } - p = ptr; + return ptr; } + SHM_UNLOCK(hash); return p; } From 1a5a259909cb35456aae6abea8a3c1057a27eb1e Mon Sep 17 00:00:00 2001 From: Razvan Crainea Date: Tue, 8 Apr 2014 15:18:23 +0300 Subject: [PATCH 39/44] fix engage fixup function when called without any parameters Reported by Ovidiu Sas Closes #192 (cherry picked from commit cee47941726c03583eb37ae046a6f5c0293c9913) --- modules/rtpproxy/rtpproxy.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/modules/rtpproxy/rtpproxy.c b/modules/rtpproxy/rtpproxy.c index e9b0d974d67..185aaafe61a 100644 --- a/modules/rtpproxy/rtpproxy.c +++ b/modules/rtpproxy/rtpproxy.c @@ -814,6 +814,8 @@ static int fixup_two_options(void ** param, int param_no) static int fixup_offer_answer(void ** param, int param_no) { + if (param_no < 1) + return 0; if (param_no < 3) return fixup_spve(param); if (param_no == 3) @@ -928,7 +930,7 @@ static int fixup_engage_warn(void ** param, int param_no) static int fixup_engage(void** param, int param_no) { - if (param_no == 1 && !dlg_api.create_dlg) { + if (param_no < 2 && !dlg_api.create_dlg) { LM_ERR("Dialog module not loaded. Can't use engage_rtp_proxy function\n"); return -1; } From cdaad309926824fb347d18851440101a0f679380 Mon Sep 17 00:00:00 2001 From: Liviu Chircu Date: Wed, 9 Apr 2014 11:04:13 +0300 Subject: [PATCH 40/44] exec doc: update the OpenSIPS routes for each function (cherry picked from commit 2f47930ce189815bd9793f7304b00a9dae17f7ac) --- modules/exec/README | 9 ++++++--- modules/exec/doc/exec_admin.xml | 7 ++++--- 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/modules/exec/README b/modules/exec/README index 96f8bb65f62..48f73ae22d9 100644 --- a/modules/exec/README +++ b/modules/exec/README @@ -179,7 +179,8 @@ exec_dset("ruri-changer.sh '$ct'"); unexpected behaviour (e.g. unwanted extra parameters, errors due to special bash characters, etc.) - This function can be used from REQUEST_ROUTE, FAILURE_ROUTE. + This function can be used from REQUEST_ROUTE, FAILURE_ROUTE, + LOCAL_ROUTE, TIMER_ROUTE, EVENT_ROUTE, ONREPLY_ROUTE. Example 1.5. exec_msg usage ... @@ -207,7 +208,8 @@ exec_msg("call-logger.sh '$ct' >> /var/log/call-logger/'$rU'.calls"); due to special bash characters, etc.) This function can be used from REQUEST_ROUTE, FAILURE_ROUTE, - LOCAL_ROUTE, STARTUP_ROUTE. + LOCAL_ROUTE, STARTUP_ROUTE, TIMER_ROUTE, EVENT_ROUTE, + ONREPLY_ROUTE. Example 1.6. exec_avp usage ... @@ -232,7 +234,8 @@ model)"); exec_getenv("'$ct'"); This function can be used from REQUEST_ROUTE, FAILURE_ROUTE, - LOCAL_ROUTE, STARTUP_ROUTE. + LOCAL_ROUTE, STARTUP_ROUTE, TIMER_ROUTE, EVENT_ROUTE, + ONREPLY_ROUTE. Example 1.7. exec_getenv usage ... diff --git a/modules/exec/doc/exec_admin.xml b/modules/exec/doc/exec_admin.xml index b367e73685c..f35287e1a5a 100644 --- a/modules/exec/doc/exec_admin.xml +++ b/modules/exec/doc/exec_admin.xml @@ -236,7 +236,8 @@ exec_dset("ruri-changer.sh '$ct'"); (e.g. unwanted extra parameters, errors due to special bash characters, etc.) - This function can be used from REQUEST_ROUTE, FAILURE_ROUTE. + This function can be used from REQUEST_ROUTE, FAILURE_ROUTE, LOCAL_ROUTE, + TIMER_ROUTE, EVENT_ROUTE, ONREPLY_ROUTE. <function moreinfo="none">exec_msg</function> usage @@ -279,7 +280,7 @@ exec_msg("call-logger.sh '$ct' >> /var/log/call-logger/'$rU'.calls"); This function can be used from REQUEST_ROUTE, FAILURE_ROUTE, - LOCAL_ROUTE, STARTUP_ROUTE. + LOCAL_ROUTE, STARTUP_ROUTE, TIMER_ROUTE, EVENT_ROUTE, ONREPLY_ROUTE. <function moreinfo="none">exec_avp</function> usage @@ -318,7 +319,7 @@ exec_avp("get-subscriber-details.sh '$rU'", "$avp(credit) $avp(contract_model)") This function can be used from REQUEST_ROUTE, FAILURE_ROUTE, - LOCAL_ROUTE, STARTUP_ROUTE. + LOCAL_ROUTE, STARTUP_ROUTE, TIMER_ROUTE, EVENT_ROUTE, ONREPLY_ROUTE. <function moreinfo="none">exec_getenv</function> usage From 425255ba400f40daf14bb95c5978880209355787 Mon Sep 17 00:00:00 2001 From: Ovidiu Sas Date: Wed, 9 Apr 2014 12:11:38 -0400 Subject: [PATCH 41/44] parser: increase the number of accepted URI unknown params from 5 -> 10 (cherry picked from commit a6fd82d2d38b95c8815429dad2d5a25b4d998d68) --- parser/msg_parser.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/parser/msg_parser.h b/parser/msg_parser.h index 807a0b5e2c5..34ec7c48386 100644 --- a/parser/msg_parser.h +++ b/parser/msg_parser.h @@ -108,7 +108,7 @@ enum request_method { * callbacks were registered */ /* define the # of unknown URI parameters to parse */ -#define URI_MAX_U_PARAMS 5 +#define URI_MAX_U_PARAMS 10 #define IFISMETHOD(methodname,firstchar) \ if ( (*tmp==(firstchar) || *tmp==((firstchar) | 32)) && \ From 30fa2438229e8d48bbfc47b6aa711c63a6811be9 Mon Sep 17 00:00:00 2001 From: Razvan Crainea Date: Thu, 10 Apr 2014 14:49:13 +0300 Subject: [PATCH 42/44] rtpproxy: fix rtpproxy_engage() pvar expansion Reported by Ovidiu Sas Closes #195 --- modules/rtpproxy/rtpproxy.c | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/modules/rtpproxy/rtpproxy.c b/modules/rtpproxy/rtpproxy.c index 185aaafe61a..a869dc27eca 100644 --- a/modules/rtpproxy/rtpproxy.c +++ b/modules/rtpproxy/rtpproxy.c @@ -2977,6 +2977,7 @@ engage_rtp_proxy4_f(struct sip_msg *msg, char *param1, char *param2, char *param struct dlg_cell *dlg; struct rtpp_set *set = NULL; pv_value_t val1, val2; + str aux_str; LM_DBG("engage called from script 1:%p 2:%p 3:%p 4:%p\n", param1, param2, param3, param4); @@ -3016,6 +3017,22 @@ engage_rtp_proxy4_f(struct sip_msg *msg, char *param1, char *param2, char *param return -1; } + if (param1) { + if (rtpp_get_var_svalue(msg, (gparam_p)param1, &aux_str, 0)<0) { + LM_ERR("bogus flags parameter\n"); + return -1; + } + param1 = aux_str.s; + } + + if (param2) { + if (rtpp_get_var_svalue(msg, (gparam_p)param2, &aux_str, 1)<0) { + LM_ERR("bogus IP addr parameter\n"); + return -1; + } + param2 = aux_str.s; + } + /* is this a late negociation scenario? */ if (msg_has_sdp(msg)) { LM_DBG("message has sdp body -> forcing rtp proxy\n"); From d427267bb98a22cdc747caf1cbfbc3796a5dea0c Mon Sep 17 00:00:00 2001 From: Liviu Chircu Date: Fri, 11 Apr 2014 16:59:20 +0300 Subject: [PATCH 43/44] msilo dbschema: avoid setting a default value for the body field * this causes errors/warnings on backends such as MySQL/MariaDB (cherry picked from commit 5c790aa9431401dc0b906a9a8694dffb6bd1d34b) --- db/schema/silo.xml | 1 - scripts/db_berkeley/opensips/silo | 2 +- scripts/mysql/msilo-create.sql | 2 +- scripts/oracle/msilo-create.sql | 2 +- scripts/postgres/msilo-create.sql | 2 +- 5 files changed, 4 insertions(+), 5 deletions(-) diff --git a/db/schema/silo.xml b/db/schema/silo.xml index 5c0a1fc8496..2560ae3e96d 100644 --- a/db/schema/silo.xml +++ b/db/schema/silo.xml @@ -92,7 +92,6 @@ body binary - Body of the message diff --git a/scripts/db_berkeley/opensips/silo b/scripts/db_berkeley/opensips/silo index c164e3d53c5..cae879ba29c 100644 --- a/scripts/db_berkeley/opensips/silo +++ b/scripts/db_berkeley/opensips/silo @@ -7,4 +7,4 @@ METADATA_READONLY METADATA_LOGFLAGS 0 METADATA_DEFAULTS -NIL|''|''|''|''|0|0|0|'text/plain'|'' +NIL|''|''|''|''|0|0|0|'text/plain'|NIL diff --git a/scripts/mysql/msilo-create.sql b/scripts/mysql/msilo-create.sql index 691e5cbdc7a..07d80a20947 100644 --- a/scripts/mysql/msilo-create.sql +++ b/scripts/mysql/msilo-create.sql @@ -9,7 +9,7 @@ CREATE TABLE silo ( exp_time INT DEFAULT 0 NOT NULL, snd_time INT DEFAULT 0 NOT NULL, ctype CHAR(32) DEFAULT 'text/plain' NOT NULL, - body BLOB DEFAULT '' NOT NULL + body BLOB NOT NULL ) ENGINE=MyISAM; CREATE INDEX account_idx ON silo (username, domain); diff --git a/scripts/oracle/msilo-create.sql b/scripts/oracle/msilo-create.sql index 1ae2b27c10f..08e375c7b95 100644 --- a/scripts/oracle/msilo-create.sql +++ b/scripts/oracle/msilo-create.sql @@ -9,7 +9,7 @@ CREATE TABLE silo ( exp_time NUMBER(10) DEFAULT 0 NOT NULL, snd_time NUMBER(10) DEFAULT 0 NOT NULL, ctype VARCHAR2(32) DEFAULT 'text/plain', - body BLOB DEFAULT '' + body BLOB ); CREATE OR REPLACE TRIGGER silo_tr diff --git a/scripts/postgres/msilo-create.sql b/scripts/postgres/msilo-create.sql index f59e64f01aa..d6323d0af51 100644 --- a/scripts/postgres/msilo-create.sql +++ b/scripts/postgres/msilo-create.sql @@ -9,7 +9,7 @@ CREATE TABLE silo ( exp_time INTEGER DEFAULT 0 NOT NULL, snd_time INTEGER DEFAULT 0 NOT NULL, ctype VARCHAR(32) DEFAULT 'text/plain' NOT NULL, - body BYTEA DEFAULT '' NOT NULL + body BYTEA NOT NULL ); CREATE INDEX silo_account_idx ON silo (username, domain); From 5478bf025f4c15d2d0348f222455f64a6fda7f22 Mon Sep 17 00:00:00 2001 From: fabriziopicconi Date: Sat, 12 Apr 2014 16:45:23 +0200 Subject: [PATCH 44/44] thrift 0.9 compilation with thrift 0.9 support --- modules/cachedb_cassandra/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/cachedb_cassandra/Makefile b/modules/cachedb_cassandra/Makefile index dc812346df0..9326177ef09 100644 --- a/modules/cachedb_cassandra/Makefile +++ b/modules/cachedb_cassandra/Makefile @@ -5,7 +5,7 @@ NAME=cachedb_cassandra.so CXX=g++ LD=g++ LIBS=cachedb_cassandra_dbase.o cassandra_constants.o cassandra_types.o Cassandra.o -L/usr/local/lib -lthrift -CXXFLAGS=$(CFLAGS:-Wno-deprecated option=) +CXXFLAGS=$(CFLAGS:-Wno-deprecated option=) -DHAVE_NETINET_IN_H # suppress a TON of warnings CXXFLAGS+= -Wno-write-strings -Wno-deprecated -Wno-unused-function -Wno-sign-compare -Wno-strict-aliasing