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 #include <stdio.h>
30 #include <string.h>
31
32 #include "db_headers.h"
33 #include "db_vers.h"
34 #include "nisdb_mt.h"
35
36 const long unsigned MAXLOW = 32768*32768;
37
38 /* Constructor that makes copy of 'other'. */
vers(vers * other)39 vers::vers(vers* other)
40 {
41 INITRW(vers);
42 assign(other);
43 }
44
45 void
assign(vers * other)46 vers::assign(vers* other)
47 {
48 WRITELOCKV(this, "w vers::assign");
49 if (other == NULL) {
50 syslog(LOG_ERR, "vers::vers: making copy of null vers?");
51 vers_high = vers_low = time_sec = time_usec = 0;
52 } else {
53 time_sec = other->time_sec;
54 time_usec = other->time_usec;
55 vers_low = other->vers_low;
56 vers_high = other->vers_high;
57 }
58 WRITEUNLOCKV(this, "wu vers::assign");
59 }
60
61 /*
62 * Creates new 'vers' with next higher minor version.
63 * If minor version exceeds MAXLOW, bump up major version instead.
64 * Set timestamp to that of the current time.
65 */
66 vers*
nextminor()67 vers::nextminor()
68 {
69 READLOCK(this, NULL, "r vers::nextminor");
70
71 vers * newvers = new vers;
72
73 if (newvers == NULL) {
74 READUNLOCK(this, NULL, "ru vers::nextminor DB_MEMORY_LIMIT");
75 FATAL3("vers::nextminor: cannot allocation space",
76 DB_MEMORY_LIMIT, NULL);
77 }
78
79 struct timeval mt;
80 gettimeofday(&mt, NULL);
81
82 newvers->time_sec = (unsigned int) mt.tv_sec;
83 newvers->time_usec = (unsigned int) mt.tv_usec;
84 newvers->vers_low = (this->vers_low + 1);
85 newvers->vers_high = (this->vers_high);
86
87 if (newvers->vers_low >= MAXLOW){
88 newvers->vers_high++;
89 newvers->vers_low = 0;
90 }
91
92 READUNLOCK(this, newvers, "ru vers::nextminor");
93 return (newvers);
94 }
95
96 /*
97 * Creates new 'vers' with next higher major version.
98 * Set timestamp to that of the current time.
99 */
100 vers*
nextmajor()101 vers::nextmajor()
102 {
103 READLOCK(this, NULL, "r vers::nextmajor");
104
105 vers * newvers = new vers;
106
107 if (newvers == NULL) {
108 READUNLOCK(this, NULL, "ru vers::nextmajor DB_MEMORY_LIMIT");
109 FATAL3("vers::nextminor: cannot allocation space",
110 DB_MEMORY_LIMIT, NULL);
111 }
112
113 struct timeval mt;
114 gettimeofday(&mt, NULL);
115
116 newvers->time_sec = (unsigned int) mt.tv_sec;
117 newvers->time_usec = (unsigned int) mt.tv_usec;
118 newvers->vers_low = 0;
119 newvers->vers_high = (this->vers_high+1);
120
121 READUNLOCK(this, newvers, "ru vers::nextmajor");
122 return (newvers);
123 }
124
125 /*
126 * Predicate indicating whether this vers is earlier than 'other' in
127 * terms of version numbers.
128 */
129 bool_t
earlier_than(vers * other)130 vers::earlier_than(vers *other)
131 {
132 int ret, lret;
133
134 if (other == NULL) {
135 syslog(LOG_ERR,
136 "vers::earlier_than: comparing against null vers");
137 return (FALSE);
138 }
139
140 READLOCK(this, FALSE, "r vers::earlier_than");
141 READLOCKNR(other, lret, "r other vers::earlier_than");
142 if (lret != 0) {
143 READUNLOCK(this, FALSE, "ru + r other vers::earlier_than");
144 return (FALSE);
145 }
146
147 if (other->vers_high > vers_high) ret = TRUE;
148 else if (other->vers_high < vers_high) ret = FALSE;
149 else if (other->vers_low > vers_low) ret = TRUE;
150 else ret = FALSE;
151
152 READUNLOCKNR(other, lret, "ru other vers::earlier_than");
153 READUNLOCK(this, ret, ((lret != 0) ?
154 "ru + ru other vers::earlier_than" :
155 "ru vers::earlier_than"));
156 return (ret);
157 }
158
159 /* Print the value of this 'vers' to specified file. */
160 void
print(FILE * file)161 vers::print(FILE* file)
162 {
163 char *thetime;
164 thetime = ctime((long *) (&(time_sec)));
165 thetime[strlen(thetime)-1] = 0;
166
167 READLOCKV(this, "r vers::print");
168 fprintf(file, "version=%u.%u %s:%u",
169 vers_high,
170 vers_low,
171 /* time_sec, */
172 thetime,
173 time_usec);
174 READUNLOCKV(this, "ru vers::print");
175 }
176
177 void
zero()178 vers::zero() {
179 WRITELOCKV(this, "r vers::zero");
180 vers_high = vers_low = time_sec = time_usec = 0;
181 WRITEUNLOCKV(this, "ru vers::zero");
182 }
183
184 bool_t
equal(vers * other)185 vers::equal( vers *other) {
186 READLOCK(this, FALSE, "r vers::equal");
187 bool_t ret = other != NULL &&
188 vers_high == other->vers_high &&
189 vers_low == other->vers_low &&
190 time_sec == other->time_sec &&
191 time_usec == other->time_usec;
192 READUNLOCK(this, ret, "ru vers::equal");
193 return (ret);
194 };
195