tm: which_cancel renamed and takes more parameters
authorAndrei Pelinescu-Onciul <andrei@iptel.org>
Tue, 14 Jul 2009 12:44:21 +0000 (14:44 +0200)
committerAndrei Pelinescu-Onciul <andrei@iptel.org>
Tue, 14 Jul 2009 12:44:21 +0000 (14:44 +0200)
- which_cancel() renamed to prepare_to_cancel() to better reflect
  its real purpose.
- which_cancel_f renamed to prepare_to_cancel_f
- tm_binds which_cancel member renamed to prepare_to_cancel
- should_cancel_branch() renamed to prepare_cancel_branch().
- prepare_to_cancel() takes now an extra parameter (skip_branches)
  which contains a bitmap of the branches that should be skipped
  (not canceled).

modules/tm/t_cancel.c
modules/tm/t_cancel.h
modules/tm/t_fwd.c
modules/tm/t_reply.c
modules/tm/timer.c
modules/tm/tm_load.c
modules/tm/tm_load.h

index c89295a..bf12c3c 100644 (file)
  * 2008-03-08  e2e_cancel handles non replied branches in 3 different ways,
  *              selectable by the tm cancel_b_method parameter: fake reply,
  *              retransmit request and send cancel on branch (andrei)
+ * 2009-07-14  renamed which_cancel() to prepare_to_cancel() for better
+ *              reflecting its purpose
+ *             prepare_to_cancel() takes now an additional skip_branches
+ *              bitmap parameter (andrei)
  */
 
 #include <stdio.h> /* for FILE* in fifo_uac_cancel */
 #include "t_hooks.h"
 
 
-/* determine which branches should be canceled; can be called 
-   without REPLY_LOCK, since should_cancel_branch() is atomic now
-   -- andrei
- WARNING: - has side effects, see should_cancel_branch()
-          - one _must_ call cancel_uacs(cancel_bm) if *cancel_bm!=0 or
-            you'll have some un-cancelable branches */
-void which_cancel( struct cell *t, branch_bm_t *cancel_bm )
+/** Prepare to cancel a transaction.
+ * Determine which branches should be canceled and prepare them (internally
+ * mark them as "cancel in progress", see prepare_cancel_branch()).
+ * Can be called without REPLY_LOCK, since prepare_cancel_branch() is atomic 
+ *  now *  -- andrei
+ * WARNING: - has side effects, see prepare_cancel_branch()
+ *          - one _must_ call cancel_uacs(cancel_bm) if *cancel_bm!=0 or
+ *             you'll have some un-cancelable branches (because they remain
+ *             "marked" internally)
+ * @param t - transaction whose branches will be canceled
+ * @param cancel_bm - pointer to a branch bitmap that will be filled with
+*    the branches that must be canceled (must be passed to cancel_uacs() if
+*    !=0).
+*  @param skip - branch bitmap of branches that should not be canceled
+*/
+void prepare_to_cancel(struct cell *t, branch_bm_t *cancel_bm,
+                                               branch_bm_t skip_branches)
 {
        int i;
        int branches_no;
@@ -77,7 +91,7 @@ void which_cancel( struct cell *t, branch_bm_t *cancel_bm )
        branches_no=t->nr_of_outgoings;
        membar_depends(); 
        for( i=0 ; i<branches_no ; i++ ) {
-               if (should_cancel_branch(t, i, 1)) 
+               if (!(skip_branches & (1<<i)) &&  prepare_cancel_branch(t, i, 1))
                        *cancel_bm |= 1<<i ;
        }
 }
@@ -91,7 +105,7 @@ void which_cancel( struct cell *t, branch_bm_t *cancel_bm )
  *                       canceled 
  *          flags     - how_to_cancel flags, see cancel_branch()
  * returns: bitmap with the still active branches (on fr timer)
