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