11 /* QMGR_PEER *qmgr_peer_create(job, queue)
15 /* QMGR_PEER *qmgr_peer_find(job, queue)
19 /* QMGR_PEER *qmgr_peer_obtain(job, queue)
23 /* void qmgr_peer_free(peer)
26 /* QMGR_PEER *qmgr_peer_select(job)
30 /* These routines add/delete/manipulate per-job peers.
31 /* Each peer corresponds to a specific job and destination.
32 /* It is similar to per-transport queue structure, but groups
33 /* only the entries of the given job.
35 /* qmgr_peer_create() creates an empty peer structure for the named
36 /* job and destination. It is an error to call this function
37 /* if a peer for given combination already exists.
39 /* qmgr_peer_find() looks up the peer for the named destination
40 /* for the named job. A null result means that the peer
43 /* qmgr_peer_obtain() looks up the peer for the named destination
44 /* for the named job. If it doesn't exist yet, it creates it.
46 /* qmgr_peer_free() disposes of a per-job peer after all
47 /* its entries have been taken care of. It is an error to dispose
48 /* of a peer still in use.
50 /* qmgr_peer_select() attempts to find a peer of named job that
51 /* has messages pending delivery. This routine implements
52 /* round-robin search among job's peers.
54 /* Panic: consistency check failure.
58 /* The Secure Mailer license must be distributed with this software.
68 /* Utility library. */
74 /* Application-specific. */
78 /* qmgr_peer_create - create and initialize message peer structure */
80 QMGR_PEER
*qmgr_peer_create(QMGR_JOB
*job
, QMGR_QUEUE
*queue
)
84 peer
= (QMGR_PEER
*) mymalloc(sizeof(QMGR_PEER
));
87 QMGR_LIST_APPEND(job
->peer_list
, peer
, peers
);
88 htable_enter(job
->peer_byname
, queue
->name
, (char *) peer
);
90 QMGR_LIST_INIT(peer
->entry_list
);
94 /* qmgr_peer_free - release peer structure */
96 void qmgr_peer_free(QMGR_PEER
*peer
)
98 const char *myname
= "qmgr_peer_free";
99 QMGR_JOB
*job
= peer
->job
;
100 QMGR_QUEUE
*queue
= peer
->queue
;
103 * Sanity checks. It is an error to delete a referenced peer structure.
105 if (peer
->refcount
!= 0)
106 msg_panic("%s: refcount: %d", myname
, peer
->refcount
);
107 if (peer
->entry_list
.next
!= 0)
108 msg_panic("%s: entry list not empty: %s", myname
, queue
->name
);
110 QMGR_LIST_UNLINK(job
->peer_list
, QMGR_PEER
*, peer
, peers
);
111 htable_delete(job
->peer_byname
, queue
->name
, (void (*) (char *)) 0);
112 myfree((char *) peer
);
115 /* qmgr_peer_find - lookup peer associated with given job and queue */
117 QMGR_PEER
*qmgr_peer_find(QMGR_JOB
*job
, QMGR_QUEUE
*queue
)
119 return ((QMGR_PEER
*) htable_find(job
->peer_byname
, queue
->name
));
122 /* qmgr_peer_obtain - find/create peer associated with given job and queue */
124 QMGR_PEER
*qmgr_peer_obtain(QMGR_JOB
*job
, QMGR_QUEUE
*queue
)
128 if ((peer
= qmgr_peer_find(job
, queue
)) == 0)
129 peer
= qmgr_peer_create(job
, queue
);
133 /* qmgr_peer_select - select next peer suitable for delivery within given job */
135 QMGR_PEER
*qmgr_peer_select(QMGR_JOB
*job
)
141 * If we find a suitable site, rotate the list to enforce round-robin
142 * selection. See similar selection code in qmgr_transport_select().
144 for (peer
= job
->peer_list
.next
; peer
; peer
= peer
->peers
.next
) {
146 if (queue
->window
> queue
->busy_refcount
&& peer
->entry_list
.next
!= 0) {
147 QMGR_LIST_ROTATE(job
->peer_list
, peer
, peers
);
149 msg_info("qmgr_peer_select: %s %s %s (%d of %d)",
150 job
->message
->queue_id
, queue
->transport
->name
, queue
->name
,
151 queue
->busy_refcount
+ 1, queue
->window
);