home *** CD-ROM | disk | FTP | other *** search
/ Simtel MSDOS - Coast to Coast / simteldosarchivecoasttocoast2.iso / qbasic / qbtree42.zip / QBTREE42.DOC < prev    next >
Text File  |  1989-10-19  |  44KB  |  1,079 lines

  1.  
  2.  
  3.                            A B-Tree Access Method
  4.                          for QuickBASIC Programmers.
  5.  
  6.                          QBTREE (C)1989 Cornel Huth
  7.  
  8.  
  9.         The QBTREE package is a shareware product.  You may try this
  10.         software to see if it fits your needs.  You may copy and distribute
  11.         this package freely.  If you continue to use it, fill out the
  12.         registration form and send it along with payment of $45 to:
  13.  
  14.                           Cornel Huth
  15.                           ATTN: QBTREE 4.20 REGISTRATION
  16.                           6402 Ingram Rd.
  17.                           San Antonio, TX  78238
  18.  
  19.  
  20.          Source code for the QBTREE interface will be sent upon
  21.          registration.  This interface is all that is needed to
  22.          modify QBTREE for most situations since all I/O is performed
  23.          at this level (QuickBASIC).  If you also need the low-level
  24.          btree routine, I'll make it available.  It's written in MASM
  25.          assembly.  (Contact me for more details.)
  26.  
  27.          QBTREE requires QuickBASIC 4.x or above.  For file and
  28.          record locking functions, DOS 3.0 or above, is needed.
  29.  
  30.  
  31.         -----------------------------------------------------------------
  32.  
  33.  
  34.         QBTREE is a keyed-file system based on the b-tree sorting method.
  35.         It maintains up to 10 key files and also 10 data files.  In
  36.         addition to finding any particular key and its associated
  37.         data record very quickly, QBTREE allows sequential access to
  38.         the data file.  QBTREE automatically maintains the data file.
  39.         QBTREE automatically balances the tree at assembly language
  40.         speed.
  41.  
  42.         The following files should be found on the disk:
  43.  
  44.            QBTREE42.LIB       QBTREE42.DOC       QBTREE42.BI
  45.  
  46.            SPEEDCHK.BAS       SPEEDCHK.EXE       SPEEDCHK.DOC
  47.              MAILAB.BAS         MAILAB.EXE         MAILAB.DOC
  48.             CONVERT.BAS                           CONVERT.DOC
  49.            TREETEST.BAS                          TREETEST.DOC
  50.             MEMCOPY.ASM
  51.  
  52.  
  53.         Add QBTREE42.LIB to your standard library if you like, and then
  54.         LINK /QU it into a QLB library for the environment.
  55.  
  56.                 C>lib yourstd.lib + QBTREE42.lib;
  57.  
  58.                 C>link /qu yourstd.lib,qb.qlb,nul,bqlb41.lib
  59.  
  60.         You may prefer to keep QBTREE42.LIB as a separate library, instead.
  61.  
  62.                 C>link /qu yourstd.lib+QBTREE42.lib,qb.qlb,nul,bqlb41.lib
  63.  
  64.         The networking functions are included in the library as a
  65.         separate module and thus will only be included in your
  66.         applications if you use them.  The QuickBASIC source code
  67.         for them is included with registration.
  68.  
  69.         Note that INTERRUPT and INTERRUPTX are defined in the module
  70.         INTRPT within QBTREE42.LIB.  If you prefer to not have it there
  71.         but instead in your own library, remove it from QBTREE.LIB, e.g.,
  72.  
  73.                 C>lib QBTREE42.lib -INTRPT;
  74.  
  75.         -----------------------------------------------------------------
  76.  
  77.  
  78.         Interface summary:
  79.  
  80.         All QBTREE routines are FUNCTIONs and return an integer code
  81.         which is detailed in Error Codes.  These must be DECLAREd.
  82.  
  83.          1)  CreateKeyFile% (filename$, keyl%)
  84.          2)  CreateDataFile% (filename$, recl%)
  85.          3)  OpenKeyFile% (filename$, fileno%)
  86.          4)  OpenDataFile% (filename$, fileno%)
  87.          5)  LockKeyFile% (kfile%)
  88.          6)  UnlockKeyFile% (kfile%)
  89.          7)  LockDataHeader% (dfile%)
  90.          8)  LockRecord% (dfile%, recno&)
  91.          9)  UnlockRecord% (dfile%, recno&)
  92.         10)  AddRecord% (kfile%, dfile%, Qkey$, Qrec$)
  93.         11)  GetEqual% (kfile%, dfile%, Qkey$, Qrec$)
  94.         12)  GetFirst% (kfile%, dfile%, Qkey$, Qrec$)
  95.         13)  GetLast% (kfile%, dfile%, Qkey$, Qrec$)
  96.         14)  GetNext% (kfile%, dfile%, Qkey$, Qrec$)
  97.         15)  GetPrev% (kfile%, dfile%, Qkey$, Qrec$)
  98.         16)  GetPosition% (kfile%, recno&)
  99.         17)  GetDirect% (dfile%, recno&, Qrec$)
  100.         18)  PutKey% (kfile%, dfile%, Qkey$)
  101.         19)  UpdateRecord% (dfile%, Qrec$)
  102.         20)  RewindKeyFile% (fileno%)
  103.         21)  DeleteKey% (kfile%, Qkey$)
  104.         22)  DeleteRecord% (kfile%, dfile%, Qkey$)
  105.         23)  StatKeyFile% (kfile%, keyl%, keys&, bfileno%)
  106.         24)  StatDataFile% (dfile%, recl%, recs&, bfileno%)
  107.         25)  FlushKeyFile% (kfile%, dup%)
  108.         26)  FlushDataFile% (dfile%, dup%)
  109.         27)  CloseKeyFile% (fileno%)
  110.         28)  CloseDataFile% (fileno%)
  111.         29)  QBTreeVer (ver%)
  112.  
  113.  
  114.         -----------------------------------------------------------------
  115.  
  116.  
  117.         Interface detail:
  118.  
  119.          1)  CreateKeyFile(filename$,keylen)
  120.  
  121.              Create a new key file.  filename$ must not already
  122.              exist.
  123.  
  124.              filename$ - string.   Pathname of key file to create.
  125.                          Any valid DOS drive/path/filename can be used.
  126.  
  127.              keylen    - integer.  Length of key for this key file.
  128.                          Valid range is 1 to 64 bytes.
  129.  
  130.              DEFINT A-Z
  131.              filename$ = "C:\HIST\AR89.KEY"
  132.              keylen = 16
  133.              stat = CreateKeyFile(filename$,keylen)
  134.  
  135.  
  136.          2)  CreateDataFile(filename$,reclen)
  137.  
  138.              Create a new data file.  filename$ must not already.
  139.  
  140.              filename$ - string.   Pathname of data file to create.
  141.                          Any valid DOS drive/path/filename can be used.
  142.     
  143.              reclen    - integer.  Length of record for this data file.
  144.                          Valid range is 3 to 32767 bytes, though QB's
  145.                          string space will be the limiting factor.
  146.  
  147.              filename$ = "C:\HIST\AR89.DAT"
  148.              reclen = 128
  149.              stat = CreateDataFile(filename$,reclen)
  150.  
  151.  
  152.          3)  OpenKeyFile(filename$,fileno)
  153.  
  154.              Open an EXISTING key file and associate it with fileno.
  155.              Before USING the key file, a data file will also need
  156.              to be opened.  You may have multiple index files opened for
  157.              a data file.
  158.  
  159.              The fileno is an arbitrary number, 0 to 9.  It does
  160.              not reflect either a BASIC or DOS handle.  It is used
  161.              to reference the key file in any later operation.
  162.              QBTREE uses the QuickBASIC FREEFILE function to obtain an
  163.              available channel but hides this from the application.
  164.              Use StatKeyFile() for information on the key file.
  165.  
  166.              If version 3.0 or greater of DOS is detected then the open
  167.              is performed with a READ/WRITE access and a DENY NONE
  168.              sharing.  Older versions of DOS will have a normal
  169.              open call.  What this means is that other processes may
  170.              read from and write to the key file, filename$.  See the
  171.              LockKeyFile() and UnlockKeyFile() functions for details
  172.              on locking the key file.  To perform these DOS LAN functions
  173.              the DOS program SHARE.EXE needs to be run.
  174.  
  175.              filename$ - string.   Pathname of existing key file.
  176.     
  177.              fileno    - integer.  Number to associate the key file
  178.                          with for future operations.  Valid range is
  179.                          0 to 9.
  180.  
  181.              filename$ = "C:\HIST\AR89."
  182.              ARKEY = 0
  183.              ARDAT = 0
  184.              stat = OpenKeyFile(filename$+"KEY",ARKEY)
  185.              if stat = 0 then stat = OpenDataFile(filename$+"DAT",ARDAT)
  186.              if stat <> 0 then DoErrorProc stat
  187.  
  188.  
  189.          4)  OpenDataFile(filename$,fileno)
  190.  
  191.              Open an EXISTING data file and associate it with fileno
  192.              and allocate a data buffer.  The buffer will be the size
  193.              of the record length.
  194.  
  195.              The fileno is an arbitrary number, 0 to 9.  It does
  196.              not reflect either a BASIC or DOS handle.  It is used
  197.              to reference the data file in any later operation.
  198.              QBTREE uses the QuickBASIC FREEFILE function to obtain an
  199.              available channel but hides this from the application.
  200.              Use StatDataFile() for information on the data file.
  201.  
  202.              If version 3.0 or greater of DOS is detected then the open
  203.              is performed with a READ/WRITE access and a DENY NONE
  204.              sharing.  Older versions of DOS will have a normal
  205.              open call.  What this means is that other processes may
  206.              read from and write to the data file, filename$.  See the
  207.              LockRecord() and UnlockRecord() functions for details on
  208.              locking records.  To perform these DOS LAN functions the
  209.              DOS program SHARE.EXE needs to be run.
  210.  
  211.              filename$ - string.   Pathname of existing data file.
  212.     
  213.              fileno    - integer.  Number to associate the data file
  214.                          with for future operations.  Valid range is
  215.                          0 to 9.
  216.  
  217.              {see OpenKeyFile() for an example}
  218.  
  219.  
  220.          5)  LockKeyFile(kfile)
  221.  
  222.              Lock the key file, kfile, to the current process.  Any
  223.              other process requesting access to kfile will be denied
  224.              permission.  It is recommended that this be used, in LAN
  225.              applications, prior to AddRecord(), PutKey(), DeleteKey(),
  226.              DeleteRecord().  To perform this DOS LAN function, the
  227.              DOS program SHARE.EXE needs to be run.
  228.  
  229.              kfile     - integer.  Number that was used as fileno in
  230.                          OpenKeyFile().
  231.  
  232.              kfile = 0
  233.              stat = LockKeyFile(kfile)
  234.              if stat = 229 then
  235.                 print "Lock already in force"
  236.              elseif stat = 232 then
  237.                 print "SHARE.EXE has not been run"
  238.  
  239.  
  240.          6)  UnlockKeyFile(kfile)
  241.  
  242.              Unlock the key file, kfile.  You should do this as soon as
  243.              you have finished the AddRecord(), PutKey(), DeleteKey(),
  244.              DeleteRecord() operation.  To perform this DOS LAN function,
  245.              the DOS program SHARE.EXE needs to be run.
  246.  
  247.              kfile     - integer.  Number that was used as fileno in
  248.                          OpenKeyFile().
  249.  
  250.              kfile = 0
  251.              stat = UnlockKeyFile(kfile)
  252.              if stat = 232 then
  253.                 print "SHARE.EXE has not been run"
  254.  
  255.  
  256.          7)  LockDataHeader(dfile)
  257.  
  258.              Lock the data header in dfile to the current process.  Any
  259.              other process requesting access to the header will be denied
  260.              permission.  This function should be used before adding or
  261.              deleting a data record, though not needed for updating an
  262.              existing record.  To perform this DOS LAN function, the DOS
  263.              program SHARE.EXE must be run.
  264.  
  265.              dfile     - integer.  Number that was used as fileno in
  266.                          OpenDataFile().
  267.  
  268.              dfile = 0
  269.              stat = LockDataHeader(dfile)
  270.              if stat = 229 then
  271.                 print "Lock already in force"
  272.              elseif stat = 232 then
  273.                 print "SHARE.EXE needs to be run"
  274.  
  275.  
  276.          8)  LockRecord(dfile,recno&)
  277.  
  278.              Lock a specific record, recno&, in dfile, to the current
  279.              process.  Any other process requesting access to recno&
  280.              will be denied permission.  If recno&=0& then all records
  281.              in dfile will be locked (records 1 to EOF plus).  To
  282.              perform this DOS LAN function, the DOS program SHARE.EXE
  283.              must be run.
  284.  
  285.              dfile     - integer.  Number that was used as fileno in
  286.                          OpenDataFile().
  287.  
  288.              recno&    - long.     Data record number in data file to
  289.                          lock.
  290.  
  291.              dfile = 0
  292.              recno& = 1&        '{lock the first record in dfile}
  293.              stat = LockRecord(dfile,recno&)
  294.              if stat = 229 then
  295.                 print "Lock already in force"
  296.              elseif stat = 232 then
  297.                 print "SHARE.EXE needs to be run"
  298.  
  299.  
  300.          9)  UnlockRecord(dfile,recno&)
  301.  
  302.              Unlock a specific record, recno&, in dfile.  Once the record
  303.              that was locked is no longer needed, you should unlock it.
  304.              If a process terminates without releasing active locks on
  305.              a file, the result is undefined.  If recno&=0& then all
  306.              records in dfile will be unlocked (records 1 to EOF plus).
  307.              To perform this DOS LAN function, the DOS program SHARE.EXE
  308.              must be installed.
  309.  
  310.              dfile     - integer.  Number that was used as fileno in
  311.                          OpenDataFile().
  312.  
  313.              recno&    - long.     Data record number in data file to
  314.                          unlock.
  315.  
  316.              dfile = 0
  317.              recno& = 1&        '{unlock the first record in dfile}
  318.              stat = UnlockRecord(dfile,recno&)
  319.              if stat = 232 then
  320.                 print "SHARE.EXE has not been run"
  321.  
  322.  
  323.         10)  AddRecord(kfile,dfile,Qkey$,Qrec$)
  324.  
  325.              Add the key, Qkey$, to the key file, kfile, and the data
  326.              record, Qrec$, to the data file, dfile.  Qkey$ must
  327.              not already exist.  QBTREE is case-sensative so it is
  328.              recommended that keys be made upper-case (or lower) unless
  329.              there is a reason not to do this.
  330.  
  331.              kfile     - integer.  Number that was used as fileno in
  332.                          OpenKeyFile().
  333.  
  334.              dfile     - integer.  Number that was used as fileno in
  335.                          OpenDataFile().
  336.  
  337.              Qkey$     - string.   Key to add to key file.
  338.  
  339.              Qrec$     - string.   Data record to add to the data file
  340.                          that is indexed by Qkey$.
  341.  
  342.              kfile = 0
  343.              dfile = 0
  344.              Qkey$ = acctid$ + acctxn$
  345.              Qrec$ = xaction$
  346.              stat = AddRecord(kfile,dfile,Qkey$,Qrec$)
  347.  
  348.  
  349.         11)  GetEqual(kfile,dfile,Qkey$,Qrec$)
  350.  
  351.              Search for key, Qkey$, in kfile, and if found, retrieve
  352.              the data record from dfile, and place it in Qrec$.  If
  353.              not found, the internal pointers indicate where it would
  354.              have been.  By using GetNext(), GetPrev(), the next or
  355.              previous ordered key and data can be obtained.
  356.  
  357.              kfile     - integer.  Number that was used as fileno in
  358.                          OpenKeyFile().
  359.  
  360.              dfile     - integer.  Number that was used as fileno in
  361.                          OpenDataFile().
  362.  
  363.              Qkey$     - string.   Key for which to search in key file.
  364.  
  365.              Qrec$     - string.   Returned data record associated with
  366.                          Qkey$.
  367.  
  368.              kfile = 0
  369.              dfile = 0
  370.              Qkey$ = acctid$ + acctxn$
  371.              stat = GetEqual(kfile,dfile,Qkey$,Qrec$)
  372.              '{Qrec$ is read}
  373.              if stat = 200 then
  374.                 stat = GetNext(kfile,dfile,Qkey$,Qrec$)
  375.                 '{Qkey$ & Qrec$ are read}
  376.  
  377.  
  378.         12)  GetFirst(kfile,dfile,Qkey$,Qrec$)
  379.  
  380.              Retrieve the first ordered key in kfile, placing it in
  381.              Qkey$, and place its data record from dfile into Qrec$.
  382.  
  383.              kfile     - integer.  Number that was used as fileno in
  384.                          OpenKeyFile().
  385.  
  386.              dfile     - integer.  Number that was used as fileno in
  387.                          OpenDataFile().
  388.  
  389.              Qkey$     - string.   Returned first ordered key.
  390.  
  391.              Qrec$     - string.   Returned data record associated with
  392.                          the returned key, Qkey$.
  393.  
  394.              kfile = 0
  395.              dfile = 0
  396.              stat = GetFirst(kfile,dfile,Qkey$,Qrec$)
  397.  
  398.  
  399.         13)  GetLast(kfile,dfile,Qkey$,Qrec$)
  400.  
  401.              Retrieve the last ordered key in kfile, placing it in
  402.              Qkey$, and place its data record from dfile into Qrec$.
  403.  
  404.              kfile     - integer.  Number that was used as fileno in
  405.                          OpenKeyFile().
  406.  
  407.              dfile     - integer.  Number that was used as fileno in
  408.                          OpenDataFile().
  409.  
  410.              Qkey$     - string.   Returned last ordered key.
  411.  
  412.              Qrec$     - string.   Returned data record associated with
  413.                          the returned key, Qkey$.
  414.  
  415.              kfile = 0
  416.              dfile = 0
  417.              stat = GetLast(kfile,dfile,Qkey$,Qrec$)
  418.  
  419.  
  420.         14)  GetNext(kfile,dfile,Qkey$,Qrec$)
  421.  
  422.              Retrieve the next ordered key in kfile, placing it in Qkey$,
  423.              and place its data record from dfile into Qrec$.  This
  424.              function allows for sequential processing of the data file.
  425.  
  426.              kfile     - integer.  Number that was used as fileno in
  427.                          OpenKeyFile().
  428.  
  429.              dfile     - integer.  Number that was used as fileno in
  430.                          OpenDataFile().
  431.  
  432.              Qkey$     - string.   Returned key which immediately follows
  433.                          the key found (or not found) in GetEqual() file.
  434.                          Or the first key if the key file is rewound.
  435.  
  436.              Qrec$     - string.   Returned data record associated with
  437.                          the returned key, Qkey$.
  438.  
  439.              kfile = 0
  440.              dfile = 0
  441.              Qkey$ = acctid$ + acctxn$
  442.              stat = GetNext(kfile,dfile,Qkey$,Qrec$)
  443.  
  444.  
  445.         15)  GetPrev(kfile,dfile,Qkey$,Qrec$)
  446.  
  447.              Retrieve the prev ordered key in kfile, placing it in Qkey$,
  448.              and place its data record from dfile into Qrec$.  This
  449.              function allows for sequential processing of the data file
  450.              in reverse order.
  451.  
  452.              kfile     - integer.  Number that was used as fileno in
  453.                          OpenKeyFile().
  454.  
  455.              dfile     - integer.  Number that was used as fileno in
  456.                          OpenDataFile().
  457.  
  458.              Qkey$     - string.   Returned key which immediately precedes
  459.                          the key found (or not found) in GetEqual() file.
  460.  
  461.              Qrec$     - string.   Returned data record associated with
  462.                          the returned key, Qkey$.
  463.  
  464.              kfile = 0
  465.              dfile = 0
  466.              Qkey$ = acctid$ + acctxn$
  467.              stat = GetPrevl(kfile,dfile,Qkey$,Qrec$)
  468.  
  469.  
  470.         16)  GetPosition(kfile,recno&)
  471.  
  472.              Return the logical record number of the current record
  473.              pointed to by the last key FOUND in kfile.
  474.  
  475.              kfile     - integer.  Number that was used as fileno in
  476.                          OpenKeyFile().
  477.  
  478.              recno&    - long.     Returned current record number in the
  479.                          last used (current) data file.
  480.  
  481.              kfile = 0
  482.              stat = GetPosition(kfile,recno&)
  483.              if stat = 0 then
  484.                 print "Current data record of kfile";kfile;" is";recno&
  485.  
  486.  
  487.         17)  GetDirect(dfile,recno&,Qrec$)
  488.  
  489.              Return the data in dfile at the logical record number,
  490.              recno&.  This is especially useful for reindexing data
  491.              files,  provided that the key is imbedded in the data
  492.              record.  It is possible to retrieve deleted records from
  493.              the data file; records are not physically deleted but are
  494.              marked 'available' for a new data record.  It is also
  495.              possible to give recno& a value past the true end of file.
  496.              This function does not affect the index file's internal
  497.              pointers.
  498.  
  499.              dfile     - integer.  Number that was used as fileno in
  500.                          OpenDataFile().
  501.  
  502.              recno&    - long.     Record number to seek.
  503.  
  504.              Qrec$     - string.   Returned record data.
  505.  
  506.              dfile = 0
  507.              recno& = 456&
  508.              stat = GetDirect(dfile,recno&,Qrec$)
  509.              if stat = 0 then
  510.                 print "Record#";recno&;" =";Qrec$
  511.  
  512.  
  513.         18)  PutKey(kfile,dfile,Qkey$)
  514.  
  515.              After having found a key, insert the key Qkey$ into the
  516.              key file, kfile, (which most likely is an index file
  517.              other than the one where the key was found, though it can
  518.              be the same) and have associated with it the data record
  519.              that was indexed by the found key.  This allows you have
  520.              multiple indexes per data file.
  521.  
  522.              kfile     - integer.  Number that was used as fileno in
  523.                          OpenKeyFile().
  524.  
  525.              dfile     - integer.  Number that was used as fileno in
  526.                          OpenDataFile().
  527.  
  528.              Qkey$     - string.   Key for which you want to add to the
  529.                          key file, kfile, and have it also point to
  530.                          the data record in dfile whose key was last
  531.                          found.
  532.  
  533.              kfile = 0
  534.              dfile = 0
  535.              Qkey$ = namekey$
  536.              stat = GetEqual(kfile,dfile,Qkey$,Qrec$)
  537.              if stat = 0 then
  538.                 kfile = 1
  539.                 Qkey$ = SSNkey$
  540.                 stat = PutKey(kfile,dfile,Qkey$)
  541.  
  542.  
  543.         19)  UpdateRecord(dfile,Qrec$)
  544.  
  545.              Overwrite the current data record in dfile with Qrec$.
  546.              This allows you to update the contents of a record
  547.              in a data file.
  548.  
  549.              dfile     - integer.  Number that was used as fileno in
  550.                          OpenDataFile().
  551.  
  552.              Qrec$     - string.   Data to use in replacing the previous
  553.                          data in dfile.
  554.  
  555.              kfile = 0
  556.              dfile = 0
  557.              Qkey$ = acctid$
  558.              stat = GetEqual(kfile,dfile,Qkey$,Qrec$)
  559.              if stat = 0 then
  560.                 Qrec$ = newQrec$
  561.                 stat = UpdateRecord(dfile,Qrec$)
  562.  
  563.  
  564.         20)  RewindKeyFile(kfile)
  565.  
  566.              Position the key file, kfile, to the first ordered key.
  567.  
  568.              kfile     - integer.  Number that was used as fileno in
  569.                          OpenKeyFile().
  570.  
  571.              kfile = 0
  572.              stat = RewindKeyFile(kfile)
  573.  
  574.  
  575.         21)  DeleteKey(kfile,Qkey$)
  576.  
  577.              Delete the key, Qkey$, from kfile.  The data record
  578.              associated with Qkey$ is not affected.  This is necessary
  579.              since you may have multiple indexes per data file.
  580.  
  581.              kfile     - integer.  Number that was used as fileno in
  582.                          OpenKeyFile().
  583.  
  584.              Qkey$     - string.   Key to remove from kfile.
  585.  
  586.              kfile = 0
  587.              Qkey$ = acctid$ + acctxn$
  588.              stat = DeleteKey(kfile,Qkey$)
  589.  
  590.  
  591.         22)  DeleteRecord(kfile,dfile,Qkey$)
  592.  
  593.              Delete the key, Qkey$, from file kfile and also delete
  594.              the associated record from dfile.  Any other index files
  595.              keying to this record should have DeleteKey() performed
  596.              before using DeleteRecord() since the record space will
  597.              have been made 'available' for a new data record.
  598.  
  599.              kfile     - integer.  Number that was used as fileno in
  600.                          OpenKeyFile().
  601.  
  602.              dfile     - integer.  Number that was used as fileno in
  603.                          OpenDataFile().
  604.  
  605.              Qkey$     - string.   Key for which you want to delete from
  606.                          the key file, kfile, and also delete its
  607.                          associated data record in dfile.
  608.  
  609.              kfile = 0
  610.              dfile = 0
  611.              Qkey$ = acctid$ + acctxn$
  612.              stat = DeleteRecord(kfile,dfile,Qkey$)
  613.  
  614.  
  615.         23)  StatKeyFile(kfile,keylen,keys&,bfileno)
  616.  
  617.              Return information about the key file, kfile.
  618.  
  619.              kfile     - integer.  Number that was used as fileno in
  620.                          OpenKeyFile().
  621.  
  622.              keylen    - integer.  Returned length of keys for kfile.
  623.  
  624.              keys&     - long.     Returned number of keys in kfile.
  625.  
  626.              bfileno   - integer.  Returned BASIC's file number for kfile.
  627.  
  628.              kfile = 0
  629.              stat = StatKeyFile(kfile,keylen,keys&,bfileno)
  630.  
  631.  
  632.         24)  StatDataFile(dfile,reclen,recs&,bfileno)
  633.  
  634.              Return information about the data file, dfile.
  635.  
  636.              dfile     - integer.  Number that was used as fileno in
  637.                          OpenDataFile().
  638.  
  639.              reclen    - integer.  Returned length of records for dfile.
  640.  
  641.              recs&     - long.     Returned number of records in dfile.
  642.  
  643.              bfileno   - integer.  Returned BASIC's file number for dfile.
  644.  
  645.              dfile = 0
  646.              stat = StatDataFile(dfile,reclen,recs&,bfileno)
  647.  
  648.  
  649.         25)  FlushKeyFile(kfile,dup)
  650.  
  651.              Updates the key header information and, if dup is non-zero,
  652.              causes DOS to update the directory entry for kfile.  This
  653.              is done by writing the key header out, having DOS duplicate
  654.              kfile's handle, then closing the duplicate handle.
  655.              This does not have the overhead of having to re-open
  656.              the key file.  This also flushes DOS's internal buffers.
  657.  
  658.              In LAN applications you should perform this function before
  659.              releasing a key file lock, but dup must be equal to 0.
  660.              If you force DOS to update the directory entry, UnlockKeyFile()
  661.              will return error 229 - Lock already in force.  Not flushing
  662.              the buffers is not a problem in LAN applications since the
  663.              SHARE.EXE will not allow 'local buffer' problems to occur.
  664.  
  665.              kfile     - integer.  Number that was used as fileno in
  666.                          OpenKeyFile().
  667.  
  668.              kfile = 0
  669.              dup = -1           'dup must be 0 for LAN applications
  670.              stat = FlushKeyFile(kfile,dup)
  671.  
  672.  
  673.         26)  FlushDataFile(dfile,dup)
  674.  
  675.              Updates the data header information and, if dup is non-zero,
  676.              causes DOS to update the directory entry for dfile.  This
  677.              is done by writing the data header out, having DOS duplicate
  678.              dfile's handle, then closing the duplicate handle.
  679.              This does not have the overhead of having to re-open
  680.              the data file.  This also flushes DOS's internal buffers.
  681.  
  682.              In LAN applications you should perform this function before
  683.              releasing a data record lock, but dup must be equal to 0.
  684.              If you force DOS to update the directory entry, UnlockRecord()
  685.              will return error 229 - Lock already in force.  Not flushing
  686.              the buffers is not a problem in LAN applications since the
  687.              SHARE.EXE will not allow 'local buffer' problems to occur.
  688.  
  689.              dfile     - integer.  Number that was used as fileno in
  690.                          OpenDataFile().
  691.  
  692.              dfile = 0
  693.              dup = -1           'dup must be 0 for LAN applications
  694.              stat = FlushDataFile(dfile,dup)
  695.  
  696.  
  697.         27)  CloseKeyFile(kfile)
  698.  
  699.              Close the key file, kfile.  This is essential for proper
  700.              termination in QBTREE.  Header information is written only
  701.              when the file is closed, or flushed.  Release any active
  702.              locks first.
  703.  
  704.              kfile     - integer.  Number that was used as fileno in
  705.                          OpenKeyFile().
  706.  
  707.              kfile = 0
  708.              stat = CloseKeyFile(kfile)
  709.  
  710.  
  711.         28)  CloseDataFile(dfile)
  712.  
  713.              Close the data file, dfile, releasing the data buffer
  714.              allocated to it.  This function is essential for proper
  715.              termination in QBTREE.  Release any active locks first.
  716.  
  717.              dfile     - integer.  Number that was used as fileno in
  718.                          OpenDataFile().
  719.  
  720.              dfile = 0
  721.              stat = CloseDataFile(dfile)
  722.  
  723.  
  724.         29)  QBTreeVer(ver)
  725.  
  726.              Returns the version of the QBTREE access method (X100).
  727.  
  728.              ver        - integer.  Returned version number * 100.
  729.  
  730.              stat = QBTreeVer(ver)
  731.              print "QBTREE version";ver\100
  732.  
  733.  
  734.         -----------------------------------------------------------------
  735.  
  736.  
  737.         Error Codes:
  738.  
  739.            200  Key not found
  740.                 - the key is not in the index file.  This will occur
  741.                   during a GetEqual(), DeleteKey(), DeleteRecord().
  742.  
  743.            201  Key already exists
  744.                 - duplicate keys are not allowed in QBTREE.  This
  745.                   will occur during AddRecord(), PutKey().
  746.  
  747.            202  End of file
  748.                 - GetNext() has reached the end of file.
  749.  
  750.            203  Top of file
  751.                 - GetPrev() has reached the top of file.
  752.  
  753.            204  Empty file
  754.                 - there are no keys in the index file.  This will
  755.                   occur when you attempt to perform functions that
  756.                   would require a non-empty file.
  757.  
  758.            205  Disk full
  759.                 - if the key file drive and the data file drive are the
  760.                   same a minimum of 2 clusters are needed for the key
  761.                   file plus the clusters required to completely hold the
  762.                   data record before you can AddRecord() or PutKey().
  763.                   If they are separate drives, the key file needs at
  764.                   least 2 clusters free on its disk and the data file
  765.                   disk as many clusters as needed to hold the data record.
  766.                   This will also occur during CreateKeyFile(),
  767.                   CreateDataFile().
  768.  
  769.            206  Data pointer invalid
  770.                 - a valid QBTREE key access, either GetEqual(), GetNext(),
  771.                   GetPrev(), GetFirst(), GetLast() but NOT RewindKeyFile(),
  772.                   must occur right before a data record can be updated.
  773.  
  774.            207-
  775.            209  reserved
  776.  
  777.            210  Stack overflow (10 levels)
  778.                 - the internal tracking stack exceeds capacity.  This
  779.                   will probably never occur.
  780.  
  781.            211  Function not implemented
  782.                 - this won't happen unless you call the low-level
  783.                   driver.
  784.  
  785.            212-
  786.            219  reserved
  787.  
  788.            220  Data record length invalid
  789.                 - data record length must be from 3 to 32767 bytes
  790.                    when creating data file.
  791.  
  792.            221  Key length invalid
  793.                 - key length must be from 1 to 64 bytes when creating
  794.                   key file.
  795.  
  796.            222  File not open
  797.                 - the file number for StatKeyFile(), StatDataFile(),
  798.                   FlushKeyFile(), FlushDataFile(), GetDirect(), or
  799.                   any of the locking functions is not valid.  If other
  800.                   QBTREE functions are used to access an unopen file,
  801.                   QuickBASIC will handle the error since all disk I/O
  802.                   is done by QuickBASIC.
  803.  
  804.            223  Invalid null key assignment
  805.                 - a null key cannot be used.  Null is defined in QBTREE
  806.                   as either ASCII 0 or ASCII 255.  This will occur in
  807.                   AddRecord(), DeleteKey(), DeleteRecord(), GetEqual(),
  808.                   PutKey().
  809.  
  810.            224  Invalid record number
  811.                 - a record number less than 1 was used in GetDirect().
  812.                   Upper bounds is not validated.
  813.  
  814.            225  No handle available for DUP
  815.                 - no DOS handles are available to flush files.  Use a
  816.                   greater value in config.sys FILES= (FILES=20).
  817.  
  818.            226  Invalid drive specifier
  819.                 - the drive specified in CreateKeyFile(),
  820.                   CreateDataFile() is not a valid DOS drive.
  821.  
  822.            227  File needs to be converted
  823.                 - QBTREE version 4.2 uses a new key file format.  A
  824.                   utility program is included to convert QSAM versions
  825.                   1 to 3.xx, and BTREE 4.0x to QBTREE 4.20.  Previous
  826.                   versions of this program should no longer be used since
  827.                   a coding error causes DeleteKey() & DeleteRecord() to
  828.                   fail.  This error will occur only at OpenKeyFile() or
  829.                   OpenDataFile() functions.
  830.  
  831.            228  File not QBTREE
  832.                 - the filename in OpenKeyFile() or OpenDataFile() is not
  833.                   recognized as a QBTREE file.
  834.  
  835.            229  Lock already in force
  836.                 - the lock requested cannot be made because an existing
  837.                   lock of the header, record or file is in force.
  838.                   See FlushKeyFile() and FlushDataFile() also.
  839.  
  840.            230  File already exists
  841.                 - the CreateKeyFile() or CreateDataFile() filename
  842.                   already exists.  Delete the filename if you really
  843.                   want to use the same filename.  Note that the create
  844.                   functions do not explicitly check for valid pathnames.
  845.                   If an invalid pathname is given, QuickBASIC will report
  846.                   then error.
  847.  
  848.            231  File not found
  849.                 - the filename$ specified in OpenKeyFile() or
  850.                   OpenDataFile() does not exist or is not valid.
  851.  
  852.            232  General lock failure
  853.                 - usually means that SHARE.EXE was not run before using
  854.                   LockDataHeader(), LockRecord(), UnlockRecord(),
  855.                   LockKeyFile(), UnlockKeyFile().
  856.  
  857.            233-
  858.            255  reserved
  859.  
  860.         -----------------------------------------------------------------
  861.  
  862.  
  863.         Technical Specifications:
  864.  
  865.             Key length:  1 - 64 bytes (ASCII sort), constant
  866.          Record length:  3 - 32767 bytes, constant (avail near memory)
  867.              Node size:  512 bytes
  868.          Keys per node:  7 - 84 keys, (512-3)\(key length+5)
  869.          Max keys/file:  16 million keys
  870.          Max data/file:  16 million bytes
  871.          Max key files:  10 opened at one time (avail DOS files)
  872.         Max data files:  10 opened at one time (avail DOS files)
  873.  
  874.  
  875.         Key file header format (first sector (512 bytes) of key file):
  876.  
  877.            filetype        char    ;  0 file type, "*", ASCII 42
  878.            rootnode        int     ;  1 sector in file of root node
  879.            nokeyslo        int     ;  3 number of keys (low word)
  880.            nokeyshi        byte    ;  5 number of keys (high byte)
  881.            keyavsec        int     ;  6 key available list head
  882.            nxkeysec        int     ;  8 next free sector
  883.            keylen          byte    ; 10 length of key
  884.            maxkeys         byte    ; 11 maximum keys per node
  885.            ackysc          int     ; 12 actual key sector in buffer
  886.            cukysc          int     ; 14 current key sector
  887.            cukyof          byte    ; 16 current key offset
  888.            iflag           byte    ; 17 internal flag
  889.            stkcnt          byte    ; 18 tree level count
  890.            pstack          long    ; 19 - 58 tree stack (4 bytes per level)
  891.            reserved        any     ; 59 - 255
  892.            free use        any     ; 256 - 383
  893.            reserved        any     ; 384 - 511
  894.  
  895.  
  896.         Data file header format (first 32 bytes of data file):
  897.  
  898.            filetype        char    ;  0 file type, "S"
  899.            reclen          int     ;  1 length of record
  900.            norecslo        int     ;  3 number of records (low word)
  901.            norecshi        byte    ;  5 number of records (high byte)
  902.            datavlo         int     ;  6 data available list (low word)
  903.            datavhi         byte    ;  8 data available list (high byte)
  904.            nxdalo          int     ;  9 next data record avail (low word)
  905.            nxdahi          byte    ; 11 next data record avail (high byte)
  906.            internal        byte    ; 12
  907.            cudalo          int     ; 13  current data record (low word)
  908.            cudahi          byte    ; 15  current data record (high byte)
  909.            internal        any     ; 16 - 31 reserved
  910.  
  911.  
  912.         Key format:
  913.  
  914.            There is an internal first key with a null value immediately
  915.            following the key header.
  916.  
  917.            Beginning each node (sector) is a count key byte.  This
  918.            is the count of keys on that sector.  Then for each key
  919.            is a 16-bit previous node pointer, the key itself, the
  920.            24-bit data pointer for that key, and a 16-bit next node
  921.            pointer (node pointers are zero at the leaf nodes).
  922.  
  923.            02  00 00  000000  00 00 00  00 00  KEY001  01 00 00  00 00 ...
  924.            1.    2.     3.       4.       5.     6.       7.       8.   9.
  925.  
  926.            1.  Key count for that node
  927.            2.  Node back pointer (for non-leaf nodes)
  928.            3.  The internal null key
  929.            4.  The 24-bit data record pointer (zero)
  930.            5.  Fwd ptr/back ptr (for non-leaf nodes)
  931.            6.  First logical key
  932.            7.  Its data pointer (record number in data file)
  933.            8.  Its forward pointer (for non-leaf nodes)
  934.            9.  Unused space to end of sector
  935.  
  936.  
  937.         Data record format:
  938.  
  939.            Straight data after the header.  Logical record #1 follows
  940.            the header.
  941.  
  942.  
  943.         BTREE42.BAS, the I/O and interface portion of QBTREE was written
  944.         and compiled with QuickBASIC 4.00b.  The BTREE42.BAS file was
  945.         compiled with the /O option only.  If using QuickBASIC 4.00b+,
  946.         which has a better error handling algorithm than 4.0, you can trap
  947.         I/O errors with QB even though the BTREE42 module was compiled
  948.         without the /E or /X options.  Version 4.00, however, will instead
  949.         dump the program to DOS, so you need to perform common I/O checks
  950.         such as checking to see if a file exists, etc., before using
  951.         QBTREE functions with QB/BC 4.0.
  952.  
  953.         One check that is not handled well by QBTREE42 is an open
  954.         drive door.  It is thus necessary to check for a ready drive
  955.         if the media is removable (not a problem with hard disks).
  956.  
  957.         For those of you still using version 4.00, contact Microsoft
  958.         Customer Support (it's toll-free) for a free maintenance
  959.         upgrade to 4.00b.  All you need are the original disk serial
  960.         numbers.  Within a week you'll get it.
  961.  
  962.  
  963.         Storage for the data buffers and headers are allocated in the
  964.         default data area of QB.  BTREE42.BAS storage allocation is
  965.         as follows:
  966.  
  967.           2 integer arrays (0 to 9) for file handles.
  968.           1 key hdr array (0 to 9) for key file headers, ea 62 bytes.
  969.           1 data hdr array (0 to 9) for data file headers, ea 32 bytes.
  970.           1 key node array (0 to 9) for node buffers, ea 512 bytes.
  971.           1 data buffer array$ (0 to 9) for data record I/O, size
  972.             allocated is equal to that dfile's record length (var-len$).
  973.           1 long integer array (0 to 9) to track current record numbers.
  974.           2 integer arrays (0 to 9) to track file drives
  975.           1 type variable for interfacing with QBTREE low-level, 18 bytes.
  976.             ... and other miscellaneous variables
  977.  
  978.  
  979.         Tip 1:  QBTREE uses a simple variable, namely a var-len string,
  980.         to get and put data in the data file.  To work around this,
  981.         you may want to use the method below.  Go ahead and set up your
  982.         TYPEd variable, then allocate enough space in a var-len
  983.         string to copy to and from it.
  984.  
  985.         TYPE dataTYPE
  986.            whatis AS INTEGER
  987.            whatbe AS STRING * 8
  988.            whaton AS LONG
  989.         END TYPE
  990.  
  991.         DIM whatit AS dataTYPE
  992.  
  993.         whatit.whatis = 2
  994.         whatit.whatbe = "right on"
  995.         whatit.whaton = 6&
  996.  
  997.         DIM SHARED thatit$
  998.         thatit$ = SPACE$(LEN(whatit))
  999.  
  1000.         FromSec = VARSEG(whatit.whatis)
  1001.         FromOff = VARPTR(whatit.whatis)
  1002.         ToSec = VARSEG(thatit$)      '{we want the offset to the string's}
  1003.         ToOff = SADD(thatit$)        '{address, not the string descriptor's}
  1004.         count = len(thatit$)
  1005.         dir = 1
  1006.         MemCopy FromSec,FromOff,ToSec,ToOff,count,dir
  1007.  
  1008.         '{You now have the TYPEd variable data in a var-len string that}
  1009.         '{can be used as the Qrec$.  To put Qrec$ in the typed variable,}
  1010.         '{reverse the from/to assignments.}
  1011.  
  1012.         '{MemCopy is included in the QBTREE42.LIB and QBTREE42.BI}
  1013.  
  1014.  
  1015.         TIP 2:  QBTREE does not allow duplicate keys (this may be an
  1016.         inconvenience in some data base programming) but this can easily
  1017.         be worked around by adding to each key an additional byte.  This
  1018.         byte would act to differentiate up to 256 'identical' keys.  E.g.,
  1019.  
  1020.                 If the needed key length is 16 bytes, make it 17.
  1021.                 Reserve the 17th byte so that you can enumerate
  1022.                 identical keys.  When adding a key that does not
  1023.                 already exist, place an ASCII 0 in byte 17 of the
  1024.                 key.  If the key already exists (error 201), use
  1025.                 ASCII 1, and so on, until no error is returned.
  1026.                 By adding a 2-byte enumerator, 65536 identical keys
  1027.                 can be used.
  1028.  
  1029.  
  1030.          ****************** QBTREE REGISTRATION FORM ********** 420 **
  1031.  
  1032.         Name of registrant: __________________________________________
  1033.  
  1034.         Amount paid: $ ____________ ($45 ea.)  If you want me to send
  1035.                                                the interface source
  1036.                                                code, fill out the non-
  1037.                                                release form below.
  1038.  
  1039.         Comments:  ___________________________________________________
  1040.  
  1041.                    ___________________________________________________
  1042.  
  1043.         Contact:   ________________________ Phone:(   )____-__________
  1044.  
  1045.                    Would you like to be added to our mailing list? ___
  1046.  
  1047.         Mail to:   ___________________________________________________
  1048.  
  1049.                    ___________________________________________________
  1050.  
  1051.                    ___________________________________________________
  1052.  
  1053.         Send payment to:  Cornel Huth
  1054.                           ATTN: QBTREE 4.20 REGISTRATION
  1055.                           6402 Ingram Rd.
  1056.                           San Antonio, TX  78238
  1057.  
  1058.  
  1059.         *** NON-RELEASE FORM for QBTREE 4.20 INTERFACE SOURCE CODE ****
  1060.  
  1061.         I, _______________________________________, hereby agree not
  1062.  
  1063.         to distribute, nor claim ownership of, QBTREE source code, or
  1064.  
  1065.         any modification, to the QBTREE interface, and not remove the
  1066.  
  1067.         copyright notice of Cornel Huth from any part of QBTREE.
  1068.  
  1069.  
  1070.         DATE:__________________
  1071.  
  1072.  
  1073.         _______________________
  1074.  
  1075.  
  1076.         (If you would like the interface source code in QB 4.00b,
  1077.          print your name in the first blank, date the second, and
  1078.          sign the third.)
  1079.