home *** CD-ROM | disk | FTP | other *** search
/ Shareware Overload / ShartewareOverload.cdr / database / datamage.zip / CODE.ZIP / ISAM.TXT < prev    next >
Text File  |  1990-08-20  |  16KB  |  303 lines

  1.                               D I S C L A I M E R
  2.  
  3.  
  4. The  code included is provided AS IS, with NO WARRANTY WHATEVER.  If you  chose
  5. to  place  it  into your programs YOU are responsible for  verifying  that  the
  6. overall  program,  including  code furnished by HCWP, works.  I  will  bear  no
  7. liability  OF ANY KIND for this code.  And I will MOST CERTAINLY NOT  guarantee
  8. it to work in YOUR program!  All I can say is:  It works here, in mine.
  9.  
  10. DATAMAGE
  11.  
  12. The  draw_border function included with your sample places the DATAMAGE  banner
  13. atop  the screen.  DATAMAGE is a registered trademark of Monte Ward  and  HCWP.
  14. You may NOT use it in your programs!
  15.  
  16. THE CORE LIBRARY
  17.  
  18. The  module  of code called HCWP_LIB.C is the core library, and  has  it's  own
  19. docs in the file: HCWP_LIB.TXT.
  20.  
  21. THE ISAM LIBRARY
  22.  
  23. The  module  of  code called MAGEISAM.C (and MAGEISAM.H)  are  the  C  language
  24. interface to DATAMAGE files.  So far.  This module was compiled with the  QUICK
  25. C compiler (2.5) and, save a few of those dern long/short mis-matches, compiled
  26. perfectly.   If  you try to use another compiler, GOOD LUCK.  MIGHT  work,  but
  27. you'll find dieeetomsbin and dmsbintoieee functions, which turn BASIC formatted
  28. double-floats into ieee formatted double-floats don't exist in many  compilers,
  29. so be prepared to do it yourself.
  30.  
  31. The  module  called MAGEDEMO.C uses SOME of the functions to  create  a  simple
  32. program.   It's purpose is to provide a practical demonstration of the  use  of
  33. the  ISAM,  and to provide a platform for your programs.  It is  NOT  a  slick,
  34. finished product.  Merely a template.
  35.  
  36. WHAT IS AN I.S.A.M. ?
  37.  
  38. What we have, here, folks, is the GUTS of a database.  ISAM stands for  Indexed
  39. Sequential  Access  Method/Manager.  In this module is the code  to  read/write
  40. records, find records, load DATAMAGE files - the basics.
  41.  
  42. The DATAMAGE ISAM was designed for maximum speed, low disk/memory overhead,  to
  43. make  optimum use of MS-DOS and, most importantly, to be easy to program  with.
  44. This is FAR easier/simpler than dBase methodology, for instance.
  45.  
  46. DATAMAGE ISAM PARTICULARS
  47.  
  48. The files are flat and assessable to the BASIC interpreter.  So, you CAN  write
  49. hybrid programs with it, if you must.  But, PLEASE do yourself a favor and  get
  50. QUICK BASIC if BASIC is your thing.  See POWRMAIL.BAS.
  51.  
  52. For  those  of us who prefer C, the format of the files on  disk  makes  little
  53. difference.    Whatever   it  is,  we  can  handle  it.   But   simplicity   of
  54. design/operation  and  the  aforementioned speed and  LOW  OVERHEAD  are  still
  55. valuable.   And,  of course, the accessibility of your files  to  the  DATAMAGE
  56. system  adds  many features to your programs.  The ISAM is NOT designed  to  be
  57. state-of-the-art, just to WORK (fast!) and to be used by ordinary human beings.
  58.  
  59. DEFINITION FILES
  60.  
  61. One BIG difference between DATAMAGE files and ordinary files produced by  BASIC
  62. is that they have definition files.  In a "dedicated" program definition  files
  63. aren't necessary - we know the details of the file and hard-code them into  our
  64. program.  This necessary with some of the big-name ISAMs, like B-TRIEVE.
  65.  
  66. Other  files,  like  dBase, have the file definition "built  in"  to  the  main
  67. datafile.  This makes it MURDER to process the file and almost completely  dis-
  68. allows  BASIC  from  processing the files.  But, it DOES make  it  possible  to
  69. transport  the file more easily.  To transport a DATAMAGE file you simply  copy
  70. all the files in the sub-dir.  That's harder.
  71.  
  72. DATAMAGE  files have their definition in two files:  HEADINGS.SAD and  KEY.SAD.
  73. The  headings  file has strings, maximum 25 chars, and the key file  has  three
  74. numbers  in  it's 33 byte records, ascii format.  These files are read  by  the
  75. open_file function, and the DATAMAGE file structure is filled.
  76.  
  77. From then on, the information about a particular field in a particular file  is
  78. at  hand in the structure.  To find out if field four in file four  is  numeric
  79. you might go:  if (fi [4].key [4] -> type > 1).  fi is the file-info structure,
  80. subscript  gets  us file four (the FIFTH file loaded), .key gets  us  into  the
  81. array  of far pointers to structures defining the fields, -> type gets  us  the
  82. field type, which is defined in the code.
  83.  
  84. So, the DATAMAGE isam provides you with the power to load and process ANY  file
  85. created by/accessible to DATAMAGE.  It's loaded with PRACTICAL features the big
  86. boys  just don't have, like read/writing ANY individual file/field, instead  of
  87. having  to  move seven thousand bytes to/from disk just to change one.   And  a
  88. window that allows the user to select a field in a file, etc, etc, etc.
  89.  
  90. DATAMAGE ISAM - FORMAT AND PARTICULARS
  91.  
  92. SPECS
  93.  
  94.      RECORDS IN FILE:  32,000
  95.      FIELDS IN FILE:  200
  96.      MAX STRING FIELD LENGTH:  35
  97.      ALL NUMERICS DOUBLE PRECISION, MBF FORMATTED 8-BYTE STRINGS
  98.      MAX INDEXES: 5
  99.      INDEX MODES:  UNIQUE, NON-UNIQUE, CROSS
  100.      RECORD NUMBERS: MANDATORY, UNIQUE
  101.      MAX FILES OPEN: 8
  102.  
  103. RECORD NUMBERS
  104.  
  105. Each record in a DATAMAGE file has a number.  It may be 1 - 32,727.  The number
  106. is  stored  in the file CTRLFILE.RAD.  If the number is zero, the record  is  a
  107. "hole" and is available for use.  No record number can be duplicated.
  108.  
  109. FILE INDEXES
  110.  
  111. DATAMAGE  indexes  are simple NUMBERS.  The targeted string is  turned  into  a
  112. signed  word  and recorded in the file:  FILEINDX.RAD.  The  indexes  have  the
  113. capacity  to  hold five two-byte integers, so the records in the file  are  ten
  114. bytes  long.   This  SIMPLE method offers INCREDIBLE  speed  in  searching  and
  115. updating, and is the easiest to understand BY FAR.
  116.  
  117. SEQUENCING
  118.  
  119. The  first record in YOURDATA.RAD, the main datafile, is numbered by the  first
  120. record in CTRLFILE.RAD and indexed by the first record in FILEINDX.RAD.  So, if
  121. we were searching in FILEINDX and found something we liked, we would know  that
  122. the  record  to read in YOURDATA.RAD would be the SAME sequence  as  the  index
  123. record  we  now had.  We could get a field out of it to compare,  or  even  the
  124. whole record if we needed it.
  125.  
  126. Likewise,  if we went searching in the CTRLFILE.RAD and found a  record  number
  127. that struck our fancy, we would know that it's record was the SAME sequence  in
  128. YOURDATA.RAD as the record number we now had from CTRLFILE.RAD.
  129.  
  130. CUSTOMIZATION
  131.  
  132. The ISAM is provided as SOURCE CODE.  If you have a program to do that requires
  133. only  two  files open you may find it convenient to open the  three  associated
  134. files in each DATAMAGE file and just LEAVE them open during the program.   Feel
  135. free to do so.  The ISAM is set up to process eight files, and thirty-two files
  136. open  is  more than most folks allot for in their config.sys  file,  and  would
  137. waste memory most of the time.
  138.  
  139. In a program you have you want it to process one file, and ONLY one file.   So,
  140. you  won't need the show_datafiles function.  You will pass a constant  to  the
  141. open_file  routine.   Feel  free to REMOVE unused  functions  from  your  final
  142. version.  There's no sense having un-used code.
  143.  
  144. LAN OPERATION
  145.  
  146. You  will  need  to add your own record locking.  May I suggest  you  read  the
  147. file's  record  from  the CRTLFILE.RAD file, multiply it by -1,  and  write  it
  148. back?   That  way,  the main record could be "read-only."   Locked,  but  still
  149. readable.  This bypasses the locking on the lan, and a LOT of grief!
  150.  
  151. PROGRAMMING EXPERTISE
  152.  
  153. I  can  but  assume that you are a better C programmer  than  my  humble  self.
  154. I  am  just a hacker from Indiana who likes to punch these keys.   Anyhow,  you
  155. SHOULD  understand  C  (if anyone REALLY does?) and  have  written  random-file
  156. programs of your own, possibly incorporating an ISAM.
  157.  
  158. If  you are just learning C (aren't we all?) this AINT the place to start.   If
  159. you  are  wanting to learn random-file processing and already know C  you  will
  160. find the code invaluable.
  161.  
  162. Whatever your level of digital dexterity you are going to have to THINK to  get
  163. this.   There are remarks in the code, but they are "slim."  You will  need  to
  164. read the function's code to figure out what global variables it takes as input,
  165. and changes as output.  If I listed this you wouldn't read the code.
  166.  
  167. NOTHING NEW
  168.  
  169. After  programming for a number of years I realized that the  really  BEAUTIFUL
  170. solutions  all had only one common ingredient:  SIMPLICITY.  And  the  DATAMAGE
  171. ISAM,  pretty  or not, has a liberal dose of that.  This is the way  it's  been
  172. done for YEARS, folks, on many a multi-million dollar mainframe computer.
  173.  
  174. All  I've done is to simplify it, adapt it to a PC, and add my indexing  scheme
  175. which  I thought about FOR YEARS while using convoluted and  overhead-intensive
  176. alternatives.   My  way may be described as brute-force computing, but  I,  for
  177. one, can do without the errors that "finesse" often generates.
  178.  
  179. DATAMAGE INDEXES - THE BRUTE FORCE THEORY
  180.  
  181. As  the  hardware  progresses  BRUTE FORCE works  better  and  better.   Modern
  182. machines  running at 20 Mhz with RLL controllers on FAST hard drives,  possibly
  183. cacheted  with smartdrv etc, might as well be SLOW ram.  While other ISAMs  are
  184. half-way  up  their B-trees I will have checked a thousand records  with  brute
  185. force.  They say:  "I'll find the last record as quickly as the first!"   Isn't
  186. that like saying:  The first record takes as long to find as the last?
  187.  
  188. You  may  have noticed that the RAM_BASE program within DATAMAGE  will  find  a
  189. record  in a hurry.  That's because it can load up to eight  thousand  record's
  190. indexes  into 80K of ram.  Then, it does index searches without  bothering  the
  191. disk drive.  In this case, I will have checked FIVE thousand records with brute
  192. force before the B-tree is clumb.
  193.  
  194. In  either case, all I need to do to update an index is to decode  the  string,
  195. turn it into a number (routines supplied) then write it into the index file  in
  196. the  proper sequence.  The write_MAGE_record function does this for you.   And,
  197. from it, you can easily see how to do it yourself.
  198.  
  199. BRUTE  FORCE programming provides both the programmer and the computer  a  rare
  200. opportunity  to run flat out.  You don't spend a lot of time reasoning;  that's
  201. not what a computer does well, and reasoning introduces the opportunity to err.
  202.  
  203. Just target 10 bytes, gotten off disk or in ram, compare one or more of then to
  204. search values, repeat if not equal and not end of file.  THAT's what a computer
  205. does:  many FAST repetitions of some MINDLESS operation.
  206.  
  207. BRUTE FORCE, when well-directed, often results in the lowest overhead to do the
  208. job.   DATAMAGE  indexes  are just ten bytes per record,  and  can  cover  five
  209. fields; any/all of which can be unique or cross.
  210.  
  211. I  have often seen data "sets" (consisting on one or more files) in  which  the
  212. indexes  took  up  FAR  more disk space than the  data.   And  the  PROGRAMMING
  213. overhead  often  equaled/surpassed  the actual procedure  of  the  program  and
  214. entailed linking in object files for which I had no code or using code I didn't
  215. understand and couldn't have fixed if my life depended on it.  And, for what?
  216.  
  217. GETTING STARTED
  218.  
  219. In  the first couple screens of the MAGEISAM file the structures: fi  (defining
  220. DATAMAGE files) and finfo (defining fields within DATAMAGE files) are  defined.
  221. Copy these definitions to a piece of paper, then load the MAGEISAM.C file  into
  222. your  compiler.  Search for open_file.  Read the function, while  referring  to
  223. the  paper.  Dig it.  All the information on the loaded file is there, but  YOU
  224. will have to write the if statements to check it, and your understanding of the
  225. ISAM depends on "C-ing" these structures.
  226.  
  227. Once you "C" the open_file function the rest should become crystal clear.
  228.  
  229. The open_file function uses two of it's own FILE *s.  Such is not the case with
  230. the majority of ISAM functions.  In any environment that has up to eight  files
  231. open,  requiring the use of three FILE *s each, there's going to be a  shortage
  232. of IOCBs.  And, it's FASTER to test a file to see if it's open than to (attempt
  233. to) open it.  LOTS faster.
  234.  
  235. So,  then, HOW to test a file for open status?  LOTS of ways to do  that,  too,
  236. Many of which involve linking in and calling yet another function.  Got lots of
  237. THEM,  now.   I decided to set the file pointers in the fi structures  to  NULL
  238. during the load, then set them to NULL every time I closed them.  That's  EVERY
  239. TIME, hear?  The first time you don't, you'll be SORRY!
  240.  
  241. The  ISAM functions test the files, then open/close them if they  were  closed.
  242. If you don't set the FILE * to NULL after closing a file the next ISAM function
  243. you call on that file will "think" it's open.  NOT good.  Not to mention trying
  244. to close it, when it's not open.
  245.  
  246. A "cheapie" way around this is to use your own FILE *s.  NOT recommended.   Use
  247. mine.  Like I said, they're in short supply.  Let's say you have the main  file
  248. open and you call write_MAGE_rcd.  Stipulate further that there are no  "holes"
  249. in  the file, and a record is ADDED.  But, it was added "to" the FILE * in  the
  250. fi structure, which was closed.  YOUR file pointer doesn't "know" it's there.
  251.  
  252. What  will actually happen is dependent on your DOS version,  your  controller,
  253. etc,  etc.  It's a chance you DON'T need to take.  I have seen it  corrupt  the
  254. fat, (yeah, I make mistakes, too) and maybe it could do worse?
  255.  
  256. THE files_loaded VARIABLE
  257.  
  258. Every  time you load a file you MUST increment files_loaded.  And decrement  it
  259. when  you close it.  It's defined in the first screen of code.  If you wish  to
  260. add this to the open_file function, by all means.  But I sometimes read it  off
  261. disk, then use it as comparitor for a for loop when loading files.
  262.  
  263. If  the files_loaded BYTE is set to a value not equalling the number  of  files
  264. open,  expect trouble.  The files are opened/closed IN ORDER.  You  COULD  open
  265. file #8 first, but WHY?  I never have, so I don't know if it will work.
  266.  
  267. COMPILING
  268.  
  269. The ISAM is contained in a module of code.  Most all of it's functions are FAR,
  270. so that they can be called from other modules.  This means you will need to use
  271. the medium memory module when compiling.  NO, huge won't work.
  272.  
  273. The  ISAM  calls many of it's own functions.  These functions are in  the  same
  274. module  as the calling function, but their definition requires them to  be  far
  275. calls.  Far calls take longer than near calls, and occupy more code space.
  276.  
  277. To rectify the catche-22 above, the linker has a /F option.  This converts  all
  278. far calls to functions that occur in the same module to near calls.  Saves time
  279. and memory.  To use it, type /F after link/qlink.
  280.  
  281. WRAP-UP
  282.  
  283. Yeah,  I could have compiled it all to object files and simply made a  list  of
  284. functions,  their parameters and returns.  I always like to be different.   YOU
  285. may  have to do a little work, but you will actually understand the ISAM  after
  286. you do.  You can even change it, if you DARE.
  287.  
  288. It's  true  that only a real programmer can understand the code.   And,  in  my
  289. opinion,  just  as well.  If you can't read and understand the code  you've  no
  290. business writing this kind of program in C.
  291.  
  292. If  you think you might, but avoid dis-appointment by not playing -  you  LOSE.
  293.  
  294. If you're just plain too lazy to read the code and, thereby, understand it  and
  295. be,  therefore,  able to modify it - you LOSE, too.  But there  are  PLENTY  of
  296. high-tech, object-file (and even tsr) ISAMs to fill your "need."  And, all  you
  297. have to do is to link them in, call them like THIS, and they return like  THAT.
  298. You won't be able to access their files with DATAMAGE, though.
  299.  
  300. It's fine, until you need to "call" them a way they don't call, or get a return
  301. they  don't return.  If you are satisfied with limiting your programs, in  both
  302. scope and performance, to their capabilities then your standards are lower than
  303. mine.  I like to take PRIDE in MY work.