budb: Only have one build rule for budb_errs.c
[openafs.git] / src / budb / db_lock.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 #include <afsconfig.h>
11 #include <afs/param.h>
12
13 #include <roken.h>
14
15 #include <sys/types.h>
16 #ifdef AFS_NT40_ENV
17 #include <winsock2.h>
18 #else
19 #include <netinet/in.h>
20 #include <sys/time.h>
21 #endif
22 #include <afs/afsutil.h>
23 #include <ubik.h>
24 #include <afs/bubasics.h>
25 #include "budb_errs.h"
26 #include "database.h"
27 #include "budb_internal.h"
28 #include "error_macros.h"
29 #include "afs/audit.h"
30
31 #define DBH_POS(ptr)            ( (char *) (ptr) - (char *) &db.h )
32
33 afs_int32 FreeAllLocks(struct rx_call *, afs_uint32);
34 afs_int32 FreeLock(struct rx_call *, afs_uint32);
35 afs_int32 GetInstanceId(struct rx_call *, afs_uint32 *);
36 afs_int32 GetLock(struct rx_call *, afs_uint32, afs_int32, afs_int32,
37                   afs_uint32 *);
38
39 afs_int32
40 SBUDB_FreeAllLocks(struct rx_call *call, afs_uint32 instanceId)
41 {
42     afs_int32 code;
43
44     code = FreeAllLocks(call, instanceId);
45     osi_auditU(call, BUDB_FrALckEvent, code, AUD_END);
46     return code;
47 }
48
49 afs_int32
50 FreeAllLocks(struct rx_call *call, afs_uint32 instanceId)
51 {
52     db_lockP startPtr, endPtr;
53     struct ubik_trans *ut;
54     afs_int32 code;
55
56     if (callPermitted(call) == 0)
57         return (BUDB_NOTPERMITTED);
58
59     code = InitRPC(&ut, LOCKWRITE, 1);
60     if (code)
61         return (code);
62
63     startPtr = &db.h.textLocks[0];
64     endPtr = &db.h.textLocks[TB_NUM - 1];
65     while (startPtr <= endPtr) {
66         if ((ntohl(startPtr->lockState) == 1)
67             && (ntohl(startPtr->instanceId) == instanceId)
68             ) {
69             /* release the lock */
70             startPtr->lockState = 0;    /* unlock it */
71             startPtr->lockTime = 0;
72             startPtr->expires = 0;
73             startPtr->instanceId = 0;
74             dbwrite(ut, DBH_POS(startPtr), (char *)startPtr,
75                     sizeof(db_lockT));
76         }
77         startPtr++;
78     }
79     code = ubik_EndTrans(ut);
80     return (code);
81 }
82
83 afs_int32
84 SBUDB_FreeLock(struct rx_call *call, afs_uint32 lockHandle)
85 {
86     afs_int32 code;
87
88     code = FreeLock(call, lockHandle);
89     osi_auditU(call, BUDB_FreLckEvent, code, AUD_END);
90     return code;
91 }
92
93 afs_int32
94 FreeLock(struct rx_call *call, afs_uint32 lockHandle)
95 {
96     db_lockP lockPtr = 0;
97     struct ubik_trans *ut;
98     afs_int32 code;
99
100     if (callPermitted(call) == 0)
101         return (BUDB_NOTPERMITTED);
102
103     code = InitRPC(&ut, LOCKWRITE, 1);
104     if (code)
105         return (code);
106
107     if (checkLockHandle(ut, lockHandle) == 0)
108         ABORT(BUDB_BADARGUMENT);
109
110     lockPtr = &db.h.textLocks[lockHandle - 1];
111
112     lockPtr->lockState = 0;     /* unlock it */
113     lockPtr->lockTime = 0;
114     lockPtr->expires = 0;
115     lockPtr->instanceId = 0;
116     dbwrite(ut, DBH_POS(lockPtr), (char *)lockPtr, sizeof(db_lockT));
117
118     code = ubik_EndTrans(ut);
119     return (code);
120
121   abort_exit:
122     ubik_AbortTrans(ut);
123     return (code);
124 }
125
126 afs_int32
127 SBUDB_GetInstanceId(struct rx_call *call, afs_uint32 *instanceId)
128 {
129     afs_int32 code;
130
131     code = GetInstanceId(call, instanceId);
132     osi_auditU(call, BUDB_GetIIdEvent, code, AUD_END);
133     return code;
134 }
135
136 afs_int32
137 GetInstanceId(struct rx_call *call, afs_uint32 *instanceId)
138 {
139     struct ubik_trans *ut;
140     afs_int32 code;
141     afs_int32 instanceValue;
142
143     LogDebug(4, "GetInstanceId:\n");
144
145     /* *** Allow anyone to get the instance id ***
146      * if ( callPermitted(call) == 0 )
147      *    return(BUDB_NOTPERMITTED);
148      */
149
150     code = InitRPC(&ut, LOCKWRITE, 1);
151     if (code)
152         return (code);
153
154     instanceValue = ntohl(db.h.lastInstanceId) + 1;
155
156     set_header_word(ut, lastInstanceId, htonl(instanceValue));
157
158     code = ubik_EndTrans(ut);
159     return (code);
160 }
161
162
163 afs_int32
164 SBUDB_GetLock(struct rx_call *call, afs_uint32 instanceId, afs_int32 lockName,
165               afs_int32 expiration, afs_uint32 *lockHandle)
166 {
167     afs_int32 code;
168
169     code = GetLock(call, instanceId, lockName, expiration, lockHandle);
170     osi_auditU(call, BUDB_GetLckEvent, code, AUD_END);
171     return code;
172 }
173
174 afs_int32
175 GetLock(struct rx_call *call, afs_uint32 instanceId, afs_int32 lockName,
176         afs_int32 expiration, afs_uint32 *lockHandle)
177 {
178     struct timeval tv;
179     db_lockP lockPtr;
180     struct ubik_trans *ut;
181
182     afs_int32 code;
183
184     if (callPermitted(call) == 0)
185         return (BUDB_NOTPERMITTED);
186
187     if ((lockName < 0) || (lockName >= TB_NUM))
188         return (BUDB_BADARGUMENT);
189
190     /* get the current time */
191     gettimeofday(&tv, 0);
192
193     code = InitRPC(&ut, LOCKWRITE, 1);
194     if (code)
195         return (code);
196
197     lockPtr = &db.h.textLocks[lockName];
198
199     if ((ntohl(lockPtr->lockState) != 0)        /* lock set */
200         &&(ntohl(lockPtr->expires) > tv.tv_sec) /* not expired */
201         ) {
202         if (ntohl(lockPtr->instanceId) == instanceId)
203             code = BUDB_SELFLOCKED;
204         else
205             code = BUDB_LOCKED;
206         goto abort_exit;
207     }
208
209     lockPtr->lockState = htonl(1);      /* lock it */
210     lockPtr->lockTime = htonl(tv.tv_sec);       /* when locked */
211     lockPtr->expires = htonl(tv.tv_sec + expiration);
212     lockPtr->instanceId = htonl(instanceId);
213     code = dbwrite(ut, DBH_POS(lockPtr), (char *)lockPtr, sizeof(db_lockT));
214     if (code)
215         ABORT(code);
216
217     *lockHandle = (afs_uint32) (lockName + 1);
218     code = ubik_EndTrans(ut);
219     return (code);
220
221   abort_exit:
222     ubik_AbortTrans(ut);
223     return (code);
224 }
225
226
227 /* checkLockHandle
228  * exit:
229  *      0 - if invalid handle
230  *      1 - if handle is valid
231  */
232 int
233 checkLockHandle(struct ubik_trans *ut, afs_uint32 lockHandle)
234 {
235     return (((lockHandle > 0) && (lockHandle <= TB_NUM)) ? 1 : 0);
236 }