File:  [Coherent Logic Development] / freem / src / fma_journals.c
Revision 1.3: download - view: text, annotated - select for diffs
Sun Mar 9 19:14:25 2025 UTC (3 weeks, 2 days ago) by snw
Branches: MAIN
CVS tags: v0-62-3, v0-62-2, v0-62-1, v0-62-0, HEAD
First phase of REUSE compliance and header reformat

/*
 *   $Id: fma_journals.c,v 1.3 2025/03/09 19:14:25 snw Exp $
 *    Journal utilities for fmadm
 *
 *  
 *   Author: Serena Willis <snw@coherent-logic.com>
 *    Copyright (C) 1998 MUG Deutschland
 *    Copyright (C) 2020, 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: fma_journals.c,v $
 *   Revision 1.3  2025/03/09 19:14:25  snw
 *   First 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 <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <dirent.h>
#include <time.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>

#include "fmadm.h"
#include "jnldefs.h"

void cvt_key (char *buf, char *key);
extern short ierr;

int fma_journals_examine (int optc, char **opts)
{
    register int i;
    register int k;
    int fd;
    unsigned long siz;
    unsigned long ct;
    
    char buf[2048];
    char kbuf[1024];
    char *tbuf;

    char dbuf[2049];
    
    jnl_hdr_t hdr;
    jnl_ent_t ent;
    
    if ((fd = open (fma_journal_path, O_RDONLY)) == -1) {
        fprintf (stderr, "fmadm:  error %d opening journal file %s (%s)\n", errno, fma_journal_path, strerror (errno));
        
        exit (2);
    }
    
    if (read (fd, &hdr, sizeof (jnl_hdr_t)) == -1) {
        fprintf (stderr, "fmadm:  error %d reading header from journal file %s (%s)\n", errno, fma_journal_path, strerror (errno));
        
        exit (3);
    }

    printf ("\nFreeM Journal Dump\n");
    printf ("------------------\n\n");

    printf ("Namespace:               %s\n", fma_namespace);
    printf ("Journal File:            %s\n", fma_journal_path);
    printf ("Journal Format Version:  %d\n", hdr.fmt_version);
    printf ("Cut Threshold:           %s bytes\n", fma_journal_cut_threshold);
    
    lseek (fd, 0L, SEEK_SET);
    siz = lseek (fd, 0L, SEEK_END);
    
    ct = (siz - sizeof (jnl_hdr_t)) / sizeof (jnl_ent_t);
    
    printf ("Journal Entries:         %ld\n\n", ct);

    printf ("%-26s %-6s %-7s %-10s %s\n", "DATE", "PID", "TRNID", "ACTION", "DATA");
    printf ("%-26s %-6s %-7s %-10s %s\n", "----", "---", "-----", "------", "----");
    
    lseek (fd, sizeof (jnl_hdr_t), SEEK_SET);
    
    for (i = 0; i < ct; i++) {
        
        read (fd, &ent, sizeof (jnl_ent_t));
        
        switch (ent.action) {
            
            case JNLA_TSTART:
                strcpy (buf, "TSTART");
                break;
                
            case JNLA_TROLLBACK:
                strcpy (buf, "TROLLBACK");
                break;
                
            case JNLA_TCOMMIT:
                strcpy (buf, "TCOMMIT");
                break;
                
            case JNLA_SET:
                strcpy (buf, "SET");
                break;
                
            case JNLA_KILL:
                strcpy (buf, "KILL");
                break;
		
        }
        
        cvt_key (kbuf, ent.key);

        
        tbuf = ctime (&ent.ts);
        tbuf[strlen(tbuf) - 1] = '\0';

        if (ent.action == JNLA_SET) {

            snprintf (dbuf, 2049, "%s=%s", kbuf, ent.data);

            for (k = 0; k < strlen (dbuf); k++) {
                if (dbuf[k] == '\201') dbuf[k] = '\0';
            }
        
            printf ("%-26s %-6d %-7ld %-10s %s\n", tbuf, ent.pid, ent.tran_id, buf, dbuf);

        }
        else {
            printf ("%-26s %-6d %-7ld %-10s %s\n", tbuf, ent.pid, ent.tran_id, buf, kbuf);
        }
                
    }

    return 0;
    
}

int fma_journals_restore (int optc, char **opts)
{

    register int i;
    register int k;
    int fd;
    unsigned long siz;
    unsigned long ct;
    
    char kbuf[1024];
    char *tbuf;

    char dbuf[2049];
    
    jnl_hdr_t hdr;
    jnl_ent_t ent;
    
    if ((fd = open (fma_journal_path, O_RDONLY)) == -1) {
        fprintf (stderr, "error: error %d opening journal file %s\n", errno, fma_journal_path);
        
        exit (2);
    }
    
    if (read (fd, &hdr, sizeof (jnl_hdr_t)) == -1) {
        fprintf (stderr, "error: error %d reading header from journal file %s\n", errno, fma_journal_path);
        
        exit (3);
    }

    printf ("\nFreeM Journal Playback\n");
    printf ("----------------------\n\n");

    printf ("Namespace:               %s\n", fma_namespace);
    printf ("Journal File:            %s\n", fma_journal_path);
    printf ("Journal Format Version:  %d\n", hdr.fmt_version);
    printf ("Cut Threshold:           %s bytes\n", fma_journal_cut_threshold);
    
    lseek (fd, 0L, SEEK_SET);
    siz = lseek (fd, 0L, SEEK_END);
    
    ct = (siz - sizeof (jnl_hdr_t)) / sizeof (jnl_ent_t);
    
    printf ("Journal Entries:         %ld\n\n", ct);

    
    lseek (fd, sizeof (jnl_hdr_t), SEEK_SET);
    
    for (i = 0; i < ct; i++) {
        
        read (fd, &ent, sizeof (jnl_ent_t));
        
        switch (ent.action) {
            
            case JNLA_TSTART:
                printf (" Played back TSTART (transaction id %ld)\n", ent.tran_id);
                break;
                
            case JNLA_TROLLBACK:
                printf (" Played back TROLLBACK (transaction id %ld)\n", ent.tran_id);
                break;
                
            case JNLA_TCOMMIT:
                printf (" Played back TCOMMIT (transaction id %ld)\n", ent.tran_id);                
                break;
                
            case JNLA_SET:
                global (set_sym, ent.key, ent.data);
                printf (" Played back SET (transaction id %ld)\n", ent.tran_id);                
                break;
                
            case JNLA_KILL:                
                global (kill_sym, ent.key, ent.data);
                printf (" Played back KILL (transaction id %ld)\n", ent.tran_id);
                break;
		
        }
           
    }

    return 0;
    
}


void cvt_key (char *buf, char *key)
{
    int i;
    int j = 0;
    int first = 1;
    
    if (key[0] == '\0') {
        buf[0] = '\0';
        
        return;
    }
    
    for(i = 0; i < 1023; i++) {
        
        switch (key[i]) {
            
            case '\201':
                if (first == 0) {
                    buf[j] = ')';
                    buf[j + 1] = '\0';
                }
                else {
                    buf[j] = '\0';
                }
                return;
                
            case '\202':
                if (first == 1) {
                    buf[j] = '(';
                    first = 0;
                }
                else {
                    buf[j] = ',';
                }
                
                break;
                
            default:
                buf[j] = key[i];
                break;
        }
        
        j++;
    }

}

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>