Method for maintaining log compatibility in database systems6014674Abstract A relational database system providing improved data structures and methods which operate for translating log records is described. A table of translation functions or methods (pointers) is provided, one per "logop" (i.e., log operation) record type. The logop, which is a single byte value, can be used as an index into the table. During times when a log incompatibility state exists in a database, a Log Compatibility module is invoked for performing appropriate translations. In the client's stack space, hidden from client code, a buffer is provided in which a reformatted log record can be stored. An appropriate translate method installed for the current logop is called; it procures a pointer to that buffer, and reformats the log record into that space. The system returns to the client a pointer to a reformatted log record in its own stack space, with the client largely unaware of the issue. Thus, each logop code indexes (in natural order) into an array or table which, in turn, references particular methods which perform appropriate translation, with the client (caller) receiving a pointer to the translated log record in the client's stack space. Claims What is claimed is: Description COPYRIGHT NOTICE
______________________________________
typedef struct xxs
/* Link for active transaction list - MUST BE FIRST */
LINK xxs.sub.-- activelist;
/* External data to XLS - none */
/* Internal data */
/*
** This set remain constant once the XXS object
** is attached to the XDES object.
*/
struct xdes *xxs.sub.-- xdes;
/* Pointer to attaced XDES */
struct pss *xxs.sub.-- pss;
/* Pointer to task's PSS
** (housekeeping)
*/
PLCSTATE *xxs.sub.-- plc;
/* Pointer to task's PLC */
/*
** This set remain constant during a transaction.
*/
struct dbtable *xxs.sub.-- dbx; /* Database for transaction */
/*
** This set varies over the life of a transaction.
*/
struct sdes
*xxs.sub.-- syslogs.sub.-- xact; /* SDES for SYSLOGS for xacts
*/
uint32 xxs.sub.-- state; /* State of XLS session */
int xxs.sub.-- plclrn; /* LRN id of first lr in PLC */
int xxs.sub.-- count; /* Total number of lr's written */
circ.sub.-- long
xxs.sub.-- flushseq; /* Current dirty seq. for flush */
int xxs.sub.-- error; /* Error for last failure */
struct sdes
*xxs.sub.-- syslogs.sub.-- scan; /* SDES for SYSLOGS for
SCANs */
XLSCAN *xxs.sub.-- scan; /* Current scan structure */
uint32 xxs.sub.-- reqmarkers;
uint32 xxs.sub.-- nlreqmarkers;
XLRMARKER xxs.sub.-- markers[XLSM.sub.-- NUM.sub.-- MARKERS];
}XXS;
______________________________________
The XXS data structure references a private log cache data structure or "PLC object," as shown at 365. This controls the region in memory where the log records are actually cached. In an exemplary embodiment, the PLC object (an object of type PLCSTATE) may be constructed as follows.
______________________________________
**
** The PLCSTATE holds the state information for the PLC itself.
** Each PLCSTATE owns one PLC.sub.-- DATA object, which is where log
** records are actually cached.
**
** XXS <-> PLC synchronisation
** plc.sub.-- xkeeper -
Identifies the the XLS session (via the internal
** descriptor (XXS *)) that keeps the PLC. This field
** may only be changed by the task that owns
** the XLS session and only when holding the PLC
** lock.
** This means that the keeper of the PLC can read
** this field without any synchronisation. All other
** tasks must grab the PLC lock to see a stable value for
** this field.
** The PLC at any time is kept by at most one XLS session.
** If an XLS session does not have the PLC kept
** (plc.sub.-- xkeeper is NULL), then there can be
** no log records in the PLC. The thread owning
** the PLC may avoid locking the PLC if the current XLS
** session does not have the PLC kept. The assumption
** is that other threads have no interest in the PLC
** when it is empty.
**
** plc.sub.-- lockcount Can only be read and modified under the PLC
** spinlock.
*/
typedef struct plcstate
/* External data to XLS - none */
/* Internal data */
/*
** This set remain constant once the PLCSTATE object
** is attached to the PLC.sub.-- DATA object.
*/
struct spinlock *plc.sub.-- spinlock; /* Spinlock for PLC */
BYTE *plc.sub.-- start;
/* Start of PLC.sub.-- DATA */
BYTE *plc.sub.-- end;
/* End of PLC.sub.-- DATA */
int plc.sub.-- maxpagecount;
/* Maximum number of
** log pages required
** to flush the PLC.
*/
/*
** This set is variable during the life of the PLCSTATE
*/
int plc.sub.-- lockcount
/* PLC semaphore count */
int plc.sub.-- waiters;
/* # of waiters for PLC lock */
int plc.sub.-- maxlength;
/* max len of next log rec */
int plc.sub.-- count;
/* # of log records in PLC */
int plc.sub.-- logspace.sub.-- free;
/* number of bytes still
** reserved in log through
** the threshold manager.
*/
/*
** plc.sub.-- offset :
**
** if the PLC is not being flushed then plc.sub.-- offset is the
** address where the next log record will be placed in the PLC.
**
** Otherwise plc.sub.-- offset is the address of the next log record
** to be removed from the PLC.
*/
BYTE *plc.sub.-- offset;
struct xxs
*plc.sub.-- xkeeper;
/* Current XXS keeper of PLC */
struct pss
*plc.sub.-- locker;
/* Pss of task locking the PLC */
struct syb.sub.-- buf
*plc.sub.-- bufhead;
/* Header of pinned buffer chain
*/
}PLCSTATE;
______________________________________
Although the PLC is shown inside the XXS data structure, in a preferred embodiment the XXS data structure would instead store a pointer or handle referencing the PLC structure or object. The XXS data structure 360 also stores or is associated with an array of transaction log record (XLR) markers 370. In a preferred embodiment, the array 370 comprises a fixed array (size=6) XLR markers. Each array entry, which serves as a pre-defined marker pointing to a particular part of the transaction, may be constructed from the following definitions.
______________________________________
/*
** XLRMARKER - Log Record Marker - OPAQUE to XLS clients.
**
** Clients of the XLS must not assume or have knowledge of
** any of the below.
**
** Internally a XLRMARKER has two formats, non-permanent and
** permanent.
**
** In the non-permanent form the marker is the numeric
** order of the log record with the first being XXS.sub.-- LRN.sub.--
FIRST (==1).
** This is stored in u.sub.-- xlr.sub.-- marker.
**
** In the permanent form the marker is the RID of the log record
** (ie. once it has made it to the log page chain). This is stored
** in u.sub.-- xlr.sub.-- rid.
*/
typedef struct xlrmarker
union
{
struct
{
pgid.sub.-- t fakepage;
int32 u.sub.-- xlr.sub.-- marker;
}s;
RID u.sub.-- xlr.sub.-- rid;
}u;
} XLRMARKER;
/* Markers stored in XXS */
#define
XLSM.sub.-- FIRST 0 /* First log record of transaction */
#define
XLSM.sub.-- LAST 1 /* Last log record of transaction */
#define
XLSM.sub.-- CMDSTART 2 /* Client defined CMDSTART */
#define
XLSM.sub.-- ABORTMARK 3 /* Client defined ABORTMARK i.e.
** a place in log to rollback to
#define
XLSM.sub.-- LASTSAVE 4 /* Client define LASTSAVE
** i.e. a savepoint in log to rollback to
#define
XLSM.sub.-- LASTINPAGECHAIN 5 /* Last log record added to
page chain */
#define
XLSM.sub.-- NUM.sub.-- MARKERS 6 /* Number stored in XXS */
/* Markers not stored in XXS */
#define
XLSM.sub.-- SCAN (-1) /* Current log record of log scan */
#define
XLSM.sub.-- OLDESTXACT (-2) /* Oldest active transaction */
#define
XLSM.sub.-- LOGLAST (-3) /* Last log record in log page chain */
#define
XLSM.sub.-- LOGFIRST (-4) /* First log record in log page chain
*/
______________________________________
Client code refers to the markers by indexing into the array. The first three markers are of particular interest to the present invention. The "first" XLR marker 371 points to the first log record associated with a transaction. In a corresponding manner, the "last" XLR marker 372 points to the last log record associated with the transaction. Finally, the "command start" XLR marker 373 points to the log record associated with the first data access/manipulation command of the current SQL statement (e.g., SQL INSERT command). As indicated by the definition for XLRMARKER and illustrated in FIG. 3B, each XLR marker can take one or two forms. In a first form, the marker stores a pointer 381 to a log record while the log record is in a private log cache. In an alternative form, the marker stores a "RID"--a record ID--as shown at 391. In this latter form, the marker points to the log record in the page chain by referencing a particular ID of the page together with a row number on that page where the record is located. The index stored by pointer 381, on the other hand, simply is the ordinal number of the log record within the transaction; it is used to locate a record within the PLC. 3. Two-Phase "Pinning" and "Unpinning" Recall that the "log pin" represents where in the log page chain log records must be flushed to disk before the corresponding data page can be flushed. Besides this mechanism, the present invention introduces a second mechanism. Because log records can reside in a (user) private log cache (i.e., per "user" connection), a mechanism is needed to ensure that such records are flushed (to the log page chain). If a change which affects a data page is represented in a private log cache, the PLC pin for that page will be instantiated and will point to the corresponding PLC.sub.-- DATA data structure (through the xdes data structure). In this manner, when such a data page is written, the system first unpins the PLC pin, thus causing the corresponding PLC.sub.-- DATA data structure to be flushed to the log page chain. Now, the data page will get a pin to the log, for indicating where in the log records must be flushed in order to write the data page. The addition of the second pointer to the data page buffer provides a two-phase unpinning mechanism. Unpinning a page now requires that the corresponding private log cache (i.e., the one being pointed to by the pointer stored in the page) be first flushed to the log page chain. Secondly, the in-memory log itself is Log Translation A. Need for Log Translation Log records might need translation for a variety of reasons. Consider, for instance, the following log records.
TABLE
______________________________________
V10.sub.-- 1xxx log record structures
V10.sub.-- 1.sub.-- xxx log record structure
Need for translation (see below)
______________________________________
V10.sub.-- 1.sub.-- XALLOC
b)
V10.sub.-- 1.sub.-- XCHANGE
a)
V10.sub.-- 1.sub.-- XDROPCOL
a)
V10.sub.-- 1.sub.-- XEXTALLOC
b)
V10.sub.-- 1.sub.-- XNOOP
a)
______________________________________
a) A new field has been added, and while it is unused by Recovery, it could not be introduced at the end of the structure, because there is a variable-length field, which of course must be at the end. As a result, the displacement of data needed by Recovery means the record must be translated so that Recovery will find the data at its expected offset; or b) A new field is introduced and is used by Recovery. Recovery accepts a default value of zero for the field. Translate methods need not know the new field's identity; they need only MEMZERO the translation buffer and map the prior version (V10.sub.-- 1.sub.-- Xxxx) fields into the current version (System 11) structure; or c) A new field is introduced and is used by Recovery, and Recovery cannot use a default of zero. Here, the translate method must synthesize a reasonable value for the new field. Even if reasonable values can be synthesized, having to know about fields unique to the output structure makes the translate methods less maintainable; or d) The log record format has not changed, but an existing field has been given a new use. This is the case for the XSORTREC structure, which is not treated by the Table 1.1, since there is no V10.sub.-- 1.sub.-- version of this log record. In XSORTREC, a field that is uninitialized storage prior to SQL Server version 10.1 becomes meaningful in 10.1. SQL Server Version 10.1 has no Log Compatibility module, so its do layer must clear this field to its default, zero, value, when it detects an XSORTREC record of pre-10.1 provenance. In System 11, this task is moved out of the do layer into a log translation method. B. Approaches of Prior SQL Server Architecture 1. Prior system (e.g., System 10) invalidated customer dumps Before describing preferred methodology of the present invention, it is helpful to review approaches of prior versions to addressing the problem. One approach to log compatibility is to simply have the new system not support the prior system. For instance, in the design of a new system, the new system can be designed such that a "load" of database "dumps" created by previous versions would not be recognizable. Such an approach, however, is unlikely to be unacceptable to customers. Instead, customers require that dump compatibility be maintained from one version to the next. Since a DUMP DATABASE performed against an active database requires log recovery, a dump with incompatible log records cannot be recovered by LOAD DATABASE recovery. Without log translation, a prior system's dumps might not be compatible. As a result, the marketplace demands that database designers not invalidate dumps of the preceding release. 2. Previous Attempt at Handling Changes to Log Records In earlier SQL Server architecture, an attempt at handling changes to log records (e.g., in SQL Server 4.0) tried to cope with the replacement of a pad spare by a status word in the generic LOG header that is found up through and including System 10 log records. The spare was uninitialized in customer databases. The 4.0 implementation of a text/image feature required a status bit to indicate a second flavor of an existing logop. The implementors added not only a "text" bit, but also a "this status word is not garbage (honest)" bit in the same field. Then, to reduce the chance that this second bit might be garbage, log record readers came eventually to test for bits in a complementary "must be zero" mask, reasoning that at least the probability of error would thereby be reduced. Realizing the difficulty presented by uninitialized storage, one might have assumed that the 4.0 implementation must have included the effort to modify every SQL Server log writer to initialize the new generic status word. Such an assumption would be incorrect, however. As late as System 10, there are still log writers which did not initialize that field. In System 11, the XLS implementation finally meets this modest standard. C. Alternative Strategies 1. Maintain Log Version at the Log Record Level Instead of the Database level Version bits could be inscribed in the generic log header status word, which System 11 puts under control of the log translation system or XLS. A "master bit", one with no meaning prior to System 11, would indicate that the log record version incorporates this log record version bit scheme; without the bit, the log record would be taken to be of pre-System 11 vintage. If there were no future need for new other-than-log-version bits in that space, there would be at least eight log versions that could be defined before value rollover. The approach has pronounced disadvantages, however. The issue of possible variances in physical log record format should not encumber record-by-record log reading and writing. In general, special case logic should intrude on main-line code as little as possible, especially at low level. The design which is preferred should impose no special case logic on log record writes, and allow the chance of avoiding it for reads in a future amendment by a more innovative designer. As another disadvantage, the version-bit approach is impracticable, since the contents of the log header status word in SQL Server versions prior to System 11 can be garbage for many logops. The master bit would suffer from the same ambiguity as the "this status word is not garbage" bit. Preferred Log Translation Methodology A. Overview Implementation of the methodology of the present invention is facilitated by the log translation system or XLS. In the presently-preferred embodiment, therefore, this feature is checked in before the "Log Compatibility" module is invoked. XLS imposes a discipline on log reading that allows simple, easy mapping of Log Compatibility resources and entry points. The ONLINE DATABASE command, which shares Log Compatibility's ECO, is required in order to create the quiescent-Checkpoint boundary which prevents Recovery from reading both old- and new-format log records. It also ensures that the correct set of this module's log translation methods is installed, by calling the Log Compatibility module to install the appropriate log translation methods each time it modifies the value of the log version field in the database table (dbtable). In accordance with the present invention, the logging system is modified as follows. An XLS (transaction logging system) method is provided which enforces a single entry point for log readers, enabling virtual transparency of the translation module. Underneath that entry point, XLS invokes a "Log Compatibility" module when necessary, with XLS client code (i.e., internal SQL Server client modules) largely unaware of the automatic translation. The XLS design previously added XLSCAN to each log reader's stack space. Log Compatibility replaces XLSCAN with a higher-level structure (LOGSCAN) incorporating both the XLS-dedicated XLSCAN and a Log Compatibility translation buffer (XRECORD). As a result, memory allocation for the buffer is achieved one-for-one with each instance of a reader of a log record, transparently to that client code (since the XLS design had already required that log readers declare a scan structure before Log Compatibility came along). XLS links the translation buffer to the XDES with no conscious involvement by the internal client; underneath XLS, the buffer is filled and its address returned as a log record pointer with no visible client code aware of the concept. Although XLS clients, upon receipt of a log record pointer, could perform their own log translation based upon their own detection of the log incompatibility state, such an approach is undesirable. Providing special-case log format translation considerations in other logic layers is highly undesirable, as maintenance would become significantly more difficult. Thus, log-reading XLS clients preferably would not do their own log translation. Log version information, DBTABLE.dbt.sub.-- logvers, is maintained by ONLINE DATABASE and the DB manager to indicate the provenance of the log records in the active portion of the log. ONLINE DATABASE, a command which indicates that the load sequence is over, writes a quiescent log record indicating that nothing occurred before that log record. If necessary, it will install a new log identifier. During Recovery, encounter of the identifier will cause new log translation methods to be employed. It in effect serves as a fire wall keeping Recovery from looking at log record versions which do not match the version installed in the database. If DBTABLE.dbt.sub.-- logvers differs from the defined constant CUR.sub.-- LOGVERS.sub.-- ID, then the database is in a log incompatibility state. Log record translation is performed by per-logop translation method functions, invoked by using the logop as an index into an array of function pointers. This invocation is performed by a translate get next method, xls.sub.-- getnext(), as its last act before returning control to its client, when the database is in a log incompatibility state. DBTABLE.dbt.sub.-- logxlate is a pointer to such an array. It is made non-null whenever dbt.sub.-- logvers receives a value that creates a log incompatibility state. In System 11, this event occurs when Recovery is about to commence after the load of a dump that was created by System 10. B. Basic Operation of Core Methods FIG. 4 illustrates a high-level diagram for internal data structures and methods which operate for translating log records when there is a skew or difference between a system version and that of log records begin processed. As shown in FIG. 4, when such a difference exists, Translation Methods Function Table 401 is instantiated. The table is a table of functions (pointers), one per logop. The logop, which is a single byte value, can be used as an index into the table. For instance, the value of zero defines the log operation for "began transaction" or BEGIN.sub.-- XACT log record. Therefore, the first entry in the table is one for translating a BEGIN.sub.-- XACT log record. As shown in FIG. 5, a set of translation tables can be defined at run time, one for each version being supported. During the case that a log incompatibility state exists in a database, XLS operation takes a detour into the Log Compatibility module for performing appropriate translations. In the XLS client's stack space, hidden from client code, is a buffer 403 in FIG. 4 in which a reformatted log record can be stored. A translate method installed for the current logop is called; it procures from the passed-in XDES a pointer to that buffer, and reformats the log record into that space. XLS returns to the client a pointer to a reformatted log record in its own stack space, with the client largely unaware of the issue. As shown in the figure, for instance, the system indexes into the fourth entry. The method performing this indexing is a translate method, LOGX.sub.-- XLATE.sub.-- XREC (405). As shown at 407, this entry references a translation function, LOGX.sub.-- V10.sub.-- 1.sub.-- XCHANGE.sub.-- INSERT, which performs log translation for, in this example, an insert log record. In this manner, each op code indexes (in natural order) into an array or table which, in turn, references particular methods which perform the translation. What the client (caller) gets back is a pointer to the translated log record in the client's stack space. All log reader access is preferably funneled through xls.sub.-- getnext(), shown at 409. Via an ONLINE DATABASE command, a quiescent Checkpoint record establishes a clean boundary between old log records and new, such that Recovery will read log records only from one version or the other, and not both. Private log cache (PLC) and log-record-reading trigger code will never be active at the same time as log translation methods, since those two components operate only after the database has come on-line. Replication, which can ignore the log boundary created by ONLINE DATABASE's Checkpoint Record, or SQL Server, ensures that all of a replicated SQL Server database's log has been transmitted to persistent Replication storage, and that its persistent start-of-the-log pointer is updated, before the upgrade to the next SQL Server version is begun. In this manner, when the database system of the next version begins transmission to the Replication Server, it will read only new-format log records, generated after the boot of the new executable. The PLC and the trigger code that reads log records have no impact on Log Compatibility design, because both operate after a database has come on-line, when a log incompatibility state cannot exits. In the preferred embodiment, great effort is taken to avoid exposing log readers to log format translation issues. For most log records, log reader code does not change. A few readers, of log records with variable-length data fields, access those data fields via macros that disguise the location of those fields, which may not be in the C data structure in which they were written. To this end, the XLS serves as the sole main-line interface with the Log Compatibility module. On behalf of the Log Compatibility module, xls.sub.-- startscan() inserts into the XDES a pointer to the client's translation buffer. Just prior to concluding execution, xls.sub.-- getnext() performs a single function call to logx.sub.-- xlate.sub.-- xrec() if SQL Server is in a state of log incompatibility. On behalf of the Log Compatibility module, xls.sub.-- endscan() clears the XDES pointer to the client's translation buffer, as illustrated in the figure. C. Implementation 1. New Data Structures An XRECORD data structure is introduced as a union of all log record structures. It is used to define a translation buffer into which the log translation methods can deposit a translation of a prior system's log record (e.g., in System 10). This union is desirable even without Log Compatibility, simply to improve log record pointer data typing. Prior to XLS, log scans unqualified by logop (which would connote an expectation of the logop's associated C structure type) are typed as (LOG *), because that header structure was held in common by all records. XLS removes the header from public view, so the initial implementation of XLS could only give its clients a (BYTE *) as a generic log record handle. The Log Compatibility implementation changes the XLS scan API (application programming interface) so that xls.sub.-- getnext() returns an (XRECORD *). As an additional benefit, Log Compatibility removes from the highest-level do layer functions, and other log reading functions with a use for more than one logop, casts in the following in style: ##EQU1## in favor of the following safer style (with corresponding mnemonic change):
______________________________________
if (1ch.loh.sub.-- op == XREC.sub.-- MODIFY)
do.sub.-- row (&xrec->xchange, ...);
______________________________________
thus, achieving better log pointer data typing. A LOGSCAN data structure is provided which incorporates the XLSCAN structure required of each log reader. It adds the XRECORD union of all log record structures, a buffer into which the Log Compatibility methods can deposit their work. This design replaces each xls.sub.-- startscan() caller's XLSCAN declaration with a LOGSCAN declaration. By replacing one opaque datatype with another, this design unobtrusively plants storage for expanding each log record returned by xls.sub.-- getnext(), when the log incompatibility state exists. This buffer is only used when recovering a database whose log records were written by SQL Server version with different log record formats. It is not used in a database that is on-line. For supporting their versions, System 10 log formats are provided (typically implemented in a separate header file, logxlate.h). The log record structures in this file are the System 10 versions of log record structures that are seen with a different format in the System 11 version of log.h. Also included is the System 10 generic "log header" structure which is not seen in System 11 log.h, because that portion of each log record is held in private by the XLS. Their names take a prefix indicating the latest SQL Server version in which they would been used at the time of the prefix was needed by the Log Compatibility implementation. There could be a SQL Server released later than the version indicated by that prefix which nonetheless uses these formats, but its release would have occurred after this prefix had been chosen. V10.sub.-- 1.sub.-- LOG is the System 10 generic log header structure (LOG). V10.sub.-- 1.sub.-- LOG is required by each System 10-format log record structure definition, and is also directly required by the log translation methods, because its internals are required in the System 10 approach to determining correct logical record lengths. The other structures prefix "V10.sub.-- 1" to structures names identical to the those of the System 11 log records to which they correspond. They allow access to these System 10 log records in log disk buffers as sources for remapping their fields into System 11 log record structures. 2. Changes to Existing Data Structures: Variable Fields Become Unions Issues regarding variable-length data fields in log record structures require special attention since this area is prone to errors in implementation and maintenance. XCHANGE.xchgtype, XDROPCOL.xdata, and XNOOP.xnoopins each represent a variable field that typically extends beyond the end of the C structure defined for the log record. Since there is no fixed end of the structure as it is actually used, there is no clean way to append a new field at the end. So, a new field added to each of these structures by System 11 is placed before the end, displacing the variable-length field from its location in the previous log version. Reformatting is required in order for log recovery to find the data in log records of the previous format. The data in these variable-length fields should not be stored directly in the translation buffer. With such a data field, a log record can approach SYBPAGESIZE, which would be too much to allocate on the stack. Thus, only the fixed portion of the log record is reformatted into the translation buffer. In such a reformatted log record, in place of the data found embedded at the end of a current-format log record, is a pointer to the data field in the original, untranslated log record in the log I/O buffer. Hence, these log structures are defined with unions for the variable data field. By way of example, the following is the simpler, pre- Log Compatibility XCHANGE.xchgtype union; it serves four styles of XCHANGE use. Two styles use variable data fields:
______________________________________
union xchgtype
{
struct xins ind
{
XLRMARKER xptr; /* log row
pointer */
int16 xdatarnum; /* data row number */
} xinsind; /* for INSIND */
BYTE xrow[2]; /* for INSERT, DELETE,
IINSERT, IDELETE */
int16 xvallen; /* for MODIFY */
pgid.sub.-- t xnewpg; /* for SPLIT */
} xchgtype;
______________________________________
The following is the XCHANGE.xchgtype union modified by the Log Compatibility design: xrow and xvalue themselves become unions:
______________________________________
union xchgtype
{
/*
** For INSIN), INSINDTEXT
*/
struct xinsind
{
XLRMARKER xptr; /* log row pointer */
int16 xdatarnum; /* data row number */
} xinsind;
/*
** For INSERT, DELETE, IINSERT, IDELETE, TEXTINSERT,
TEXTDELETE
*/
union xrow
{
/* Embedded, variable, BYTE array
** This is how data is stored on disk.
*/
BYTE xvalue[2];
/* Pointer to BYTE array on disk --
** used if translated form of log record
** is necessary.
** This field not seen on disk.
*/
BYTE *xvalueptr;
} xrow;
/*
** For MODIFY, OAMATPUT
*/
struct modifychg
{
int16 xvallen; /* length of each of
** old and new values
*/
union xvalues
{
/* -Two- arrays, each xvallen bytes long,
** concatenated into one array, which
extends
** off the end of this log record
structure.
** Old value array at offset xvalues [0].
** New value array at offset
xvalues [xvallen].
** This is how update values are stored on
disk.
BYTE xvalues [2];
/* Pointers to values on disk --
**used if translated form of log record
** is necessary.
** This structure not seen on disk.
*/
struct xvalueptrs
{
BYTE *xoldvalptr;
BYTE *xnewvalptr;
} xvalueptrs;
} xvalues;
} xmodifychg;
/*
** For SPLIT
*/
pgid.sub.-- t xnewpg;
xchgtype;
______________________________________
Note this positive benefit from having to define a union with pointers for variable data fields: for XREC.sub.-- MODIFY and XREC.sub.-- OAMATPUT, explicit data fields must also exist, where before Log Compatibility, the entire data field(s), even the beginning, was implicit. Similarly to its XCHANGE.xchgtype modifications, Log Compatibility transforms the two-byte "xdata" fake array at the end of XDROPCOL into this union:
______________________________________
union xdata /* beginning of dropped data */
/* Embedded, variable, BYTE array
**This is how data is stored on disk.
*/
BYTE xdata[2];
/* pointer to BYTE array on disk --
** used by log readers if translated
** form of log record is necessary.
** This field not seen on disk.
*/
BYTE *xdataptr;
} xdata;
______________________________________
XNOOP.xnoopins changes form in the same way XDROPCOL.xdata changes form. A fixed, 60-byte array at the end of XBEGIN.sub.-- EXT is made variable, by replacing it with the standard fake two-byte array seen at the end of other log record structures with variable fields. This change reduces the hit on process stack space made by the LOGSCAN structure's XRECORD union. 3. Methods (pseudo code) Methods are described using pseudocode. The pseudocode descriptions for several functions include the statement, "use' unneeded<variable>". These statements indicate code in the form "varname=varname". All functions installed in the translate methods table fit the same prototype, but a few do not need all their arguments. a. Log Translate Methods The procedural flow for a single log translate method, with the generic log translate method function prototype given in dbtable.h to define DBTABLE.dbt.sub.-- logxlate is illustrated by the following function prototype and pseudo code.
______________________________________
typedef union xrecord * (*LOGXLATEFNPTR)
PROTO((struct xdes *, struct loh *, union xrecord *));
Overstore translate buffer with zeroes. Tbere will be a value of zero
in any field that is defined only in the output (newer) format.
For each field in old format
If field is fixed-length
copy field from old format in log page buffer
to new format in translation buffer
else
copy address of variable-length field in log page buffer
into new format's unioned BYTE array/BYTE pointer
in translation buffer
calculate logical record length for new format
store adjusted logical record length into client's LOH.loh.sub.-- len
Set "record has been translated" bit in LOH.loh.sub.-- status word;
this activates translation macros for variable-length fields
return pointer to translate buffer
______________________________________
This functionality is split out into subroutines wherever it is shared with other logop/log structure mappings/methods. b. Aberrant Log Translate Methods These functions are installed in the log translate methods table, but their pseudocode differs from the template shown in the Log translate methods section above. (1) logx.sub.-- v10.sub.-- 1.sub.-- xbegin.sub.-- beginxact This is a log translation module, but it does not remap fields into the translate buffer. It exists only to recalculate the logical record length per the System 11 logical record length formula.
______________________________________
XRECORD * logx.sub.-- v10.sub.-- 1.sub.-- xbegin.sub.-- beginxact
(xdes, loh,
unxlated.sub.-- xrec)
"use" unneeded xdes
get logical trnsaction name length from unxlated.sub.-- logrec
per System 10 logical transaction name length formula
using logical tranaction name length,
put logical record length into loh.loh.sub.-- len
per System 11 logical record length formula
return
______________________________________
(2) logx.sub.-- v10.sub.-- 1.sub.-- xinooptext.sub.-- inooptext Like logx.sub.-- v10.sub.-- 1.sub.-- xbegin.sub.-- beginxact(), this method translates only the logical record length, and not the log record itself. Its pseudocode is identical, even to the extent of referencing "transaction name". (3) logx.sub.-- v10.sub.-- 1.sub.-- xsavept.sub.-- savexact Like logx.sub.-- v10.sub.-- 1.sub.-- xbegin.sub.-- beginxact(), this method translates only the logical record length, and not the log record itself. Its pseudocode is identical to that for logx.sub.-- v10.sub.-- 1.sub.-- xbegin.sub.-- beginxact(), except that it replaces "transaction name" with "data". (4) logx.sub.-- v10.sub.-- 1.sub.-- xsortrec.sub.-- sort This function performs translation in that it copies from the log I/O buffer into the log translation buffer. However, this act is conditional, and there is no difference between the input and output log record formats.
______________________________________
XRECORD * logx.sub.-- v10.sub.-- 1.sub.-- xsortrec.sub.-- sort (xdes,
loh, unxlated.sub.-- xrec)
if (xdes->xdbptr->(dbt.sub.-- logvers >=
MROWSPG.sub.-- SUPT.sub.-- LOGVERS.sub.-- ID)
return unxlated.sub.-- xrec
else
structassign unxlated.sub.-- xrec to xdes->xxrec.sub.-- xlate
zero output XSORTREC.xsoindex.indmrowsperpg
set LHSR.sub.-- XLATED in loh->loh.sub.-- status
return xdes->xxrec.sub.-- xlate
______________________________________
While the invention is described in some detail with specific reference to a single-preferred embodiment and certain alternatives, there is no intent to limit the invention to that particular embodiment or those specific alternatives. Thus, the true scope of the present invention is not limited to any one of the foregoing exemplary embodiments but is instead defined by the appended claims.
|
Same subclass Same class Consider this |
||||||||||
