241 lines
6.8 KiB
C
241 lines
6.8 KiB
C
/*
|
|
* Copyright (c) 1993 by the University of Southern California
|
|
*
|
|
* For copying and distribution information, please see the file
|
|
* <usc-license.h>
|
|
*
|
|
* Written by bcn 1991 as part of the Prospero distribution
|
|
* Modified by bcn 1/93 extended rreq structure
|
|
* Modified by swa 11/93 multithreaded
|
|
*/
|
|
|
|
#include <usc-license.h>
|
|
#include <stdio.h>
|
|
#include <ardp.h>
|
|
#include <stdlib.h> /* malloc or free */
|
|
#include <pmachine.h> /* for bzero() */
|
|
#include <pfs.h> /* for pafree and stfree */
|
|
|
|
/* When debugging the ARDP window flow control stuff, use these definitions. */
|
|
/* Defaults are set here. */
|
|
#if 0
|
|
#define ARDP_MY_WINDOW_SZ 2 /* Our window size;currently only implemented on
|
|
the client. Here, the client asks for a
|
|
window size of 2, for testing. */
|
|
#undef ARDP_DEFAULT_WINDOW_SZ /* Peer window size the server will use for its
|
|
default flow-control strategy. */ */
|
|
#define ARDP_DEFAULT_WINDOW_SZ 1 /* for testing. */
|
|
#endif
|
|
|
|
static ardp_default_timeout = ARDP_DEFAULT_TIMEOUT;
|
|
static ardp_default_retry = ARDP_DEFAULT_RETRY;
|
|
int ardp_priority = 0; /* Default priority */
|
|
|
|
static RREQ lfree = NOREQ;
|
|
int rreq_count = 0;
|
|
int rreq_max = 0;
|
|
|
|
#ifndef NDEBUG
|
|
static int rreq_member_of_list(RREQ rr, RREQ list);
|
|
#endif
|
|
|
|
extern RREQ ardp_pendingQ, ardp_runQ, ardp_doneQ;
|
|
|
|
|
|
/*
|
|
* rralloc - allocate and initialize an rreq structure
|
|
*
|
|
* ardp_rqalloc returns a pointer to an initialized structure of type
|
|
* RREQ. If it is unable to allocate such a structure, it
|
|
* returns NOREQ (NULL).
|
|
*/
|
|
RREQ
|
|
ardp_rqalloc()
|
|
{
|
|
RREQ rq;
|
|
|
|
p_th_mutex_lock(p_th_mutexARDP_RQALLOC);
|
|
if(lfree) {
|
|
rq = lfree;
|
|
lfree = lfree->next;
|
|
}
|
|
else {
|
|
rq = (RREQ) malloc(sizeof(RREQ_ST));
|
|
if (!rq) return(NOREQ);
|
|
rreq_max++;
|
|
}
|
|
rreq_count++;
|
|
p_th_mutex_unlock(p_th_mutexARDP_RQALLOC);
|
|
|
|
rq->status = ARDP_STATUS_NOSTART;
|
|
#ifdef ARDP_MY_WINDOW_SZ
|
|
rq->flags = ARDP_FLAG_SEND_MY_WINDOW_SIZE; /* used by clients. */
|
|
#else
|
|
rq->flags = 0;
|
|
#endif
|
|
rq->cid = 0;
|
|
rq->priority = ardp_priority;
|
|
rq->pf_priority = 0;
|
|
rq->peer_ardp_version = 0;
|
|
rq->inpkt = NOPKT;
|
|
rq->rcvd_tot = 0;
|
|
rq->rcvd = NOPKT;
|
|
rq->rcvd_thru = 0;
|
|
#ifdef ARDP_MY_WINDOW_SZ /* This sets the window size we'll ask for */
|
|
rq->window_sz = ARDP_MY_WINDOW_SZ;
|
|
#else
|
|
rq->window_sz = 0;
|
|
#endif
|
|
rq->pwindow_sz = ARDP_DEFAULT_WINDOW_SZ; /* sets the window size we assume
|
|
our peer will accept in the
|
|
absence of an explicit
|
|
request. */
|
|
rq->comp_thru = NOPKT;
|
|
rq->outpkt = NOPKT;
|
|
rq->trns_tot = 0;
|
|
rq->trns = NOPKT;
|
|
rq->prcvd_thru = 0;
|
|
bzero(&(rq->peer),sizeof(rq->peer));
|
|
rq->rcvd_time.tv_sec = 0;
|
|
rq->rcvd_time.tv_usec = 0;
|
|
rq->svc_start_time.tv_sec = 0;
|
|
rq->svc_start_time.tv_usec = 0;
|
|
rq->svc_comp_time.tv_sec = 0;
|
|
rq->svc_comp_time.tv_usec = 0;
|
|
rq->timeout.tv_sec = ardp_default_timeout;
|
|
rq->timeout.tv_usec = 0;
|
|
rq->timeout_adj.tv_sec = ardp_default_timeout;
|
|
rq->timeout_adj.tv_usec = 0;
|
|
rq->wait_till.tv_sec = 0;
|
|
rq->wait_till.tv_usec = 0;
|
|
rq->retries = ardp_default_retry;
|
|
rq->retries_rem = ardp_default_retry;
|
|
rq->svc_rwait = 0;
|
|
rq->svc_rwait_seq = 0;
|
|
rq->inf_queue_pos = 0;
|
|
rq->inf_sys_time = 0;
|
|
#ifdef PROSPERO
|
|
rq->auth_info = NULL;
|
|
#endif /* PROSPERO */
|
|
rq->client_name = NULL;
|
|
rq->peer_sw_id = NULL;
|
|
rq->cfunction = NULL;
|
|
rq->cfunction_args = NULL;
|
|
rq->previous = NOREQ;
|
|
rq->next = NOREQ;
|
|
return(rq);
|
|
}
|
|
|
|
/*
|
|
* ardp_rqfree - free a RREQ structure
|
|
*
|
|
* ardp_rqfree takes a pointer to a RREQ structure and adds it to
|
|
* the free list for later reuse.
|
|
*/
|
|
void ardp_rqfree(rq)
|
|
RREQ rq;
|
|
{
|
|
#ifndef NDEBUG
|
|
/* This is different from the way we do consistency checking in the PFS
|
|
library, because here the status field is just sitting to be used. */
|
|
assert(rq->status != ARDP_STATUS_FREE);
|
|
rq->status = ARDP_STATUS_FREE;
|
|
CHECK_OFFLIST(rq); /* MITRA macro; probably does the same as those
|
|
listed below. Might never be defined. */
|
|
assert(!rreq_member_of_list(rq, ardp_pendingQ));
|
|
assert(!rreq_member_of_list(rq, ardp_runQ));
|
|
assert(!rreq_member_of_list(rq, ardp_doneQ));
|
|
#endif
|
|
/* Don't free inpkt or comp_thru, already on rcvd */
|
|
if(rq->rcvd) ardp_ptlfree(rq->rcvd);
|
|
/* But outpkt has not been added to trns */
|
|
if(rq->outpkt) ardp_ptlfree(rq->outpkt);
|
|
if(rq->trns) ardp_ptlfree(rq->trns);
|
|
#ifdef PROSPERO
|
|
if (rq->auth_info) pafree(rq->auth_info);
|
|
#endif /* PROSPERO */
|
|
if (rq->client_name) stfree(rq->client_name);
|
|
if (rq->peer_sw_id) stfree(rq->peer_sw_id);
|
|
|
|
p_th_mutex_lock(p_th_mutexARDP_RQALLOC);
|
|
rq->next = lfree;
|
|
rq->previous = NOREQ;
|
|
lfree = rq;
|
|
rreq_count--;
|
|
p_th_mutex_unlock(p_th_mutexARDP_RQALLOC);
|
|
}
|
|
|
|
|
|
|
|
#ifndef NDEBUG
|
|
/* Free just the fields that are needed only while processing the request
|
|
but not the fields that will be used for a request that is on the ardp_doneQ
|
|
so that the results can be retransmitted. This is only needed when
|
|
debugging the server. It is used in ardp_respond() and is #ifdef'd NDEBUG.
|
|
*/
|
|
void
|
|
ardp_rq_partialfree(RREQ rq)
|
|
{
|
|
#ifdef PROSPERO
|
|
if (rq->auth_info) { pafree(rq->auth_info); rq->auth_info = NULL; }
|
|
#endif /* PROSPERO */
|
|
if (rq->client_name) { stfree(rq->client_name); rq->client_name = NULL; }
|
|
if (rq->peer_sw_id) { stfree(rq->peer_sw_id); rq->peer_sw_id = NULL; }
|
|
}
|
|
#endif
|
|
|
|
|
|
/*
|
|
* ardp_rqlfree - free many RREQ structures
|
|
*
|
|
* ardp_rqlfree takes a pointer to a RREQ structure frees it and any linked
|
|
* RREQ structures. It is used to free an entrie list of RREQ
|
|
* structures.
|
|
*/
|
|
|
|
void
|
|
ardp_rqlfree(rq)
|
|
RREQ rq;
|
|
{
|
|
RREQ nxt;
|
|
|
|
while(rq != NOREQ) {
|
|
nxt = rq->next;
|
|
ardp_rqfree(rq);
|
|
rq = nxt;
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
* ardp_set_retry - change default values for timeout
|
|
*
|
|
* ardp_set_retry takes a value for timout in seconds and a count
|
|
* of the number of retries to allow. It sets static variables in this
|
|
* file used by pralloc to set the default values in request structures
|
|
* it allocates.
|
|
*/
|
|
int
|
|
ardp_set_retry(int to, int rt)
|
|
{
|
|
/* XXX This is a critical section, but it is safe as long as we are not on
|
|
a multiprocessor and don't block. So no mutexes. */
|
|
ardp_default_timeout = to;
|
|
ardp_default_retry = rt;
|
|
/*** XXX End Critical section */
|
|
return(ARDP_SUCCESS);
|
|
}
|
|
|
|
|
|
#ifndef NDEBUG
|
|
/* Return 1 if the RREQ rr is a member of the list LIST. */
|
|
static int
|
|
rreq_member_of_list(RREQ rr, RREQ list)
|
|
{
|
|
for ( ; list; list = list->next) {
|
|
if (rr == list) return 1;
|
|
}
|
|
return 0; /* false */
|
|
}
|
|
#endif
|