xref: /illumos-gate/usr/src/lib/libnisdb/db_vers.cc (revision 1da57d551424de5a9d469760be7c4b4d4f10a755)
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