1

I might be the last guy on the planet relying on B-Tree Filer but I made the jump from Delphi 2007 to XE2.

After getting over all the AnsiChar and PAnsiChar issues, the code now crashes with a Range Check with zero items on a page.

Is anyone successfully running B-Tree Filer under Delphi XE2? If so, how'd ya do it? :)

Update Range check error here:

procedure IsamUnPack(var Page : IsamPage; KeyL : Word); 
var 
  I, K, S : Word; 
  P : Array [0..0] Of Byte absolute Page; {Real bounds [0..65535]} 
begin 
 K := KeyL + 9; 
 S := Pred (Page.ItemsOnPage) * K + 6; 
 if KeyL <> MaxKeyLen then begin 
    for I := Page.ItemsOnPage downto 2 do begin 
     Move(P[S], Page.ItemArray[I], K); // Range Check error in Warren P's suggestion 
     S := S - K;  
     end; 
 end; 
end; 

While Page.ItemsOnPage should never be zero (the Range Check error is valid here) it may have been caused by data alignment issues. This code, added to BTDEFINE.INC seems to be doing the trick...

{$IFDEF VER230}
{$DEFINE UsingDelphi}
{$ENDIF}

{$IFDEF VER230} {Delphi XE2}
{$A-} {align data on byte boundaries}
{$B-} {short circuit boolean evaluation}
{$H+} {long string support}
{$I-} {suppress I/O checking}
{$J+} {writeable typed constants}
{$P-} {do not allow open string parameters}
{$Q-} {overflow checking off}
{$R-} {range checking off}
{$T-} {no type checked pointers with @}
{$V-} {no var string checking}
{$X+} {extended syntax on}
{$DEFINE Delphi2006}
{$DEFINE Delphi1Plus}
{$DEFINE Delphi2Plus}
{$DEFINE Delphi3Plus}
{$DEFINE Delphi4Plus}
{$DEFINE Delphi5Plus}
{$DEFINE Delphi6Plus}
{$DEFINE Delphi7Plus}
{$DEFINE Delphi2005Plus}
{$DEFINE Delphi2006Plus}
{$ENDIF}
Bookup
  • 13
  • 5
  • I see from the B-Tree filer forums that you downloaded the very latest source code from the SourceForge website, and that the latest version on SourceForge is still not really ready to go on XE2. Perhaps you should post the code-snippet of where it crashes, with some context (call stack). – Warren P Jan 12 '12 at 16:12
  • related forum post: http://sourceforge.net/projects/tpbtreefiler/forums/forum/241867/topic/4942532 – Warren P Jan 12 '12 at 16:12
  • @Warren, you should note that particular post is from the OP here. Wading through the other messages there it doesn't look like anyone officially made the transition to Unicode. – Mike W Jan 12 '12 at 16:15
  • 1
    Welcome to Stackoverflow! Nice to see here people from the chess community. – menjaraz Jan 12 '12 at 16:16
  • The last SVN commit date on the sourceforge project is 2 years ago, so I doubt anybody is actively committing to this project any more. – Warren P Jan 12 '12 at 16:21
  • Even the demo code for this project does ancient weird DOS TurboPascal things like Assignable Typed Constants, and directly writing to String[0] to set the length of a string (valid in TurboPascal, and delphi 1.0 only) – Warren P Jan 12 '12 at 16:32
  • @Warren I seem to have made all the apparent changes for Unicode but the problem seems to lie in another area. In IsamPack() and IsamUnack() the Page.ItemsOnPage goes to zero (which never should happen in a B-Tree) and this generates a Range Check error as it should. – Bookup Jan 12 '12 at 17:12
  • You should probably investigate and debug it yourself, and when you get to a specific chunk of code that you want to ask about, post it here. – Warren P Jan 12 '12 at 18:01
  • 1
    @Warren - writing to string[0] to set the length is still legal even in XE2 as long as the string is a short string, i.e., string[10], which is what BTF uses. I'm not saying it's a good idea ... – Mike W Jan 12 '12 at 18:31
  • The compiler complained when I tried it today in XE2, because the BTree code does this with AnsiString types too. – Warren P Jan 12 '12 at 20:37

3 Answers3

1

I did a quick port, and I currently have it basically working, well enough for the included Delphi demo to work. My first try failed when I overlooked some string -> ansistring changes in the DEMO CODE, which caused the demo code function PadCH to malfunction. After I fixed that, the demo, and underlying library appears functional, at least for reading, but I did not test writing, modifying, and creating files yet. The above file in the demo was created in an earlier version, so at least it's binary-read compatible. I wouldn't be surprised if there were lots of bugs, data corruption issues, and so on, so please do not use this code in production, or if you do, you do so at your own risk.

enter image description here

My work is here: hosted at microsoft skydrive (4.3 megs, ZIP) (filename tpbtreefiler_xe2_v2.zip)

Update Function IsamUnpack is in ISAMWORK.INC.

