1 /*********** File AM Map C++ Program Source Code File (.CPP) ***********/
2 /* PROGRAM NAME: FILAMAP */
3 /* ------------- */
4 /* Version 1.6 */
5 /* */
6 /* COPYRIGHT: */
7 /* ---------- */
8 /* (C) Copyright to the author Olivier BERTRAND 2005-2020 */
9 /* */
10 /* WHAT THIS PROGRAM DOES: */
11 /* ----------------------- */
12 /* This program are the MAP file access method classes. */
13 /* */
14 /***********************************************************************/
15
16 /***********************************************************************/
17 /* Include relevant sections of the System header files. */
18 /***********************************************************************/
19 #include "my_global.h"
20 #if defined(_WIN32)
21 #if defined(__BORLANDC__)
22 #define __MFC_COMPAT__ // To define min/max as macro
23 #endif // __BORLANDC__
24 //#include <windows.h>
25 #else // !_WIN32
26 #if defined(UNIX)
27 #include <errno.h>
28 #include <unistd.h>
29 #else // !UNIX
30 #include <io.h>
31 #endif // !UNIX
32 #include <fcntl.h>
33 #endif // !_WIN32
34
35 /***********************************************************************/
36 /* Include application header files: */
37 /* global.h is header containing all global declarations. */
38 /* plgdbsem.h is header containing the DB application declarations. */
39 /* filamtxt.h is header containing the file AM classes declarations. */
40 /* Note: these files are included inside the include files below. */
41 /***********************************************************************/
42 #include "global.h"
43 #include "plgdbsem.h"
44 #include "osutil.h"
45 #include "maputil.h"
46 #include "filamap.h"
47 #include "tabdos.h"
48 #include "tabfmt.h"
49
50 /* --------------------------- Class MAPFAM -------------------------- */
51
52 /***********************************************************************/
53 /* Constructors. */
54 /***********************************************************************/
MAPFAM(PDOSDEF tdp)55 MAPFAM::MAPFAM(PDOSDEF tdp) : TXTFAM(tdp)
56 {
57 Memory = NULL;
58 Mempos = NULL;
59 Tpos = NULL;
60 Fpos = NULL;
61 Spos = NULL;
62 Top = NULL;
63 } // end of MAPFAM standard constructor
64
MAPFAM(PMAPFAM tmfp)65 MAPFAM::MAPFAM(PMAPFAM tmfp) : TXTFAM(tmfp)
66 {
67 Memory = tmfp->Memory;
68 Mempos = tmfp->Mempos;
69 Fpos = tmfp->Fpos;
70 Spos = tmfp->Spos;
71 Tpos = tmfp->Tpos;
72 Top = tmfp->Top;
73 } // end of MAPFAM copy constructor
74
75 /***********************************************************************/
76 /* Reset: reset position values at the beginning of file. */
77 /***********************************************************************/
Reset(void)78 void MAPFAM::Reset(void)
79 {
80 TXTFAM::Reset();
81 Fpos = Tpos = Spos = NULL;
82 } // end of Reset
83
84 /***********************************************************************/
85 /* MAP GetFileLength: returns file size in number of bytes. */
86 /***********************************************************************/
GetFileLength(PGLOBAL g)87 int MAPFAM::GetFileLength(PGLOBAL g)
88 {
89 int len;
90
91 len = (To_Fb && To_Fb->Count) ? To_Fb->Length : TXTFAM::GetFileLength(g);
92
93 if (trace(1))
94 htrc("Mapped file length=%d\n", len);
95
96 return len;
97 } // end of GetFileLength
98
99 /***********************************************************************/
100 /* OpenTableFile: Open a DOS/UNIX table file as a mapped file. */
101 /***********************************************************************/
OpenTableFile(PGLOBAL g)102 bool MAPFAM::OpenTableFile(PGLOBAL g)
103 {
104 char filename[_MAX_PATH];
105 size_t len;
106 MODE mode = Tdbp->GetMode();
107 PFBLOCK fp;
108 PDBUSER dbuserp = (PDBUSER)g->Activityp->Aptr;
109
110 #if defined(_DEBUG)
111 // Insert mode is no more handled using file mapping
112 assert(mode != MODE_INSERT);
113 #endif // _DEBUG
114
115 /*********************************************************************/
116 /* We used the file name relative to recorded datapath. */
117 /*********************************************************************/
118 PlugSetPath(filename, To_File, Tdbp->GetPath());
119
120 /*********************************************************************/
121 /* Under Win32 the whole file will be mapped so we can use it as */
122 /* if it were entirely read into virtual memory. */
123 /* Firstly we check whether this file have been already mapped. */
124 /*********************************************************************/
125 if (mode == MODE_READ) {
126 for (fp = dbuserp->Openlist; fp; fp = fp->Next)
127 if (fp->Type == TYPE_FB_MAP && !stricmp(fp->Fname, filename)
128 && fp->Count && fp->Mode == mode)
129 break;
130
131 if (trace(1))
132 htrc("Mapping file, fp=%p\n", fp);
133
134 } else
135 fp = NULL;
136
137 if (fp) {
138 /*******************************************************************/
139 /* File already mapped. Just increment use count and get pointer. */
140 /*******************************************************************/
141 fp->Count++;
142 Memory = fp->Memory;
143 len = fp->Length;
144 } else {
145 /*******************************************************************/
146 /* If required, delete the whole file if no filtering is implied. */
147 /*******************************************************************/
148 bool del;
149 HANDLE hFile;
150 MEMMAP mm;
151
152 del = mode == MODE_DELETE && !Tdbp->GetNext();
153
154 if (del)
155 DelRows = Cardinality(g);
156
157 /*******************************************************************/
158 /* Create the mapping file object. */
159 /*******************************************************************/
160 hFile = CreateFileMap(g, filename, &mm, mode, del);
161
162 if (hFile == INVALID_HANDLE_VALUE) {
163 DWORD rc = GetLastError();
164
165 if (!(*g->Message))
166 sprintf(g->Message, MSG(OPEN_MODE_ERROR),
167 "map", (int) rc, filename);
168
169 if (trace(1))
170 htrc("CreateFileMap: %s\n", g->Message);
171
172 return (mode == MODE_READ && rc == ENOENT)
173 ? false : true;
174 // ? PushWarning(g, Tdbp) : true; --> assert fails into MariaDB
175 } // endif hFile
176
177 /*******************************************************************/
178 /* Get the file size. */
179 /*******************************************************************/
180 len = (size_t)mm.lenL;
181
182 if (mm.lenH)
183 len += ((size_t)mm.lenH * 0x000000001LL);
184
185 Memory = (char *)mm.memory;
186
187 if (!len) { // Empty or deleted file
188 CloseFileHandle(hFile);
189 Tdbp->ResetSize();
190 return false;
191 } // endif len
192
193 if (!Memory) {
194 CloseFileHandle(hFile);
195 sprintf(g->Message, MSG(MAP_VIEW_ERROR),
196 filename, GetLastError());
197 return true;
198 } // endif Memory
199
200 #if defined(_WIN32)
201 if (mode != MODE_DELETE) {
202 #else // !_WIN32
203 if (mode == MODE_READ) {
204 #endif // !_WIN32
205 CloseFileHandle(hFile); // Not used anymore
206 hFile = INVALID_HANDLE_VALUE; // For Fblock
207 } // endif Mode
208
209 /*******************************************************************/
210 /* Link a Fblock. This make possible to reuse already opened maps */
211 /* and also to automatically unmap them in case of error g->jump. */
212 /* Note: block can already exist for previously closed file. */
213 /*******************************************************************/
214 fp = (PFBLOCK)PlugSubAlloc(g, NULL, sizeof(FBLOCK));
215 fp->Type = TYPE_FB_MAP;
216 fp->Fname = PlugDup(g, filename);
217 fp->Next = dbuserp->Openlist;
218 dbuserp->Openlist = fp;
219 fp->Count = 1;
220 fp->Length = len;
221 fp->Memory = Memory;
222 fp->Mode = mode;
223 fp->File = NULL;
224 fp->Handle = hFile; // Used for Delete
225 } // endif fp
226
227 To_Fb = fp; // Useful when closing
228
229 /*********************************************************************/
230 /* The pseudo "buffer" is here the entire file mapping view. */
231 /*********************************************************************/
232 Fpos = Mempos = Memory;
233 Top = Memory + len;
234
235 if (trace(1))
236 htrc("fp=%p count=%d MapView=%p len=%d Top=%p\n",
237 fp, fp->Count, Memory, len, Top);
238
239 return AllocateBuffer(g); // Useful for DBF files
240 } // end of OpenTableFile
241
242 /***********************************************************************/
243 /* GetRowID: return the RowID of last read record. */
244 /***********************************************************************/
245 int MAPFAM::GetRowID(void)
246 {
247 return Rows;
248 } // end of GetRowID
249
250 /***********************************************************************/
251 /* GetPos: return the position of last read record. */
252 /***********************************************************************/
253 int MAPFAM::GetPos(void)
254 {
255 return (int)(Fpos - Memory);
256 } // end of GetPos
257
258 /***********************************************************************/
259 /* GetNextPos: return the position of next record. */
260 /***********************************************************************/
261 int MAPFAM::GetNextPos(void)
262 {
263 return (int)(Mempos - Memory);
264 } // end of GetNextPos
265
266 /***********************************************************************/
267 /* SetPos: Replace the table at the specified position. */
268 /***********************************************************************/
269 bool MAPFAM::SetPos(PGLOBAL g, int pos)
270 {
271 Fpos = Mempos = Memory + pos;
272
273 if (Mempos >= Top || Mempos < Memory) {
274 strcpy(g->Message, MSG(INV_MAP_POS));
275 return true;
276 } // endif Mempos
277
278 Placed = true;
279 return false;
280 } // end of SetPos
281
282 /***********************************************************************/
283 /* Record file position in case of UPDATE or DELETE. */
284 /***********************************************************************/
285 bool MAPFAM::RecordPos(PGLOBAL)
286 {
287 Fpos = Mempos;
288 return false;
289 } // end of RecordPos
290
291 /***********************************************************************/
292 /* Initialize Fpos and Mempos for indexed DELETE. */
293 /***********************************************************************/
294 int MAPFAM::InitDelete(PGLOBAL, int fpos, int spos)
295 {
296 Fpos = Memory + (ptrdiff_t)fpos;
297 Mempos = Memory + (ptrdiff_t)spos;
298 return RC_OK;
299 } // end of InitDelete
300
301 /***********************************************************************/
302 /* Skip one record in file. */
303 /***********************************************************************/
304 int MAPFAM::SkipRecord(PGLOBAL g, bool header)
305 {
306 PDBUSER dup = (PDBUSER)g->Activityp->Aptr;
307
308 // Skip this record
309 while (*Mempos++ != '\n') // What about Unix ???
310 if (Mempos == Top)
311 return RC_EF;
312
313 // Update progress information
314 dup->ProgCur = GetPos();
315
316 if (header)
317 Fpos = Tpos = Spos = Mempos; // For Delete
318
319 return RC_OK;
320 } // end of SkipRecord
321
322 /***********************************************************************/
323 /* ReadBuffer: Read one line for a mapped text file. */
324 /***********************************************************************/
325 int MAPFAM::ReadBuffer(PGLOBAL g)
326 {
327 int rc, len, n = 1;
328
329 // Are we at the end of the memory
330 if (Mempos >= Top) {
331 if ((rc = GetNext(g)) != RC_OK)
332 return rc;
333 else if (Tdbp->GetAmType() == TYPE_AM_CSV && ((PTDBCSV)Tdbp)->Header)
334 if ((rc = SkipRecord(g, true)) != RC_OK)
335 return rc;
336
337 } // endif Mempos
338
339
340 if (!Placed) {
341 /*******************************************************************/
342 /* Record file position in case of UPDATE or DELETE. */
343 /*******************************************************************/
344 next:
345 Fpos = Mempos;
346 CurBlk = (int)Rows++;
347
348 /*******************************************************************/
349 /* Check whether optimization on ROWID */
350 /* can be done, as well as for join as for local filtering. */
351 /*******************************************************************/
352 switch (Tdbp->TestBlock(g)) {
353 case RC_EF:
354 if ((rc = GetNext(g)) != RC_OK)
355 return rc;
356
357 /* falls through */
358 case RC_NF:
359 // Skip this record
360 if ((rc = SkipRecord(g, false)) != RC_OK)
361 return rc;
362
363 goto next;
364 } // endswitch rc
365
366 } else
367 Placed = false;
368
369 // Immediately calculate next position (Used by DeleteDB)
370 while (*Mempos++ != '\n') // What about Unix ???
371 if (Mempos == Top) {
372 n = 0;
373 break;
374 } // endif Mempos
375
376 // Set caller line buffer
377 len = (int)(Mempos - Fpos) - n;
378
379 // Don't rely on ENDING setting
380 if (len > 0 && *(Mempos - 2) == '\r')
381 len--; // Line ends by CRLF
382
383 memcpy(Tdbp->GetLine(), Fpos, len);
384 Tdbp->GetLine()[len] = '\0';
385 return RC_OK;
386 } // end of ReadBuffer
387
388 /***********************************************************************/
389 /* WriteBuffer: File write routine for MAP access method. */
390 /***********************************************************************/
391 int MAPFAM::WriteBuffer(PGLOBAL g __attribute__((unused)))
392 {
393 #if defined(_DEBUG)
394 // Insert mode is no more handled using file mapping
395 if (Tdbp->GetMode() == MODE_INSERT) {
396 strcpy(g->Message, MSG(NO_MAP_INSERT));
397 return RC_FX;
398 } // endif
399 #endif // _DEBUG
400
401 /*********************************************************************/
402 /* Copy the updated record back into the memory mapped file. */
403 /*********************************************************************/
404 memcpy(Fpos, Tdbp->GetLine(), strlen(Tdbp->GetLine()));
405 return RC_OK;
406 } // end of WriteBuffer
407
408 /***********************************************************************/
409 /* Data Base delete line routine for MAP (and FIX?) access methods. */
410 /* Lines between deleted lines are moved in the mapfile view. */
411 /***********************************************************************/
412 int MAPFAM::DeleteRecords(PGLOBAL g, int irc)
413 {
414 int n;
415
416 if (trace(1))
417 htrc("MAP DeleteDB: irc=%d mempos=%p tobuf=%p Tpos=%p Spos=%p\n",
418 irc, Mempos, To_Buf, Tpos, Spos);
419
420 if (irc != RC_OK) {
421 /*******************************************************************/
422 /* EOF: position Fpos at the top of map position. */
423 /*******************************************************************/
424 Fpos = Top;
425
426 if (trace(1))
427 htrc("Fpos placed at file top=%p\n", Fpos);
428
429 } // endif irc
430
431 if (Tpos == Spos) {
432 /*******************************************************************/
433 /* First line to delete. Move of eventual preceding lines is */
434 /* not required here, just setting of future Spos and Tpos. */
435 /*******************************************************************/
436 Tpos = Spos = Fpos;
437 } else if ((n = (int)(Fpos - Spos)) > 0) {
438 /*******************************************************************/
439 /* Non consecutive line to delete. Move intermediate lines. */
440 /*******************************************************************/
441 memmove(Tpos, Spos, n);
442 Tpos += n;
443
444 if (trace(1))
445 htrc("move %d bytes\n", n);
446
447 } // endif n
448
449 if (irc == RC_OK) {
450 Spos = Mempos; // New start position
451
452 if (trace(1))
453 htrc("after: Tpos=%p Spos=%p\n", Tpos, Spos);
454
455 } else if (To_Fb) { // Can be NULL for deleted files
456 /*******************************************************************/
457 /* Last call after EOF has been reached. */
458 /* We must firstly Unmap the view and use the saved file handle */
459 /* to put an EOF at the end of the copied part of the file. */
460 /*******************************************************************/
461 PFBLOCK fp = To_Fb;
462
463 CloseMemMap(fp->Memory, (size_t)fp->Length);
464 fp->Count = 0; // Avoid doing it twice
465
466 if (!Abort) {
467 /*****************************************************************/
468 /* Remove extra records. */
469 /*****************************************************************/
470 n = (int)(Tpos - Memory);
471
472 #if defined(_WIN32)
473 DWORD drc = SetFilePointer(fp->Handle, n, NULL, FILE_BEGIN);
474
475 if (drc == 0xFFFFFFFF) {
476 sprintf(g->Message, MSG(FUNCTION_ERROR),
477 "SetFilePointer", GetLastError());
478 CloseHandle(fp->Handle);
479 return RC_FX;
480 } // endif
481
482 if (trace(1))
483 htrc("done, Tpos=%p newsize=%d drc=%d\n", Tpos, n, drc);
484
485 if (!SetEndOfFile(fp->Handle)) {
486 sprintf(g->Message, MSG(FUNCTION_ERROR),
487 "SetEndOfFile", GetLastError());
488 CloseHandle(fp->Handle);
489 return RC_FX;
490 } // endif
491
492 #else // UNIX
493 if (ftruncate(fp->Handle, (off_t)n)) {
494 sprintf(g->Message, MSG(TRUNCATE_ERROR), strerror(errno));
495 close(fp->Handle);
496 return RC_FX;
497 } // endif
498
499 #endif // UNIX
500 } // endif Abort
501
502 #if defined(_WIN32)
503 CloseHandle(fp->Handle);
504 #else // UNIX
505 close(fp->Handle);
506 #endif // UNIX
507 } // endif irc
508
509 return RC_OK; // All is correct
510 } // end of DeleteRecords
511
512 /***********************************************************************/
513 /* Table file close routine for MAP access method. */
514 /***********************************************************************/
515 void MAPFAM::CloseTableFile(PGLOBAL g, bool)
516 {
517 PlugCloseFile(g, To_Fb);
518 //To_Fb = NULL; // To get correct file size in Cardinality
519
520 if (trace(1))
521 htrc("MAP Close: closing %s count=%d\n",
522 To_File, (To_Fb) ? To_Fb->Count : 0);
523
524 } // end of CloseTableFile
525
526 /***********************************************************************/
527 /* Rewind routine for MAP access method. */
528 /***********************************************************************/
529 void MAPFAM::Rewind(void)
530 {
531 Mempos = Memory;
532 } // end of Rewind
533
534 /* --------------------------- Class MBKFAM -------------------------- */
535
536 /***********************************************************************/
537 /* Constructors. */
538 /***********************************************************************/
539 MBKFAM::MBKFAM(PDOSDEF tdp) : MAPFAM(tdp)
540 {
541 Blocked = true;
542 Block = tdp->GetBlock();
543 Last = tdp->GetLast();
544 Nrec = tdp->GetElemt();
545 BlkPos = tdp->GetTo_Pos();
546 CurNum = Nrec;
547 } // end of MBKFAM standard constructor
548
549 /***********************************************************************/
550 /* Reset: reset position values at the beginning of file. */
551 /***********************************************************************/
552 void MBKFAM::Reset(void)
553 {
554 MAPFAM::Reset();
555 CurNum = Nrec; // To start by a new block
556 } // end of Reset
557
558 /***********************************************************************/
559 /* Cardinality: returns table cardinality in number of rows. */
560 /* This function can be called with a null argument to test the */
561 /* availability of Cardinality implementation (1 yes, 0 no). */
562 /***********************************************************************/
563 int MBKFAM::Cardinality(PGLOBAL g)
564 {
565 return (g) ? (int)((Block - 1) * Nrec + Last) : 1;
566 } // end of Cardinality
567
568 /***********************************************************************/
569 /* Skip one record in file. */
570 /***********************************************************************/
571 int MBKFAM::SkipRecord(PGLOBAL, bool)
572 {
573 return RC_OK;
574 } // end of SkipRecord
575
576 /***********************************************************************/
577 /* GetRowID: return the RowID of last read record. */
578 /***********************************************************************/
579 int MBKFAM::GetRowID(void)
580 {
581 return CurNum + Nrec * CurBlk + 1;
582 } // end of GetRowID
583
584 /***********************************************************************/
585 /* ReadBuffer: Read one line for a mapped Fix file. */
586 /***********************************************************************/
587 int MBKFAM::ReadBuffer(PGLOBAL g)
588 {
589 int rc, len;
590
591 /*********************************************************************/
592 /* Sequential block reading when Placed is not true. */
593 /*********************************************************************/
594 if (Placed) {
595 Placed = false;
596 } else if (Mempos >= Top) { // Are we at the end of the memory
597 if ((rc = GetNext(g)) != RC_OK)
598 return rc;
599
600 } else if (++CurNum < Nrec) {
601 Fpos = Mempos;
602 } else {
603 /*******************************************************************/
604 /* New block. */
605 /*******************************************************************/
606 CurNum = 0;
607
608 next:
609 if (++CurBlk >= Block)
610 if ((rc = GetNext(g)) != RC_OK)
611 return rc;
612
613 /*******************************************************************/
614 /* Before reading a new block, check whether block optimization */
615 /* can be done, as well as for join as for local filtering. */
616 /*******************************************************************/
617 switch (Tdbp->TestBlock(g)) {
618 case RC_EF:
619 if ((rc = GetNext(g)) != RC_OK)
620 return rc;
621
622 break;
623 case RC_NF:
624 goto next;
625 } // endswitch rc
626
627 Fpos = Mempos = Memory + BlkPos[CurBlk];
628 } // endif's
629
630 // Immediately calculate next position (Used by DeleteDB)
631 while (*Mempos++ != '\n') // What about Unix ???
632 if (Mempos == Top)
633 break;
634
635 // Set caller line buffer
636 len = (int)(Mempos - Fpos) - Ending;
637 memcpy(Tdbp->GetLine(), Fpos, len);
638 Tdbp->GetLine()[len] = '\0';
639 return RC_OK;
640 } // end of ReadBuffer
641
642 /***********************************************************************/
643 /* Rewind routine for FIX MAP access method. */
644 /***********************************************************************/
645 void MBKFAM::Rewind(void)
646 {
647 Mempos = Memory + Headlen;
648 CurBlk = -1;
649 CurNum = Nrec;
650 } // end of Rewind
651
652 /* --------------------------- Class MPXFAM -------------------------- */
653
654 /***********************************************************************/
655 /* Constructors. */
656 /***********************************************************************/
657 MPXFAM::MPXFAM(PDOSDEF tdp) : MBKFAM(tdp)
658 {
659 Blksize = tdp->GetBlksize();
660 Padded = tdp->GetPadded();
661
662 if (Padded && Blksize)
663 Nrec = Blksize / Lrecl;
664 else {
665 Nrec = (tdp->GetElemt()) ? tdp->GetElemt() : DOS_BUFF_LEN;
666 Blksize = Nrec * Lrecl;
667 Padded = false;
668 } // endelse
669
670 CurNum = Nrec;
671 } // end of MPXFAM standard constructor
672
673 #if 0 // MBKFAM routine is correct
674 /***********************************************************************/
675 /* GetRowID: return the RowID of last read record. */
676 /***********************************************************************/
677 int MPXFAM::GetRowID(void)
678 {
679 return (Mempos - Memory - Headlen) / Lrecl;
680 } // end of GetRowID
681 #endif
682
683 /***********************************************************************/
684 /* GetPos: return the position of last read record. */
685 /***********************************************************************/
686 int MPXFAM::GetPos(void)
687 {
688 return (CurNum + Nrec * CurBlk); // Computed file index
689 } // end of GetPos
690
691 /***********************************************************************/
692 /* SetPos: Replace the table at the specified position. */
693 /***********************************************************************/
694 bool MPXFAM::SetPos(PGLOBAL g, int pos)
695 {
696 if (pos < 0) {
697 strcpy(g->Message, MSG(INV_REC_POS));
698 return true;
699 } // endif recpos
700
701 CurBlk = pos / Nrec;
702 CurNum = pos % Nrec;
703 Fpos = Mempos = Memory + Headlen + pos * Lrecl;
704
705 // Indicate the table position was externally set
706 Placed = true;
707 return false;
708 } // end of SetPos
709
710 /***********************************************************************/
711 /* Initialize CurBlk, CurNum, Mempos and Fpos for indexed DELETE. */
712 /***********************************************************************/
713 int MPXFAM::InitDelete(PGLOBAL, int fpos, int)
714 {
715 Fpos = Memory + Headlen + (ptrdiff_t)fpos * Lrecl;
716 Mempos = Fpos + Lrecl;
717 return RC_OK;
718 } // end of InitDelete
719
720 /***********************************************************************/
721 /* ReadBuffer: Read one line for a mapped Fix file. */
722 /***********************************************************************/
723 int MPXFAM::ReadBuffer(PGLOBAL g)
724 {
725 int rc;
726
727 /*********************************************************************/
728 /* Sequential block reading when Placed is not true. */
729 /*********************************************************************/
730 if (Placed) {
731 Placed = false;
732 } else if (Mempos >= Top) { // Are we at the end of the memory
733 if ((rc = GetNext(g)) != RC_OK)
734 return rc;
735
736 } else if (++CurNum < Nrec) {
737 Fpos = Mempos;
738 } else {
739 /*******************************************************************/
740 /* New block. */
741 /*******************************************************************/
742 CurNum = 0;
743
744 next:
745 if (++CurBlk >= Block)
746 return GetNext(g);
747
748 /*******************************************************************/
749 /* Before reading a new block, check whether block optimization */
750 /* can be done, as well as for join as for local filtering. */
751 /*******************************************************************/
752 switch (Tdbp->TestBlock(g)) {
753 case RC_EF:
754 if ((rc = GetNext(g)) != RC_OK)
755 return rc;
756
757 break;
758 case RC_NF:
759 goto next;
760 } // endswitch rc
761
762 Fpos = Mempos = Headlen + Memory + CurBlk * Blksize;
763 } // endif's
764
765 Tdbp->SetLine(Mempos);
766
767 // Immediately calculate next position (Used by DeleteDB)
768 Mempos += Lrecl;
769 return RC_OK;
770 } // end of ReadBuffer
771
772 /***********************************************************************/
773 /* WriteBuffer: File write routine for MAP access method. */
774 /***********************************************************************/
775 int MPXFAM::WriteBuffer(PGLOBAL g __attribute__((unused)))
776 {
777 #if defined(_DEBUG)
778 // Insert mode is no more handled using file mapping
779 if (Tdbp->GetMode() == MODE_INSERT) {
780 strcpy(g->Message, MSG(NO_MAP_INSERT));
781 return RC_FX;
782 } // endif
783 #endif // _DEBUG
784
785 // In Update mode, file was modified in memory
786 return RC_OK;
787 } // end of WriteBuffer
788
789