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 */
db_dictlog_entry(int a,vers * v,char * tname,table_obj * obj)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
~db_dictlog_entry()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
print()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
free_table_entry(table_obj * obj)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
delete_log_entry(db_dictlog_entry * lentry)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
execute_on_log(bool_t (* func)(db_dictlog_entry *,char *,int *),char * dict,bool_t clean)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
print_log_entry(db_dictlog_entry * j,char *,int * count)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
print()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
get()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
append(db_dictlog_entry * j)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