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