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
38const long unsigned MAXLOW = 32768*32768;
39
40/* Constructor that makes copy of 'other'. */
41vers::vers(vers* other)
42{
43	INITRW(vers);
44	assign(other);
45}
46
47void
48vers::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 */
68vers*
69vers::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 */
102vers*
103vers::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*/
131bool_t
132vers::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. */
162void
163vers::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
179void
180vers::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
186bool_t
187vers::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