xref: /titanic_52/usr/src/lib/libnisdb/db_dictlog.cc (revision 7c478bd95313f5f23a4c958a745db2134aa03244)
1*7c478bd9Sstevel@tonic-gate /*
2*7c478bd9Sstevel@tonic-gate  * CDDL HEADER START
3*7c478bd9Sstevel@tonic-gate  *
4*7c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5*7c478bd9Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
6*7c478bd9Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
7*7c478bd9Sstevel@tonic-gate  * with the License.
8*7c478bd9Sstevel@tonic-gate  *
9*7c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10*7c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
11*7c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
12*7c478bd9Sstevel@tonic-gate  * and limitations under the License.
13*7c478bd9Sstevel@tonic-gate  *
14*7c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
15*7c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16*7c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
17*7c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
18*7c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
19*7c478bd9Sstevel@tonic-gate  *
20*7c478bd9Sstevel@tonic-gate  * CDDL HEADER END
21*7c478bd9Sstevel@tonic-gate  */
22*7c478bd9Sstevel@tonic-gate /*
23*7c478bd9Sstevel@tonic-gate  *	db_dictlog.cc
24*7c478bd9Sstevel@tonic-gate  *
25*7c478bd9Sstevel@tonic-gate  *	Copyright (c) 1988-2000 by Sun Microsystems, Inc.
26*7c478bd9Sstevel@tonic-gate  *	All Rights Reserved.
27*7c478bd9Sstevel@tonic-gate  */
28*7c478bd9Sstevel@tonic-gate 
29*7c478bd9Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
30*7c478bd9Sstevel@tonic-gate 
31*7c478bd9Sstevel@tonic-gate #include <stdio.h>
32*7c478bd9Sstevel@tonic-gate 
33*7c478bd9Sstevel@tonic-gate #include <malloc.h>
34*7c478bd9Sstevel@tonic-gate #include <string.h>
35*7c478bd9Sstevel@tonic-gate #ifdef TDRPC
36*7c478bd9Sstevel@tonic-gate #include <sysent.h>
37*7c478bd9Sstevel@tonic-gate #endif
38*7c478bd9Sstevel@tonic-gate #include <unistd.h>
39*7c478bd9Sstevel@tonic-gate 
40*7c478bd9Sstevel@tonic-gate #include "nisdb_rw.h"
41*7c478bd9Sstevel@tonic-gate 
42*7c478bd9Sstevel@tonic-gate #include "db_headers.h"
43*7c478bd9Sstevel@tonic-gate #include "db_dictlog.h"
44*7c478bd9Sstevel@tonic-gate 
45*7c478bd9Sstevel@tonic-gate #include "nisdb_mt.h"
46*7c478bd9Sstevel@tonic-gate 
47*7c478bd9Sstevel@tonic-gate 
48*7c478bd9Sstevel@tonic-gate /*
49*7c478bd9Sstevel@tonic-gate  * Constructor:  Create a log entry using the given parameters.  Note that
50*7c478bd9Sstevel@tonic-gate  * pointers to db_query and entry_object are simply assigned, not copied.
51*7c478bd9Sstevel@tonic-gate  */
52*7c478bd9Sstevel@tonic-gate db_dictlog_entry::db_dictlog_entry(int a, vers * v, char *tname,
53*7c478bd9Sstevel@tonic-gate 				    table_obj *obj)
54*7c478bd9Sstevel@tonic-gate {
55*7c478bd9Sstevel@tonic-gate 	action = a;
56*7c478bd9Sstevel@tonic-gate 	aversion.assign(v);
57*7c478bd9Sstevel@tonic-gate 	table_name = tname;
58*7c478bd9Sstevel@tonic-gate 	table_object = obj;
59*7c478bd9Sstevel@tonic-gate 	next = NULL;
60*7c478bd9Sstevel@tonic-gate 	bversion.assign(v);
61*7c478bd9Sstevel@tonic-gate }
62*7c478bd9Sstevel@tonic-gate 
63*7c478bd9Sstevel@tonic-gate db_dictlog_entry::~db_dictlog_entry()
64*7c478bd9Sstevel@tonic-gate {
65*7c478bd9Sstevel@tonic-gate /* we might not have allocated these ourselves, so we cannot delete them */
66*7c478bd9Sstevel@tonic-gate }
67*7c478bd9Sstevel@tonic-gate 
68*7c478bd9Sstevel@tonic-gate /* prints a line from the journal */
69*7c478bd9Sstevel@tonic-gate void
70*7c478bd9Sstevel@tonic-gate db_dictlog_entry::print()
71*7c478bd9Sstevel@tonic-gate {
72*7c478bd9Sstevel@tonic-gate 	switch (action) {
73*7c478bd9Sstevel@tonic-gate 	case DB_ADD_TABLE:
74*7c478bd9Sstevel@tonic-gate 	    printf ("add: ");
75*7c478bd9Sstevel@tonic-gate 	    break;
76*7c478bd9Sstevel@tonic-gate 	case DB_REMOVE_TABLE:
77*7c478bd9Sstevel@tonic-gate 	    printf ("remove: ");
78*7c478bd9Sstevel@tonic-gate 	    break;
79*7c478bd9Sstevel@tonic-gate 	default:
80*7c478bd9Sstevel@tonic-gate 	    printf ("action(%d): ", action);
81*7c478bd9Sstevel@tonic-gate 	    break;
82*7c478bd9Sstevel@tonic-gate 	}
83*7c478bd9Sstevel@tonic-gate 
84*7c478bd9Sstevel@tonic-gate 	aversion.print(stdout);
85*7c478bd9Sstevel@tonic-gate 	putchar(' ');
86*7c478bd9Sstevel@tonic-gate 	if (table_name != NULL)
87*7c478bd9Sstevel@tonic-gate 		printf ("table %s\n", table_name);
88*7c478bd9Sstevel@tonic-gate 	else
89*7c478bd9Sstevel@tonic-gate 		printf("no table!\n");
90*7c478bd9Sstevel@tonic-gate 	bversion.print(stdout);
91*7c478bd9Sstevel@tonic-gate 	putchar('\n');
92*7c478bd9Sstevel@tonic-gate }
93*7c478bd9Sstevel@tonic-gate 
94*7c478bd9Sstevel@tonic-gate static void
95*7c478bd9Sstevel@tonic-gate free_table_entry(table_obj* obj)
96*7c478bd9Sstevel@tonic-gate {
97*7c478bd9Sstevel@tonic-gate 	if (obj == NULL)
98*7c478bd9Sstevel@tonic-gate 		return;
99*7c478bd9Sstevel@tonic-gate 
100*7c478bd9Sstevel@tonic-gate 	if (obj->ta_type != NULL)
101*7c478bd9Sstevel@tonic-gate 		free(obj->ta_type);
102*7c478bd9Sstevel@tonic-gate 
103*7c478bd9Sstevel@tonic-gate 	table_col* tcs = obj->ta_cols.ta_cols_val;
104*7c478bd9Sstevel@tonic-gate 	int i;
105*7c478bd9Sstevel@tonic-gate 	for (i = 0; i < obj->ta_cols.ta_cols_len; i++) {
106*7c478bd9Sstevel@tonic-gate 		if (tcs[i].tc_name != NULL)
107*7c478bd9Sstevel@tonic-gate 			delete tcs[i].tc_name;
108*7c478bd9Sstevel@tonic-gate 	}
109*7c478bd9Sstevel@tonic-gate 	if (tcs != NULL)
110*7c478bd9Sstevel@tonic-gate 		delete tcs;
111*7c478bd9Sstevel@tonic-gate 	if (obj->ta_path != NULL)
112*7c478bd9Sstevel@tonic-gate 		free(obj->ta_path);
113*7c478bd9Sstevel@tonic-gate 	free(obj);
114*7c478bd9Sstevel@tonic-gate }
115*7c478bd9Sstevel@tonic-gate 
116*7c478bd9Sstevel@tonic-gate static void
117*7c478bd9Sstevel@tonic-gate delete_log_entry(db_dictlog_entry *lentry)
118*7c478bd9Sstevel@tonic-gate {
119*7c478bd9Sstevel@tonic-gate 	char *tname;
120*7c478bd9Sstevel@tonic-gate 	table_obj *obj;
121*7c478bd9Sstevel@tonic-gate 	if (lentry) {
122*7c478bd9Sstevel@tonic-gate 		if ((tname = lentry->get_table_name())) {
123*7c478bd9Sstevel@tonic-gate 			delete tname;
124*7c478bd9Sstevel@tonic-gate 		}
125*7c478bd9Sstevel@tonic-gate 		if ((obj = lentry->get_table_object())) {
126*7c478bd9Sstevel@tonic-gate 		    free_table_entry(obj);
127*7c478bd9Sstevel@tonic-gate 		}
128*7c478bd9Sstevel@tonic-gate 		delete lentry;
129*7c478bd9Sstevel@tonic-gate 	}
130*7c478bd9Sstevel@tonic-gate }
131*7c478bd9Sstevel@tonic-gate 
132*7c478bd9Sstevel@tonic-gate /*
133*7c478bd9Sstevel@tonic-gate  * Execute given function 'func' on log.
134*7c478bd9Sstevel@tonic-gate  * function takes as arguments: pointer to log entry, character pointer to
135*7c478bd9Sstevel@tonic-gate  * another argument, and pointer to an integer, which is used as a counter.
136*7c478bd9Sstevel@tonic-gate  * 'func' should increment this value for each successful application.
137*7c478bd9Sstevel@tonic-gate  * The log is traversed until either 'func' returns FALSE, or when the log
138*7c478bd9Sstevel@tonic-gate  * is exhausted.  The second argument to 'execute_on_log' is passed as the
139*7c478bd9Sstevel@tonic-gate  * second argument to 'func'.  The third argument, 'clean' determines whether
140*7c478bd9Sstevel@tonic-gate  * the log entry is deleted after the function has been applied.
141*7c478bd9Sstevel@tonic-gate  * Returns the number of times that 'func' incremented its third argument.
142*7c478bd9Sstevel@tonic-gate  */
143*7c478bd9Sstevel@tonic-gate int
144*7c478bd9Sstevel@tonic-gate db_dictlog::execute_on_log(bool_t (*func) (db_dictlog_entry *,
145*7c478bd9Sstevel@tonic-gate 					    char *, int *),
146*7c478bd9Sstevel@tonic-gate 					    char* dict, bool_t clean)
147*7c478bd9Sstevel@tonic-gate {
148*7c478bd9Sstevel@tonic-gate 	db_dictlog_entry    *j;
149*7c478bd9Sstevel@tonic-gate 	int count = 0;
150*7c478bd9Sstevel@tonic-gate 	bool_t done = FALSE;
151*7c478bd9Sstevel@tonic-gate 
152*7c478bd9Sstevel@tonic-gate 	WRITELOCK(this, 0, "w db_dictlog::execute_on_log");
153*7c478bd9Sstevel@tonic-gate 	if (open() == FALSE) {   // open log
154*7c478bd9Sstevel@tonic-gate 		WRITEUNLOCK(this, 0, "wu db_dictlog::execute_on_log");
155*7c478bd9Sstevel@tonic-gate 		return (0);
156*7c478bd9Sstevel@tonic-gate 	}
157*7c478bd9Sstevel@tonic-gate 	while (!done) {
158*7c478bd9Sstevel@tonic-gate 		j = get();
159*7c478bd9Sstevel@tonic-gate 		if (j == NULL)
160*7c478bd9Sstevel@tonic-gate 			break;
161*7c478bd9Sstevel@tonic-gate 		if ((*func)(j, dict, &count) == FALSE) done = TRUE;
162*7c478bd9Sstevel@tonic-gate 		if (clean) delete_log_entry(j);
163*7c478bd9Sstevel@tonic-gate 	}
164*7c478bd9Sstevel@tonic-gate 
165*7c478bd9Sstevel@tonic-gate 	close();
166*7c478bd9Sstevel@tonic-gate 	WRITEUNLOCK(this, count, "wu db_dictlog::execute_on_log");
167*7c478bd9Sstevel@tonic-gate 	return (count);
168*7c478bd9Sstevel@tonic-gate }
169*7c478bd9Sstevel@tonic-gate 
170*7c478bd9Sstevel@tonic-gate static bool_t
171*7c478bd9Sstevel@tonic-gate print_log_entry(db_dictlog_entry *j, char*, int *count)
172*7c478bd9Sstevel@tonic-gate {
173*7c478bd9Sstevel@tonic-gate 	j->print();
174*7c478bd9Sstevel@tonic-gate 	++ *count;
175*7c478bd9Sstevel@tonic-gate 	return (TRUE);
176*7c478bd9Sstevel@tonic-gate }
177*7c478bd9Sstevel@tonic-gate 
178*7c478bd9Sstevel@tonic-gate /* Print contents of log file to stdout */
179*7c478bd9Sstevel@tonic-gate int
180*7c478bd9Sstevel@tonic-gate db_dictlog::print()
181*7c478bd9Sstevel@tonic-gate {
182*7c478bd9Sstevel@tonic-gate 	return (execute_on_log(&(print_log_entry), NULL));
183*7c478bd9Sstevel@tonic-gate }
184*7c478bd9Sstevel@tonic-gate 
185*7c478bd9Sstevel@tonic-gate /*
186*7c478bd9Sstevel@tonic-gate  * Return the next element in current log; return NULL if end of log or error.
187*7c478bd9Sstevel@tonic-gate  * Log must have been opened for READ.
188*7c478bd9Sstevel@tonic-gate  */
189*7c478bd9Sstevel@tonic-gate db_dictlog_entry
190*7c478bd9Sstevel@tonic-gate *db_dictlog::get()
191*7c478bd9Sstevel@tonic-gate {
192*7c478bd9Sstevel@tonic-gate 	db_dictlog_entry *j;
193*7c478bd9Sstevel@tonic-gate 
194*7c478bd9Sstevel@tonic-gate 	READLOCK(this, NULL, "r db_dictlog::get");
195*7c478bd9Sstevel@tonic-gate 	if (mode != PICKLE_READ) {
196*7c478bd9Sstevel@tonic-gate 		READUNLOCK(this, NULL, "ru db_dictlog::get");
197*7c478bd9Sstevel@tonic-gate 		return (NULL);
198*7c478bd9Sstevel@tonic-gate 	}
199*7c478bd9Sstevel@tonic-gate 
200*7c478bd9Sstevel@tonic-gate 	j = new db_dictlog_entry;
201*7c478bd9Sstevel@tonic-gate 
202*7c478bd9Sstevel@tonic-gate 	if (j == NULL) {
203*7c478bd9Sstevel@tonic-gate 		READUNLOCK(this, NULL, "ru db_dictlog::get");
204*7c478bd9Sstevel@tonic-gate 		return (NULL);
205*7c478bd9Sstevel@tonic-gate 	}
206*7c478bd9Sstevel@tonic-gate 	if (xdr_db_dictlog_entry(&(xdr), j) == FALSE) {
207*7c478bd9Sstevel@tonic-gate 		delete_log_entry (j);
208*7c478bd9Sstevel@tonic-gate /*    WARNING("Could not sucessfully finish reading log"); */
209*7c478bd9Sstevel@tonic-gate 		READUNLOCK(this, NULL, "ru db_dictlog::get");
210*7c478bd9Sstevel@tonic-gate 		return (NULL);
211*7c478bd9Sstevel@tonic-gate 	}
212*7c478bd9Sstevel@tonic-gate 	if (! j->sane()) {
213*7c478bd9Sstevel@tonic-gate 		WARNING("truncated log entry found");
214*7c478bd9Sstevel@tonic-gate 		delete_log_entry(j);
215*7c478bd9Sstevel@tonic-gate 		j = NULL;
216*7c478bd9Sstevel@tonic-gate 	}
217*7c478bd9Sstevel@tonic-gate 	READUNLOCK(this, j, "ru db_dictlog::get");
218*7c478bd9Sstevel@tonic-gate 	return (j);
219*7c478bd9Sstevel@tonic-gate }
220*7c478bd9Sstevel@tonic-gate 
221*7c478bd9Sstevel@tonic-gate /* Append given log entry to log. */
222*7c478bd9Sstevel@tonic-gate int
223*7c478bd9Sstevel@tonic-gate db_dictlog::append(db_dictlog_entry *j)
224*7c478bd9Sstevel@tonic-gate {
225*7c478bd9Sstevel@tonic-gate 	int status;
226*7c478bd9Sstevel@tonic-gate 
227*7c478bd9Sstevel@tonic-gate 	WRITELOCK(this, -1, "w db_dictlog::append");
228*7c478bd9Sstevel@tonic-gate 	if (mode != PICKLE_APPEND) {
229*7c478bd9Sstevel@tonic-gate 		WRITEUNLOCK(this, -1, "wu db_dictlog::append");
230*7c478bd9Sstevel@tonic-gate 		return (-1);
231*7c478bd9Sstevel@tonic-gate 	}
232*7c478bd9Sstevel@tonic-gate 
233*7c478bd9Sstevel@tonic-gate 	/* xdr returns TRUE if successful, FALSE otherwise */
234*7c478bd9Sstevel@tonic-gate 	status = ((xdr_db_dictlog_entry(&(xdr), j)) ? 0 : -1);
235*7c478bd9Sstevel@tonic-gate 	if (status < 0) {
236*7c478bd9Sstevel@tonic-gate 		WARNING("db_dictlog: could not write log entry");
237*7c478bd9Sstevel@tonic-gate 		WRITEUNLOCK(this, status, "wu db_dictlog::append");
238*7c478bd9Sstevel@tonic-gate 		return (status);
239*7c478bd9Sstevel@tonic-gate 	}
240*7c478bd9Sstevel@tonic-gate 
241*7c478bd9Sstevel@tonic-gate 	status = fflush(file);
242*7c478bd9Sstevel@tonic-gate 	if (status < 0) {
243*7c478bd9Sstevel@tonic-gate 		WARNING("db_dictlog: could not flush log entry to disk");
244*7c478bd9Sstevel@tonic-gate 		WRITEUNLOCK(this, status, "wu db_dictlog::append");
245*7c478bd9Sstevel@tonic-gate 		return (status);
246*7c478bd9Sstevel@tonic-gate 	}
247*7c478bd9Sstevel@tonic-gate 
248*7c478bd9Sstevel@tonic-gate 	status = fsync(fileno(file));
249*7c478bd9Sstevel@tonic-gate 	if (status < 0) {
250*7c478bd9Sstevel@tonic-gate 		WARNING("db_dictlog: could not sync log entry to disk");
251*7c478bd9Sstevel@tonic-gate 	}
252*7c478bd9Sstevel@tonic-gate 
253*7c478bd9Sstevel@tonic-gate 	WRITEUNLOCK(this, status, "wu db_dictlog::append");
254*7c478bd9Sstevel@tonic-gate 	return (status);
255*7c478bd9Sstevel@tonic-gate }
256