/*
* $Id: tp_check.c,v 1.4 2025/03/22 18:43:54 snw Exp $
* TP global checkpointing code
*
*
* Author: Serena Willis <snw@coherent-logic.com>
* Copyright (C) 1998 MUG Deutschland
* Copyright (C) 2022, 2025 Coherent Logic Development LLC
*
*
* This file is part of FreeM.
*
* FreeM is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* FreeM is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero Public License for more details.
*
* You should have received a copy of the GNU Affero Public License
* along with FreeM. If not, see <https://www.gnu.org/licenses/>.
*
* $Log: tp_check.c,v $
* Revision 1.4 2025/03/22 18:43:54 snw
* Make STRLEN 255 chars and add BIGSTR macro for larger buffers
*
* Revision 1.3 2025/03/09 19:50:47 snw
* Second phase of REUSE compliance and header reformat
*
*
* SPDX-FileCopyrightText: (C) 2025 Coherent Logic Development LLC
* SPDX-License-Identifier: AGPL-3.0-or-later
**/
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include "tp_check.h"
#include "mpsdef.h"
#include "transact.h"
#include "journal.h"
#include "fs.h"
short frm_global_exists(char *, char *, char *);
cptab *cptab_head[TP_MAX_NEST];
cptab *cptab_insert(int tlevel, char *global)
{
cptab *t;
char mode;
short g_exists;
char *gc_ns;
char *gc_pth;
gc_ns = (char *) malloc (STRLEN * sizeof (char));
NULLPTRCHK(gc_ns,"cptab_insert");
gc_pth = (char *) malloc (PATHLEN * sizeof (char));
NULLPTRCHK(gc_pth,"cptab_insert");
for (t = cptab_head[tlevel]; t != NULL; t = t->next) {
if ((strcmp (t->global, global) == 0) && (t->mode > CP_UNUSED)) {
/* found match */
return t;
}
}
/* insert */
t = (cptab *) malloc (sizeof (cptab));
NULLPTRCHK(t,"cptab_insert");
t->global = (char *) malloc (sizeof (char) * (strlen (global) + 1));
NULLPTRCHK(t->global,"cptab_insert");
strcpy (t->global, global);
g_exists = frm_global_exists (gc_ns, gc_pth, global);
t->file = (char *) malloc (sizeof (char) * (strlen (gc_pth)));
NULLPTRCHK(t->file,"cptab_insert");
t->cp_file = (char *) malloc (sizeof (char) * PATHLEN);
NULLPTRCHK(t->cp_file,"cptab_insert");
strcpy (t->file, gc_pth);
stcnv_m2c (t->file);
snprintf (t->cp_file, PATHLEN, "%s.%d.%d.chk", t->file, pid, tp_level);
free (gc_ns);
free (gc_pth);
if (!g_exists) {
t->mode = CP_REMOVE;
}
else {
t->mode = CP_RESTORE;
}
t->next = cptab_head[tlevel];
cptab_head[tlevel] = t;
return t;
}
short cptab_precommit(int tlevel)
{
cptab *t;
/*char *cmd;*/
char *pctmp;
int rc;
/*
cmd = (char *) malloc (STRLEN * sizeof (char));
NULLPTRCHK(cmd,"cptab_precommit");
*/
pctmp = (char *) malloc (STRLEN * sizeof (char));
NULLPTRCHK(pctmp,"cptab_precommit");
for (t = cptab_head[tlevel]; t != NULL; t = t->next) {
if (t->mode == CP_RESTORE) {
/*
snprintf (cmd, STRLEN - 1, "/bin/cp %s %s", t->file, t->cp_file);
rc = system (cmd);
*/
rc = cp (t->cp_file, t->file);
if (rc != 0) {
strcpy (pctmp, t->file);
stcnv_c2m (pctmp);
jnl_ent_write (JNLA_CHECKPOINT_FAIL, " \201", pctmp);
/*free (cmd);*/
free (pctmp);
return FALSE;
}
else {
strcpy (pctmp, t->file);
stcnv_c2m (pctmp);
jnl_ent_write (JNLA_CHECKPOINT_OK, " \201", pctmp);
}
}
}
/*free (cmd);*/
free (pctmp);
return TRUE;
}
void cptab_postcommit(int tlevel)
{
cptab *t;
/*char *cmd;*/
int rc;
/*
cmd = (char *) malloc (STRLEN * sizeof (char));
NULLPTRCHK(cmd,"cptab_postcommit");
*/
for (t = cptab_head[tlevel]; t != NULL; t = t->next) {
if (t->mode == CP_RESTORE) {
/*
snprintf (cmd, STRLEN - 1, "/bin/rm -f '%s'", t->cp_file);
rc = system (cmd);
*/
unlink (t->cp_file);
}
}
cptab_head[tlevel] = NULL;
}
short cptab_rollback(int tlevel)
{
cptab *t;
/*char *cmd;*/
int rc;
/*
cmd = (char *) malloc (STRLEN * sizeof (char));
NULLPTRCHK(cmd,"cptab_rollback");
*/
for (t = cptab_head[tlevel]; t != NULL; t = t->next) {
switch (t->mode) {
case CP_REMOVE:
unlink (t->file);
/*
snprintf (cmd, STRLEN - 1, "/bin/rm -f '%s'", t->file);
rc = system (cmd);
*/
break;
case CP_RESTORE:
/*
snprintf (cmd, STRLEN - 1, "/bin/cp '%s' '%s'", t->cp_file, t->file);
rc = system (cmd);
*/
rc = cp (t->file, t->cp_file);
if (rc != 0) {
cptab_head[tlevel] = NULL;
/*free (cmd);*/
return FALSE;
}
/*
snprintf (cmd, STRLEN - 1, "/bin/rm -f %s", t->cp_file);
rc = system (cmd);
*/
unlink (t->cp_file);
if (rc != 0) {
cptab_head[tlevel] = NULL;
/*free (cmd);*/
return FALSE;
}
break;
}
}
cptab_head[tlevel] = NULL;
return TRUE;
}
void cptab_dump(int tlevel)
{
cptab *gt;
char cp_mode[15];
printf ("\n Global database checkpoints:\n");
printf ("\n %-30s%-20s%s\n", "GLOBAL", "MODE", "FILES");
printf (" %-30s%-20s%s\n", "------", "----", "-----");
for (gt = cptab_head[tlevel]; gt != NULL; gt = gt->next) {
switch (gt->mode) {
case CP_UNUSED:
strcpy (cp_mode, "CP_UNUSED");
break;
case CP_REMOVE:
strcpy (cp_mode, "CP_REMOVE");
break;
case CP_RESTORE:
strcpy (cp_mode, "CP_RESTORE");
break;
}
if (gt->mode > CP_UNUSED) {
printf (" %-30s%-20sIN: %s\n", gt->global, cp_mode, gt->file);
}
else {
printf (" N/A\n");
}
if (gt->mode == CP_RESTORE) {
printf (" %-30s%-20sOUT: %s\n", "", "", gt->cp_file);
}
}
}
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>