Update2 It appears that the OP has discovered now that adding some ifdef-version-constant support causes the {$R-} and some alignment flags to be switched on which are also required, for the library to work properly. May I suggest the following different way of declaring in BTDEFINE.INC, that gets around a classic Delphi "break every time we change Delphi compiler versions" by using a comparison that won't break on the next delphi release:

{$IF CompilerVersion > 20.0 } 
{ Keep working from Delphi 2009 UP}
{$DEFINE UsingDelphi}
{$A-} {align data on byte boundaries}
{$B-} {short circuit boolean evaluation}
{$H+} {long string support}
{$I-} {suppress I/O checking}
{$J+} {writeable typed constants}
{$P-} {do not allow open string parameters}
{$Q-} {overflow checking off}
{$R-} {range checking off}
{$T-} {no type checked pointers with @}
{$V-} {no var string checking}
{$X+} {extended syntax on}
{$DEFINE Delphi2006}
{$DEFINE Delphi1Plus}
{$DEFINE Delphi2Plus}
{$DEFINE Delphi3Plus}
{$DEFINE Delphi4Plus}
{$DEFINE Delphi5Plus}
{$DEFINE Delphi6Plus}
{$DEFINE Delphi7Plus}
{$DEFINE Delphi2005Plus}
{$DEFINE Delphi2006Plus}
{$ENDIF}

Update 3 I suspect there are still porting issues in the code, that could cause data loss and data file corruption. Here's an example where the number of records (which should be a number in the range around 50 in my demo app) is being reported as a number > 1 million, which is clearly invalid.

enter image description here

Warren P
  • 65,725
  • 40
  • 181
  • 316
  • Sorry about the formatting. It seems it won't let me answer my own question and I cannot figure out how to get it to accept a formatted comment... – Bookup Jan 13 '12 at 20:34
  • procedure IsamUnPack(var Page : IsamPage; KeyL : Word); var I, K, S : Word; P : Array [0..0] Of Byte absolute Page; {Real bounds [0..65535]} begin K := KeyL + 9; S := Pred (Page.ItemsOnPage) * K + 6; if KeyL <> MaxKeyLen then begin for I := Page.ItemsOnPage downto 2 do begin Move(P[S], Page.ItemArray[I], K); <- Range Check error in Warren P's suggestion S := S - K; end; end; end; – Bookup Jan 13 '12 at 20:34
  • I posted and formatted your code sample into the question, which is where you should put such snippets of more than 1 line in length. – Warren P Jan 13 '12 at 21:40
  • Try putting `{$R-}` declaration into the unit that contains IsamUnpack. That Array[0..0] thing might be generating some bogus range check exceptions. – Warren P Jan 13 '12 at 21:42
  • I shudder when I think of suppressing range check exceptions. I'm rather anal like that. I even ship code with hundreds of assertions turned on because I want to know right away if anything is going wrong in deployed code. That said, I think you may be right. See my updated question. THANKS! – Bookup Jan 16 '12 at 22:09
  • You rock, by the way. Writing and sharing your ported code when you don't even use the library is above and beyond the call of duty. My hat is off to you. – Bookup Jan 16 '12 at 22:16
  • I see from your question, that you have found a block of code that would already have turned off range checking, so in fact, it is necessary along with the alignment. – Warren P Jan 17 '12 at 14:03
  • My code has quite a few checks for corruption but I have yet to do thorough enough testing to put the code into production. And thanks for the "Delphi 2009 and beyond" idea. I hope I don't need it as the plan for my next revision is to move to SQLite. :) – Bookup Jan 18 '12 at 15:05
  • In that case I suggest you accept this answer, it helps everybody in the future figure out what you did. – Warren P Jan 18 '12 at 17:26
  • Answer "accepted." Thanks for helping a StackOverflow newb as well. – Bookup Jan 19 '12 at 15:37
0

After I had it all working, I found that re-indexing from a XE2 app broke the B-TreeFiler (BTreeFiler) tables with a isam error #10122 ("The page size for the file block is greater then the MaxPageSize"). Here is the fix:

This one needs to be changed in Filer.pas for reindexing to work:

IsamInfoRec = packed Record
    InfoRec : IsamSmallInfoRec;
    DummyFill : AnsiChar; <<<<<<<< Here!
    KeysUsed : LongInt;{Must start on an even offset for C-compatibility}
    PageSizeUsed : Word; {!!.42}
End;

I hope Warren (above) updated his work with this additional fix. I have also posted this one on the TurboPower BTreeFiler SourceForge location.

0

Two more items to check

  1. change "string" to "AnsiString"
  2. If target build is 64 bits, your changes won't make it ready yet

Cheers

APZ28
  • 997
  • 5
  • 4
  • The target is 32bit. All the strings are short strings as best I can tell. – Bookup Jan 12 '12 at 19:55
  • Besides this, it is important to change Windows.API functions to call Windows.API(A) with the A (ansi) prefix, instead of Windows.API(nosuffix) which resolves to W (wide) API versions. – Warren P Jan 13 '12 at 17:03