summaryrefslogtreecommitdiff
path: root/storage/connect/filamfix.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'storage/connect/filamfix.cpp')
-rw-r--r--storage/connect/filamfix.cpp403
1 files changed, 236 insertions, 167 deletions
diff --git a/storage/connect/filamfix.cpp b/storage/connect/filamfix.cpp
index 9338ae322db..1fa72d52746 100644
--- a/storage/connect/filamfix.cpp
+++ b/storage/connect/filamfix.cpp
@@ -1,7 +1,7 @@
/*********** File AM Fix C++ Program Source Code File (.CPP) ***********/
/* PROGRAM NAME: FILAMFIX */
/* ------------- */
-/* Version 1.5 */
+/* Version 1.6 */
/* */
/* COPYRIGHT: */
/* ---------- */
@@ -80,6 +80,37 @@ FIXFAM::FIXFAM(PFIXFAM txfp) : BLKFAM(txfp)
} // end of FIXFAM copy constructor
/***********************************************************************/
+/* SetPos: Replace the table at the specified position. */
+/***********************************************************************/
+bool FIXFAM::SetPos(PGLOBAL g, int pos)
+ {
+ if (pos < 0) {
+ strcpy(g->Message, MSG(INV_REC_POS));
+ return true;
+ } // endif recpos
+
+ CurBlk = pos / Nrec;
+ CurNum = pos % Nrec;
+#if defined(_DEBUG)
+ num_eq[(CurBlk == OldBlk) ? 1 : 0]++;
+#endif
+
+ // Indicate the table position was externally set
+ Placed = true;
+ return false;
+ } // end of SetPos
+
+/***********************************************************************/
+/* Initialize CurBlk and CurNum for indexed DELETE. */
+/***********************************************************************/
+int FIXFAM::InitDelete(PGLOBAL g, int fpos, int spos)
+ {
+ CurBlk = fpos / Nrec;
+ CurNum = fpos % Nrec;
+ return RC_OK;
+ } // end of InitDelete
+
+/***********************************************************************/
/* Allocate the block buffer for the table. */
/***********************************************************************/
bool FIXFAM::AllocateBuffer(PGLOBAL g)
@@ -128,12 +159,9 @@ void FIXFAM::ResetBuffer(PGLOBAL g)
/*********************************************************************/
/* If access is random, performances can be much better when the */
/* reads are done on only one row, except for small tables that can */
- /* be entirely read in one block. If the index is just used as a */
- /* bitmap filter as for Update or Delete reading will be sequential */
- /* and we better keep block reading. */
+ /* be entirely read in one block. */
/*********************************************************************/
- if (Tdbp->GetMode() == MODE_READ && ReadBlks != 1 && !Padded &&
- Tdbp->GetKindex() /*&& Tdbp->GetKindex()->IsRandom()*/) {
+ if (Tdbp->GetKindex() && ReadBlks != 1 && !Padded) {
Nrec = 1; // Better for random access
Rbuf = 0;
Blksize = Lrecl;
@@ -144,79 +172,93 @@ void FIXFAM::ResetBuffer(PGLOBAL g)
} // end of ResetBuffer
/***********************************************************************/
+/* WriteModifiedBlock: Used when updating. */
+/***********************************************************************/
+int FIXFAM::WriteModifiedBlock(PGLOBAL g)
+ {
+ /*********************************************************************/
+ /* The old block was modified in Update mode. */
+ /* In Update mode we simply rewrite the old block on itself. */
+ /*********************************************************************/
+ int rc = RC_OK;
+ bool moved = false;
+
+ // Using temp copy any intermediate lines.
+ if (UseTemp && MoveIntermediateLines(g, &moved))
+ rc = RC_FX;
+
+ // Fpos is last position, Headlen is DBF file header length
+ else if (!moved && fseek(Stream, Headlen + Fpos * Lrecl, SEEK_SET)) {
+ sprintf(g->Message, MSG(FSETPOS_ERROR), 0);
+ rc = RC_FX;
+ } else if (fwrite(To_Buf, Lrecl, Rbuf, T_Stream) != (size_t)Rbuf) {
+ sprintf(g->Message, MSG(FWRITE_ERROR), strerror(errno));
+ rc = RC_FX;
+ } else
+ Spos = Fpos + Nrec; // + Rbuf ???
+
+ if (Closing || rc != RC_OK) { // Error or called from CloseDB
+ Closing = true; // To tell CloseDB about error
+ return rc;
+ } // endif Closing
+
+ // NOTE: Next line was added to avoid a very strange fread bug.
+ // When the fseek is not executed (even the file has the good
+ // pointer position) the next read can happen anywhere in the file.
+ OldBlk = CurBlk; // This will force fseek to be executed
+ Modif = 0;
+ return rc;
+ } // end of WriteModifiedBlock
+
+/***********************************************************************/
/* ReadBuffer: Read one line for a FIX file. */
/***********************************************************************/
int FIXFAM::ReadBuffer(PGLOBAL g)
{
int n, rc = RC_OK;
- if (!Closing) {
+ /*********************************************************************/
+ /* Sequential reading when Placed is not true. */
+ /*********************************************************************/
+ if (Placed) {
+ Tdbp->SetLine(To_Buf + CurNum * Lrecl);
+ Placed = false;
+ } else if (++CurNum < Rbuf) {
+ Tdbp->IncLine(Lrecl); // Used by DOSCOL functions
+ return RC_OK;
+ } else if (Rbuf < Nrec && CurBlk != -1) {
+ return RC_EF;
+ } else {
/*******************************************************************/
- /* Sequential reading when Placed is not true. */
+ /* New block. */
/*******************************************************************/
- if (Placed) {
- Tdbp->SetLine(To_Buf + CurNum * Lrecl);
- Placed = false;
- } else if (++CurNum < Rbuf) {
- Tdbp->IncLine(Lrecl); // Used by DOSCOL functions
- return RC_OK;
- } else if (Rbuf < Nrec && CurBlk != -1) {
- return RC_EF;
- } else {
- /*****************************************************************/
- /* New block. */
- /*****************************************************************/
- CurNum = 0;
- Tdbp->SetLine(To_Buf);
-
- if (++CurBlk >= Block)
- return RC_EF;
-
- } // endif's
-
- if (OldBlk == CurBlk) {
- IsRead = true; // Was read indeed
- return RC_OK; // Block is already there
- } // endif OldBlk
+ CurNum = 0;
+ Tdbp->SetLine(To_Buf);
- } // endif !Closing
+ next:
+ if (++CurBlk >= Block)
+ return RC_EF;
- if (Modif) {
/*******************************************************************/
- /* The old block was modified in Update mode. */
- /* In Update mode we simply rewrite the old block on itself. */
+ /* Before reading a new block, check whether block indexing */
+ /* can be done, as well as for join as for local filtering. */
/*******************************************************************/
- bool moved = false;
+ switch (Tdbp->TestBlock(g)) {
+ case RC_EF:
+ return RC_EF;
+ case RC_NF:
+ goto next;
+ } // endswitch rc
+ } // endif's
- if (UseTemp) // Copy any intermediate lines.
- if (MoveIntermediateLines(g, &moved))
- rc = RC_FX;
+ if (OldBlk == CurBlk) {
+ IsRead = true; // Was read indeed
+ return RC_OK; // Block is already there
+ } // endif OldBlk
- if (rc == RC_OK) {
- // Fpos is last position, Headlen is DBF file header length
- if (!moved && fseek(Stream, Headlen + Fpos * Lrecl, SEEK_SET)) {
- sprintf(g->Message, MSG(FSETPOS_ERROR), 0);
- rc = RC_FX;
- } else if (fwrite(To_Buf, Lrecl, Rbuf, T_Stream) != (size_t)Rbuf) {
- sprintf(g->Message, MSG(FWRITE_ERROR), strerror(errno));
- rc = RC_FX;
- } // endif fwrite
-
- Spos = Fpos + Nrec; // + Rbuf ???
- } // endif rc
-
- if (Closing || rc != RC_OK) { // Error or called from CloseDB
- Closing = true; // To tell CloseDB about error
- return rc;
- } // endif Closing
-
- // NOTE: Next line was added to avoid a very strange fread bug.
- // When the fseek is not executed (even the file has the good
- // pointer position) the next read can happen anywhere in the file.
- OldBlk = CurBlk; // This will force fseek to be executed
- Modif = 0;
-// Spos = Fpos + Nrec; done above
- } // endif Mode
+ // Write modified block in mode UPDATE
+ if (Modif && (rc = WriteModifiedBlock(g)) != RC_OK)
+ return rc;
// This could be done only for new block. However note that FPOS
// is used as block position when updating and as line position
@@ -234,8 +276,6 @@ int FIXFAM::ReadBuffer(PGLOBAL g)
if (trace > 1)
htrc("File position is now %d\n", ftell(Stream));
-//long tell = ftell(Stream); not used
-
if (Padded)
n = fread(To_Buf, (size_t)Blksize, 1, Stream);
else
@@ -304,19 +344,23 @@ int FIXFAM::WriteBuffer(PGLOBAL g)
} else { // Mode == MODE_UPDATE
// T_Stream is the temporary stream or the table file stream itself
- if (!T_Stream)
- {
- if (UseTemp /*&& Tdbp->GetMode() == MODE_UPDATE*/) {
+ if (!T_Stream) {
+ if (UseTemp) {
if (OpenTempFile(g))
return RC_FX;
-
- if (CopyHeader(g)) // For DBF tables
+ else if (CopyHeader(g)) // For DBF tables
return RC_FX;
} else
T_Stream = Stream;
- }
- Modif++; // Modified line in Update mode
+
+ } // endif T_Stream
+
+ if (Nrec > 1)
+ Modif++; // Modified line in blocked mode
+ else if (WriteModifiedBlock(g)) // Indexed update
+ return RC_FX;
+
} // endif Mode
return RC_OK;
@@ -516,36 +560,37 @@ bool FIXFAM::MoveIntermediateLines(PGLOBAL g, bool *b)
/***********************************************************************/
/* Table file close routine for FIX access method. */
/***********************************************************************/
-void FIXFAM::CloseTableFile(PGLOBAL g)
+void FIXFAM::CloseTableFile(PGLOBAL g, bool abort)
{
int rc = RC_OK, wrc = RC_OK;
MODE mode = Tdbp->GetMode();
+ Abort = abort;
+
// Closing is True if last Write was in error
if (mode == MODE_INSERT && CurNum && !Closing) {
// Some more inserted lines remain to be written
Rbuf = CurNum--;
-// Closing = true;
wrc = WriteBuffer(g);
} else if (mode == MODE_UPDATE) {
if (Modif && !Closing) {
// Last updated block remains to be written
- Closing = true;
- wrc = ReadBuffer(g);
+ Closing = true; // ???
+ wrc = WriteModifiedBlock(g);
} // endif Modif
if (UseTemp && T_Stream && wrc == RC_OK) {
- // Copy any remaining lines
- bool b;
-
- Fpos = Tdbp->Cardinality(g);
-
- if ((rc = MoveIntermediateLines(g, &b)) == RC_OK) {
- // Delete the old file and rename the new temp file.
- RenameTempFile(g);
- goto fin;
- } // endif rc
-
+ if (!Abort) {
+ // Copy any remaining lines
+ bool b;
+
+ Fpos = Tdbp->Cardinality(g);
+ Abort = MoveIntermediateLines(g, &b) != RC_OK;
+ } // endif Abort
+
+ // Delete the old file and rename the new temp file.
+ RenameTempFile(g);
+ goto fin;
} // endif UseTemp
} // endif's mode
@@ -602,7 +647,9 @@ bool BGXFAM::BigSeek(PGLOBAL g, HANDLE h, BIGINT pos, int org)
} // endif
#else // !WIN32
if (lseek64(h, pos, org) < 0) {
- sprintf(g->Message, MSG(ERROR_IN_LSK), errno);
+// sprintf(g->Message, MSG(ERROR_IN_LSK), errno);
+ sprintf(g->Message, "lseek64: %s", strerror(errno));
+ printf("%s\n", g->Message);
return true;
} // endif
#endif // !WIN32
@@ -804,7 +851,7 @@ bool BGXFAM::OpenTableFile(PGLOBAL g)
#else // UNIX
int rc = 0;
int oflag = O_LARGEFILE; // Enable file size > 2G
- mode_t tmode = 0;
+ mode_t tmode = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH;
/*********************************************************************/
/* Create the file object according to access mode */
@@ -829,7 +876,7 @@ bool BGXFAM::OpenTableFile(PGLOBAL g)
break;
case MODE_INSERT:
oflag |= (O_WRONLY | O_CREAT | O_APPEND);
- tmode = S_IREAD | S_IWRITE;
+ // tmode = S_IREAD | S_IWRITE;
break;
default:
sprintf(g->Message, MSG(BAD_OPEN_MODE), mode);
@@ -988,73 +1035,92 @@ int BGXFAM::Cardinality(PGLOBAL g)
} // end of Cardinality
/***********************************************************************/
+/* WriteModifiedBlock: Used when updating. */
+/***********************************************************************/
+int BGXFAM::WriteModifiedBlock(PGLOBAL g)
+ {
+ /*********************************************************************/
+ /* The old block was modified in Update mode. */
+ /* In Update mode we simply rewrite the old block on itself. */
+ /*********************************************************************/
+ int rc = RC_OK;
+ bool moved = false;
+
+ if (UseTemp) // Copy any intermediate lines.
+ if (MoveIntermediateLines(g, &moved))
+ rc = RC_FX;
+
+ if (rc == RC_OK) {
+ // Set file position to OldBlk position (Fpos)
+ if (!moved && BigSeek(g, Hfile, (BIGINT)Fpos * (BIGINT)Lrecl))
+ rc = RC_FX;
+ else if (BigWrite(g, Tfile, To_Buf, Lrecl * Rbuf))
+ rc = RC_FX;
+
+ Spos = Fpos + Nrec; // + Rbuf ???
+ } // endif rc
+
+ if (Closing || rc != RC_OK) // Error or called from CloseDB
+ return rc;
+
+ // NOTE: Next line was added to avoid a very strange fread bug.
+ // When the fseek is not executed (even the file has the good
+ // pointer position) the next read can happen anywhere in the file.
+ OldBlk = CurBlk; // This will force fseek to be executed
+ Modif = 0;
+ return rc;
+ } // end of WriteModifiedBlock
+
+/***********************************************************************/
/* ReadBuffer: Read Nrec lines for a big fixed/binary file. */
/***********************************************************************/
int BGXFAM::ReadBuffer(PGLOBAL g)
{
int nbr, rc = RC_OK;
- if (!Closing) {
+ /*********************************************************************/
+ /* Sequential reading when Placed is not true. */
+ /*********************************************************************/
+ if (Placed) {
+ Tdbp->SetLine(To_Buf + CurNum * Lrecl);
+ Placed = false;
+ } else if (++CurNum < Rbuf) {
+ Tdbp->IncLine(Lrecl); // Used by DOSCOL functions
+ return RC_OK;
+ } else if (Rbuf < Nrec && CurBlk != -1) {
+ return RC_EF;
+ } else {
/*******************************************************************/
- /* Sequential reading when Placed is not true. */
+ /* New block. */
/*******************************************************************/
- if (Placed) {
- Tdbp->SetLine(To_Buf + CurNum * Lrecl);
- Placed = false;
- } else if (++CurNum < Rbuf) {
- Tdbp->IncLine(Lrecl); // Used by DOSCOL functions
- return RC_OK;
- } else if (Rbuf < Nrec && CurBlk != -1) {
+ CurNum = 0;
+ Tdbp->SetLine(To_Buf);
+
+ next:
+ if (++CurBlk >= Block)
return RC_EF;
- } else {
- /*****************************************************************/
- /* New block. */
- /*****************************************************************/
- CurNum = 0;
- Tdbp->SetLine(To_Buf);
- if (++CurBlk >= Block)
+ /*******************************************************************/
+ /* Before reading a new block, check whether block optimization */
+ /* can be done, as well as for join as for local filtering. */
+ /*******************************************************************/
+ switch (Tdbp->TestBlock(g)) {
+ case RC_EF:
return RC_EF;
+ case RC_NF:
+ goto next;
+ } // endswitch rc
- } // endif's
+ } // endif's
- if (OldBlk == CurBlk) {
- IsRead = true; // Was read indeed
- return RC_OK; // Block is already there
- } // endif OldBlk
+ if (OldBlk == CurBlk) {
+ IsRead = true; // Was read indeed
+ return RC_OK; // Block is already there
+ } // endif OldBlk
- } // endif !Closing
-
- if (Modif) {
- /*******************************************************************/
- /* The old block was modified in Update mode. */
- /* In Update mode we simply rewrite the old block on itself. */
- /*******************************************************************/
- bool moved = false;
-
- if (UseTemp) // Copy any intermediate lines.
- if (MoveIntermediateLines(g, &moved))
- rc = RC_FX;
-
- if (rc == RC_OK) {
- // Set file position to OldBlk position (Fpos)
- if (!moved && BigSeek(g, Hfile, (BIGINT)Fpos * (BIGINT)Lrecl))
- rc = RC_FX;
- else if (BigWrite(g, Tfile, To_Buf, Lrecl * Rbuf))
- rc = RC_FX;
-
- Spos = Fpos + Nrec; // + Rbuf ???
- } // endif rc
-
- if (Closing || rc != RC_OK) // Error or called from CloseDB
- return rc;
-
- // NOTE: Next line was added to avoid a very strange fread bug.
- // When the fseek is not executed (even the file has the good
- // pointer position) the next read can happen anywhere in the file.
- OldBlk = CurBlk; // This will force fseek to be executed
- Modif = 0;
- } // endif Mode
+ // Write modified block in mode UPDATE
+ if (Modif && (rc = WriteModifiedBlock(g)) != RC_OK)
+ return rc;
Fpos = CurBlk * Nrec;
@@ -1116,16 +1182,21 @@ int BGXFAM::WriteBuffer(PGLOBAL g)
} else { // Mode == MODE_UPDATE
// Tfile is the temporary file or the table file handle itself
- if (Tfile == INVALID_HANDLE_VALUE)
- {
+ if (Tfile == INVALID_HANDLE_VALUE) {
if (UseTemp /*&& Tdbp->GetMode() == MODE_UPDATE*/) {
if (OpenTempFile(g))
return RC_FX;
} else
Tfile = Hfile;
- }
- Modif++; // Modified line in Update mode
+
+ } // endif Tfile
+
+ if (Nrec > 1)
+ Modif++; // Modified line in blocked mode
+ else if (WriteModifiedBlock(g)) // Indexed update
+ return RC_FX;
+
} // endif Mode
return RC_OK;
@@ -1210,14 +1281,10 @@ int BGXFAM::DeleteRecords(PGLOBAL g, int irc)
if (trace > 1)
htrc("after: Tpos=%d Spos=%d\n", Tpos, Spos);
- } else {
+ } else if (irc != RC_OK) {
/*******************************************************************/
/* Last call after EOF has been reached. */
/*******************************************************************/
- char filename[_MAX_PATH];
-
- PlugSetPath(filename, To_File, Tdbp->GetPath());
-
if (UseTemp) {
/*****************************************************************/
/* Ok, now delete old file and rename new temp file. */
@@ -1352,11 +1419,13 @@ bool BGXFAM::MoveIntermediateLines(PGLOBAL g, bool *b)
/***********************************************************************/
/* Data Base close routine for BIGFIX access method. */
/***********************************************************************/
-void BGXFAM::CloseTableFile(PGLOBAL g)
+void BGXFAM::CloseTableFile(PGLOBAL g, bool abort)
{
int rc = RC_OK, wrc = RC_OK;
MODE mode = Tdbp->GetMode();
+ Abort = abort;
+
// Closing is True if last Write was in error
if (mode == MODE_INSERT && CurNum && !Closing) {
// Some more inserted lines remain to be written
@@ -1366,21 +1435,21 @@ void BGXFAM::CloseTableFile(PGLOBAL g)
if (Modif && !Closing) {
// Last updated block remains to be written
Closing = true;
- wrc = ReadBuffer(g);
+ wrc = WriteModifiedBlock(g);
} // endif Modif
if (UseTemp && Tfile && wrc == RC_OK) {
- // Copy any remaining lines
- bool b;
-
- Fpos = Tdbp->Cardinality(g);
-
- if ((rc = MoveIntermediateLines(g, &b)) == RC_OK) {
- // Delete the old file and rename the new temp file.
- RenameTempFile(g);
- goto fin;
- } // endif rc
-
+ if (!Abort) {
+ // Copy any remaining lines
+ bool b;
+
+ Fpos = Tdbp->Cardinality(g);
+ Abort = MoveIntermediateLines(g, &b) != RC_OK;
+ } // endif Abort
+
+ // Delete the old file and rename the new temp file.
+ RenameTempFile(g);
+ goto fin;
} // endif UseTemp
} // endif's mode