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
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.
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]
25 * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
26 * Use is subject to license terms.
29 #pragma ident "%Z%%M% %I% %E% SMI"
41 #include "db_headers.h"
47 delete_log_entry(db_log_entry
*lentry
)
52 if ((q
= lentry
->get_query())) {
55 if ((obj
= lentry
->get_object())) {
63 * Execute given function 'func' on log.
64 * function takes as arguments: pointer to log entry, character pointer to
65 * another argument, and pointer to an integer, which is used as a counter.
66 * 'func' should increment this value for each successful application.
67 * The log is traversed until either 'func' returns FALSE, or when the log
68 * is exhausted. The second argument to 'execute_on_log' is passed as the
69 * second argument to 'func'. The third argument, 'clean' determines whether
70 * the log entry is deleted after the function has been applied.
71 * Returns the number of times that 'func' incremented its third argument.
74 db_log::execute_on_log(bool_t (*func
) (db_log_entry
*, char *, int *),
75 char* arg
, bool_t clean
)
81 WRITELOCK(this, 0, "w db_log::execute_on_log");
82 if (open() == TRUE
) { // open log
87 if ((*func
)(j
, arg
, &count
) == FALSE
) done
= TRUE
;
88 if (clean
) delete_log_entry(j
);
94 WRITEUNLOCK(this, count
, "wu db_log::execute_on_log");
100 print_log_entry(db_log_entry
*j
, char * /* dummy */, int *count
)
107 /* Print contents of log file to stdout */
111 return (execute_on_log(&(print_log_entry
), NULL
));
114 /* Make copy of current log to log pointed to by 'f'. */
116 db_log::copy(db_log
*f
)
121 WRITELOCK(f
, -1, "w f db_log::copy");
122 if ((l
= acqnonexcl()) != 0) {
123 WRITEUNLOCK(f
, l
, "wu f db_log::copy");
130 if (f
->append(j
) < 0) {
132 "db_log::copy: could not append to log file: ");
138 if ((l
= relnonexcl()) != 0) {
141 WRITEUNLOCK(f
, ret
, "wu f db_log::copy");
145 /* Rewinds current log */
149 return (fseek(file
, 0L, 0));
153 * Return the next element in current log; return NULL if end of log or error.
154 * Log must have been opened for READ.
161 READLOCK(this, NULL
, "r db_log::get");
162 if (mode
!= PICKLE_READ
) {
163 READUNLOCK(this, NULL
, "ru db_log::get");
167 j
= new db_log_entry
;
170 READUNLOCK(this, NULL
, "ru db_log::get");
173 if (xdr_db_log_entry(&(xdr
), j
) == FALSE
) {
174 delete_log_entry (j
);
175 /* WARNING("Could not sucessfully finish reading log"); */
176 READUNLOCK(this, NULL
, "ru db_log::get");
180 WARNING("truncated log entry found");
184 READUNLOCK(this, j
, "ru db_log::get");
188 /* Append given log entry to log. */
190 db_log::append(db_log_entry
*j
)
194 WRITELOCK(this, -1, "w db_log::append");
195 if (mode
!= PICKLE_APPEND
) {
196 WRITEUNLOCK(this, -1, "wu db_log::append");
200 /* xdr returns TRUE if successful, FALSE otherwise */
201 status
= ((xdr_db_log_entry(&(xdr
), j
)) ? 0 : -1);
203 WARNING("db_log: could not write log entry");
207 WRITEUNLOCK(this, status
, "wu db_log::append");
212 copy_log_file(char *oldname
, char *newname
) {
214 int from
, to
, ret
= 0;
218 if ((from
= open(oldname
, O_RDONLY
, 0666)) < 0) {
219 if (errno
== ENOENT
) {
225 if ((to
= open(newname
, O_WRONLY
|O_CREAT
|O_TRUNC
, 0660)) < 0) {
231 while ((size
= read(from
, buf
, sizeof (buf
))) > 0) {
234 w
= write(to
, &buf
[b
], size
);
252 WARNING_M("db_log: error copying log file")
257 if (fsync(to
) != 0) {
259 WARNING_M("db_log: error syncing log file");
269 * Return value is expected to be the usual C convention of non-zero
270 * for success, 0 for failure.
277 WRITELOCK(this, -1, "w db_log::sync_log");
278 status
= fflush(file
);
280 WARNING("db_log: could not flush log entry to disk");
281 WRITEUNLOCK(this, status
, "wu db_log::sync_log");
285 status
= fsync(fileno(file
));
287 WARNING("db_log: could not sync log entry to disk");
288 } else if (tmplog
!= 0) {
289 if (syncstate
== 0) {
290 /* Log already stable; nothing to do */
292 } else if ((err
= copy_log_file(tmplog
, stablelog
)) == 0) {
293 if (rename(stablelog
, oldlog
) != 0) {
294 WARNING_M("db_log: could not mv stable log");
300 WARNING_M("db_log: could not stabilize log");
305 * Successful sync of file, but no tmplog to sync
306 * so we make sure we return 'success'.
310 WRITEUNLOCK(this, status
, "wu db_log::sync_log");
319 WRITELOCK(this, -1, "w db_log::close");
320 if (mode
!= PICKLE_READ
&& oldlog
!= 0) {
321 if (syncstate
!= 0) {
322 WARNING("db_log: closing unstable tmp log");
328 ret
= pickle_file::close();
330 (void) unlink(tmplog
);
334 if (stablelog
!= 0) {
338 WRITEUNLOCK(this, ret
, "wu db_log::close");
348 WRITELOCK(this, FALSE
, "w db_log::open");
349 if (mode
== PICKLE_READ
|| (!copylog
)) {
350 ret
= pickle_file::open();
351 WRITEUNLOCK(this, ret
, "wu db_log::open");
355 len
= strlen(filename
);
356 tmplog
= new char[len
+ sizeof (".tmp")];
358 WARNING("db_log: could not allocate tmp log name");
359 ret
= pickle_file::open();
360 WRITEUNLOCK(this, ret
, "wu db_log::open");
363 stablelog
= new char[len
+ sizeof (".stable")];
364 if (stablelog
== 0) {
365 WARNING("db_log: could not allocate stable log name");
368 ret
= pickle_file::open();
369 WRITEUNLOCK(this, ret
, "wu db_log::open");
372 sprintf(tmplog
, "%s.tmp", filename
);
373 sprintf(stablelog
, "%s.stable", filename
);
375 if ((cpstat
= copy_log_file(filename
, tmplog
)) == 0) {
380 "db_log: Error copying \"%s\" to \"%s\": %s",
381 filename
, tmplog
, strerror(cpstat
));
388 ret
= pickle_file::open();
389 WRITEUNLOCK(this, ret
, "wu db_log::open");