xref: /illumos-gate/usr/src/lib/libnisdb/db_vers.cc (revision 7c478bd9)
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'. */
41 vers::vers(vers* other)
42 {
43 	INITRW(vers);
44 	assign(other);
45 }
46 
47 void
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*
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*
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
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
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
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
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