Initial IBM OpenAFS 1.0 tree
[openafs.git] / src / volser / voltrans.c
1 /*
2  * (C) COPYRIGHT IBM CORPORATION 1988
3  * LICENSED MATERIALS - PROPERTY OF IBM
4  */
5 /*
6  *  Module:         Voltrans.c
7  *  System:         Volser
8  *  Instituition:           ITC, CMU
9  *  Date:                   December, 88
10  */
11
12 #include <afs/param.h>
13 #ifdef AFS_NT40_ENV
14 #include <afs/afsutil.h>
15 #else
16 #include <sys/time.h>
17 #endif
18 #include <rx/rx.h>
19 #include "volser.h"
20
21 static struct volser_trans *allTrans=0;
22 static afs_int32 transCounter = 1;
23
24 /* create a new transaction, returning ptr to same with high ref count */
25 struct volser_trans *NewTrans(avol, apart)
26 afs_int32 avol;
27 afs_int32 apart; {
28     /* set volid, next, partition */
29     register struct volser_trans *tt;
30     struct timeval tp;
31     struct timezone tzp;
32
33     /* don't allow the same volume to be attached twice */
34     for(tt=allTrans;tt;tt=tt->next) {
35         if ((tt->volid == avol) && (tt->partition == apart)){
36             return (struct volser_trans *) 0;   /* volume busy */
37         }
38     }
39     tt = (struct volser_trans *) malloc(sizeof(struct volser_trans));
40     bzero(tt, sizeof(struct volser_trans));
41     tt->volid = avol;
42     tt->partition = apart;
43     tt->next = allTrans;
44     tt->tid = transCounter++;
45     tt->refCount = 1;
46     tt->rxCallPtr = (struct rx_call *)0;
47     strcpy(tt->lastProcName,"");
48     gettimeofday(&tp,&tzp);
49     tt->creationTime = tp.tv_sec;
50     allTrans = tt;
51     tt->time = FT_ApproxTime();
52     return tt;
53 }
54
55 /* find a trans, again returning with high ref count */
56 struct volser_trans *FindTrans(atrans)
57 register afs_int32 atrans; {
58     register struct volser_trans *tt;
59     for(tt=allTrans;tt;tt=tt->next) {
60         if (tt->tid == atrans) {
61             tt->time = FT_ApproxTime();
62             tt->refCount++;
63             return tt;
64         }
65     }
66     return (struct volser_trans *) 0;
67 }
68
69 /* delete transaction if refcount == 1, otherwise queue delete for later.  Does implicit TRELE */
70 DeleteTrans(atrans)
71 register struct volser_trans *atrans; {
72     register struct volser_trans *tt, **lt;
73     afs_int32 error;
74
75     if (atrans->refCount > 1) {
76         /* someone else is using it now */
77         atrans->refCount--;
78         atrans->tflags |= TTDeleted;
79         return 0;
80     }
81     /* otherwise we zap it ourselves */
82     lt = &allTrans;
83     for(tt = *lt; tt; lt = &tt->next, tt = *lt) {
84         if (tt == atrans) {
85             if (tt->volume)
86                 VDetachVolume(&error, tt->volume);
87             tt->volume = (struct Volume *) 0;
88             *lt = tt->next;
89             free(tt);
90             return 0;
91         }
92     }
93     return -1;  /* failed to find the transaction in the generic list */
94 }
95
96 /* THOLD is a macro defined in volser.h */
97
98 /* put a transaction back */
99 TRELE (at)
100 register struct volser_trans *at; {
101     if (at->refCount == 0){ 
102         Log("TRELE: bad refcount\n");
103         return VOLSERTRELE_ERROR;
104     }
105     
106     at->time = FT_ApproxTime(); /* we're still using it */
107     if (at->refCount == 1 && (at->tflags & TTDeleted)) {
108         DeleteTrans(at);
109         return 0;
110     }
111     /* otherwise simply drop refcount */
112     at->refCount--;
113     return 0;
114 }
115
116 /* look for old transactions and delete them */
117 #define OLDTRANSTIME        600     /* seconds */
118 #define OLDTRANSWARN        300     /* seconds */
119 static int GCDeletes = 0;
120 GCTrans() 
121 {
122     register struct volser_trans *tt, *nt;
123     afs_int32 now;
124     
125     now = FT_ApproxTime();
126
127     for(tt = allTrans; tt; tt=nt) {
128         nt = tt->next;          /* remember in case we zap it */
129         if (tt->time + OLDTRANSWARN < now) {
130             Log("trans %u on volume %u %s than %d seconds\n",
131                 tt->tid, tt->volid, 
132                 ((tt->refCount>0)?"is older":"has been idle for more"),
133                 (((now-tt->time)/GCWAKEUP)*GCWAKEUP));
134         }
135         if (tt->refCount > 0) continue;
136         if (tt->time + OLDTRANSTIME < now) {
137             Log("trans %u on volume %u has timed out\n", tt->tid, tt->volid);
138             tt->refCount++;     /* we're using it now */
139             DeleteTrans(tt);    /* drops refCount or deletes it */
140             GCDeletes++;
141         }
142     }
143     return 0;
144 }
145 /*return the head of the transaction list */
146 struct volser_trans *TransList()
147 {
148     return(allTrans);
149 }