- * WARNING: always fill cancel_bm using which_cancel(), supplying values
+ * WARNING: always fill cancel_bm using prepare_to_cancel(), supplying values
  *          in any other way is a bug*/
 int cancel_uacs( struct cell *t, branch_bm_t cancel_bm, int flags)
 {
@@ -125,7 +139,7 @@ int cancel_all_uacs(struct cell *trans, int how)
        DBG("Canceling T@%p [%u:%u]\n", trans, trans->hash_index, trans->label);
        
        cancel_bm=0;
-       which_cancel(trans, &cancel_bm);
+       prepare_to_cancel(trans, &cancel_bm, 0);
         /* tell tm to cancel the call */
        i=cancel_uacs(trans, cancel_bm, how);
        
@@ -151,7 +165,7 @@ int cancel_all_uacs(struct cell *trans, int how)
 
 
 /* should be called directly only if one of the condition bellow is true:
- *  - should_cancel_branch or which_cancel returned true for this branch
+ *  - prepare_cancel_branch or prepare_to_cancel returned true for this branch
  *  - buffer value was 0 and then set to BUSY in an atomic op.:
  *     if (atomic_cmpxchg_long(&buffer, 0, BUSY_BUFFER)==0).
  *
@@ -346,7 +360,7 @@ void rpc_cancel(rpc_t* rpc, void* c)
        }
        /*  find the branches that need cancel-ing */
        LOCK_REPLIES(trans);
-               which_cancel(trans, &cancel_bm);
+               prepare_to_cancel(trans, &cancel_bm, 0);
        UNLOCK_REPLIES(trans);
         /* tell tm to cancel the call */
        DBG("Now calling cancel_uacs\n");
index d3ff20a..0ef3f37 100644 (file)
@@ -32,6 +32,9 @@
  *               no response or with response <100 (andrei)
  *  2007-06-04  should_cancel_branch() takes another parameter and it is safe
  *               to be called w/o REPLY_LOCK held (andrei)
+ *  2009-07-14  should_cancel_branch() renamed to prepare_cancel_branch() to
+ *               better reflect its purpose
+ *              which_cancel() renamed to prepare_to_cancel() (andrei)
  */
 
 
@@ -75,7 +78,7 @@
 #define F_CANCEL_UNREF 16 /* unref the trans after canceling */
 
 
-void which_cancel( struct cell *t, branch_bm_t *cancel_bm );
+void prepare_to_cancel(struct cell *t, branch_bm_t *cancel_bm, branch_bm_t s);
 int cancel_uacs( struct cell *t, branch_bm_t cancel_bm, int flags );
 int cancel_all_uacs(struct cell *trans, int how);
 int cancel_branch( struct cell *t, int branch, int flags );
@@ -84,10 +87,11 @@ typedef int(*cancel_uacs_f)( struct cell *t, branch_bm_t cancel_bm,
                                                                int flags );
 typedef int (*cancel_all_uacs_f)(struct cell *trans, int how);
 
-typedef void (*which_cancel_f)(struct cell *t, branch_bm_t *cancel_bm );
+typedef void (*prepare_to_cancel_f)(struct cell *t, branch_bm_t *cancel_bm,
+                                                                       branch_bm_t skip_branches);
 
 
-/* 
+/** Check if one branch needs CANCEL-ing and prepare it if it does.
  * Can be called w/o REPLY_LOCK held
  *  between this call and the call to cancel_uacs()/cancel_branch()
  *  if noreply is set to 1 it will return true even if no reply was received
@@ -96,8 +100,18 @@ typedef void (*which_cancel_f)(struct cell *t, branch_bm_t *cancel_bm );
  *  if noreply is set to 0 it will return true only if no cancel has already 
  *   been sent and a provisional (<200) reply >=100 was received.
  *  WARNING: has side effects: marks branches that should be canceled
- *   and a second call won't return them again */
-inline short static should_cancel_branch( struct cell *t, int b, int noreply )
+ *   and a second call won't return them again.
+ * @param t - transaction
+ * @param b - branch number
+ * @param noreply - 0 or 1. If 1 it will consider a branch with no replies
+ *  received so far as cancel-able. If 0 only branches that have received
+ * a provisional reply (>=100 <200) will be considered.
+ *
+ * @return 1 if the branch must be canceled (it will be internally marked as
+ *  cancel-in-progress) and 0 if it doesn't (either a CANCEL is not needed or a
+ *  CANCEL is in progress: somebody else is trying to CANCEL in the same time).
+ */
+inline short static prepare_cancel_branch( struct cell *t, int b, int noreply )
 {
        int last_received;
        unsigned long old;
index 969720b..0f14ecd 100644 (file)
@@ -358,7 +358,7 @@ int add_blind_uac( /*struct cell *t*/ )
        }
        /* make sure it will be replied */
        t->flags |= T_NOISY_CTIMER_FLAG;
