1: /*
2: * $Id: tp_check.c,v 1.7 2025/04/13 15:12:21 snw Exp $
3: * TP global checkpointing code
4: *
5: *
6: * Author: Serena Willis <snw@coherent-logic.com>
7: * Copyright (C) 1998 MUG Deutschland
8: * Copyright (C) 2022, 2025 Coherent Logic Development LLC
9: *
10: *
11: * This file is part of FreeM.
12: *
13: * FreeM is free software: you can redistribute it and/or modify
14: * it under the terms of the GNU Affero Public License as published by
15: * the Free Software Foundation, either version 3 of the License, or
16: * (at your option) any later version.
17: *
18: * FreeM is distributed in the hope that it will be useful,
19: * but WITHOUT ANY WARRANTY; without even the implied warranty of
20: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21: * GNU Affero Public License for more details.
22: *
23: * You should have received a copy of the GNU Affero Public License
24: * along with FreeM. If not, see <https://www.gnu.org/licenses/>.
25: *
26: * $Log: tp_check.c,v $
27: * Revision 1.7 2025/04/13 15:12:21 snw
28: * Fix transaction checkpoints on OS/2 [CLOSES #34]
29: *
30: * Revision 1.6 2025/04/13 04:22:43 snw
31: * Fix snprintf calls
32: *
33: * Revision 1.5 2025/04/09 19:52:02 snw
34: * Eliminate as many warnings as possible while building with -Wall
35: *
36: * Revision 1.4 2025/03/22 18:43:54 snw
37: * Make STRLEN 255 chars and add BIGSTR macro for larger buffers
38: *
39: * Revision 1.3 2025/03/09 19:50:47 snw
40: * Second phase of REUSE compliance and header reformat
41: *
42: *
43: * SPDX-FileCopyrightText: (C) 2025 Coherent Logic Development LLC
44: * SPDX-License-Identifier: AGPL-3.0-or-later
45: **/
46:
47: #include <stdlib.h>
48: #include <string.h>
49: #include <unistd.h>
50: #include "tp_check.h"
51: #include "mpsdef.h"
52: #include "transact.h"
53: #include "journal.h"
54: #include "fs.h"
55:
56: #if defined(__OS2__)
57: # include <os2.h>
58: #endif
59:
60: short frm_global_exists(char *, char *, char *);
61:
62: cptab *cptab_head[TP_MAX_NEST];
63:
64: cptab *cptab_insert(int tlevel, char *global)
65: {
66: cptab *t;
67: short g_exists;
68: char *gc_ns;
69: char *gc_pth;
70:
71: gc_ns = (char *) malloc (STRLEN * sizeof (char));
72: NULLPTRCHK(gc_ns,"cptab_insert");
73:
74: gc_pth = (char *) malloc (PATHLEN * sizeof (char));
75: NULLPTRCHK(gc_pth,"cptab_insert");
76:
77: for (t = cptab_head[tlevel]; t != NULL; t = t->next) {
78:
79: if ((strcmp (t->global, global) == 0) && (t->mode > CP_UNUSED)) {
80: /* found match */
81: return t;
82: }
83:
84: }
85:
86: /* insert */
87: t = (cptab *) malloc (sizeof (cptab));
88: NULLPTRCHK(t,"cptab_insert");
89:
90: t->global = (char *) malloc (sizeof (char) * (strlen (global) + 1));
91: NULLPTRCHK(t->global,"cptab_insert");
92:
93: strcpy (t->global, global);
94:
95: g_exists = frm_global_exists (gc_ns, gc_pth, global);
96:
97: t->file = (char *) malloc (sizeof (char) * (strlen (gc_pth)));
98: NULLPTRCHK(t->file,"cptab_insert");
99:
100: t->cp_file = (char *) malloc (sizeof (char) * PATHLEN);
101: NULLPTRCHK(t->cp_file,"cptab_insert");
102:
103: strcpy (t->file, gc_pth);
104: stcnv_m2c (t->file);
105:
106: snprintf (t->cp_file, PATHLEN - 1, "%s.%d.%d.chk", t->file, pid, tp_level);
107:
108: free (gc_ns);
109: free (gc_pth);
110:
111: if (!g_exists) {
112: t->mode = CP_REMOVE;
113: }
114: else {
115: t->mode = CP_RESTORE;
116: }
117:
118: t->next = cptab_head[tlevel];
119: cptab_head[tlevel] = t;
120:
121: return t;
122: }
123:
124: short cptab_precommit(int tlevel)
125: {
126: cptab *t;
127: /*char *cmd;*/
128: char *pctmp;
129: int rc;
130:
131: /*
132: cmd = (char *) malloc (STRLEN * sizeof (char));
133: NULLPTRCHK(cmd,"cptab_precommit");
134: */
135:
136: pctmp = (char *) malloc (STRLEN * sizeof (char));
137: NULLPTRCHK(pctmp,"cptab_precommit");
138:
139: for (t = cptab_head[tlevel]; t != NULL; t = t->next) {
140:
141: if (t->mode == CP_RESTORE) {
142:
143: /*
144: snprintf (cmd, STRLEN - 1, "/bin/cp %s %s", t->file, t->cp_file);
145: rc = system (cmd);
146: */
147:
148: rc = cp (t->cp_file, t->file);
149:
150: if (rc != 0) {
151:
152: strcpy (pctmp, t->file);
153: stcnv_c2m (pctmp);
154:
155: jnl_ent_write (JNLA_CHECKPOINT_FAIL, " \201", pctmp);
156:
157: /*free (cmd);*/
158: free (pctmp);
159:
160: return FALSE;
161:
162: }
163: else {
164:
165: strcpy (pctmp, t->file);
166: stcnv_c2m (pctmp);
167:
168: jnl_ent_write (JNLA_CHECKPOINT_OK, " \201", pctmp);
169:
170: }
171:
172: }
173:
174: }
175:
176: /*free (cmd);*/
177: free (pctmp);
178:
179: return TRUE;
180: }
181:
182: void cptab_postcommit(int tlevel)
183: {
184: cptab *t;
185: /*char *cmd;*/
186:
187: /*
188: cmd = (char *) malloc (STRLEN * sizeof (char));
189: NULLPTRCHK(cmd,"cptab_postcommit");
190: */
191:
192: for (t = cptab_head[tlevel]; t != NULL; t = t->next) {
193:
194: if (t->mode == CP_RESTORE) {
195: /*
196: snprintf (cmd, STRLEN - 1, "/bin/rm -f '%s'", t->cp_file);
197: rc = system (cmd);
198: */
199: unlink (t->cp_file);
200: }
201:
202: }
203:
204: cptab_head[tlevel] = NULL;
205: }
206:
207: short cptab_rollback(int tlevel)
208: {
209: cptab *t;
210: int rc;
211:
212: for (t = cptab_head[tlevel]; t != NULL; t = t->next) {
213:
214: switch (t->mode) {
215:
216: case CP_REMOVE:
217: unlink (t->file);
218: break;
219:
220: case CP_RESTORE:
221: #if !defined(__OS2__)
222: rc = cp (t->file, t->cp_file);
223: #else
224: rc = DosCopy (t->cp_file, t->file, 1);
225: #endif
226: if (rc != 0) {
227: cptab_head[tlevel] = NULL;
228: /*free (cmd);*/
229: return FALSE;
230: }
231:
232: unlink (t->cp_file);
233: if (rc != 0) {
234: cptab_head[tlevel] = NULL;
235: /*free (cmd);*/
236: return FALSE;
237: }
238:
239: break;
240:
241:
242: }
243:
244: }
245:
246: cptab_head[tlevel] = NULL;
247:
248: return TRUE;
249:
250: }
251:
252: void cptab_dump(int tlevel)
253: {
254: cptab *gt;
255: char cp_mode[15];
256:
257: printf ("\n Global database checkpoints:\n");
258:
259: printf ("\n %-30s%-20s%s\n", "GLOBAL", "MODE", "FILES");
260: printf (" %-30s%-20s%s\n", "------", "----", "-----");
261:
262: for (gt = cptab_head[tlevel]; gt != NULL; gt = gt->next) {
263:
264: switch (gt->mode) {
265:
266: case CP_UNUSED:
267: strcpy (cp_mode, "CP_UNUSED");
268: break;
269:
270: case CP_REMOVE:
271: strcpy (cp_mode, "CP_REMOVE");
272: break;
273:
274: case CP_RESTORE:
275: strcpy (cp_mode, "CP_RESTORE");
276: break;
277:
278: }
279:
280: if (gt->mode > CP_UNUSED) {
281: printf (" %-30s%-20sIN: %s\n", gt->global, cp_mode, gt->file);
282: }
283: else {
284: printf (" N/A\n");
285: }
286:
287: if (gt->mode == CP_RESTORE) {
288: printf (" %-30s%-20sOUT: %s\n", "", "", gt->cp_file);
289: }
290:
291: }
292: }
293:
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>