Subject | Re: [IB-Architect] Re: Fixing a corrupt database |
---|---|
Author | Ann Harrison |
Post date | 2000-09-28T15:50:31Z |
At 03:22 PM 9/28/2000 +0000, Paul Klerlein wrote:
V4 specific help from Inprise.
Below my signature you'll find the V6 page definitions
and the checksum computation.
Good luck,
Ann
/*
* PROGRAM: JRD Access Method
* MODULE: ods.h
* DESCRIPTION: On disk structure definitions
*
* copyright (c) 1999 by Inprise Corporation
* copyright (c) 1998 by Interbase Software Corporation
*/
#ifndef _JRD_ODS_H_
#define _JRD_ODS_H_
/**********************************************************************
**
** NOTE:
**
** ODS 5 was shipped with version 3.3 but no longer supported
** ODS 6 and ODS 7 never went out the door
** ODS 8 was shipped with version 4.0
** ODS 9 is going to be shipped with version 4.5
**
***********************************************************************/
/* ODS major version -- major versions are not compatible */
#define ODS_VERSION6 6 /* on-disk structure as of v3.0 */
#define ODS_VERSION7 7 /* new on disk structure for fixing index
bug */
#define ODS_VERSION8 8 /* new btree structure to support pc
semantics */
#define ODS_VERSION9 9 /* btree leaf pages are always propogated up */
#define ODS_VERSION10 10 /* V6.0 features. SQL delimited idetifier,
SQLDATE, and 64-bit exact numeric
type */
/* ODS minor version -- minor versions ARE compatible, but may be
increasingly functional. Add new minor versions, but leave previous
names intact */
/* Minor versions for ODS 6 */
#define ODS_GRANT6 1 /* adds fields for field level grant */
#define ODS_INTEGRITY6 2 /* adds fields for referential integrity */
#define ODS_FUNCTIONS6 3 /* modifies type of RDB$MODULE_NAME field */
#define ODS_SQLNAMES6 4 /* permits SQL security on > 27 SCHAR names */
#define ODS_CURRENT6 4
/* Minor versions for ODS 7 */
#define ODS_FUNCTIONS7 1 /* modifies type of RDB$MODULE_NAME field */
#define ODS_SQLNAMES7 2 /* permits SQL security on > 27 SCHAR names */
#define ODS_CURRENT7 2
/* Minor versions for ODS 8 */
#define ODS_CASCADE_RI8 1 /* permits cascading referential integrity */
/* ODS 8.2 is the same as ODS 8.1 */
#define ODS_CURRENT8 2
/* Minor versions for ODS 9 */
#define ODS_CURRENT_9_0 0 /* SQL roles & Index garbage collection */
#define ODS_SYSINDEX9 1 /* Index on RDB$CHECK_CONSTRAINTS
(RDB$TRIGGER_NAME) */
#define ODS_CURRENT9 1
/* Minor versions for ODS 10 */
#define ODS_CURRENT10 0 /* V6.0 features. SQL delimited identifier,
SQLDATE, and 64-bit exact numeric
type */
/* useful ODS macros. These are currently used to flag the version of the
system triggers and system indices in ini.e */
#define ENCODE_ODS(major,minor) (((major) << 4) | (minor))
#define ODS_8_0 ENCODE_ODS (ODS_VERSION8, 0)
#define ODS_8_1 ENCODE_ODS (ODS_VERSION8, 1)
#define ODS_9_0 ENCODE_ODS (ODS_VERSION9, 0)
#define ODS_9_1 ENCODE_ODS (ODS_VERSION9, 1)
#define ODS_10_0 ENCODE_ODS (ODS_VERSION10, 0)
/* Decode ODS version to Major and Minor parts. The 4 LSB's are minor and
the next 4 bits are major version number */
#define DECODE_ODS_MAJOR(ods_version) ((ods_version & 0xFFF0) >> 4)
#define DECODE_ODS_MINOR(ods_version) (ods_version & 0x000F)
/* Set current ODS major and minor version */
#define ODS_VERSION ODS_VERSION10 /* current ods major version -- always
the highest */
#define ODS_CURRENT ODS_CURRENT10 /* the highest defined minor version
number for this ODS_VERSION!! */
#define ODS_CURRENT_VERSION ODS_10_0/* Current ODS version in use which
includes
both Major and Minor ODS
versions! */
#define USER_REL_INIT_ID_ODS8 31 /* ODS <= 8 */
#define USER_DEF_REL_INIT_ID 128 /* ODS >= 9 */
/* Page types */
#define pag_undefined 0
#define pag_header 1 /* Database header page */
#define pag_pages 2 /* Page inventory page */
#define pag_transactions 3 /* Transaction inventory page */
#define pag_pointer 4 /* Pointer page */
#define pag_data 5 /* Data page */
#define pag_root 6 /* Index root page */
#define pag_index 7 /* Index (B-tree) page */
#define pag_blob 8 /* Blob data page */
#define pag_ids 9 /* Gen-ids */
#define pag_log 10 /* Write ahead log information */
#define pag_max 10 /* Max page type */
#define HEADER_PAGE 0
#define LOG_PAGE 2
#ifdef _CRAY
#define MIN_PAGE_SIZE 4096
#else
#define MIN_PAGE_SIZE 1024
#endif
#define MAX_PAGE_SIZE 8192
#define DEFAULT_PAGE_SIZE 4096
/* Basic page header */
typedef struct pag {
SCHAR pag_type;
SCHAR pag_flags;
USHORT pag_checksum;
ULONG pag_generation;
ULONG pag_seqno; /* WAL seqno of last update */
ULONG pag_offset; /* WAL offset of last update */
} *PAG;
/* Blob page */
typedef struct blp {
struct pag blp_header;
SLONG blp_lead_page; /* First page of blob (for
redundancy only) */
SLONG blp_sequence; /* Sequence within blob */
USHORT blp_length; /* Bytes on page */
USHORT blp_pad; /* Unused */
SLONG blp_page [1]; /* Page number if level 1 */
} *BLP;
#define blp_data blp_page /* Formerly defined field */
#define BLP_SIZE OFFSETA (BLP, blp_page)
#define blp_pointers 1 /* Blob pointer page, not data page */
/* B-tree node */
typedef struct btn {
UCHAR btn_prefix; /* size of compressed prefix */
UCHAR btn_length; /* length of data in node */
UCHAR btn_number [4]; /* page or record number */
UCHAR btn_data [1];
#ifdef _CRAY
};
#else
} *BTN;
#endif
#define BTN_SIZE 6
/* B-tree page ("bucket") */
typedef struct btr {
struct pag btr_header;
SLONG btr_sibling; /* right sibling page */
SLONG btr_left_sibling; /* left sibling page */
SLONG btr_prefix_total; /* sum of all prefixes on page */
USHORT btr_relation; /* relation id for consistency */
USHORT btr_length; /* length of data in bucket */
UCHAR btr_id; /* index id for consistency */
UCHAR btr_level; /* index level (0 = leaf) */
struct btn btr_nodes [1];
} *BTR;
#define btr_dont_gc 1 /* Don't garbage-collect
this page */
#define btr_not_propogated 2 /* page is not propogated
upward */
#define btr_descending 8 /* Page/bucket is part of a
descending index */
#define MAX_NODES ((dbb->dbb_page_size - OFFSETA (BTR, btr_nodes)) /
sizeof (struct btn))
/* Data Page */
typedef struct dpg {
struct pag dpg_header;
SLONG dpg_sequence; /* Sequence number in relation */
USHORT dpg_relation; /* Relation id */
USHORT dpg_count; /* Number of record segments on page */
struct dpg_repeat
{
USHORT dpg_offset; /* Offset of record fragment */
USHORT dpg_length; /* Length of record fragment */
} dpg_rpt [1];
} *DPG;
#define DPG_SIZE (sizeof (struct dpg) - sizeof (struct dpg_repeat))
#define dpg_orphan 1 /* Data page is NOT in pointer page */
#define dpg_full 2 /* Pointer page is marked FULL */
#define dpg_large 4 /* Large object is on page */
/* Index root page */
typedef struct irt {
struct pag irt_header;
USHORT irt_relation; /* relation id (for consistency) */
USHORT irt_count; /* Number of indices */
struct irt_repeat
{
SLONG irt_root; /* page number of index root */
union
{
float irt_selectivity; /* selectivity of index */
SLONG irt_transaction; /* transaction in progress */
} irt_stuff;
USHORT irt_desc; /* offset to key descriptions */
UCHAR irt_keys; /* number of keys in index */
UCHAR irt_flags;
} irt_rpt [1];
} *IRT;
/* Header page */
typedef struct hdr {
struct pag hdr_header;
USHORT hdr_page_size; /* Page size of database */
USHORT hdr_ods_version; /* Version of on-disk structure */
SLONG hdr_PAGES; /* Page number of PAGES relation */
ULONG hdr_next_page; /* Page number of next hdr page */
SLONG hdr_oldest_transaction; /* Oldest interesting transaction */
SLONG hdr_oldest_active; /* Oldest transaction thought
active */
SLONG hdr_next_transaction; /* Next transaction id */
USHORT hdr_sequence; /* sequence number of file */
USHORT hdr_flags; /* Flag settings, see below */
SLONG hdr_creation_date [2]; /* Date/time of creation */
SLONG hdr_attachment_id; /* Next attachment id */
SLONG hdr_shadow_count; /* Event count for shadow
synchronization */
SSHORT hdr_implementation; /* Implementation number */
USHORT hdr_ods_minor; /* Update version of ODS */
USHORT hdr_ods_minor_original; /* Update version of ODS at
creation */
USHORT hdr_end; /* offset of HDR_end in page */
ULONG hdr_page_buffers; /* Page buffers for database cache */
SLONG hdr_bumped_transaction; /* Bumped transaction id for log
optimization */
SLONG hdr_oldest_snapshot; /* Oldest snapshot of active
transactions */
SLONG hdr_misc [4]; /* Stuff to be named later */
UCHAR hdr_data [1]; /* Misc data */
} *HDR;
#define HDR_SIZE OFFSETA (HDR, hdr_data)
#define hdr_cache_file hdr_data
/* Page Inventory Page */
typedef struct pip {
struct pag pip_header;
SLONG pip_min; /* Lowest (possible) free page */
UCHAR pip_bits [1];
} *PIP;
/* Pointer Page */
typedef struct ppg {
struct pag ppg_header;
SLONG ppg_sequence; /* Sequence number in relation */
SLONG ppg_next; /* Next pointer page in relation */
USHORT ppg_count; /* Number of slots active */
USHORT ppg_relation; /* Relation id */
USHORT ppg_min_space; /* Lowest slot with space available */
USHORT ppg_max_space; /* Highest slot with space available */
SLONG ppg_page [1]; /* Data page vector */
} *PPG;
#define ppg_bits ppg_page
#define ppg_eof 1 /* Last pointer page in relation */
/* Transaction Inventory Page */
typedef struct tip {
struct pag tip_header;
SLONG tip_next; /* Next transaction inventory page */
UCHAR tip_transactions [1];
} *TIP;
/* Log page */
typedef struct ctrl_pt {
SLONG cp_seqno;
SLONG cp_offset;
SLONG cp_p_offset;
SSHORT cp_fn_length;
} CP;
typedef struct log_info_page {
struct pag log_header;
SLONG log_flags; /* flags */
CP log_cp_1; /* control point 1 */
CP log_cp_2; /* control point 2 */
CP log_file; /* current file */
SLONG log_next_page; /* Next log page */
SLONG log_mod_tip; /* tip of modify transaction */
SLONG log_mod_tid; /* transaction id of modify process */
SLONG log_creation_date [2]; /* Date/time of log creation */
SLONG log_free [4]; /* some extra space for later use */
USHORT log_end; /* similar to hdr_end */
UCHAR log_data [1];
} *LIP;
#define LIP_SIZE OFFSETA (LIP, log_data);
#endif /* _JRD_ODS_H_ */
Here's the checksum computation.
USHORT CCH_checksum (
BDB bdb)
{
/**************************************
*
* C C H _ c h e c k s u m
*
**************************************
*
* Functional description
* Compute the checksum of a page.
*
**************************************/
#ifdef NO_CHECKSUM
return DUMMY_CHECKSUM;
#else
#ifdef WINDOWS_ONLY
ULONG checksum, huge *p, huge *end;
#else
ULONG checksum, *p, *end;
#endif
USHORT old_checksum;
PAG page;
DBB dbb;
dbb = bdb->bdb_dbb;
#ifdef WIN_NT
/* ODS_VERSION8 for NT was shipped before page checksums
were disabled on other platforms. Continue to compute
checksums for ODS_VERSION8 databases but eliminate them
for ODS_VERSION9 databases. The following code can be
deleted when development on ODS_VERSION10 begins and
NO_CHECKSUM is defined for all platforms. */
if (dbb->dbb_ods_version >= ODS_VERSION9)
return DUMMY_CHECKSUM;
#endif
page = bdb->bdb_buffer;
#ifdef WINDOWS_ONLY
end = (ULONG huge*) ((SCHAR huge *) page + dbb->dbb_page_size);
#else
end = (ULONG*) ((SCHAR*) page + dbb->dbb_page_size);
#endif
old_checksum = page->pag_checksum;
page->pag_checksum = 0;
#ifdef WINDOWS_ONLY
p = (ULONG huge*) page;
#else
p = (ULONG*) page;
#endif
checksum = 0;
do
{
checksum += *p++;
checksum += *p++;
checksum += *p++;
checksum += *p++;
checksum += *p++;
checksum += *p++;
checksum += *p++;
checksum += *p++;
}
while (p < end);
page->pag_checksum = old_checksum;
if (checksum)
return (USHORT) checksum;
/* If the page is all zeros, return an artificial checksum */
for (p = (ULONG*) page; p < end;)
if (*p++)
return checksum;
/* Page is all zeros -- invent a checksum */
return 12345;
#endif
}
>Where can I find the page layout to try and patch the offending page.Unfortunately the V4 code is proprietary. You might get
V4 specific help from Inprise.
Below my signature you'll find the V6 page definitions
and the checksum computation.
Good luck,
Ann
/*
* PROGRAM: JRD Access Method
* MODULE: ods.h
* DESCRIPTION: On disk structure definitions
*
* copyright (c) 1999 by Inprise Corporation
* copyright (c) 1998 by Interbase Software Corporation
*/
#ifndef _JRD_ODS_H_
#define _JRD_ODS_H_
/**********************************************************************
**
** NOTE:
**
** ODS 5 was shipped with version 3.3 but no longer supported
** ODS 6 and ODS 7 never went out the door
** ODS 8 was shipped with version 4.0
** ODS 9 is going to be shipped with version 4.5
**
***********************************************************************/
/* ODS major version -- major versions are not compatible */
#define ODS_VERSION6 6 /* on-disk structure as of v3.0 */
#define ODS_VERSION7 7 /* new on disk structure for fixing index
bug */
#define ODS_VERSION8 8 /* new btree structure to support pc
semantics */
#define ODS_VERSION9 9 /* btree leaf pages are always propogated up */
#define ODS_VERSION10 10 /* V6.0 features. SQL delimited idetifier,
SQLDATE, and 64-bit exact numeric
type */
/* ODS minor version -- minor versions ARE compatible, but may be
increasingly functional. Add new minor versions, but leave previous
names intact */
/* Minor versions for ODS 6 */
#define ODS_GRANT6 1 /* adds fields for field level grant */
#define ODS_INTEGRITY6 2 /* adds fields for referential integrity */
#define ODS_FUNCTIONS6 3 /* modifies type of RDB$MODULE_NAME field */
#define ODS_SQLNAMES6 4 /* permits SQL security on > 27 SCHAR names */
#define ODS_CURRENT6 4
/* Minor versions for ODS 7 */
#define ODS_FUNCTIONS7 1 /* modifies type of RDB$MODULE_NAME field */
#define ODS_SQLNAMES7 2 /* permits SQL security on > 27 SCHAR names */
#define ODS_CURRENT7 2
/* Minor versions for ODS 8 */
#define ODS_CASCADE_RI8 1 /* permits cascading referential integrity */
/* ODS 8.2 is the same as ODS 8.1 */
#define ODS_CURRENT8 2
/* Minor versions for ODS 9 */
#define ODS_CURRENT_9_0 0 /* SQL roles & Index garbage collection */
#define ODS_SYSINDEX9 1 /* Index on RDB$CHECK_CONSTRAINTS
(RDB$TRIGGER_NAME) */
#define ODS_CURRENT9 1
/* Minor versions for ODS 10 */
#define ODS_CURRENT10 0 /* V6.0 features. SQL delimited identifier,
SQLDATE, and 64-bit exact numeric
type */
/* useful ODS macros. These are currently used to flag the version of the
system triggers and system indices in ini.e */
#define ENCODE_ODS(major,minor) (((major) << 4) | (minor))
#define ODS_8_0 ENCODE_ODS (ODS_VERSION8, 0)
#define ODS_8_1 ENCODE_ODS (ODS_VERSION8, 1)
#define ODS_9_0 ENCODE_ODS (ODS_VERSION9, 0)
#define ODS_9_1 ENCODE_ODS (ODS_VERSION9, 1)
#define ODS_10_0 ENCODE_ODS (ODS_VERSION10, 0)
/* Decode ODS version to Major and Minor parts. The 4 LSB's are minor and
the next 4 bits are major version number */
#define DECODE_ODS_MAJOR(ods_version) ((ods_version & 0xFFF0) >> 4)
#define DECODE_ODS_MINOR(ods_version) (ods_version & 0x000F)
/* Set current ODS major and minor version */
#define ODS_VERSION ODS_VERSION10 /* current ods major version -- always
the highest */
#define ODS_CURRENT ODS_CURRENT10 /* the highest defined minor version
number for this ODS_VERSION!! */
#define ODS_CURRENT_VERSION ODS_10_0/* Current ODS version in use which
includes
both Major and Minor ODS
versions! */
#define USER_REL_INIT_ID_ODS8 31 /* ODS <= 8 */
#define USER_DEF_REL_INIT_ID 128 /* ODS >= 9 */
/* Page types */
#define pag_undefined 0
#define pag_header 1 /* Database header page */
#define pag_pages 2 /* Page inventory page */
#define pag_transactions 3 /* Transaction inventory page */
#define pag_pointer 4 /* Pointer page */
#define pag_data 5 /* Data page */
#define pag_root 6 /* Index root page */
#define pag_index 7 /* Index (B-tree) page */
#define pag_blob 8 /* Blob data page */
#define pag_ids 9 /* Gen-ids */
#define pag_log 10 /* Write ahead log information */
#define pag_max 10 /* Max page type */
#define HEADER_PAGE 0
#define LOG_PAGE 2
#ifdef _CRAY
#define MIN_PAGE_SIZE 4096
#else
#define MIN_PAGE_SIZE 1024
#endif
#define MAX_PAGE_SIZE 8192
#define DEFAULT_PAGE_SIZE 4096
/* Basic page header */
typedef struct pag {
SCHAR pag_type;
SCHAR pag_flags;
USHORT pag_checksum;
ULONG pag_generation;
ULONG pag_seqno; /* WAL seqno of last update */
ULONG pag_offset; /* WAL offset of last update */
} *PAG;
/* Blob page */
typedef struct blp {
struct pag blp_header;
SLONG blp_lead_page; /* First page of blob (for
redundancy only) */
SLONG blp_sequence; /* Sequence within blob */
USHORT blp_length; /* Bytes on page */
USHORT blp_pad; /* Unused */
SLONG blp_page [1]; /* Page number if level 1 */
} *BLP;
#define blp_data blp_page /* Formerly defined field */
#define BLP_SIZE OFFSETA (BLP, blp_page)
#define blp_pointers 1 /* Blob pointer page, not data page */
/* B-tree node */
typedef struct btn {
UCHAR btn_prefix; /* size of compressed prefix */
UCHAR btn_length; /* length of data in node */
UCHAR btn_number [4]; /* page or record number */
UCHAR btn_data [1];
#ifdef _CRAY
};
#else
} *BTN;
#endif
#define BTN_SIZE 6
/* B-tree page ("bucket") */
typedef struct btr {
struct pag btr_header;
SLONG btr_sibling; /* right sibling page */
SLONG btr_left_sibling; /* left sibling page */
SLONG btr_prefix_total; /* sum of all prefixes on page */
USHORT btr_relation; /* relation id for consistency */
USHORT btr_length; /* length of data in bucket */
UCHAR btr_id; /* index id for consistency */
UCHAR btr_level; /* index level (0 = leaf) */
struct btn btr_nodes [1];
} *BTR;
#define btr_dont_gc 1 /* Don't garbage-collect
this page */
#define btr_not_propogated 2 /* page is not propogated
upward */
#define btr_descending 8 /* Page/bucket is part of a
descending index */
#define MAX_NODES ((dbb->dbb_page_size - OFFSETA (BTR, btr_nodes)) /
sizeof (struct btn))
/* Data Page */
typedef struct dpg {
struct pag dpg_header;
SLONG dpg_sequence; /* Sequence number in relation */
USHORT dpg_relation; /* Relation id */
USHORT dpg_count; /* Number of record segments on page */
struct dpg_repeat
{
USHORT dpg_offset; /* Offset of record fragment */
USHORT dpg_length; /* Length of record fragment */
} dpg_rpt [1];
} *DPG;
#define DPG_SIZE (sizeof (struct dpg) - sizeof (struct dpg_repeat))
#define dpg_orphan 1 /* Data page is NOT in pointer page */
#define dpg_full 2 /* Pointer page is marked FULL */
#define dpg_large 4 /* Large object is on page */
/* Index root page */
typedef struct irt {
struct pag irt_header;
USHORT irt_relation; /* relation id (for consistency) */
USHORT irt_count; /* Number of indices */
struct irt_repeat
{
SLONG irt_root; /* page number of index root */
union
{
float irt_selectivity; /* selectivity of index */
SLONG irt_transaction; /* transaction in progress */
} irt_stuff;
USHORT irt_desc; /* offset to key descriptions */
UCHAR irt_keys; /* number of keys in index */
UCHAR irt_flags;
} irt_rpt [1];
} *IRT;
/* Header page */
typedef struct hdr {
struct pag hdr_header;
USHORT hdr_page_size; /* Page size of database */
USHORT hdr_ods_version; /* Version of on-disk structure */
SLONG hdr_PAGES; /* Page number of PAGES relation */
ULONG hdr_next_page; /* Page number of next hdr page */
SLONG hdr_oldest_transaction; /* Oldest interesting transaction */
SLONG hdr_oldest_active; /* Oldest transaction thought
active */
SLONG hdr_next_transaction; /* Next transaction id */
USHORT hdr_sequence; /* sequence number of file */
USHORT hdr_flags; /* Flag settings, see below */
SLONG hdr_creation_date [2]; /* Date/time of creation */
SLONG hdr_attachment_id; /* Next attachment id */
SLONG hdr_shadow_count; /* Event count for shadow
synchronization */
SSHORT hdr_implementation; /* Implementation number */
USHORT hdr_ods_minor; /* Update version of ODS */
USHORT hdr_ods_minor_original; /* Update version of ODS at
creation */
USHORT hdr_end; /* offset of HDR_end in page */
ULONG hdr_page_buffers; /* Page buffers for database cache */
SLONG hdr_bumped_transaction; /* Bumped transaction id for log
optimization */
SLONG hdr_oldest_snapshot; /* Oldest snapshot of active
transactions */
SLONG hdr_misc [4]; /* Stuff to be named later */
UCHAR hdr_data [1]; /* Misc data */
} *HDR;
#define HDR_SIZE OFFSETA (HDR, hdr_data)
#define hdr_cache_file hdr_data
/* Page Inventory Page */
typedef struct pip {
struct pag pip_header;
SLONG pip_min; /* Lowest (possible) free page */
UCHAR pip_bits [1];
} *PIP;
/* Pointer Page */
typedef struct ppg {
struct pag ppg_header;
SLONG ppg_sequence; /* Sequence number in relation */
SLONG ppg_next; /* Next pointer page in relation */
USHORT ppg_count; /* Number of slots active */
USHORT ppg_relation; /* Relation id */
USHORT ppg_min_space; /* Lowest slot with space available */
USHORT ppg_max_space; /* Highest slot with space available */
SLONG ppg_page [1]; /* Data page vector */
} *PPG;
#define ppg_bits ppg_page
#define ppg_eof 1 /* Last pointer page in relation */
/* Transaction Inventory Page */
typedef struct tip {
struct pag tip_header;
SLONG tip_next; /* Next transaction inventory page */
UCHAR tip_transactions [1];
} *TIP;
/* Log page */
typedef struct ctrl_pt {
SLONG cp_seqno;
SLONG cp_offset;
SLONG cp_p_offset;
SSHORT cp_fn_length;
} CP;
typedef struct log_info_page {
struct pag log_header;
SLONG log_flags; /* flags */
CP log_cp_1; /* control point 1 */
CP log_cp_2; /* control point 2 */
CP log_file; /* current file */
SLONG log_next_page; /* Next log page */
SLONG log_mod_tip; /* tip of modify transaction */
SLONG log_mod_tid; /* transaction id of modify process */
SLONG log_creation_date [2]; /* Date/time of log creation */
SLONG log_free [4]; /* some extra space for later use */
USHORT log_end; /* similar to hdr_end */
UCHAR log_data [1];
} *LIP;
#define LIP_SIZE OFFSETA (LIP, log_data);
#endif /* _JRD_ODS_H_ */
Here's the checksum computation.
USHORT CCH_checksum (
BDB bdb)
{
/**************************************
*
* C C H _ c h e c k s u m
*
**************************************
*
* Functional description
* Compute the checksum of a page.
*
**************************************/
#ifdef NO_CHECKSUM
return DUMMY_CHECKSUM;
#else
#ifdef WINDOWS_ONLY
ULONG checksum, huge *p, huge *end;
#else
ULONG checksum, *p, *end;
#endif
USHORT old_checksum;
PAG page;
DBB dbb;
dbb = bdb->bdb_dbb;
#ifdef WIN_NT
/* ODS_VERSION8 for NT was shipped before page checksums
were disabled on other platforms. Continue to compute
checksums for ODS_VERSION8 databases but eliminate them
for ODS_VERSION9 databases. The following code can be
deleted when development on ODS_VERSION10 begins and
NO_CHECKSUM is defined for all platforms. */
if (dbb->dbb_ods_version >= ODS_VERSION9)
return DUMMY_CHECKSUM;
#endif
page = bdb->bdb_buffer;
#ifdef WINDOWS_ONLY
end = (ULONG huge*) ((SCHAR huge *) page + dbb->dbb_page_size);
#else
end = (ULONG*) ((SCHAR*) page + dbb->dbb_page_size);
#endif
old_checksum = page->pag_checksum;
page->pag_checksum = 0;
#ifdef WINDOWS_ONLY
p = (ULONG huge*) page;
#else
p = (ULONG*) page;
#endif
checksum = 0;
do
{
checksum += *p++;
checksum += *p++;
checksum += *p++;
checksum += *p++;
checksum += *p++;
checksum += *p++;
checksum += *p++;
checksum += *p++;
}
while (p < end);
page->pag_checksum = old_checksum;
if (checksum)
return (USHORT) checksum;
/* If the page is all zeros, return an artificial checksum */
for (p = (ULONG*) page; p < end;)
if (*p++)
return checksum;
/* Page is all zeros -- invent a checksum */
return 12345;
#endif
}