1 /*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License, Version 1.0 only
6 * (the "License"). You may not use this file except in compliance
7 * with the License.
8 *
9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10 * or http://www.opensolaris.org/os/licensing.
11 * See the License for the specific language governing permissions
12 * and limitations under the License.
13 *
14 * When distributing Covered Code, include this CDDL HEADER in each
15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16 * If applicable, add the following below this CDDL HEADER, with the
17 * fields enclosed by brackets "[]" replaced with your own identifying
18 * information: Portions Copyright [yyyy] [name of copyright owner]
19 *
20 * CDDL HEADER END
21 */
22 /*
23 * db_vers.cc
24 *
25 * Copyright (c) 1988-2000 by Sun Microsystems, Inc.
26 * All Rights Reserved.
27 */
28
29 #pragma ident "%Z%%M% %I% %E% SMI"
30
31 #include <stdio.h>
32 #include <string.h>
33
34 #include "db_headers.h"
35 #include "db_vers.h"
36 #include "nisdb_mt.h"
37
38 const long unsigned MAXLOW = 32768*32768;
39
40 /* Constructor that makes copy of 'other'. */
vers(vers * other)41 vers::vers(vers* other)
42 {
43 INITRW(vers);
44 assign(other);
45 }
46
47 void
assign(vers * other)48 vers::assign(vers* other)
49 {
50 WRITELOCKV(this, "w vers::assign");
51 if (other == NULL) {
52 syslog(LOG_ERR, "vers::vers: making copy of null vers?");
53 vers_high = vers_low = time_sec = time_usec = 0;
54 } else {
55 time_sec = other->time_sec;
56 time_usec = other->time_usec;
57 vers_low = other->vers_low;
58 vers_high = other->vers_high;
59 }
60 WRITEUNLOCKV(this, "wu vers::assign");
61 }
62
63 /*
64 * Creates new 'vers' with next higher minor version.
65 * If minor version exceeds MAXLOW, bump up major version instead.
66 * Set timestamp to that of the current time.
67 */
68 vers*
nextminor()69 vers::nextminor()
70 {
71 READLOCK(this, NULL, "r vers::nextminor");
72
73 vers * newvers = new vers;
74
75 if (newvers == NULL) {
76 READUNLOCK(this, NULL, "ru vers::nextminor DB_MEMORY_LIMIT");
77 FATAL3("vers::nextminor: cannot allocation space",
78 DB_MEMORY_LIMIT, NULL);
79 }
80
81 struct timeval mt;
82 gettimeofday(&mt, NULL);
83
84 newvers->time_sec = (unsigned int) mt.tv_sec;
85 newvers->time_usec = (unsigned int) mt.tv_usec;
86 newvers->vers_low = (this->vers_low + 1);
87 newvers->vers_high = (this->vers_high);
88
89 if (newvers->vers_low >= MAXLOW){
90 newvers->vers_high++;
91 newvers->vers_low = 0;
92 }
93
94 READUNLOCK(this, newvers, "ru vers::nextminor");
95 return (newvers);
96 }
97
98 /*
99 * Creates new 'vers' with next higher major version.
100 * Set timestamp to that of the current time.
101 */
102 vers*
nextmajor()103 vers::nextmajor()
104 {
105 READLOCK(this, NULL, "r vers::nextmajor");
106
107 vers * newvers = new vers;
108
109 if (newvers == NULL) {
110 READUNLOCK(this, NULL, "ru vers::nextmajor DB_MEMORY_LIMIT");
111 FATAL3("vers::nextminor: cannot allocation space",
112 DB_MEMORY_LIMIT, NULL);
113 }
114
115 struct timeval mt;
116 gettimeofday(&mt, NULL);
117
118 newvers->time_sec = (unsigned int) mt.tv_sec;
119 newvers->time_usec = (unsigned int) mt.tv_usec;
120 newvers->vers_low = 0;
121 newvers->vers_high = (this->vers_high+1);
122
123 READUNLOCK(this, newvers, "ru vers::nextmajor");
124 return (newvers);
125 }
126
127 /*
128 * Predicate indicating whether this vers is earlier than 'other' in
129 * terms of version numbers.
130 */
131 bool_t
earlier_than(vers * other)132 vers::earlier_than(vers *other)
133 {
134 int ret, lret;
135
136 if (other == NULL) {
137 syslog(LOG_ERR,
138 "vers::earlier_than: comparing against null vers");
139 return (FALSE);
140 }
141
142 READLOCK(this, FALSE, "r vers::earlier_than");
143 READLOCKNR(other, lret, "r other vers::earlier_than");
144 if (lret != 0) {
145 READUNLOCK(this, FALSE, "ru + r other vers::earlier_than");
146 return (FALSE);
147 }
148
149 if (other->vers_high > vers_high) ret = TRUE;
150 else if (other->vers_high < vers_high) ret = FALSE;
151 else if (other->vers_low > vers_low) ret = TRUE;
152 else ret = FALSE;
153
154 READUNLOCKNR(other, lret, "ru other vers::earlier_than");
155 READUNLOCK(this, ret, ((lret != 0) ?
156 "ru + ru other vers::earlier_than" :
157 "ru vers::earlier_than"));
158 return (ret);
159 }
160
161 /* Print the value of this 'vers' to specified file. */
162 void
print(FILE * file)163 vers::print(FILE* file)
164 {
165 char *thetime;
166 thetime = ctime((long *) (&(time_sec)));
167 thetime[strlen(thetime)-1] = 0;
168
169 READLOCKV(this, "r vers::print");
170 fprintf(file, "version=%u.%u %s:%u",
171 vers_high,
172 vers_low,
173 /* time_sec, */
174 thetime,
175 time_usec);
176 READUNLOCKV(this, "ru vers::print");
177 }
178
179 void
zero()180 vers::zero() {
181 WRITELOCKV(this, "r vers::zero");
182 vers_high = vers_low = time_sec = time_usec = 0;
183 WRITEUNLOCKV(this, "ru vers::zero");
184 }
185
186 bool_t
equal(vers * other)187 vers::equal( vers *other) {
188 READLOCK(this, FALSE, "r vers::equal");
189 bool_t ret = other != NULL &&
190 vers_high == other->vers_high &&
191 vers_low == other->vers_low &&
192 time_sec == other->time_sec &&
193 time_usec == other->time_usec;
194 READUNLOCK(this, ret, "ru vers::equal");
195 return (ret);
196 };
197