-       membar_write(); /* to allow lockless which_cancel() we want to be sure 
+       membar_write(); /* to allow lockless prepare_to_cancel() we want to be sure
                                           all the writes finished before updating branch number*/
        t->nr_of_outgoings=(branch+1);
        /* start FR timer -- protocol set by default to PROTO_NONE,
@@ -460,7 +460,7 @@ int add_uac( struct cell *t, struct sip_msg *request, str *uri, str* next_hop,
                t->uac[branch].flags = TM_UAC_FLAG_RR|TM_UAC_FLAG_R2;
 #endif
        getbflagsval(0, &t->uac[branch].branch_flags);
-       membar_write(); /* to allow lockless ops (e.g. which_cancel()) we want
+       membar_write(); /* to allow lockless ops (e.g. prepare_to_cancel()) we want
                                           to be sure everything above is fully written before
                                           updating branches no. */
        t->nr_of_outgoings=(branch+1);
@@ -538,7 +538,7 @@ static int add_uac_from_buf( struct cell *t, struct sip_msg *request, str *uri,
        t->uac[branch].uri.s=t->uac[branch].request.buffer+
                request->first_line.u.request.method.len+1;
        t->uac[branch].uri.len=uri->len;
-       membar_write(); /* to allow lockless ops (e.g. which_cancel()) we want
+       membar_write(); /* to allow lockless ops (e.g. prepare_to_cancel()) we want
                                           to be sure everything above is fully written before
                                           updating branches no. */
        t->nr_of_outgoings=(branch+1);
@@ -729,7 +729,7 @@ void e2e_cancel( struct sip_msg *cancel_msg,
        }
        
        /* determine which branches to cancel ... */
-       which_cancel( t_invite, &cancel_bm );
+       prepare_to_cancel(t_invite, &cancel_bm, 0);
 #ifdef E2E_CANCEL_HOP_BY_HOP
        /* we don't need to set t_cancel label to be the same as t_invite if
         * we do hop by hop cancel. The cancel transaction will have a different 
index b6f4229..65ccce7 100644 (file)
@@ -523,7 +523,7 @@ static int _reply_light( struct cell *trans, char* buf, unsigned int len,
                /* determine if there are some branches to be canceled */
                if ( is_invite(trans) ) {
                        if (lock) LOCK_REPLIES( trans );
-                       which_cancel(trans, &cancel_bitmap );
+                       prepare_to_cancel(trans, &cancel_bitmap, 0);
                        if (lock) UNLOCK_REPLIES( trans );
                }
                /* and clean-up, including cancellations, if needed */
@@ -532,7 +532,7 @@ static int _reply_light( struct cell *trans, char* buf, unsigned int len,
 
        cancel_bitmap=0;
        if (lock) LOCK_REPLIES( trans );
-       if ( is_invite(trans) ) which_cancel(trans, &cancel_bitmap );
+       if ( is_invite(trans) ) prepare_to_cancel(trans, &cancel_bitmap, 0);
        if (trans->uas.status>=200) {
                LOG( L_ERR, "ERROR: _reply_light: can't generate %d reply"
                        " when a final %d was sent out\n", code, trans->uas.status);
@@ -1085,7 +1085,7 @@ static enum rps t_should_relay_response( struct cell *Trans , int new_code,
                        if (new_code>=600 && new_code<=699){
                                if (!(Trans->flags & T_6xx)){
                                        /* cancel only the first time we get a 6xx */
-                                       which_cancel(Trans, cancel_bitmap);
+                                       prepare_to_cancel(Trans, cancel_bitmap, 0);
                                        Trans->flags|=T_6xx;
                                }
                        }
@@ -1205,9 +1205,9 @@ static enum rps t_should_relay_response( struct cell *Trans , int new_code,
                /* really no more pending branches -- return lowest code */
                *should_store=0;
                *should_relay=picked_branch;
-               /* we dont need 'which_cancel' here -- all branches
+               /* we dont need 'prepare_to_cancel' here -- all branches
                   known to have completed */
-               /* which_cancel( Trans, cancel_bitmap ); */
+               /* prepare_to_cancel( Trans, cancel_bitmap, 0 ); */
                return RPS_COMPLETED;
        }
 
@@ -1225,7 +1225,7 @@ static enum rps t_should_relay_response( struct cell *Trans , int new_code,
                Trans->uac[branch].last_received=new_code;
                *should_relay= new_code==100? -1 : branch;
                if (new_code>=200 ) {
-                       which_cancel( Trans, cancel_bitmap );
+                       prepare_to_cancel( Trans, cancel_bitmap, 0);
                        return RPS_COMPLETED;
                } else return RPS_PROVISIONAL;
        }
@@ -1789,7 +1789,7 @@ enum rps local_reply( struct cell *t, struct sip_msg *p_msg, int branch,
        return reply_status;
 
 error:
-       which_cancel(t, cancel_bitmap);
+       prepare_to_cancel(t, cancel_bitmap, 0);
        UNLOCK_REPLIES(t);
        cleanup_uac_timers(t);
        if ( get_cseq(p_msg)->method.len==INVITE_LEN
index 0c0139a..9c38274 100644 (file)
@@ -302,7 +302,7 @@ static void fake_reply(struct cell *t, int branch, int code )
        short do_cancel_branch;
        enum rps reply_status;
 
-       do_cancel_branch = is_invite(t) && should_cancel_branch(t, branch, 0);
+       do_cancel_branch = is_invite(t) && prepare_cancel_branch(t, branch, 0);
        /* mark branch as canceled */
        t->uac[branch].request.flags|=F_RB_CANCELED;
        if ( is_local(t) ) {
index 02dd7f5..1e38676 100644 (file)
@@ -235,7 +235,7 @@ int load_tm( struct tm_binds *tmb)
        tmb->t_lookup_original = t_lookupOriginalT;
        tmb->t_check = t_check;
        tmb->unref_cell = unref_cell;
-       tmb->which_cancel = which_cancel;
+       tmb->prepare_to_cancel = prepare_to_cancel;
        tmb->get_stats = tm_get_stats;
 
 #ifdef WITH_TM_CTX
index 8a556d6..ff77010 100644 (file)
@@ -28,6 +28,7 @@
  * History:
  * --------
  * 2003-03-06  voicemail changes accepted
+ * 2009-07-14  renamed which_cancel* to prepare_to_cancel* (andrei)
  *
  */
 
@@ -143,7 +144,7 @@ struct tm_binds {
        tlookup_original_f t_lookup_original;
        tcheck_f t_check;
        unref_cell_f unref_cell;
-       which_cancel_f which_cancel;
+       prepare_to_cancel_f prepare_to_cancel;
        tm_get_stats_f get_stats;
 #ifdef WITH_TM_CTX
        tm_ctx_get_f tm_ctx_get;