int ast_hashtab_insert_immediate(struct ast_hashtab *tab, const void *obj)
{
- /* normally, you'd insert "safely" by checking to see if the element is
- already there; in this case, you must already have checked. If an element
- is already in the hashtable, that matches this one, most likely this one
- will be found first, but.... */
-
- /* will force a resize if the resize func returns 1 */
- /* returns 1 on success, 0 if there's a problem */
unsigned int h;
- int c;
- struct ast_hashtab_bucket *b;
+ int res=0;
- if (!tab)
- return 0;
-
- if (!obj)
- return 0;
+ if (!tab || !obj)
+ return res;
if (tab->do_locking)
ast_rwlock_wrlock(&tab->lock);
h = (*tab->hash)(obj) % tab->hash_tab_size;
- for (c = 0, b = tab->array[h]; b; b = b->next)
- c++;
-
- if (c + 1 > tab->largest_bucket_size)
- tab->largest_bucket_size = c + 1;
-
- if (!(b = ast_calloc(1, sizeof(*b))))
- return 0;
-
- b->object = obj;
- b->next = tab->array[h];
-
- if (b->next)
- b->next->prev = b;
-
- tlist_add_head(&(tab->tlist), b);
-
- tab->array[h] = b;
- tab->hash_tab_elements++;
-
- if ((*tab->resize)(tab))
- ast_hashtab_resize(tab);
+ res = ast_hashtab_insert_immediate_bucket(tab,obj,h);
if (tab->do_locking)
ast_rwlock_unlock(&tab->lock);
- return 1;
+ return res;
}
int ast_hashtab_insert_immediate_bucket(struct ast_hashtab *tab, const void *obj, unsigned int h)
{
- /* normally, you'd insert "safely" by checking to see if the element is
- already there; in this case, you must already have checked. If an element
- is already in the hashtable, that matches this one, most likely this one
- will be found first, but.... */
-
- /* will force a resize if the resize func returns 1 */
- /* returns 1 on success, 0 if there's a problem */
int c;
struct ast_hashtab_bucket *b;
void *ast_hashtab_remove_object_via_lookup(struct ast_hashtab *tab, void *obj)
{
/* looks up the object; removes the corresponding bucket */
- unsigned int h;
- struct ast_hashtab_bucket *b;
+ const void *obj2;
if (!tab || !obj)
return 0;
if (tab->do_locking)
ast_rwlock_wrlock(&tab->lock);
- h = (*tab->hash)(obj) % tab->hash_tab_size;
- for (b = tab->array[h]; b; b = b->next) {
- void *obj2;
-
- if (!(*tab->compare)(obj,b->object)) {
- obj2 = ast_hashtab_remove_object_internal(tab,b,h);
-
- if (tab->do_locking)
- ast_rwlock_unlock(&tab->lock);
-
- return (void *) obj2; /* inside this code, the obj's are untouchable, but outside, they aren't */
- }
- }
+ obj2 = ast_hashtab_remove_object_via_lookup_nolock(tab,obj);
if (tab->do_locking)
ast_rwlock_unlock(&tab->lock);
- return 0;
+ return (void *)obj2;
}
void *ast_hashtab_remove_object_via_lookup_nolock(struct ast_hashtab *tab, void *obj)
h = (*tab->hash)(obj) % tab->hash_tab_size;
for (b = tab->array[h]; b; b = b->next) {
- void *obj2;
if (!(*tab->compare)(obj, b->object)) {
+ const void *obj2;
obj2 = ast_hashtab_remove_object_internal(tab, b, h);
- if (tab->do_locking)
- ast_rwlock_unlock(&tab->lock);
-
return (void *) obj2; /* inside this code, the obj's are untouchable, but outside, they aren't */
}
}
/* looks up the object by hash and then comparing pts in bucket list instead of
calling the compare routine; removes the bucket -- a slightly cheaper operation */
/* looks up the object; removes the corresponding bucket */
- unsigned int h;
- struct ast_hashtab_bucket *b;
+ const void *obj2;
if (!tab || !obj)
return 0;
if (tab->do_locking)
ast_rwlock_wrlock(&tab->lock);
- h = (*tab->hash)(obj) % tab->hash_tab_size;
- for (b = tab->array[h]; b; b = b->next) {
- const void *obj2;
-
- if (obj == b->object) {
- obj2 = ast_hashtab_remove_object_internal(tab, b, h);
- if (tab->do_locking)
- ast_rwlock_unlock(&tab->lock);
-
- return (void *) obj2; /* inside this code, the obj's are untouchable, but outside, they aren't */
- }
- }
+ obj2 = ast_hashtab_remove_this_object_nolock(tab,obj);
if (tab->do_locking)
ast_rwlock_unlock(&tab->lock);
- return 0;
+ return (void *)obj2;
}
void *ast_hashtab_remove_this_object_nolock(struct ast_hashtab *tab, void *obj)
h = (*tab->hash)(obj) % tab->hash_tab_size;
for (b = tab->array[h]; b; b = b->next) {
- const void *obj2;
if (obj == b->object) {
+ const void *obj2;
obj2 = ast_hashtab_remove_object_internal(tab, b, h);
- if (tab->do_locking)
- ast_rwlock_unlock(&tab->lock);
-
return (void *) obj2; /* inside this code, the obj's are untouchable, but outside, they aren't */
}
}
AST_LIST_LOCK(&parkinglot);
/* Check for channel variable PARKINGEXTEN */
parkingexten = pbx_builtin_getvar_helper(chan, "PARKINGEXTEN");
+ ast_log(LOG_NOTICE,"Chan cont/ext/prio = %s/%s/%d\n", chan->context, chan->exten, chan->priority);
if (!ast_strlen_zero(parkingexten)) {
if (ast_exists_extension(NULL, parking_con, parkingexten, 1, NULL)) {
AST_LIST_UNLOCK(&parkinglot);
ast_log(LOG_WARNING, "Requested parking extension already exists: %s@%s\n", parkingexten, parking_con);
return 0; /* Continue execution if possible */
}
+ ast_log(LOG_NOTICE,"2. Chan cont/ext/prio = %s/%s/%d\n", chan->context, chan->exten, chan->priority);
ast_copy_string(pu->parkingexten, parkingexten, sizeof(pu->parkingexten));
x = atoi(parkingexten);
} else {
/* Select parking space within range */
+ ast_log(LOG_NOTICE,"3. Chan cont/ext/prio = %s/%s/%d\n", chan->context, chan->exten, chan->priority);
parking_range = parking_stop - parking_start+1;
for (i = 0; i < parking_range; i++) {
x = (i + parking_offset) % parking_range + parking_start;
parking_offset = x - parking_start + 1;
}
+ ast_log(LOG_NOTICE,"4. Chan cont/ext/prio = %s/%s/%d\n", chan->context, chan->exten, chan->priority);
chan->appl = "Parked Call";
chan->data = NULL;
!ast_strlen_zero(parkmohclass) ? strlen(parkmohclass) + 1 : 0);
}
+ ast_log(LOG_NOTICE,"5. Chan cont/ext/prio = %s/%s/%d\n", chan->context, chan->exten, chan->priority);
pu->start = ast_tvnow();
pu->parkingnum = x;
pu->parkingtime = (timeout > 0) ? timeout : parkingtime;
pu->priority = chan->macropriority ? chan->macropriority : chan->priority;
AST_LIST_INSERT_TAIL(&parkinglot, pu, list);
+ ast_log(LOG_NOTICE,"6. Chan cont/ext/prio = %s/%s/%d\n", chan->context, chan->exten, chan->priority);
/* If parking a channel directly, don't quiet yet get parking running on it */
if (peer == chan)
pu->notquiteyet = 1;
AST_LIST_UNLOCK(&parkinglot);
/* Wake up the (presumably select()ing) thread */
+ ast_log(LOG_NOTICE,"7. Chan cont/ext/prio = %s/%s/%d\n", chan->context, chan->exten, chan->priority);
pthread_kill(parking_thread, SIGURG);
ast_verb(2, "Parked %s on %d@%s. Will timeout back to extension [%s] %s, %d in %d seconds\n", pu->chan->name, pu->parkingnum, parking_con, pu->context, pu->exten, pu->priority, (pu->parkingtime/1000));
if (pu->parkingnum != -1)
snprintf(pu->parkingexten, sizeof(pu->parkingexten), "%d", x);
+ ast_log(LOG_NOTICE,"8. Chan cont/ext/prio = %s/%s/%d\n", chan->context, chan->exten, chan->priority);
manager_event(EVENT_FLAG_CALL, "ParkedCall",
"Exten: %s\r\n"
"Channel: %s\r\n"
S_OR(pu->chan->cid.cid_name, "<unknown>")
);
+ ast_log(LOG_NOTICE,"9. Chan cont/ext/prio = %s/%s/%d\n", chan->context, chan->exten, chan->priority);
if (peer && adsipark && ast_adsi_available(peer)) {
adsi_announce_park(peer, pu->parkingexten); /* Only supports parking numbers */
ast_adsi_unload_session(peer);
}
+ ast_log(LOG_NOTICE,"10. Chan cont/ext/prio = %s/%s/%d\n", chan->context, chan->exten, chan->priority);
con = ast_context_find(parking_con);
if (!con)
con = ast_context_create(NULL, parking_con, registrar);
if (!con) /* Still no context? Bad */
ast_log(LOG_ERROR, "Parking context '%s' does not exist and unable to create\n", parking_con);
/* Tell the peer channel the number of the parking space */
+ ast_log(LOG_NOTICE,"11. Chan cont/ext/prio = %s/%s/%d\n", chan->context, chan->exten, chan->priority);
if (peer && pu->parkingnum != -1) { /* Only say number if it's a number */
/* Make sure we don't start saying digits to the channel being parked */
ast_set_flag(peer, AST_FLAG_MASQ_NOSTREAM);
ast_say_digits(peer, pu->parkingnum, "", peer->language);
ast_clear_flag(peer, AST_FLAG_MASQ_NOSTREAM);
+ ast_log(LOG_NOTICE,"12. Chan cont/ext/prio = %s/%s/%d\n", chan->context, chan->exten, chan->priority);
}
if (con) {
if (!ast_add_extension2(con, 1, pu->parkingexten, 1, NULL, NULL, parkedcall, ast_strdup(pu->parkingexten), ast_free_ptr, registrar))
notify_metermaids(pu->parkingexten, parking_con, AST_DEVICE_INUSE);
+ ast_log(LOG_NOTICE,"13. Chan cont/ext/prio = %s/%s/%d\n", chan->context, chan->exten, chan->priority);
}
if (pu->notquiteyet) {
/* Wake up parking thread if we're really done */
+ ast_log(LOG_NOTICE,"14. Chan cont/ext/prio = %s/%s/%d\n", chan->context, chan->exten, chan->priority);
ast_indicate_data(pu->chan, AST_CONTROL_HOLD,
S_OR(parkmohclass, NULL),
!ast_strlen_zero(parkmohclass) ? strlen(parkmohclass) + 1 : 0);
pu->notquiteyet = 0;
pthread_kill(parking_thread, SIGURG);
+ ast_log(LOG_NOTICE,"15. Chan cont/ext/prio = %s/%s/%d\n", chan->context, chan->exten, chan->priority);
}
+ ast_log(LOG_NOTICE,"16. Chan cont/ext/prio = %s/%s/%d\n", chan->context, chan->exten, chan->priority);
return 0;
}
struct ast_channel *chan;
struct ast_frame *f;
+ ast_log(LOG_NOTICE,"a. Chan cont/ext/prio = %s/%s/%d\n", chan->context, chan->exten, chan->priority);
/* Make a new, fake channel that we'll use to masquerade in the real one */
if (!(chan = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, rchan->accountcode, rchan->exten, rchan->context, rchan->amaflags, "Parked/%s",rchan->name))) {
ast_log(LOG_WARNING, "Unable to create parked channel\n");
return -1;
}
+ ast_log(LOG_NOTICE,"b. Chan cont/ext/prio = %s/%s/%d\n", chan->context, chan->exten, chan->priority);
/* Make formats okay */
chan->readformat = rchan->readformat;
chan->writeformat = rchan->writeformat;
ast_channel_masquerade(chan, rchan);
+ ast_log(LOG_NOTICE,"c. Chan cont/ext/prio = %s/%s/%d\n", chan->context, chan->exten, chan->priority);
/* Setup the extensions and such */
set_c_e_p(chan, rchan->context, rchan->exten, rchan->priority);
if (f)
ast_frfree(f);
+ ast_log(LOG_NOTICE,"d. Chan cont/ext/prio = %s/%s/%d\n", chan->context, chan->exten, chan->priority);
ast_park_call(chan, peer, timeout, extout);
+ ast_log(LOG_NOTICE,"e. Chan cont/ext/prio = %s/%s/%d\n", chan->context, chan->exten, chan->priority);
return 0;
}
set_peers(&parker, &parkee, peer, chan, sense);
/* Setup the exten/priority to be s/1 since we don't know
where this call should return */
+ ast_log(LOG_NOTICE,"A. Chan cont/ext/prio = %s/%s/%d\n", chan->context, chan->exten, chan->priority);
strcpy(chan->exten, "s");
+ ast_log(LOG_NOTICE,"B. Chan cont/ext/prio = %s/%s/%d\n", chan->context, chan->exten, chan->priority);
chan->priority = 1;
if (chan->_state != AST_STATE_UP)
res = ast_answer(chan);
res = ast_safe_sleep(chan, 1000);
if (!res)
res = ast_park_call(parkee, parker, 0, NULL);
+ ast_log(LOG_NOTICE,"C. Chan cont/ext/prio = %s/%s/%d\n", chan->context, chan->exten, chan->priority);
ast_module_user_remove(u);
char xferto[256];
int res;
+ ast_log(LOG_NOTICE,"W. Chan %s cont/ext/prio = %s/%s/%d\n", chan->name, chan->context, chan->exten, chan->priority);
+ ast_log(LOG_NOTICE,"W. Peer %s cont/ext/prio = %s/%s/%d\n", peer->name, peer->context, peer->exten, peer->priority);
set_peers(&transferer, &transferee, peer, chan, sense);
transferer_real_context = real_ctx(transferer, transferee);
/* Start autoservice on chan while we talk to the originator */
finishup(transferee);
return res;
}
+ ast_log(LOG_NOTICE,"X. Chan %s cont/ext/prio = %s/%s/%d\n", chan->name, chan->context, chan->exten, chan->priority);
+ ast_log(LOG_NOTICE,"X. Peer %s cont/ext/prio = %s/%s/%d\n", peer->name, peer->context, peer->exten, peer->priority);
if (!strcmp(xferto, ast_parking_ext())) {
res = finishup(transferee);
+ ast_log(LOG_NOTICE,"Y. Chan %s cont/ext/prio = %s/%s/%d\n", chan->name, chan->context, chan->exten, chan->priority);
+ ast_log(LOG_NOTICE,"Y. Peer %s cont/ext/prio = %s/%s/%d\n", peer->name, peer->context, peer->exten, peer->priority);
if (res)
res = -1;
else if (!ast_park_call(transferee, transferer, 0, NULL)) { /* success */
/* We return non-zero, but tell the PBX not to hang the channel when
the thread dies -- We have to be careful now though. We are responsible for
hanging up the channel, else it will never be hung up! */
-
+ ast_log(LOG_NOTICE,"Y2. Chan %s cont/ext/prio = %s/%s/%d\n", chan->name, chan->context, chan->exten, chan->priority);
+ ast_log(LOG_NOTICE,"Y2. Peer %s cont/ext/prio = %s/%s/%d\n", peer->name, peer->context, peer->exten, peer->priority);
return (transferer == peer) ? AST_PBX_KEEPALIVE : AST_PBX_NO_HANGUP_PEER;
} else {
+ ast_log(LOG_NOTICE,"Z. Chan %s cont/ext/prio = %s/%s/%d\n", chan->name, chan->context, chan->exten, chan->priority);
+ ast_log(LOG_NOTICE,"Z. Peer %s cont/ext/prio = %s/%s/%d\n", peer->name, peer->context, peer->exten, peer->priority);
ast_log(LOG_WARNING, "Unable to park call %s\n", transferee->name);
}
/*! \todo XXX Maybe we should have another message here instead of invalid extension XXX */
} else if (ast_exists_extension(transferee, transferer_real_context, xferto, 1, transferer->cid.cid_num)) {
+ ast_log(LOG_NOTICE,"ZZ. Chan cont/ext/prio = %s/%s/%d\n", chan->context, chan->exten, chan->priority);
+ ast_log(LOG_NOTICE,"ZZ. Peer cont/ext/prio = %s/%s/%d\n", peer->context, peer->exten, peer->priority);
pbx_builtin_setvar_helper(peer, "BLINDTRANSFER", transferee->name);
pbx_builtin_setvar_helper(chan, "BLINDTRANSFER", peer->name);
res=finishup(transferee);
if (option_verbose > 2)
ast_verbose(VERBOSE_PREFIX_3 "Transferring %s to '%s' (context %s) priority 1\n"
,transferee->name, xferto, transferer_real_context);
+ ast_log(LOG_NOTICE,"ZZZ. Chan cont/ext/prio = %s/%s/%d\n", chan->context, chan->exten, chan->priority);
+ ast_log(LOG_NOTICE,"ZZZ. Peer cont/ext/prio = %s/%s/%d\n", peer->context, peer->exten, peer->priority);
if (ast_async_goto(transferee, transferer_real_context, xferto, 1))
ast_log(LOG_WARNING, "Async goto failed :-(\n");
} else {
/* Set the channel's new extension, since it exists, using transferer context */
set_c_e_p(transferee, transferer_real_context, xferto, 0);
+ ast_log(LOG_NOTICE,"ZZZZ. Chan cont/ext/prio = %s/%s/%d\n", chan->context, chan->exten, chan->priority);
+ ast_log(LOG_NOTICE,"ZZZZ. Peer cont/ext/prio = %s/%s/%d\n", peer->context, peer->exten, peer->priority);
}
check_goto_on_transfer(transferer);
+ ast_log(LOG_NOTICE,"ZZZZZ. Chan cont/ext/prio = %s/%s/%d\n", chan->context, chan->exten, chan->priority);
+ ast_log(LOG_NOTICE,"ZZZZZ. Peer cont/ext/prio = %s/%s/%d\n", peer->context, peer->exten, peer->priority);
return res;
} else {
ast_verb(3, "Unable to find extension '%s' in context '%s'\n", xferto, transferer_real_context);
ast_verb(2, "Hungup during autoservice stop on '%s'\n", transferee->name);
return res;
}
+ ast_log(LOG_NOTICE,"ZZZZZZ. Chan cont/ext/prio = %s/%s/%d\n", chan->context, chan->exten, chan->priority);
+ ast_log(LOG_NOTICE,"ZZZZZZ. Peer cont/ext/prio = %s/%s/%d\n", peer->context, peer->exten, peer->priority);
return FEATURE_RETURN_SUCCESS;
}
if (!res)
res = ast_safe_sleep(chan, 1000);
/* Park the call */
+ ast_log(LOG_NOTICE,"PCE. Chan cont/ext/prio = %s/%s/%d\n", chan->context, chan->exten, chan->priority);
if (!res)
res = ast_park_call(chan, chan, 0, NULL);