BTREE.LST 120 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406340734083409341034113412341334143415341634173418341934203421342234233424342534263427342834293430343134323433343434353436343734383439344034413442344334443445344634473448344934503451345234533454345534563457345834593460346134623463346434653466346734683469347034713472347334743475347634773478347934803481348234833484348534863487348834893490349134923493349434953496349734983499350035013502350335043505350635073508350935103511351235133514351535163517351835193520352135223523352435253526352735283529353035313532353335343535353635373538353935403541354235433544354535463547354835493550355135523553355435553556355735583559356035613562356335643565356635673568356935703571357235733574357535763577357835793580358135823583358435853586358735883589359035913592359335943595359635973598359936003601360236033604360536063607360836093610361136123613361436153616361736183619362036213622362336243625362636273628362936303631363236333634363536363637363836393640364136423643364436453646364736483649365036513652365336543655
  1. Listing:
  2. 1 (*# call(o_a_size=>off) *)
  3. 2 (*# call(o_a_copy=>off) *)
  4. 3 (*# call(near_call=>on) *)
  5. 4 IMPLEMENTATION MODULE Btree;
  6. 5 (*
  7. 6 Copyright (C) 1988..1991 Jensen & Partners International
  8. 7 *)
  9. 8
  10. 9
  11. 10 IMPORT CoreMem, FIOx, Lib, Str;
  12. 11 FROM SYSTEM IMPORT Seg, Ofs, ADR;
  13. 12 (*%T _mthread *)
  14. 13 IMPORT Process;
  15. 14 (*%E *)
  16. 15
  17. 16
  18. 17 CONST
  19. 18 (* ----------------------------------------------------------- *)
  20. 19 (* For v3.0, the embedded version number has NOT been changed. *)
  21. 20 (* See BTREE.DOC for details on compatability issues. *)
  22. 21 (* ----------------------------------------------------------- *)
  23. 22 ThisVersion = 200; (* See Open() procedure for testing *)
  24. 23 Nil = MAX(LONGCARD);
  25. ***** ^ undeclared identifier
  26. ***** ^ undeclared identifier
  27. 24 SectorSize = 512;
  28. 25 PageSize = SectorSize*2;
  29. ***** ^ not supported yet
  30. 26 GuardV1 = 123456789;
  31. 27 GuardV2 = 987654321;
  32. 28 FileDataWrSize = 32;
  33. 29 IndexDataWrSize = 32;
  34. 30
  35. 31
  36. 32 TYPE
  37. 33 LockType = (Implicit,Explicit,AllImplicit,AllLocks);
  38. 34 LockRec = RECORD
  39. 35 Position : LONGCARD;
  40. ***** ^ undeclared identifier
  41. 36 ICnt,ECnt : SHORTCARD;
  42. 37 In : IHandle;
  43. ***** ^ undeclared identifier
  44. 38 END;
  45. ***** ^ not supported yet
  46. 39 LocksArray = ARRAY [0..LockQSize-1] OF LockRec;
  47. ***** ^ undeclared identifier
  48. ***** ^ not supported yet
  49. ***** ^ not supported yet
  50. 40 FileType = (IndexSlot,DataSlot,FreeSlot);
  51. 41 KeyType = ARRAY [1..MaxKeySize] OF BYTE;
  52. ***** ^ undeclared identifier
  53. ***** ^ undeclared identifier
  54. 42 PageRefRec = RECORD
  55. 43 Page : LONGCARD;
  56. ***** ^ undeclared identifier
  57. 44 Rec : CARDINAL;
  58. 45 Cnt : CARDINAL;
  59. 46 END;
  60. ***** ^ not supported yet
  61. 47 PageRef = RECORD
  62. 48 Height : CARDINAL;
  63. 49 Refs : ARRAY [1..8191] OF PageRefRec; (* last *)
  64. ***** ^ not supported yet
  65. ***** ^ not supported yet
  66. 50 END;
  67. ***** ^ not supported yet
  68. 51 PageRefPtr = POINTER TO PageRef;
  69. ***** ^ not supported yet
  70. 52 (* *************************************************************************
  71. 53 In the following two records (IndexData and IndexFile), special
  72. 54 considerations are required for some of the fields...
  73. 55 (*I*) Denotes fields which must be checked against the contents of
  74. 56 the file when the file is opened.
  75. 57 (*V*) Denotes fields that reflect the current status of the file,
  76. 58 and thus must be read after the file is locked and written
  77. 59 before the file is unlocked.
  78. 60 (*F*) Denotes fields which, if changed by a process other than the
  79. 61 current one, require that the current process flush its
  80. 62 buffers.
  81. 63 ************************************************************************* *)
  82. 64 IndexDataWr = RECORD
  83. 65 CASE : BOOLEAN OF
  84. ***** ^ not supported yet
  85. ***** ^ 'POINTER' expected
  86. 66 FALSE : RecordCnt : LONGCARD; (*V*)
  87. 67 CASE Ft : FileType OF (*I*)
  88. 68 DataSlot : RecordSize : CARDINAL; (*I*)
  89. 69 | IndexSlot : WriteCnt, (*F*)
  90. 70 TopPage : LONGCARD; (*V*)
  91. 71 Depth, (*V*)
  92. 72 KeySize, (*I*)
  93. 73 N2, (*I*)
  94. 74 N22 : CARDINAL; (*I*)
  95. 75 DupKey : BOOLEAN; (*I*)
  96. 76 END;
  97. 77 | TRUE : FILL : ARRAY[1..IndexDataWrSize] OF BYTE;
  98. 78 END;
  99. 79 END;
  100. 80 IndexFileWr = RECORD
  101. 81 CASE : BOOLEAN OF
  102. 82 FALSE : HeaderSize : CARDINAL; (*1*)(*I*)
  103. 83 FileSize : LONGCARD; (*2*)(*V*)
  104. 84 Version : CARDINAL; (*I*)
  105. 85 FreeList : LONGCARD; (*V*)
  106. 86 IndexCount : CARDINAL; (*I*)
  107. 87 Mode : AccessMode; (*I*)
  108. 88 PageSz, (*I*)
  109. 89 MaxKeySz : CARDINAL; (*I*)
  110. 90 | TRUE : FILL : ARRAY[1..FileDataWrSize] OF BYTE;
  111. 91 END;
  112. 92 END;
  113. 93 IndexData = RECORD
  114. 94 LastDataRef: LONGCARD;
  115. 95 NextIndx : IHandle;
  116. 96 LastErr : Errors;
  117. 97 ErrorNest : CARDINAL;
  118. 98 ihLock : LockRec;
  119. 99 CASE Ft : FileType OF
  120. 100 | DataSlot : Sync : BOOLEAN;
  121. 101 bufSize : CARDINAL;
  122. 102 bufPtr : ADDRESS;
  123. 103 | IndexSlot : OldWriteCnt : LONGCARD;
  124. 104 DataPtr : IHandle;
  125. 105 PageRefs : PageRefPtr;
  126. 106 PageLevel : CARDINAL;
  127. 107 CompFct : CompareFunction;
  128. 108 KeyFct : KeyFunction;
  129. 109 LastKeyOK : BOOLEAN;
  130. 110 LastKey : KeyType;
  131. 111 LastKeyRef : LONGCARD;
  132. 112 END;
  133. 113 iwr : POINTER TO IndexDataWr;
  134. 114 END;
  135. 115 IndexFile = RECORD
  136. 116 G1 : LONGCARD;
  137. 117 ReadOnly,
  138. 118 Buffered,
  139. 119 WriteThru : BOOLEAN; (* not fully implemented *)
  140. 120 Locks : LocksArray;
  141. 121 fhLock : LockRec;
  142. 122 FHandle : CARDINAL;
  143. 123 fwr : POINTER TO IndexFileWr;
  144. 124 G2 : LONGCARD; (* 2nd to last *)
  145. 125 Id : ARRAY[0..346] OF IndexData; (* last *)
  146. 126 END;
  147. 127 IndexItem = RECORD
  148. 128 IP : LONGCARD;
  149. 129 DP : LONGCARD;
  150. 130 Key : KeyType;
  151. 131 END;
  152. 132 TPage = RECORD
  153. 133 CASE : BOOLEAN OF
  154. 134 FALSE : ICount : CARDINAL;
  155. 135 IItem : IndexItem;
  156. 136 | TRUE : FILL : ARRAY [1..PageSize] OF BYTE;
  157. 137 END;
  158. 138 END;
  159. 139 (*# save *)
  160. 140 (*# data(near_ptr=>off) *)
  161. 141 TPagePointer = POINTER TO TPage;
  162. 142 (*# restore *)
  163. 143 xTPage = RECORD
  164. 144 CASE : BOOLEAN OF
  165. 145 FALSE : ICount : CARDINAL;
  166. 146 IItem : IndexItem;
  167. 147 | TRUE : FILL : ARRAY [1..PageSize] OF BYTE;
  168. 148 END;
  169. 149 extra : IndexItem;
  170. 150 END;
  171. 151 BufferPages = RECORD
  172. 152 iH : IHandle;
  173. 153 Wr : BOOLEAN;
  174. 154 Page : LONGCARD;
  175. 155 Buf : TPagePointer;
  176. 156 END;
  177. 157 FindMode = (Fnd,Ins,Src,Idx,Rec);
  178. 158 (* Fnd = first exact key match
  179. 159 Ins = place to insert into
  180. 160 Src = first exact key match or greater
  181. 161 Idx = exact entry (i.e. DataPos also)
  182. 162 Rec = exact entry (i.e. DataPos also) or greater *)
  183. 163 WalkMode = (Forward,Backward);
  184. 164 ErrorStrs = ARRAY Errors,[0..31] OF CHAR;
  185. 165
  186. 166
  187. 167 CONST
  188. 168 IndexDataSize = SIZE(IndexData);
  189. 169 IndexFileSize = VSIZE(IndexFile.G2)+IndexDataSize;
  190. 170 ErrorStr = ErrorStrs('No Error',
  191. 171 '#: Bad Open',
  192. 172 'Bad # Slot',
  193. 173 'Not a FHandle',
  194. 174 'Not an IHandle',
  195. 175 'Not a Data File',
  196. 176 'Not an Index File',
  197. 177 '#: Bad Index',
  198. 178 '#: Wrong Record Size',
  199. 179 'Key Too Large',
  200. 180 'Duplicated Key',
  201. 181 '#: Access Mode Not Supported',
  202. 182 'Error During Read',
  203. 183 'Error During Write',
  204. 184 "Couldn't Acquire Lock",
  205. 185 'Item Must Already Be Locked',
  206. 186 'File I/O Error',
  207. 187 'Lock Table Overflow',
  208. 188 'Unknown Error');
  209. 189 FileDataCheck = FileDataWrSize=SIZE(IndexFileWr);
  210. 190 IndexDataCheck = IndexDataWrSize=SIZE(IndexDataWr);
  211. 191 (*%F FileDataCheck *)
  212. 192 WARNING - FileDataWrSize must be equal to SIZE(FileDataWr);
  213. 193 (*%E *)
  214. 194 (*%F IndexDataCheck *)
  215. 195 WARNING - IndexDataWrSize must be equal to SIZE(IndexDataWr);
  216. 196 (*%E *)
  217. 197
  218. 198
  219. 199 MODULE inline;
  220. 200
  221. 201 EXPORT MemMove, MemFastMove, AddAddr, IncAddr, DecAddr;
  222. 202
  223. 203 TYPE
  224. 204 A2 = ARRAY[0..1] OF SHORTCARD;
  225. 205 A3 = ARRAY[0..2] OF SHORTCARD;
  226. 206 A6 = ARRAY[0..5] OF SHORTCARD;
  227. 207 A8 = ARRAY[0..7] OF SHORTCARD;
  228. 208 A19 = ARRAY[0..18] OF SHORTCARD;
  229. 209 A21 = ARRAY[0..20] OF SHORTCARD;
  230. 210
  231. 211 (*%T _fptr *)
  232. 212
  233. 213 (*# save *)
  234. 214 (*# call(inline=>on) *)
  235. 215 (*# call(reg_param=>(si,ax,di,es,cx),reg_saved=>(ax,bx,dx,ds,es,st1,st2,st3,st4,st5,st6)) *)
  236. 216 PROCEDURE MemMove(s,r: ADDRESS; c: CARDINAL)=A21(0E3H,013H,(* jcxz $1 *)
  237. 217 09CH, (* pushf *)
  238. 218 01EH, (* push ds *)
  239. 219 08EH,0D8H,(* mov ds,ax *)
  240. 220 03BH,0FEH,(* cmp di,si *)
  241. 221 072H,007H,(* jb $0 *)
  242. 222 003H,0F1H,(* add si,cx *)
  243. 223 003H,0F9H,(* add di,cx *)
  244. 224 04EH, (* dec si *)
  245. 225 04FH, (* dec di *)
  246. 226 0FDH, (* std *)
  247. 227 (* $0: *)
  248. 228 0F3H,0A4H,(* rep ;movsb *)
  249. 229 01FH, (* pop ds *)
  250. 230 09DH); (* popf *)
  251. 231 (* $1: *)
  252. 232 (*# restore *)
  253. 233
  254. 234 (*# save *)
  255. 235 (*# call(inline=>on) *)
  256. 236 (*# call(reg_param=>(si,ax,di,es,cx),reg_saved=>(ax,bx,dx,ds,es,st1,st2,st3,st4,st5,st6)) *)
  257. 237 PROCEDURE MemFastMove(s,r: ADDRESS; c: CARDINAL)=A8(0E3H,006H,(* jcxz $0 *)
  258. 238 01EH, (* push ds *)
  259. 239 08EH,0D8H,(* mov ds,ax *)
  260. 240 0F3H,0A4H,(* rep ;movsb *)
  261. 241 01FH); (* pop ds *)
  262. 242 (* $0: *)
  263. 243 (*# restore *)
  264. 244
  265. 245 (*# save *)
  266. 246 (*# call(inline=>on) *)
  267. 247 (*# call(reg_param=>(ax,dx,cx),reg_saved=>(bx,cx,dx,si,di,ds,es,st1,st2,st3,st4,st5,st6)) *)
  268. 248 PROCEDURE AddAddr(A: ADDRESS; I: CARDINAL): ADDRESS=A2(003H,0C1H);(*add ax,cx*)
  269. 249 (*# restore *)
  270. 250
  271. 251 (*# save *)
  272. 252 (*# call(inline=>on) *)
  273. 253 (*# call(reg_param=>(bx,es,ax),reg_saved=>(ax,bx,cx,dx,si,di,ds,es,st1,st2,st3,st4,st5,st6)) *)
  274. 254 PROCEDURE IncAddr(VAR a: ADDRESS; i: CARDINAL)=A3(026H,001H,007H); (* add es:[bx],cx *)
  275. 255 (*# restore *)
  276. 256
  277. 257 (*# save *)
  278. 258 (*# call(inline=>on) *)
  279. 259 (*# call(reg_param=>(bx,es,ax),reg_saved=>(ax,bx,cx,dx,si,di,ds,es,st1,st2,st3,st4,st5,st6)) *)
  280. 260 PROCEDURE DecAddr(VAR a: ADDRESS; i: CARDINAL)=A3(026H,029H,007H); (* sub es:[bx],cx *)
  281. 261 (*# restore *)
  282. 262
  283. 263 (*%E *)
  284. 264
  285. 265 (*%F _fptr *)
  286. 266
  287. 267 (*# save *)
  288. 268 (*# call(inline=>on) *)
  289. 269 (*# call(reg_param=>(si,di,cx),reg_saved=>(ax,bx,dx,ds,st1,st2,st3,st4,st5,st6)) *)
  290. 270 PROCEDURE MemMove(s,r: ADDRESS; c: CARDINAL)=A19(0E3H,011H,(* jcxz $1 *)
  291. 271 09CH, (* pushf *)
  292. 272 01EH, (* push ds *)
  293. 273 007H, (* pop es *)
  294. 274 03BH,0FEH,(* cmp di,si *)
  295. 275 072H,007H,(* jb $0 *)
  296. 276 003H,0F1H,(* add si,cx *)
  297. 277 003H,0F9H,(* add di,cx *)
  298. 278 04EH, (* dec si *)
  299. 279 04FH, (* dec di *)
  300. 280 0FDH, (* std *)
  301. 281 (* $0: *)
  302. 282 0F3H,0A4H,(* rep; movsb*)
  303. 283 09DH); (* popf *)
  304. 284 (* $1: *)
  305. 285 (*# restore *)
  306. 286
  307. 287 (*# save *)
  308. 288 (*# call(inline=>on) *)
  309. 289 (*# call(reg_param=>(si,di,cx),reg_saved=>(ax,bx,dx,ds,st1,st2,st3,st4,st5,st6)) *)
  310. 290 PROCEDURE MemFastMove(s,r: ADDRESS; c: CARDINAL)=A6(0E3H,004H, (* jcxz $0 *)
  311. 291 01EH, (* push ds *)
  312. 292 007H, (* pop es *)
  313. 293 0F3H,0A4H); (* rep; movsb*)
  314. 294 (* $0: *)
  315. 295 (*# restore *)
  316. 296
  317. 297 (*# save *)
  318. 298 (*# call(inline=>on) *)
  319. 299 (*# call(reg_param=>(ax,cx),reg_saved=>(bx,cx,dx,si,di,ds,es,st1,st2,st3,st4,st5,st6)) *)
  320. 300 PROCEDURE AddAddr(A: ADDRESS; I: CARDINAL): ADDRESS=A2(003H,0C1H);(*add ax,cx*)
  321. 301 (*# restore *)
  322. 302
  323. 303 (*# save *)
  324. 304 (*# call(inline=>on) *)
  325. 305 (*# call(reg_param=>(bx,ax),reg_saved=>(ax,bx,cx,dx,si,di,ds,es,st1,st2,st3,st4,st5,st6)) *)
  326. 306 PROCEDURE IncAddr(VAR a: ADDRESS; i: CARDINAL)=A2(001H,007H); (* add [bx],cx *)
  327. 307 (*# restore *)
  328. 308
  329. 309 (*# save *)
  330. 310 (*# call(inline=>on) *)
  331. 311 (*# call(reg_param=>(bx,ax),reg_saved=>(ax,bx,cx,dx,si,di,ds,es,st1,st2,st3,st4,st5,st6)) *)
  332. 312 PROCEDURE DecAddr(VAR a: ADDRESS; i: CARDINAL)=A2(029H,007H); (* sub [bx],cx *)
  333. 313 (*# restore *)
  334. 314
  335. 315 (*%E *)
  336. 316
  337. 317 END inline;
  338. 318
  339. 319
  340. 320 CONST
  341. 321 OutOfMemory = 80;
  342. 322 ioError = 81;
  343. 323 DiskFull = 82;
  344. 324
  345. 325
  346. 326 (*# save *)
  347. 327 (*# call(reg_saved=>(ax,bx,cx,dx,si,di,ds,es,st1,st2,st3,st4,st5,st6)) *)
  348. 328 PROCEDURE Die(error: BOOLEAN; code: CARDINAL);
  349. 329 VAR s : ARRAY [0..79] OF CHAR;
  350. 330 b : BOOLEAN;
  351. 331 BEGIN
  352. 332 IF error THEN
  353. 333 Str.CardToStr(LONGCARD(code),s,10,b);
  354. 334 Str.Prepend(s,CHR(13)+CHR(10)+'BTREE: Fatal error, code = ');
  355. 335 Lib.FatalError(s);
  356. 336 END;
  357. 337 END Die;
  358. 338 (*# restore *)
  359. 339
  360. 340
  361. 341 PROCEDURE AllocMem(VAR a: ADDRESS; s: CARDINAL);
  362. 342 BEGIN
  363. 343 a := CoreMem.calloc(1,s);
  364. 344 END AllocMem;
  365. 345
  366. 346
  367. 347 PROCEDURE FreeMem(VAR a: ADDRESS);
  368. 348 BEGIN
  369. 349 IF a#NIL THEN
  370. 350 CoreMem.free(a);
  371. 351 a := NIL;
  372. 352 END;
  373. 353 END FreeMem;
  374. 354
  375. 355
  376. 356 PROCEDURE AdjustBuffer(D: IHandle; rs: CARDINAL);
  377. 357 VAR
  378. 358 sz : CARDINAL;
  379. 359 BEGIN
  380. 360 WITH D.ID^ DO
  381. 361 WITH Id[D.In] DO
  382. 362 IF iwr^.RecordSize=0 THEN
  383. 363 sz := AdjustBlock(rs);
  384. 364 IF bufSize<sz THEN
  385. 365 FreeMem(bufPtr);
  386. 366 AllocMem(bufPtr,sz);
  387. 367 Die(bufPtr=NIL,OutOfMemory);
  388. 368 bufSize := sz;
  389. 369 END;
  390. 370 END;
  391. 371 END;
  392. 372 END;
  393. 373 END AdjustBuffer;
  394. 374
  395. 375
  396. 376 PROCEDURE IsFHandle(fH: FHandle): BOOLEAN;
  397. 377 BEGIN
  398. 378 RETURN (fH#NIL) AND
  399. 379 (fH^.G1=GuardV1) AND
  400. 380 (fH^.G2=GuardV2);
  401. 381 END IsFHandle;
  402. 382
  403. 383
  404. 384 PROCEDURE IsIHandle(iH: IHandle): BOOLEAN;
  405. 385 BEGIN
  406. 386 RETURN IsFHandle(iH.ID) AND (iH.In<=iH.ID^.fwr^.IndexCount) AND
  407. 387 (iH.ID^.Id[iH.In].Ft#FreeSlot) AND
  408. 388 (iH.ID^.Id[iH.In].iwr^.Ft#FreeSlot);
  409. 389 END IsIHandle;
  410. 390
  411. 391
  412. 392 PROCEDURE IsData(iH: IHandle): BOOLEAN;
  413. 393 BEGIN
  414. 394 RETURN IsIHandle(iH) AND
  415. 395 (iH.ID^.Id[iH.In].Ft=DataSlot) AND
  416. 396 (iH.ID^.Id[iH.In].iwr^.Ft=DataSlot);
  417. 397 END IsData;
  418. 398
  419. 399
  420. 400 PROCEDURE IsIndex(iH: IHandle): BOOLEAN;
  421. 401 BEGIN
  422. 402 RETURN IsIHandle(iH) AND
  423. 403 (iH.ID^.Id[iH.In].Ft=IndexSlot) AND
  424. 404 (iH.ID^.Id[iH.In].iwr^.Ft=IndexSlot);
  425. 405 END IsIndex;
  426. 406
  427. 407
  428. 408 (*# save *)
  429. 409 (*# call(o_a_size=>on) *)
  430. 410 PROCEDURE Error(err: Errors; str: ARRAY OF CHAR);
  431. 411 VAR
  432. 412 st : ARRAY [0..100] OF CHAR;
  433. 413 i : CARDINAL;
  434. 414 BEGIN
  435. 415 IF err#OK THEN
  436. 416 st := CHR(13)+CHR(10);
  437. 417 Str.Append(st,ErrorStr[err]);
  438. 418 i := Str.Pos(st,'#');
  439. 419 IF i#MAX(CARDINAL) THEN
  440. 420 Str.Delete(st,i,1);
  441. 421 Str.Insert(st,str,i);
  442. 422 ELSIF Str.Length(str)#0 THEN
  443. 423 Str.Append(st,' (');
  444. 424 Str.Append(st,str);
  445. 425 Str.Append(st,')');
  446. 426 END;
  447. 427 ErrorHandler(err,st);
  448. 428 END;
  449. 429 END Error;
  450. 430 (*# restore *)
  451. 431
  452. 432
  453. 433 PROCEDURE ClearErr(iH: IHandle);
  454. 434 BEGIN
  455. 435 IF IsIHandle(iH) THEN
  456. 436 iH.ID^.Id[iH.In].LastErr := OK;
  457. 437 END;
  458. 438 END ClearErr;
  459. 439
  460. 440
  461. 441 PROCEDURE ClearFErr(fH: FHandle);
  462. 442 VAR
  463. 443 iH : IHandle;
  464. 444 BEGIN
  465. 445 iH.ID := fH;
  466. 446 iH.In := 0;
  467. 447 ClearErr(iH);
  468. 448 END ClearFErr;
  469. 449
  470. 450
  471. 451 PROCEDURE SetErr(iH: IHandle; err: Errors);
  472. 452 BEGIN
  473. 453 IF IsIHandle(iH) AND (iH.ID^.Id[iH.In].LastErr=OK) THEN
  474. 454 iH.ID^.Id[iH.In].LastErr := err;
  475. 455 END;
  476. 456 END SetErr;
  477. 457
  478. 458
  479. 459 (*# save *)
  480. 460 (*# call(o_a_size=>on) *)
  481. 461 PROCEDURE CallErr(iH: IHandle; err: Errors; str: ARRAY OF CHAR);
  482. 462 BEGIN
  483. 463 SetErr(iH,err);
  484. 464 Error(err,str);
  485. 465 END CallErr;
  486. 466 (*# restore *)
  487. 467
  488. 468
  489. 469 PROCEDURE SetFErr(fH: FHandle; err: Errors);
  490. 470 VAR
  491. 471 iH : IHandle;
  492. 472 BEGIN
  493. 473 iH.ID := fH;
  494. 474 iH.In := 0;
  495. 475 SetErr(iH,err);
  496. 476 END SetFErr;
  497. 477
  498. 478
  499. 479 (*# save *)
  500. 480 (*# call(o_a_size=>on) *)
  501. 481 PROCEDURE CallFErr(fH: FHandle; err: Errors; str: ARRAY OF CHAR);
  502. 482 VAR
  503. 483 iH : IHandle;
  504. 484 BEGIN
  505. 485 iH.ID := fH;
  506. 486 iH.In := 0;
  507. 487 CallErr(iH,err,str);
  508. 488 END CallFErr;
  509. 489 (*# restore *)
  510. 490
  511. 491
  512. 492 (*# save *)
  513. 493 (*# call(o_a_size=>on) *)
  514. 494 PROCEDURE IOerr(iH: IHandle; str: ARRAY OF CHAR): BOOLEAN;
  515. 495 VAR
  516. 496 i : CARDINAL;
  517. 497 tmp : ARRAY[0..80] OF CHAR;
  518. 498 ok : BOOLEAN;
  519. 499 BEGIN
  520. 500 i := FIOx.Error();
  521. 501 IF i#0 THEN
  522. 502 Str.CardToStr(VAL(LONGCARD,i),tmp,10,ok);
  523. 503 Str.Insert(tmp,'#',0);
  524. 504 IF Str.Length(str) # 0 THEN
  525. 505 Str.Append(tmp,' ');
  526. 506 Str.Append(tmp,str);
  527. 507 END;
  528. 508 CallErr(IHandle(iH),FileError,tmp);
  529. 509 RETURN TRUE;
  530. 510 ELSE
  531. 511 RETURN FALSE;
  532. 512 END;
  533. 513 END IOerr;
  534. 514 (*# restore *)
  535. 515
  536. 516
  537. 517 (*# save *)
  538. 518 (*# call(o_a_size=>on) *)
  539. 519 PROCEDURE IOFerr(fH: FHandle; str: ARRAY OF CHAR): BOOLEAN;
  540. 520 VAR
  541. 521 iH: IHandle;
  542. 522 BEGIN
  543. 523 iH.ID := fH;
  544. 524 iH.In := 0;
  545. 525 RETURN IOerr(iH,str);
  546. 526 END IOFerr;
  547. 527 (*# restore *)
  548. 528
  549. 529
  550. 530 (*# save *)
  551. 531 (*# call(o_a_size=>on) *)
  552. 532 PROCEDURE IOabort(str: ARRAY OF CHAR);
  553. 533 BEGIN
  554. 534 Die(IOerr(Null,str),ioError);
  555. 535 END IOabort;
  556. 536 (*# restore *)
  557. 537
  558. 538
  559. 539 PROCEDURE ReadRec(D: IHandle; p: LONGCARD; VAR d: ARRAY OF BYTE);
  560. 540 VAR
  561. 541 l : CARDINAL;
  562. 542 BEGIN
  563. 543 WITH D.ID^ DO
  564. 544 WITH Id[D.In] DO
  565. 545 IF iwr^.RecordSize=0 THEN
  566. 546 FIOx.Seek(FHandle,p-2);
  567. 547 IOabort('ReadRec');
  568. 548 FIOx.Read(FHandle,l,SIZE(l));
  569. 549 IOabort('ReadRec');
  570. 550 IF fwr^.Mode=Compress THEN
  571. 551 AdjustBuffer(D,l);
  572. 552 FIOx.Read(FHandle,bufPtr^,l);
  573. 553 IOabort('ReadRec');
  574. 554 Unpacker(l,bufPtr,ADR(d));
  575. 555 ELSE
  576. 556 FIOx.Read(FHandle,d,l);
  577. 557 IOabort('ReadRec');
  578. 558 END;
  579. 559 ELSE
  580. 560 FIOx.Seek(FHandle,p);
  581. 561 IOabort('ReadRec');
  582. 562 FIOx.Read(FHandle,d,iwr^.RecordSize);
  583. 563 END;
  584. 564 END;
  585. 565 END;
  586. 566 END ReadRec;
  587. 567
  588. 568
  589. 569 PROCEDURE LoadRec(D: IHandle; p: LONGCARD; VAR bp: LONGCARD; VAR bs: CARDINAL);
  590. 570 VAR
  591. 571 a : ADDRESS;
  592. 572 BEGIN
  593. 573 WITH D.ID^ DO
  594. 574 WITH Id[D.In] DO
  595. 575 IF iwr^.RecordSize=0 THEN
  596. 576 bp := p-SIZE(CARDINAL);
  597. 577 FIOx.Seek(FHandle,bp);
  598. 578 IOabort('LoadRec');
  599. 579 FIOx.Read(FHandle,bs,SIZE(bs));
  600. 580 IOabort('LoadRec');
  601. 581 IF fwr^.Mode=Compress THEN
  602. 582 AllocMem(a,bs);
  603. 583 Die(a=NIL,OutOfMemory);
  604. 584 FIOx.Read(FHandle,a^,bs);
  605. 585 IOabort('LoadRec');
  606. 586 AdjustBuffer(D,UnpackedSize(bs,a));
  607. 587 Unpacker(bs,a,bufPtr);
  608. 588 FreeMem(a);
  609. 589 ELSE
  610. 590 AdjustBuffer(D,bs);
  611. 591 FIOx.Read(FHandle,bufPtr^,bs);
  612. 592 IOabort('LoadRec');
  613. 593 END;
  614. 594 ELSE
  615. 595 bp := p;
  616. 596 bs := iwr^.RecordSize;
  617. 597 FIOx.Seek(FHandle,p);
  618. 598 IOabort('LoadRec');
  619. 599 FIOx.Read(FHandle,bufPtr^,bs);
  620. 600 END;
  621. 601 END;
  622. 602 END;
  623. 603 END LoadRec;
  624. 604
  625. 605
  626. 606 MODULE LRU;
  627. 607 (* This local module encapsulates the LRU buffer. *)
  628. 608
  629. 609 IMPORT Nil, IHandle, BufferPages, TPage, CallErr, Null, UnknownError,
  630. 610 AllocMem, MemMove, IOabort, Die, OutOfMemory, DiskFull, FIOx, CoreMem;
  631. 611 (*%T _mthread *)
  632. 612 IMPORT Process;
  633. 613 (*%E *)
  634. 614 EXPORT ReadPage, WritePage, ClearPage, ClearBuffers, SaveBuffers;
  635. 615
  636. 616 CONST
  637. 617 LRUCount = 32;
  638. 618
  639. 619 VAR
  640. 620 LruPages : ARRAY [1..LRUCount] OF BufferPages;
  641. 621 (*%F _fptr *)
  642. 622 _Buf : TPage;
  643. 623 (*%E *)
  644. 624
  645. 625 PROCEDURE MovePage(i: CARDINAL; discard: BOOLEAN);
  646. 626 VAR
  647. 627 j : CARDINAL;
  648. 628 t : BufferPages;
  649. 629 src,
  650. 630 dest : ADDRESS;
  651. 631 len : CARDINAL;
  652. 632 BEGIN
  653. 633 IF discard THEN
  654. 634 src := ADR(LruPages[1]);
  655. 635 dest := ADR(LruPages[2]);
  656. 636 len := i-1;
  657. 637 j := 1;
  658. 638 ELSIF i=LRUCount THEN
  659. 639 len := 0;
  660. 640 ELSE
  661. 641 src := ADR(LruPages[i+1]);
  662. 642 dest := ADR(LruPages[i]);
  663. 643 len := LRUCount-i;
  664. 644 j := LRUCount;
  665. 645 END;
  666. 646 IF len # 0 THEN
  667. 647 t := LruPages[i];
  668. 648 MemMove(src,dest,len*SIZE(BufferPages));
  669. 649 LruPages[j] := t;
  670. 650 END;
  671. 651 END MovePage;
  672. 652
  673. 653 (*# save *)
  674. 654 (*# check(overflow=>off) *)
  675. 655 PROCEDURE FlushPage(i: CARDINAL);
  676. 656 BEGIN
  677. 657 WITH LruPages[i] DO
  678. 658 IF Wr THEN
  679. 659 FIOx.Seek(iH.ID^.FHandle,Page);
  680. 660 IOabort('FlushPage');
  681. 661 (*%F _fptr *)
  682. 662 _Buf := Buf^;
  683. 663 FIOx.Write(iH.ID^.FHandle,_Buf,SIZE(TPage));
  684. 664 (*%E *)
  685. 665 (*%T _fptr *)
  686. 666 FIOx.Write(iH.ID^.FHandle,Buf^,SIZE(TPage));
  687. 667 (*%E *)
  688. 668 IOabort('FlushPage');
  689. 669 IF iH.ID^.Id[iH.In].OldWriteCnt=iH.ID^.Id[iH.In].iwr^.WriteCnt THEN
  690. 670 INC(iH.ID^.Id[iH.In].iwr^.WriteCnt);
  691. 671 END;
  692. 672 Wr := FALSE;
  693. 673 IF iH.ID^.WriteThru THEN
  694. 674 FIOx.Flush(iH.ID^.FHandle);
  695. 675 END;
  696. 676 END;
  697. 677 END;
  698. 678 END FlushPage;
  699. 679 (*# restore *)
  700. 680
  701. 681 PROCEDURE FindPage(ih: IHandle; page: LONGCARD): BOOLEAN;
  702. 682 VAR
  703. 683 i : CARDINAL;
  704. 684 f : BOOLEAN;
  705. 685 BEGIN
  706. 686 i := LRUCount;
  707. 687 LOOP
  708. 688 WITH LruPages[i] DO
  709. 689 f := (ih=iH) AND (Page=page);
  710. 690 END;
  711. 691 IF f OR (i=1) THEN
  712. 692 EXIT;
  713. 693 END;
  714. 694 DEC(i);
  715. 695 END;
  716. 696 MovePage(i,FALSE);
  717. 697 IF NOT f THEN
  718. 698 FlushPage(LRUCount);
  719. 699 WITH LruPages[LRUCount] DO
  720. 700 iH := ih;
  721. 701 Page := page;
  722. 702 END;
  723. 703 END;
  724. 704 RETURN f;
  725. 705 END FindPage;
  726. 706
  727. 707 PROCEDURE ReadPage(ih: IHandle; page: LONGCARD; VAR TP: TPage);
  728. 708 BEGIN
  729. 709 (*%T _mthread *) Process.Lock(); (*%E *)
  730. 710 WITH LruPages[LRUCount] DO
  731. 711 IF NOT FindPage(ih,page) THEN
  732. 712 FIOx.Seek(ih.ID^.FHandle,page);
  733. 713 IOabort('ReadPage');
  734. 714 (*%F _fptr *)
  735. 715 FIOx.Read(ih.ID^.FHandle,_Buf,SIZE(TPage));
  736. 716 Buf^ := _Buf;
  737. 717 (*%E *)
  738. 718 (*%T _fptr *)
  739. 719 FIOx.Read(ih.ID^.FHandle,Buf^,SIZE(TPage));
  740. 720 (*%E *)
  741. 721 IOabort('ReadPage');
  742. 722 END;
  743. 723 TP := Buf^;
  744. 724 END;
  745. 725 (*%T _mthread *) Process.Unlock(); (*%E *)
  746. 726 END ReadPage;
  747. 727
  748. 728 PROCEDURE WritePage(ih: IHandle; page: LONGCARD; VAR TP: TPage);
  749. 729 VAR
  750. 730 r : CARDINAL;
  751. 731 BEGIN
  752. 732 IF page=Nil THEN
  753. 733 CallErr(Null,UnknownError,'WritePage');
  754. 734 Die(TRUE,DiskFull);
  755. 735 END;
  756. 736 (*%T _mthread *) Process.Lock(); (*%E *)
  757. 737 IF NOT FindPage(ih,page) THEN
  758. 738 (* nothing *)
  759. 739 END;
  760. 740 WITH LruPages[LRUCount] DO
  761. 741 Buf^ := TP;
  762. 742 Wr := TRUE;
  763. 743 IF iH.ID^.WriteThru THEN
  764. 744 FlushPage(LRUCount);
  765. 745 END;
  766. 746 END;
  767. 747 (*%T _mthread *) Process.Unlock(); (*%E *)
  768. 748 END WritePage;
  769. 749
  770. 750 PROCEDURE UnUse(ih: IHandle; page: LONGCARD; wr: BOOLEAN);
  771. 751 VAR
  772. 752 i : CARDINAL;
  773. 753 BEGIN
  774. 754 (*%T _mthread *) Process.Lock(); (*%E *)
  775. 755 i := 1;
  776. 756 WHILE i<=LRUCount DO
  777. 757 WITH LruPages[i] DO
  778. 758 IF (((ih.In=MAX(CARDINAL)) AND (ih.ID=iH.ID)) OR (ih=iH)) AND
  779. 759 ((page=Page) OR (page=Nil)) THEN
  780. 760 IF wr THEN
  781. 761 FlushPage(i);
  782. 762 ELSE
  783. 763 MovePage(i,TRUE);
  784. 764 LruPages[1].Wr := FALSE;
  785. 765 LruPages[1].iH := Null;
  786. 766 LruPages[1].Page := 0;
  787. 767 END;
  788. 768 END;
  789. 769 END;
  790. 770 INC(i);
  791. 771 END;
  792. 772 (*%T _mthread *) Process.Unlock(); (*%E *)
  793. 773 END UnUse;
  794. 774
  795. 775 PROCEDURE ClearPage(ih: IHandle; page: LONGCARD);
  796. 776 BEGIN
  797. 777 UnUse(ih,page,FALSE);
  798. 778 END ClearPage;
  799. 779
  800. 780 PROCEDURE ClearBuffers(ih: IHandle);
  801. 781 BEGIN
  802. 782 UnUse(ih,Nil,FALSE);
  803. 783 END ClearBuffers;
  804. 784
  805. 785 PROCEDURE SaveBuffers(ih: IHandle);
  806. 786 BEGIN
  807. 787 UnUse(ih,Nil,TRUE);
  808. 788 END SaveBuffers;
  809. 789
  810. 790 PROCEDURE Init;
  811. 791 VAR
  812. 792 i : CARDINAL;
  813. 793 BEGIN
  814. 794 FOR i := 1 TO LRUCount DO
  815. 795 LruPages[i] := BufferPages(Null,FALSE,0,FarNIL);
  816. 796 LruPages[i].Buf := CoreMem._fcalloc(1,SIZE(TPage));
  817. 797 Die(LruPages[i].Buf=FarNIL,OutOfMemory);
  818. 798 END;
  819. 799 END Init;
  820. 800
  821. 801 BEGIN
  822. 802 Init;
  823. 803 END LRU;
  824. 804
  825. 805
  826. 806 PROCEDURE ccOneLock(lock: LockRec; type: LockType): BOOLEAN;
  827. 807 BEGIN
  828. 808 WITH lock DO
  829. 809 RETURN ((type=Implicit) AND (ICnt=1) AND (ECnt=0)) OR
  830. 810 ((type=Explicit) AND (ECnt=1) AND (ICnt=0));
  831. 811 END;
  832. 812 END ccOneLock;
  833. 813
  834. 814
  835. 815 PROCEDURE ccLock(dH: IHandle; VAR lock: LockRec; type: LockType): BOOLEAN;
  836. 816 VAR
  837. 817 lck : FIOx.LockRec;
  838. 818 BEGIN
  839. 819 IF dH.ID^.Buffered THEN
  840. 820 RETURN TRUE;
  841. 821 END;
  842. 822 WITH lock DO
  843. 823 IF (type=Implicit) AND (ICnt#MAX(SHORTCARD)) THEN
  844. 824 INC(ICnt);
  845. 825 ELSIF (type=Explicit) AND (ECnt#MAX(SHORTCARD)) THEN
  846. 826 INC(ECnt);
  847. 827 ELSE
  848. 828 CallErr(dH,LockOverflow,'ccLock');
  849. 829 RETURN FALSE;
  850. 830 END;
  851. 831 IF (type=Implicit) AND (In=Null) THEN
  852. 832 In := dH;
  853. 833 END;
  854. 834 lck.pos := lock.Position;
  855. 835 lck.len := 1;
  856. 836 IF ccOneLock(lock,type) AND NOT FIOx.Lock(dH.ID^.FHandle,lck) THEN
  857. 837 IF type=Implicit THEN
  858. 838 DEC(ICnt);
  859. 839 ELSE
  860. 840 DEC(ECnt);
  861. 841 END;
  862. 842 SetErr(dH,Locked);
  863. 843 RETURN FALSE;
  864. 844 ELSE
  865. 845 RETURN TRUE;
  866. 846 END;
  867. 847 END;
  868. 848 END ccLock;
  869. 849
  870. 850
  871. 851 PROCEDURE cLock(dH: IHandle; dLoc: LONGCARD; type: LockType): BOOLEAN;
  872. 852 VAR
  873. 853 idx,
  874. 854 tmp : CARDINAL;
  875. 855 BEGIN
  876. 856 IF dH.ID^.Buffered THEN
  877. 857 RETURN TRUE;
  878. 858 END;
  879. 859 idx := MAX(CARDINAL);
  880. 860 LOOP
  881. 861 FOR tmp := 0 TO LockQSize-1 DO
  882. 862 WITH dH.ID^.Locks[tmp] DO
  883. 863 IF Position=dLoc THEN
  884. 864 idx := tmp;
  885. 865 EXIT;
  886. 866 ELSIF (idx=MAX(CARDINAL)) AND (Position=Nil) THEN
  887. 867 idx := tmp;
  888. 868 END;
  889. 869 END;
  890. 870 END;
  891. 871 IF idx#MAX(CARDINAL) THEN
  892. 872 WITH dH.ID^.Locks[idx] DO
  893. 873 Position := dLoc;
  894. 874 ICnt := 0;
  895. 875 ECnt := 0;
  896. 876 IF type=Implicit THEN
  897. 877 In := dH;
  898. 878 ELSE
  899. 879 In := Null;
  900. 880 END;
  901. 881 END;
  902. 882 END;
  903. 883 EXIT;
  904. 884 END;
  905. 885 IF idx#MAX(CARDINAL) THEN
  906. 886 IF NOT ccLock(dH,dH.ID^.Locks[idx],type) THEN
  907. 887 dH.ID^.Locks[idx].Position := Nil;
  908. 888 RETURN FALSE;
  909. 889 ELSE
  910. 890 RETURN TRUE;
  911. 891 END;
  912. 892 ELSE
  913. 893 CallErr(dH,LockOverflow,'cLock');
  914. 894 RETURN FALSE;
  915. 895 END;
  916. 896 END cLock;
  917. 897
  918. 898
  919. 899 PROCEDURE Lock(F: FHandle; DataLoc: LONGCARD): BOOLEAN;
  920. 900 VAR
  921. 901 dH : IHandle;
  922. 902 BEGIN
  923. 903 dH.ID := F;
  924. 904 dH.In := 0;
  925. 905 ClearErr(dH);
  926. 906 IF NOT IsIHandle(dH) THEN
  927. 907 CallFErr(dH.ID,NotIHandle,'Lock');
  928. 908 RETURN FALSE;
  929. 909 END;
  930. 910 RETURN cLock(dH,DataLoc,Explicit);
  931. 911 END Lock;
  932. 912
  933. 913
  934. 914 PROCEDURE LockDat(iH: IHandle; dLoc: LONGCARD): BOOLEAN;
  935. 915 VAR
  936. 916 idx,
  937. 917 tmp : CARDINAL;
  938. 918 BEGIN
  939. 919 IF iH.ID^.Buffered THEN
  940. 920 RETURN TRUE;
  941. 921 END;
  942. 922 idx := MAX(CARDINAL);
  943. 923 LOOP
  944. 924 FOR tmp := 0 TO LockQSize-1 DO
  945. 925 WITH iH.ID^.Id[iH.In].DataPtr.ID^.Locks[tmp] DO
  946. 926 IF Position=dLoc THEN
  947. 927 idx := tmp;
  948. 928 EXIT;
  949. 929 ELSIF (idx=MAX(CARDINAL)) AND (Position=Nil) THEN
  950. 930 idx := tmp;
  951. 931 END;
  952. 932 END;
  953. 933 END;
  954. 934 IF idx#MAX(CARDINAL) THEN
  955. 935 WITH iH.ID^.Id[iH.In].DataPtr.ID^.Locks[idx] DO
  956. 936 Position := dLoc;
  957. 937 ICnt := 0;
  958. 938 ECnt := 0;
  959. 939 In := iH;
  960. 940 END;
  961. 941 END;
  962. 942 EXIT;
  963. 943 END;
  964. 944 IF idx#MAX(CARDINAL) THEN
  965. 945 RETURN ccLock(iH,iH.ID^.Id[iH.In].DataPtr.ID^.Locks[idx],Implicit);
  966. 946 ELSE
  967. 947 CallErr(iH,LockOverflow,'LockDat');
  968. 948 RETURN FALSE;
  969. 949 END;
  970. 950 END LockDat;
  971. 951
  972. 952
  973. 953 PROCEDURE ccUnLock(dH: IHandle; VAR lock: LockRec; type: LockType);
  974. 954 VAR
  975. 955 lck : FIOx.LockRec;
  976. 956 BEGIN
  977. 957 IF dH.ID^.Buffered THEN
  978. 958 RETURN;
  979. 959 END;
  980. 960 WITH lock DO
  981. 961 IF type=Implicit THEN
  982. 962 IF ICnt#0 THEN
  983. 963 DEC(ICnt);
  984. 964 END;
  985. 965 ELSIF type=AllImplicit THEN
  986. 966 ICnt := 0;
  987. 967 ELSIF type=AllLocks THEN
  988. 968 ICnt := 0;
  989. 969 ECnt := 0;
  990. 970 ELSIF type=Explicit THEN
  991. 971 IF ECnt#0 THEN
  992. 972 DEC(ECnt);
  993. 973 ELSE
  994. 974 CallErr(dH,NotLocked,'ccUnLock');
  995. 975 RETURN;
  996. 976 END;
  997. 977 END;
  998. 978 IF ICnt=0 THEN
  999. 979 IF ECnt#0 THEN
  1000. 980 In := Null;
  1001. 981 ELSE
  1002. 982 lck.pos := Position;
  1003. 983 lck.len := 1;
  1004. 984 FIOx.UnLock(dH.ID^.FHandle,lck);
  1005. 985 END;
  1006. 986 END;
  1007. 987 END;
  1008. 988 END ccUnLock;
  1009. 989
  1010. 990
  1011. 991 PROCEDURE cUnLock(dH: IHandle; dLoc: LONGCARD; type: LockType);
  1012. 992 VAR
  1013. 993 idx : CARDINAL;
  1014. 994 BEGIN
  1015. 995 IF dH.ID^.Buffered THEN
  1016. 996 RETURN;
  1017. 997 END;
  1018. 998 FOR idx := 0 TO LockQSize-1 DO
  1019. 999 IF dH.ID^.Locks[idx].Position=dLoc THEN
  1020. 1000 ccUnLock(dH,dH.ID^.Locks[idx],type);
  1021. 1001 dH.ID^.Locks[idx].Position := Nil;
  1022. 1002 RETURN;
  1023. 1003 END;
  1024. 1004 END;
  1025. 1005 IF type=Explicit THEN
  1026. 1006 CallErr(dH,NotLocked,'cUnLock');
  1027. 1007 END;
  1028. 1008 END cUnLock;
  1029. 1009
  1030. 1010
  1031. 1011 PROCEDURE UnLock(F: FHandle; DataLoc: LONGCARD);
  1032. 1012 VAR
  1033. 1013 dH : IHandle;
  1034. 1014 BEGIN
  1035. 1015 dH.ID := F;
  1036. 1016 dH.In := 0;
  1037. 1017 ClearErr(dH);
  1038. 1018 IF NOT IsIHandle(dH) THEN
  1039. 1019 CallFErr(dH.ID,NotIHandle,'UnLock');
  1040. 1020 RETURN;
  1041. 1021 END;
  1042. 1022 cUnLock(dH,DataLoc,Explicit);
  1043. 1023 END UnLock;
  1044. 1024
  1045. 1025
  1046. 1026 PROCEDURE UnLockDat(iH: IHandle; dLoc: LONGCARD);
  1047. 1027 VAR
  1048. 1028 idx : CARDINAL;
  1049. 1029 BEGIN
  1050. 1030 IF iH.ID^.Buffered THEN
  1051. 1031 RETURN;
  1052. 1032 END;
  1053. 1033 FOR idx := 0 TO LockQSize-1 DO
  1054. 1034 WITH iH.ID^.Id[iH.In].DataPtr.ID^ DO
  1055. 1035 IF Locks[idx].Position=dLoc THEN
  1056. 1036 ccUnLock(iH,Locks[idx],Implicit);
  1057. 1037 Locks[idx].Position := Nil;
  1058. 1038 RETURN;
  1059. 1039 END;
  1060. 1040 END;
  1061. 1041 END;
  1062. 1042 END UnLockDat;
  1063. 1043
  1064. 1044 PROCEDURE FollowNextIndx(VAR H : IHandle);
  1065. 1045 BEGIN
  1066. 1046 WITH H.ID^.Id[H.In] DO H := NextIndx; END;
  1067. 1047 END FollowNextIndx;
  1068. 1048
  1069. 1049
  1070. 1050 PROCEDURE Release(H: IHandle);
  1071. 1051 VAR
  1072. 1052 idx : CARDINAL;
  1073. 1053 BEGIN
  1074. 1054 ClearErr(H);
  1075. 1055 IF NOT IsIHandle(H) THEN
  1076. 1056 CallFErr(H.ID,NotIHandle,'Release');
  1077. 1057 RETURN;
  1078. 1058 END;
  1079. 1059 IF H.ID^.Id[H.In].Ft=DataSlot THEN
  1080. 1060 FollowNextIndx(H);
  1081. 1061 WHILE H#Null DO
  1082. 1062 Release(H);
  1083. 1063 FollowNextIndx(H);
  1084. 1064 END;
  1085. 1065 ELSE
  1086. 1066 IF IsData(H.ID^.Id[H.In].DataPtr) THEN
  1087. 1067 WITH H.ID^.Id[H.In].DataPtr.ID^ DO
  1088. 1068 IF NOT Buffered THEN
  1089. 1069 FOR idx := 0 TO LockQSize-1 DO
  1090. 1070 WITH Locks[idx] DO
  1091. 1071 IF (Position#Nil) AND (In=H) THEN
  1092. 1072 ccUnLock(H,Locks[idx],AllImplicit);
  1093. 1073 Position := Nil;
  1094. 1074 END;
  1095. 1075 END;
  1096. 1076 END;
  1097. 1077 END;
  1098. 1078 END;
  1099. 1079 END;
  1100. 1080 END;
  1101. 1081 END Release;
  1102. 1082
  1103. 1083
  1104. 1084 PROCEDURE cOneLock(dH: IHandle; dLoc: LONGCARD; type: LockType): BOOLEAN;
  1105. 1085 VAR
  1106. 1086 idx : CARDINAL;
  1107. 1087 BEGIN
  1108. 1088 WITH dH.ID^ DO
  1109. 1089 IF NOT Buffered THEN
  1110. 1090 FOR idx := 0 TO LockQSize-1 DO
  1111. 1091 IF Locks[idx].Position=dLoc THEN
  1112. 1092 RETURN ccOneLock(Locks[idx],type);
  1113. 1093 END;
  1114. 1094 END;
  1115. 1095 END;
  1116. 1096 END;
  1117. 1097 RETURN FALSE;
  1118. 1098 END cOneLock;
  1119. 1099
  1120. 1100
  1121. 1101 PROCEDURE cLocked(dH: IHandle; dLoc: LONGCARD): BOOLEAN;
  1122. 1102 VAR
  1123. 1103 idx : CARDINAL;
  1124. 1104 BEGIN
  1125. 1105 WITH dH.ID^ DO
  1126. 1106 IF NOT Buffered THEN
  1127. 1107 FOR idx := 0 TO LockQSize-1 DO
  1128. 1108 IF Locks[idx].Position=dLoc THEN
  1129. 1109 RETURN TRUE;
  1130. 1110 END;
  1131. 1111 END;
  1132. 1112 RETURN FALSE;
  1133. 1113 ELSE
  1134. 1114 RETURN TRUE;
  1135. 1115 END;
  1136. 1116 END;
  1137. 1117 END cLocked;
  1138. 1118
  1139. 1119
  1140. 1120 PROCEDURE LockFile(fH: FHandle): BOOLEAN;
  1141. 1121 VAR
  1142. 1122 iH : IHandle;
  1143. 1123 BEGIN
  1144. 1124 IF NOT IsFHandle(fH) THEN
  1145. 1125 CallFErr(fH,NotFHandle,'LockFile');
  1146. 1126 RETURN FALSE;
  1147. 1127 END;
  1148. 1128 WITH fH^ DO
  1149. 1129 IF NOT Buffered THEN
  1150. 1130 iH.ID := fH;
  1151. 1131 iH.In := 0;
  1152. 1132 IF NOT ccLock(iH,fhLock,Implicit) THEN
  1153. 1133 RETURN FALSE;
  1154. 1134 END;
  1155. 1135 IF ccOneLock(fhLock,Implicit) THEN
  1156. 1136 FIOx.Seek(FHandle,fhLock.Position);
  1157. 1137 IOabort('LockFile');
  1158. 1138 FIOx.Read(FHandle,fwr^,FileDataWrSize);
  1159. 1139 IOabort('LockFile');
  1160. 1140 END;
  1161. 1141 END;
  1162. 1142 END;
  1163. 1143 RETURN TRUE;
  1164. 1144 END LockFile;
  1165. 1145
  1166. 1146
  1167. 1147 PROCEDURE FlushFHandle(fH: FHandle);
  1168. 1148 BEGIN
  1169. 1149 WITH fH^ DO
  1170. 1150 IF NOT ReadOnly THEN
  1171. 1151 FIOx.Seek(FHandle,fhLock.Position);
  1172. 1152 IOabort('FlushFHandle');
  1173. 1153 FIOx.Write(FHandle,fwr^,FileDataWrSize);
  1174. 1154 IOabort('FlushFHandle');
  1175. 1155 END;
  1176. 1156 END;
  1177. 1157 END FlushFHandle;
  1178. 1158
  1179. 1159
  1180. 1160 PROCEDURE UnLockFile(fH: FHandle);
  1181. 1161 VAR
  1182. 1162 iH : IHandle;
  1183. 1163 BEGIN
  1184. 1164 IF NOT IsFHandle(fH) THEN
  1185. 1165 CallFErr(fH,NotFHandle,'UnLockFile');
  1186. 1166 RETURN;
  1187. 1167 END;
  1188. 1168 WITH fH^ DO
  1189. 1169 IF NOT Buffered THEN
  1190. 1170 IF ccOneLock(fhLock,Implicit) THEN
  1191. 1171 FlushFHandle(fH);
  1192. 1172 END;
  1193. 1173 iH.ID := fH;
  1194. 1174 iH.In := 0;
  1195. 1175 ccUnLock(iH,fhLock,Implicit);
  1196. 1176 END;
  1197. 1177 END;
  1198. 1178 END UnLockFile;
  1199. 1179
  1200. 1180
  1201. 1181 PROCEDURE cLockIHandle(iH: IHandle; type: LockType): BOOLEAN;
  1202. 1182 BEGIN
  1203. 1183 WITH iH.ID^ DO
  1204. 1184 IF NOT Buffered THEN
  1205. 1185 WITH Id[iH.In] DO
  1206. 1186 IF ccLock(iH,ihLock,type) THEN
  1207. 1187 IF ccOneLock(ihLock,type) THEN
  1208. 1188 FIOx.Seek(FHandle,ihLock.Position);
  1209. 1189 IOabort('cLockIHandle');
  1210. 1190 FIOx.Read(FHandle,iwr^,IndexDataWrSize);
  1211. 1191 IOabort('cLockIHandle');
  1212. 1192 IF (Ft=IndexSlot) AND (OldWriteCnt#iwr^.WriteCnt) THEN
  1213. 1193 ClearBuffers(iH);
  1214. 1194 OldWriteCnt := iwr^.WriteCnt;
  1215. 1195 PageLevel := 0;
  1216. 1196 IF PageRefs^.Height<iwr^.Depth THEN
  1217. 1197 FreeMem(PageRefs);
  1218. 1198 AllocMem(PageRefs,VSIZE(PageRef.Height)+(iwr^.Depth+1)*SIZE(PageRefRec));
  1219. 1199 Die(PageRefs=NIL,OutOfMemory);
  1220. 1200 PageRefs^.Height := iwr^.Depth+1;
  1221. 1201 END;
  1222. 1202 END;
  1223. 1203 END;
  1224. 1204 ELSE
  1225. 1205 RETURN FALSE;
  1226. 1206 END;
  1227. 1207 END;
  1228. 1208 END;
  1229. 1209 END;
  1230. 1210 RETURN TRUE;
  1231. 1211 END cLockIHandle;
  1232. 1212
  1233. 1213
  1234. 1214 PROCEDURE LockIHandle(H: IHandle): BOOLEAN;
  1235. 1215 BEGIN
  1236. 1216 ClearErr(H);
  1237. 1217 IF NOT IsIHandle(H) THEN
  1238. 1218 CallFErr(H.ID,NotIHandle,'LockIHandle');
  1239. 1219 RETURN FALSE;
  1240. 1220 END;
  1241. 1221 RETURN cLockIHandle(H,Explicit);
  1242. 1222 END LockIHandle;
  1243. 1223
  1244. 1224
  1245. 1225 PROCEDURE FlushIHandle(iH: IHandle);
  1246. 1226 BEGIN
  1247. 1227 WITH iH.ID^ DO
  1248. 1228 IF NOT ReadOnly THEN
  1249. 1229 WITH Id[iH.In] DO
  1250. 1230 IF Ft=IndexSlot THEN
  1251. 1231 SaveBuffers(iH);
  1252. 1232 OldWriteCnt := iwr^.WriteCnt;
  1253. 1233 END;
  1254. 1234 FIOx.Seek(FHandle,ihLock.Position);
  1255. 1235 IOabort('FlushIHandle');
  1256. 1236 FIOx.Write(FHandle,iwr^,IndexDataWrSize);
  1257. 1237 IOabort('FlushIHandle');
  1258. 1238 END;
  1259. 1239 END;
  1260. 1240 END;
  1261. 1241 END FlushIHandle;
  1262. 1242
  1263. 1243
  1264. 1244 PROCEDURE SetLastKey(iH: IHandle);
  1265. 1245
  1266. 1246 VAR
  1267. 1247 TP : TPage;
  1268. 1248
  1269. 1249 TYPE
  1270. 1250 IPtr = POINTER Seg(TP) TO IndexItem;
  1271. 1251 A2 = ARRAY[0..1] OF SHORTCARD;
  1272. 1252
  1273. 1253 (*# save *)
  1274. 1254 (*# call(inline=>on) *)
  1275. 1255 (*# call(reg_param=>(ax,cx),reg_saved=>(bx,cx,dx,si,di,ds,es,st1,st2,st3,st4,st5,st6)) *)
  1276. 1256 PROCEDURE AddIPtr(A: IPtr; I: CARDINAL): IPtr=A2(003H,0C1H);(*add ax,cx*)
  1277. 1257 (*# restore *)
  1278. 1258
  1279. 1259 VAR
  1280. 1260 IP : IPtr;
  1281. 1261
  1282. 1262 BEGIN
  1283. 1263 WITH iH.ID^ DO
  1284. 1264 WITH Id[iH.In] DO
  1285. 1265 LastKeyOK := TRUE;
  1286. 1266 ReadPage(iH,PageRefs^.Refs[PageLevel].Page,TP);
  1287. 1267 IP := AddIPtr(IPtr(Ofs((TP.IItem))),PageRefs^.Refs[PageLevel].Rec*(2*SIZE(LONGCARD)+iwr^.KeySize));
  1288. 1268 LastKey := IP^.Key;
  1289. 1269 LastKeyRef := IP^.DP;
  1290. 1270 END;
  1291. 1271 END;
  1292. 1272 END SetLastKey;
  1293. 1273
  1294. 1274
  1295. 1275 PROCEDURE cUnLockIHandle(iH: IHandle; type: LockType);
  1296. 1276 BEGIN
  1297. 1277 WITH iH.ID^ DO
  1298. 1278 IF NOT Buffered THEN
  1299. 1279 WITH Id[iH.In] DO
  1300. 1280 IF ccOneLock(ihLock,type) THEN
  1301. 1281 IF Ft=IndexSlot THEN
  1302. 1282 IF PageLevel#0 THEN
  1303. 1283 SetLastKey(iH);
  1304. 1284 END;
  1305. 1285 FlushIHandle(iH);
  1306. 1286 END;
  1307. 1287 END;
  1308. 1288 ccUnLock(iH,ihLock,type);
  1309. 1289 END;
  1310. 1290 END;
  1311. 1291 END;
  1312. 1292 END cUnLockIHandle;
  1313. 1293
  1314. 1294
  1315. 1295 PROCEDURE UnLockIHandle(H: IHandle);
  1316. 1296 BEGIN
  1317. 1297 ClearErr(H);
  1318. 1298 IF NOT IsIHandle(H) THEN
  1319. 1299 CallFErr(H.ID,NotIHandle,'UnLockIHandle');
  1320. 1300 RETURN;
  1321. 1301 END;
  1322. 1302 cUnLockIHandle(H,Explicit);
  1323. 1303 END UnLockIHandle;
  1324. 1304
  1325. 1305
  1326. 1306 PROCEDURE N2Eval(KeySize: CARDINAL): CARDINAL;
  1327. 1307 VAR
  1328. 1308 t : CARDINAL;
  1329. 1309 BEGIN
  1330. 1310 t := (PageSize-6) DIV (8+KeySize);
  1331. 1311 IF ODD(t) THEN
  1332. 1312 DEC(t);
  1333. 1313 END;
  1334. 1314 IF (t=0) THEN
  1335. 1315 CallErr(Null,KeyTooBig,'N2Eval');
  1336. 1316 RETURN MAX(CARDINAL);
  1337. 1317 END;
  1338. 1318 RETURN t;
  1339. 1319 END N2Eval;
  1340. 1320
  1341. 1321
  1342. 1322 PROCEDURE WalkIx(iH: IHandle; mode: WalkMode);
  1343. 1323
  1344. 1324 VAR
  1345. 1325 TP : TPage;
  1346. 1326
  1347. 1327 TYPE
  1348. 1328 IPtr = POINTER Seg(TP) TO IndexItem;
  1349. 1329 A2 = ARRAY[0..1] OF SHORTCARD;
  1350. 1330 A3 = ARRAY[0..2] OF SHORTCARD;
  1351. 1331
  1352. 1332 (*# save *)
  1353. 1333 (*# call(inline=>on) *)
  1354. 1334 (*# call(reg_param=>(ax,cx),reg_saved=>(bx,cx,dx,si,di,ds,es,st1,st2,st3,st4,st5,st6)) *)
  1355. 1335 PROCEDURE AddIPtr(A: IPtr; I: CARDINAL): IPtr=A2(003H,0C1H);(*add ax,cx*)
  1356. 1336 (*# restore *)
  1357. 1337
  1358. 1338 (*%T _fptr *)
  1359. 1339 (*# save *)
  1360. 1340 (*# call(inline=>on) *)
  1361. 1341 (*# call(reg_param=>(bx,es,ax),reg_saved=>(ax,bx,cx,dx,si,di,ds,es,st1,st2,st3,st4,st5,st6)) *)
  1362. 1342 PROCEDURE IncIPtr(VAR a: IPtr; i: CARDINAL)=A3(026H,001H,007H); (* add es:[bx],cx *)
  1363. 1343 (*# restore *)
  1364. 1344 (*# save *)
  1365. 1345 (*# call(inline=>on) *)
  1366. 1346 (*# call(reg_param=>(bx,es,ax),reg_saved=>(ax,bx,cx,dx,si,di,ds,es,st1,st2,st3,st4,st5,st6)) *)
  1367. 1347 PROCEDURE DecIPtr(VAR a: IPtr; i: CARDINAL)=A3(026H,029H,007H); (* sub es:[bx],cx *)
  1368. 1348 (*# restore *)
  1369. 1349 (*%E *)
  1370. 1350
  1371. 1351 (*%F _fptr *)
  1372. 1352 (*# save *)
  1373. 1353 (*# call(inline=>on) *)
  1374. 1354 (*# call(reg_param=>(bx,ax),reg_saved=>(ax,bx,cx,dx,si,di,ds,es,st1,st2,st3,st4,st5,st6)) *)
  1375. 1355 PROCEDURE IncIPtr(VAR a: IPtr; i: CARDINAL)=A2(001H,007H); (* add [bx],cx *)
  1376. 1356 (*# restore *)
  1377. 1357 (*# save *)
  1378. 1358 (*# call(inline=>on) *)
  1379. 1359 (*# call(reg_param=>(bx,ax),reg_saved=>(ax,bx,cx,dx,si,di,ds,es,st1,st2,st3,st4,st5,st6)) *)
  1380. 1360 PROCEDURE DecIPtr(VAR a: IPtr; i: CARDINAL)=A2(029H,007H); (* sub [bx],cx *)
  1381. 1361 (*# restore *)
  1382. 1362 (*%E *)
  1383. 1363
  1384. 1364 VAR
  1385. 1365 IP,
  1386. 1366 BP : IPtr;
  1387. 1367 LeafPage : BOOLEAN;
  1388. 1368 ItemSize : CARDINAL;
  1389. 1369 Index : CARDINAL;
  1390. 1370
  1391. 1371 PROCEDURE GetP(P: LONGCARD);
  1392. 1372 BEGIN
  1393. 1373 ReadPage(iH,P,TP);
  1394. 1374 IP := BP;
  1395. 1375 WITH iH.ID^.Id[iH.In] DO
  1396. 1376 LeafPage := PageLevel=iwr^.Depth;
  1397. 1377 WITH PageRefs^.Refs[PageLevel] DO
  1398. 1378 Page := P;
  1399. 1379 IF TP.ICount=iwr^.N2 THEN
  1400. 1380 IF P=iwr^.TopPage THEN
  1401. 1381 Cnt := 2;
  1402. 1382 ELSE
  1403. 1383 Cnt := PageRefs^.Refs[PageLevel-1].Cnt+1;
  1404. 1384 END;
  1405. 1385 ELSE
  1406. 1386 Cnt := 0;
  1407. 1387 END;
  1408. 1388 END;
  1409. 1389 END;
  1410. 1390 Index := 0;
  1411. 1391 END GetP;
  1412. 1392
  1413. 1393 BEGIN
  1414. 1394 WITH iH.ID^.Id[iH.In] DO
  1415. 1395 ItemSize := 8+iwr^.KeySize;
  1416. 1396 BP := IPtr(Ofs((TP.IItem)));
  1417. 1397 LastDataRef := Nil;
  1418. 1398 IF PageLevel=0 THEN
  1419. 1399 PageLevel := 1;
  1420. 1400 GetP(iwr^.TopPage);
  1421. 1401 IF TP.ICount=0 THEN
  1422. 1402 PageLevel := 0;
  1423. 1403 RETURN;
  1424. 1404 ELSE
  1425. 1405 Index := 0;
  1426. 1406 LOOP
  1427. 1407 IF mode=Backward THEN
  1428. 1408 Index := TP.ICount;
  1429. 1409 END;
  1430. 1410 PageRefs^.Refs[PageLevel].Rec := Index;
  1431. 1411 IncIPtr(IP,Index*ItemSize);
  1432. 1412 IF LeafPage THEN
  1433. 1413 IF mode=Backward THEN
  1434. 1414 DecIPtr(IP,ItemSize);
  1435. 1415 DEC(PageRefs^.Refs[PageLevel].Rec);
  1436. 1416 END;
  1437. 1417 EXIT;
  1438. 1418 END;
  1439. 1419 INC(PageLevel);
  1440. 1420 GetP(IP^.IP);
  1441. 1421 END;
  1442. 1422 END;
  1443. 1423 ELSE
  1444. 1424 GetP(PageRefs^.Refs[PageLevel].Page);
  1445. 1425 Index := PageRefs^.Refs[PageLevel].Rec;
  1446. 1426 IF mode=Forward THEN
  1447. 1427 IF (Index+1<TP.ICount) OR
  1448. 1428 ((Index<TP.ICount) AND NOT LeafPage) THEN
  1449. 1429 INC(Index);
  1450. 1430 WHILE NOT LeafPage DO
  1451. 1431 PageRefs^.Refs[PageLevel].Rec := Index;
  1452. 1432 IncIPtr(IP,Index*ItemSize);
  1453. 1433 INC(PageLevel);
  1454. 1434 GetP(IP^.IP);
  1455. 1435 END;
  1456. 1436 ELSE
  1457. 1437 REPEAT
  1458. 1438 DEC(PageLevel);
  1459. 1439 IF PageLevel=0 THEN
  1460. 1440 RETURN;
  1461. 1441 END;
  1462. 1442 GetP(PageRefs^.Refs[PageLevel].Page);
  1463. 1443 Index := PageRefs^.Refs[PageLevel].Rec;
  1464. 1444 UNTIL Index<TP.ICount;
  1465. 1445 END;
  1466. 1446 ELSE
  1467. 1447 IF LeafPage THEN
  1468. 1448 IF Index=0 THEN
  1469. 1449 REPEAT
  1470. 1450 DEC(PageLevel);
  1471. 1451 IF PageLevel=0 THEN
  1472. 1452 RETURN;
  1473. 1453 END;
  1474. 1454 GetP(PageRefs^.Refs[PageLevel].Page);
  1475. 1455 Index := PageRefs^.Refs[PageLevel].Rec;
  1476. 1456 UNTIL Index>0;
  1477. 1457 END;
  1478. 1458 ELSE
  1479. 1459 REPEAT
  1480. 1460 PageRefs^.Refs[PageLevel].Rec := Index;
  1481. 1461 IncIPtr(IP,Index*ItemSize);
  1482. 1462 INC(PageLevel);
  1483. 1463 GetP(IP^.IP);
  1484. 1464 Index := TP.ICount;
  1485. 1465 UNTIL LeafPage;
  1486. 1466 END;
  1487. 1467 DEC(Index);
  1488. 1468 END;
  1489. 1469 PageRefs^.Refs[PageLevel].Rec := Index;
  1490. 1470 IncIPtr(IP,Index*ItemSize);
  1491. 1471 END;
  1492. 1472 LastDataRef := IP^.DP;
  1493. 1473 END;
  1494. 1474 END WalkIx;
  1495. 1475
  1496. 1476
  1497. 1477 PROCEDURE FindIx(iH: IHandle; Key: ARRAY OF BYTE; DataPos: LONGCARD;
  1498. 1478 Mode: FindMode): BOOLEAN;
  1499. 1479
  1500. 1480 VAR
  1501. 1481 TP : TPage;
  1502. 1482
  1503. 1483 TYPE
  1504. 1484 IPtr = POINTER Seg(TP) TO IndexItem;
  1505. 1485 A2 = ARRAY[0..1] OF SHORTCARD;
  1506. 1486
  1507. 1487 (*# save *)
  1508. 1488 (*# call(inline=>on) *)
  1509. 1489 (*# call(reg_param=>(ax,cx),reg_saved=>(bx,cx,dx,si,di,ds,es,st1,st2,st3,st4,st5,st6)) *)
  1510. 1490 PROCEDURE AddIPtr(A: IPtr; I: CARDINAL): IPtr=A2(003H,0C1H);(*add ax,cx*)
  1511. 1491 (*# restore *)
  1512. 1492
  1513. 1493 VAR
  1514. 1494 IP,
  1515. 1495 BP : IPtr;
  1516. 1496 LeafPage : BOOLEAN;
  1517. 1497 ItemSize : CARDINAL;
  1518. 1498 Index : CARDINAL;
  1519. 1499 C : CmpRes;
  1520. 1500 First,
  1521. 1501 Last : CARDINAL;
  1522. 1502
  1523. 1503 LABEL
  1524. 1504 _Greater,
  1525. 1505 _Less;
  1526. 1506
  1527. 1507 PROCEDURE GetPage(P: LONGCARD);
  1528. 1508 BEGIN
  1529. 1509 ReadPage(iH,P,TP);
  1530. 1510 WITH iH.ID^.Id[iH.In] DO
  1531. 1511 LeafPage := PageLevel=iwr^.Depth;
  1532. 1512 WITH PageRefs^.Refs[PageLevel] DO
  1533. 1513 Page := P;
  1534. 1514 IF TP.ICount=iwr^.N2 THEN
  1535. 1515 IF P=iwr^.TopPage THEN
  1536. 1516 Cnt := 2;
  1537. 1517 ELSE
  1538. 1518 Cnt := PageRefs^.Refs[PageLevel-1].Cnt+1;
  1539. 1519 END;
  1540. 1520 ELSE
  1541. 1521 Cnt := 0;
  1542. 1522 END;
  1543. 1523 END;
  1544. 1524 END;
  1545. 1525 First := 0;
  1546. 1526 Last := TP.ICount;
  1547. 1527 Index := (First + Last) DIV 2;
  1548. 1528 IP := AddIPtr(BP,Index*ItemSize);
  1549. 1529 END GetPage;
  1550. 1530
  1551. 1531 PROCEDURE Walk(m : WalkMode);
  1552. 1532 BEGIN
  1553. 1533 WITH iH.ID^.Id[iH.In] DO
  1554. 1534 WalkIx(iH,m);
  1555. 1535 IF PageLevel#0 THEN
  1556. 1536 GetPage(PageRefs^.Refs[PageLevel].Page);
  1557. 1537 IP := AddIPtr(BP,PageRefs^.Refs[PageLevel].Rec*ItemSize);
  1558. 1538 C := CompFct(ADR(IP^.Key),ADR(Key));
  1559. 1539 LastDataRef := IP^.DP;
  1560. 1540 ELSE
  1561. 1541 LastDataRef := Nil;
  1562. 1542 END;
  1563. 1543 END;
  1564. 1544 END Walk;
  1565. 1545
  1566. 1546 BEGIN
  1567. 1547 BP := IPtr(ADR(TP.IItem));
  1568. 1548 WITH iH.ID^.Id[iH.In] DO
  1569. 1549 ItemSize := 2*SIZE(LONGCARD)+iwr^.KeySize;
  1570. 1550 PageLevel := 1;
  1571. 1551 GetPage(iwr^.TopPage);
  1572. 1552 LOOP (* Opt1 *)
  1573. 1553 IF Index<TP.ICount THEN
  1574. 1554 C := CompFct(ADR(IP^.Key),ADR(Key));
  1575. 1555 LastDataRef := IP^.DP;
  1576. 1556 ELSE
  1577. 1557 C := Greater;
  1578. 1558 LastDataRef := Nil;
  1579. 1559 END;
  1580. 1560 IF First >= Last THEN
  1581. 1561 PageRefs^.Refs[PageLevel].Rec := Index;
  1582. 1562 IF LeafPage THEN
  1583. 1563 CASE Mode OF
  1584. 1564 | Ins : RETURN FALSE;
  1585. 1565 | Idx : RETURN FALSE;
  1586. 1566 | Rec : IF Index=TP.ICount THEN
  1587. 1567 Walk(Forward);
  1588. 1568 END;
  1589. 1569 RETURN FALSE;
  1590. 1570 | Fnd,
  1591. 1571 Src : WHILE (PageLevel#0) AND (C#Less) DO
  1592. 1572 Walk(Backward);
  1593. 1573 END;
  1594. 1574 Walk(Forward);
  1595. 1575 RETURN (PageLevel#0) AND ((C=Eq) OR (Mode=Src));
  1596. 1576 END;
  1597. 1577 ELSE
  1598. 1578 INC(PageLevel);
  1599. 1579 GetPage(IP^.IP);
  1600. 1580 END;
  1601. 1581 ELSE
  1602. 1582 CASE C OF
  1603. 1583 | Greater :
  1604. 1584 _Greater: (* This key is >= the one we want *)
  1605. 1585 Last := Index;
  1606. 1586 | Eq : CASE Mode OF
  1607. 1587 | Ins : IF NOT iwr^.DupKey THEN
  1608. 1588 CallErr(iH,ErrDupKey,'FindIx');
  1609. 1589 PageRefs^.Refs[PageLevel].Rec := Index;
  1610. 1590 RETURN FALSE;
  1611. 1591 ELSIF IP^.DP<DataPos THEN
  1612. 1592 GOTO _Less;
  1613. 1593 ELSE
  1614. 1594 GOTO _Greater;
  1615. 1595 END;
  1616. 1596 | Idx,
  1617. 1597 Rec : IF IP^.DP<DataPos THEN
  1618. 1598 GOTO _Less;
  1619. 1599 ELSIF IP^.DP=DataPos THEN
  1620. 1600 PageRefs^.Refs[PageLevel].Rec := Index;
  1621. 1601 RETURN TRUE;
  1622. 1602 ELSE
  1623. 1603 GOTO _Greater;
  1624. 1604 END;
  1625. 1605 | Fnd,
  1626. 1606 Src : GOTO _Greater;
  1627. 1607 END;
  1628. 1608 | Less :
  1629. 1609 _Less: (* This key is < the one we want *)
  1630. 1610 First := Index+1;
  1631. 1611 END;
  1632. 1612 Index := (First + Last) DIV 2;
  1633. 1613 IP := AddIPtr(BP,Index*ItemSize);
  1634. 1614 END;
  1635. 1615 END;
  1636. 1616 END;
  1637. 1617 END FindIx;
  1638. 1618
  1639. 1619
  1640. 1620 PROCEDURE FreeFreeBlock(fH: FHandle; Loc: LONGCARD);
  1641. 1621 BEGIN
  1642. 1622 FIOx.Seek(fH^.FHandle,Loc);
  1643. 1623 IOabort('FreeFreeBlock');
  1644. 1624 FIOx.Write(fH^.FHandle,fH^.fwr^.FreeList,4);
  1645. 1625 IOabort('FreeFreeBlock');
  1646. 1626 fH^.fwr^.FreeList := Loc;
  1647. 1627 END FreeFreeBlock;
  1648. 1628
  1649. 1629
  1650. 1630 PROCEDURE AllocateFreeBlock(fH: FHandle): LONGCARD;
  1651. 1631 VAR
  1652. 1632 Loc : LONGCARD;
  1653. 1633 r : CARDINAL;
  1654. 1634 BEGIN
  1655. 1635 IF fH^.fwr^.FreeList#Nil THEN
  1656. 1636 Loc := fH^.fwr^.FreeList;
  1657. 1637 FIOx.Seek(fH^.FHandle,Loc);
  1658. 1638 IOabort('AllocateFreeBlock');
  1659. 1639 FIOx.Read(fH^.FHandle,fH^.fwr^.FreeList,4);
  1660. 1640 IOabort('AllocateFreeBlock');
  1661. 1641 RETURN Loc;
  1662. 1642 ELSE
  1663. 1643 FIOx.Seek(fH^.FHandle,fH^.fwr^.FileSize+PageSize-1);
  1664. 1644 IOabort('AllocateFreeBlock');
  1665. 1645 FIOx.Write(fH^.FHandle,0,1);
  1666. 1646 IF FIOx.Error()=FIOx.DISK_FULL THEN
  1667. 1647 FIOx.Truncate(fH^.FHandle,fH^.fwr^.FileSize);
  1668. 1648 IOabort('AllocateFreeBlock');
  1669. 1649 RETURN Nil;
  1670. 1650 END;
  1671. 1651 IOabort('AllocateFreeBlock');
  1672. 1652 Loc := fH^.fwr^.FileSize;
  1673. 1653 INC(fH^.fwr^.FileSize,PageSize);
  1674. 1654 RETURN Loc;
  1675. 1655 END;
  1676. 1656 END AllocateFreeBlock;
  1677. 1657
  1678. 1658
  1679. 1659 (*# save *)
  1680. 1660 (*# check(overflow=>off) *)
  1681. 1661 PROCEDURE FreeBlock(fH: FHandle; Len,Loc: LONGCARD);
  1682. 1662 VAR
  1683. 1663 iH : IHandle;
  1684. 1664 r,
  1685. 1665 PLen,
  1686. 1666 NLen : CARDINAL;
  1687. 1667 PLoc,
  1688. 1668 PLen4 : LONGCARD;
  1689. 1669 BEGIN
  1690. 1670 iH.ID := fH;
  1691. 1671 iH.In := 0;
  1692. 1672 LOOP
  1693. 1673 WITH fH^ DO
  1694. 1674 CASE fwr^.Mode OF
  1695. 1675 FixSize : AddIndex(iH,Len,Loc);
  1696. 1676 EXIT;
  1697. 1677 | Size16,
  1698. 1678 Compress : IF Len<SIZE(CARDINAL)*2 THEN
  1699. 1679 Len := SIZE(CARDINAL)*2;
  1700. 1680 END;
  1701. 1681 FIOx.Seek(FHandle,Loc-SIZE(CARDINAL));
  1702. 1682 IOabort('FreeBlock');
  1703. 1683 FIOx.Read(FHandle,PLen,SIZE(CARDINAL));
  1704. 1684 IF FIOx.Error()#FIOx.NO_ERROR THEN
  1705. 1685 PLen := MAX(CARDINAL);
  1706. 1686 END;
  1707. 1687 PLoc := Loc-LONGCARD(PLen);
  1708. 1688 IF ((Loc-SIZE(CARDINAL))>LONGCARD(fwr^.HeaderSize)) AND (PLen<MAX(CARDINAL)-SIZE(LONGCARD)*2) AND FindIx(iH,PLen,PLoc,Idx) THEN
  1709. 1689 DeleteIndex(iH,PLen,PLoc);
  1710. 1690 IF LONGCARD(PLen)+Len<MAX(CARDINAL)-SIZE(LONGCARD)*2 THEN
  1711. 1691 NLen := PLen+CARDINAL(Len);
  1712. 1692 Loc := Loc+Len;
  1713. 1693 Len := 0;
  1714. 1694 ELSE
  1715. 1695 NLen := MAX(CARDINAL)-SIZE(LONGCARD)*2;
  1716. 1696 Len := Len-LONGCARD((MAX(CARDINAL)-SIZE(LONGCARD)*2-PLen));
  1717. 1697 Loc := Loc+LONGCARD((MAX(CARDINAL)-SIZE(LONGCARD)*2-PLen))
  1718. 1698 END;
  1719. 1699 IF (Len>0) AND (Len<SIZE(LONGCARD)) THEN
  1720. 1700 NLen := NLen-(SIZE(LONGCARD)-CARDINAL(Len));
  1721. 1701 Loc := Loc-(SIZE(LONGCARD)-Len);
  1722. 1702 Len := SIZE(LONGCARD);
  1723. 1703 END;
  1724. 1704 FIOx.Seek(FHandle,PLoc);
  1725. 1705 IOabort('FreeBlock');
  1726. 1706 FIOx.Write(FHandle,NLen,SIZE(CARDINAL));
  1727. 1707 IOabort('FreeBlock');
  1728. 1708 FIOx.Seek(FHandle,PLoc+LONGCARD(NLen)-SIZE(CARDINAL));
  1729. 1709 IOabort('FreeBlock');
  1730. 1710 FIOx.Write(FHandle,NLen,SIZE(CARDINAL));
  1731. 1711 IOabort('FreeBlock');
  1732. 1712 AddIndex(iH,NLen,PLoc);
  1733. 1713 END;
  1734. 1714 IF Len>0 THEN
  1735. 1715 FIOx.Seek(FHandle,Loc);
  1736. 1716 IOabort('FreeBlock');
  1737. 1717 FIOx.Write(FHandle,Len,SIZE(CARDINAL));
  1738. 1718 IOabort('FreeBlock');
  1739. 1719 FIOx.Seek(FHandle,Loc+Len-SIZE(CARDINAL));
  1740. 1720 IOabort('FreeBlock');
  1741. 1721 FIOx.Write(FHandle,Len,SIZE(CARDINAL));
  1742. 1722 IOabort('FreeBlock');
  1743. 1723 AddIndex(iH,Len,Loc);
  1744. 1724 PLoc := Loc+Len;
  1745. 1725 ELSE
  1746. 1726 Len := LONGCARD(NLen);
  1747. 1727 PLoc := PLoc+Len;
  1748. 1728 END;
  1749. 1729 (* Opt2 *)
  1750. 1730 FIOx.Seek(FHandle,PLoc);
  1751. 1731 IOabort('FreeBlock');
  1752. 1732 FIOx.Read(FHandle,PLen,SIZE(CARDINAL));
  1753. 1733 IF FIOx.Error()#FIOx.NO_ERROR THEN
  1754. 1734 PLen := MAX(CARDINAL);
  1755. 1735 END;
  1756. 1736 IF (Len<MAX(CARDINAL)-SIZE(LONGCARD)*2) AND (PLen<MAX(CARDINAL)-SIZE(LONGCARD)*2) AND FindIx(iH,PLen,PLoc,Idx) THEN
  1757. 1737 DeleteIndex(iH,PLen,PLoc);
  1758. 1738 Len := LONGCARD(PLen);
  1759. 1739 Loc := PLoc;
  1760. 1740 ELSE
  1761. 1741 EXIT;
  1762. 1742 END;
  1763. 1743 | Size32 : IF Len<SIZE(LONGCARD)*2 THEN
  1764. 1744 Len := SIZE(LONGCARD)*2;
  1765. 1745 END;
  1766. 1746 FIOx.Seek(FHandle,Loc-SIZE(LONGCARD));
  1767. 1747 IOabort('FreeBlock');
  1768. 1748 FIOx.Read(FHandle,PLen4,SIZE(LONGCARD));
  1769. 1749 IF FIOx.Error()#FIOx.NO_ERROR THEN
  1770. 1750 PLen4 := MAX(LONGCARD);
  1771. 1751 END;
  1772. 1752 PLoc := Loc-PLen4;
  1773. 1753 IF ((Loc-SIZE(LONGCARD))>LONGCARD(fwr^.HeaderSize)) AND (PLen4<MAX(LONGCARD)-SIZE(LONGCARD)*2) AND FindIx(iH,PLen4,PLoc,Idx) THEN
  1774. 1754 DeleteIndex(iH,PLen4,PLoc);
  1775. 1755 Len := PLen4+Len;
  1776. 1756 FIOx.Seek(FHandle,PLoc);
  1777. 1757 IOabort('FreeBlock');
  1778. 1758 FIOx.Write(FHandle,Len,SIZE(LONGCARD));
  1779. 1759 IOabort('FreeBlock');
  1780. 1760 FIOx.Seek(FHandle,PLoc+Len-SIZE(LONGCARD));
  1781. 1761 IOabort('FreeBlock');
  1782. 1762 FIOx.Write(FHandle,Len,SIZE(LONGCARD));
  1783. 1763 IOabort('FreeBlock');
  1784. 1764 AddIndex(iH,Len,PLoc);
  1785. 1765 PLoc := PLoc+Len;
  1786. 1766 ELSE
  1787. 1767 FIOx.Seek(FHandle,Loc);
  1788. 1768 IOabort('FreeBlock');
  1789. 1769 FIOx.Write(FHandle,Len,SIZE(LONGCARD));
  1790. 1770 IOabort('FreeBlock');
  1791. 1771 FIOx.Seek(FHandle,Loc+Len-SIZE(LONGCARD));
  1792. 1772 IOabort('FreeBlock');
  1793. 1773 FIOx.Write(FHandle,Len,SIZE(LONGCARD));
  1794. 1774 IOabort('FreeBlock');
  1795. 1775 AddIndex(iH,Len,Loc);
  1796. 1776 PLoc := Loc+Len;
  1797. 1777 END;
  1798. 1778 (* Opt2 *)
  1799. 1779 FIOx.Seek(FHandle,PLoc);
  1800. 1780 IOabort('FreeBlock');
  1801. 1781 FIOx.Read(FHandle,PLen4,SIZE(LONGCARD));
  1802. 1782 IF FIOx.Error()#FIOx.NO_ERROR THEN
  1803. 1783 PLen4 := MAX(LONGCARD);
  1804. 1784 END;
  1805. 1785 IF (Len<MAX(LONGCARD)-SIZE(LONGCARD)*2) AND (PLen4<MAX(LONGCARD)-SIZE(LONGCARD)*2) AND FindIx(iH,PLen4,PLoc,Idx) THEN
  1806. 1786 DeleteIndex(iH,PLen4,PLoc);
  1807. 1787 Len := PLen4;
  1808. 1788 Loc := PLoc;
  1809. 1789 ELSE
  1810. 1790 EXIT;
  1811. 1791 END;
  1812. 1792 | NoDealoc : CallFErr(fH,BadFree,'NoDealloc');
  1813. 1793 RETURN;
  1814. 1794 ELSE
  1815. 1795 CallFErr(fH,UnknownError,'FreeBlock');
  1816. 1796 RETURN;
  1817. 1797 END;
  1818. 1798 END;
  1819. 1799 END;
  1820. 1800 END FreeBlock;
  1821. 1801 (*# restore *)
  1822. 1802
  1823. 1803
  1824. 1804 PROCEDURE AllocateBlock(fH: FHandle; Len: LONGCARD): LONGCARD;
  1825. 1805
  1826. 1806 VAR
  1827. 1807 Loc : LONGCARD;
  1828. 1808
  1829. 1809 PROCEDURE Extend;
  1830. 1810 BEGIN
  1831. 1811 FIOx.Seek(fH^.FHandle,fH^.fwr^.FileSize+Len-1);
  1832. 1812 IOabort('AllocateBlock.Extend');
  1833. 1813 FIOx.Write(fH^.FHandle,0,1);
  1834. 1814 IF FIOx.Error()=FIOx.DISK_FULL THEN
  1835. 1815 FIOx.Truncate(fH^.FHandle,fH^.fwr^.FileSize);
  1836. 1816 IOabort('AllocateBlock.Extend');
  1837. 1817 Loc := Nil;
  1838. 1818 RETURN;
  1839. 1819 END;
  1840. 1820 IOabort('AllocateBlock.Extend');
  1841. 1821 Loc := fH^.fwr^.FileSize;
  1842. 1822 INC(fH^.fwr^.FileSize,Len);
  1843. 1823 END Extend;
  1844. 1824
  1845. 1825 VAR
  1846. 1826 iH : IHandle;
  1847. 1827 ActLen4,
  1848. 1828 tl : LONGCARD;
  1849. 1829 ActLen2,
  1850. 1830 r : CARDINAL;
  1851. 1831 Safe : BOOLEAN;
  1852. 1832
  1853. 1833 BEGIN
  1854. 1834 iH.ID := fH;
  1855. 1835 iH.In := 0;
  1856. 1836 WITH fH^ DO
  1857. 1837 CASE fwr^.Mode OF
  1858. 1838 FixSize : IF Len >= MAX(CARDINAL)-8 THEN
  1859. 1839 CallFErr(fH,BadSize,'Allocate');
  1860. 1840 RETURN Nil;
  1861. 1841 END;
  1862. 1842 IF FindIndex(iH,Len,Loc) THEN
  1863. 1843 DeleteIndex(iH,Len,Loc);
  1864. 1844 ELSE
  1865. 1845 Extend;
  1866. 1846 END;
  1867. 1847 | Size16,
  1868. 1848 Compress : IF Len<4 THEN
  1869. 1849 Len := 4;
  1870. 1850 END;
  1871. 1851 IF Len >= MAX(CARDINAL)-8 THEN
  1872. 1852 CallFErr(fH,BadSize,'Allocate');
  1873. 1853 RETURN Nil;
  1874. 1854 END;
  1875. 1855 IF FindIndex(iH,Len,Loc) THEN
  1876. 1856 DeleteIndex(iH,Len,Loc);
  1877. 1857 ELSIF SearchIndex(iH,Len+4,Loc) THEN
  1878. 1858 FIOx.Seek(FHandle,Loc);
  1879. 1859 IOabort('AllocateBlock');
  1880. 1860 FIOx.Read(FHandle,ActLen2,SIZE(CARDINAL));
  1881. 1861 IOabort('AllocateBlock');
  1882. 1862 DeleteIndex(iH,ActLen2,Loc);
  1883. 1863 FreeBlock(fH,LONGCARD(ActLen2)-Len,Loc+Len);
  1884. 1864 ELSE
  1885. 1865 Extend;
  1886. 1866 END;
  1887. 1867 | Size32 : IF Len<8 THEN
  1888. 1868 Len := 8;
  1889. 1869 END;
  1890. 1870 IF FindIndex(iH,Len,Loc) THEN
  1891. 1871 DeleteIndex(iH,Len,Loc);
  1892. 1872 ELSIF SearchIndex(iH,Len+8,Loc) THEN
  1893. 1873 FIOx.Seek(FHandle,Loc);
  1894. 1874 IOabort('AllocateBlock');
  1895. 1875 FIOx.Read(FHandle,ActLen4,SIZE(LONGCARD));
  1896. 1876 IOabort('AllocateBlock');
  1897. 1877 DeleteIndex(iH,ActLen4,Loc);
  1898. 1878 FreeBlock(fH,ActLen4-Len,Loc+Len);
  1899. 1879 ELSE
  1900. 1880 Extend;
  1901. 1881 END;
  1902. 1882 | NoDealoc : Extend;
  1903. 1883 ELSE
  1904. 1884 CallFErr(fH,UnknownError,'Allocate Block');
  1905. 1885 RETURN Nil;
  1906. 1886 END;
  1907. 1887 END;
  1908. 1888 RETURN Loc;
  1909. 1889 END AllocateBlock;
  1910. 1890
  1911. 1891
  1912. 1892 PROCEDURE LockIx(dH: IHandle): BOOLEAN;
  1913. 1893
  1914. 1894 PROCEDURE cLockIx(iH: IHandle): BOOLEAN;
  1915. 1895 BEGIN
  1916. 1896 IF iH#Null THEN
  1917. 1897 IF NOT cLockIHandle(iH,Implicit) THEN
  1918. 1898 RETURN FALSE;
  1919. 1899 ELSIF NOT cLockIx(iH.ID^.Id[iH.In].NextIndx) THEN
  1920. 1900 cUnLockIHandle(iH,Implicit);
  1921. 1901 RETURN FALSE;
  1922. 1902 END;
  1923. 1903 END;
  1924. 1904 RETURN TRUE;
  1925. 1905 END cLockIx;
  1926. 1906
  1927. 1907 BEGIN
  1928. 1908 IF NOT cLockIx(dH.ID^.Id[dH.In].NextIndx) THEN
  1929. 1909 SetErr(dH,Locked);
  1930. 1910 RETURN FALSE;
  1931. 1911 ELSE
  1932. 1912 RETURN TRUE;
  1933. 1913 END;
  1934. 1914 END LockIx;
  1935. 1915
  1936. 1916
  1937. 1917 PROCEDURE UnLockIx(dH: IHandle);
  1938. 1918 BEGIN
  1939. 1919 FollowNextIndx(dH);
  1940. 1920 WHILE dH#Null DO
  1941. 1921 cUnLockIHandle(dH,Implicit);
  1942. 1922 FollowNextIndx(dH);
  1943. 1923 END;
  1944. 1924 END UnLockIx;
  1945. 1925
  1946. 1926
  1947. 1927 PROCEDURE Delete(D: IHandle);
  1948. 1928 VAR
  1949. 1929 r,
  1950. 1930 Size,
  1951. 1931 BSize : CARDINAL;
  1952. 1932 t,
  1953. 1933 BPos : LONGCARD;
  1954. 1934 iH,
  1955. 1935 tH : IHandle;
  1956. 1936 Key : KeyType;
  1957. 1937 BEGIN
  1958. 1938 ClearErr(D);
  1959. 1939 IF NOT IsData(D) THEN
  1960. 1940 CallErr(D,NotData,'Delete');
  1961. 1941 RETURN;
  1962. 1942 END;
  1963. 1943 IF D.ID^.ReadOnly THEN
  1964. 1944 CallErr(D,BadWrite,'Delete with ReadOnly');
  1965. 1945 RETURN;
  1966. 1946 END;
  1967. 1947 IF NOT cLocked(D,D.ID^.Id[D.In].LastDataRef) THEN
  1968. 1948 CallErr(D,NotLocked,'Delete');
  1969. 1949 RETURN;
  1970. 1950 END;
  1971. 1951 WITH D.ID^.Id[D.In] DO
  1972. 1952 IF LastDataRef#Nil THEN
  1973. 1953 IF LockFile(D.ID) THEN
  1974. 1954 IF LockIx(D) THEN
  1975. 1955 LoadRec(D,LastDataRef,BPos,BSize);
  1976. 1956 iH := NextIndx;
  1977. 1957 LOOP
  1978. 1958 WHILE iH.ID#NIL DO
  1979. 1959 iH.ID^.Id[iH.In].KeyFct(ADR(Key),bufPtr);
  1980. 1960 DeleteIndex(iH,Key,LastDataRef);
  1981. 1961 IF LastError(iH)#OK THEN
  1982. 1962 SetErr(D,LastError(iH));
  1983. 1963 tH := NextIndx;
  1984. 1964 WHILE tH#iH DO
  1985. 1965 tH.ID^.Id[tH.In].KeyFct(ADR(Key),bufPtr);
  1986. 1966 AddIndex(tH,Key,LastDataRef);
  1987. 1967 IF LastError(tH)#OK THEN
  1988. 1968 ClearErr(D);
  1989. 1969 SetErr(D,LastError(tH));
  1990. 1970 EXIT;
  1991. 1971 END;
  1992. 1972 FollowNextIndx(tH);
  1993. 1973 END;
  1994. 1974 EXIT;
  1995. 1975 END;
  1996. 1976 FollowNextIndx(iH);
  1997. 1977 END;
  1998. 1978 FreeBlock(D.ID,LONGCARD(BSize),BPos);
  1999. 1979 EXIT;
  2000. 1980 END;
  2001. 1981 cUnLock(D,LastDataRef,AllLocks);
  2002. 1982 LastDataRef := Nil;
  2003. 1983 IF LastError(D)=OK THEN
  2004. 1984 DEC(iwr^.RecordCnt);
  2005. 1985 END;
  2006. 1986 UnLockIx(D);
  2007. 1987 END;
  2008. 1988 UnLockFile(D.ID);
  2009. 1989 ELSE
  2010. 1990 SetErr(D,Locked);
  2011. 1991 END;
  2012. 1992 END;
  2013. 1993 END;
  2014. 1994 END Delete;
  2015. 1995
  2016. 1996
  2017. 1997 PROCEDURE Add(D: IHandle; Data: ARRAY OF BYTE; Length: CARDINAL);
  2018. 1998 VAR
  2019. 1999 Size : CARDINAL;
  2020. 2000 Buf : ADDRESS;
  2021. 2001 iH,
  2022. 2002 tH : IHandle;
  2023. 2003 Key : KeyType;
  2024. 2004 BEGIN
  2025. 2005 ClearErr(D);
  2026. 2006 IF NOT IsData(D) THEN
  2027. 2007 CallErr(D,NotData,'Add');
  2028. 2008 RETURN;
  2029. 2009 END;
  2030. 2010 IF D.ID^.ReadOnly THEN
  2031. 2011 CallErr(D,BadWrite,'Add with ReadOnly');
  2032. 2012 RETURN;
  2033. 2013 END;
  2034. 2014 WITH D.ID^.Id[D.In] DO
  2035. 2015 IF LockFile(D.ID) THEN
  2036. 2016 IF LockIx(D) THEN
  2037. 2017 IF iwr^.RecordSize=0 THEN
  2038. 2018 IF D.ID^.fwr^.Mode=Compress THEN
  2039. 2019 AdjustBuffer(D,Length);
  2040. 2020 Size := Packer(Length,ADR(Data),bufPtr);
  2041. 2021 Buf := bufPtr;
  2042. 2022 ELSE
  2043. 2023 Size := Length;
  2044. 2024 Buf := ADR(Data);
  2045. 2025 END;
  2046. 2026 LastDataRef := AllocateBlock(D.ID,LONGCARD(Size+SIZE(Size)))+SIZE(Size);
  2047. 2027 IF LastDataRef#Nil THEN
  2048. 2028 FIOx.Seek(D.ID^.FHandle,LastDataRef-SIZE(Size));
  2049. 2029 IOabort('Add');
  2050. 2030 FIOx.Write(D.ID^.FHandle,Size,SIZE(Size));
  2051. 2031 IOabort('Add');
  2052. 2032 END;
  2053. 2033 ELSE
  2054. 2034 Size := iwr^.RecordSize;
  2055. 2035 Buf := ADR(Data);
  2056. 2036 LastDataRef := AllocateBlock(D.ID,LONGCARD(Size));
  2057. 2037 IF LastDataRef#Nil THEN
  2058. 2038 FIOx.Seek(D.ID^.FHandle,LastDataRef);
  2059. 2039 IOabort('Add');
  2060. 2040 END;
  2061. 2041 END;
  2062. 2042 IF LastDataRef=Nil THEN
  2063. 2043 UnLockIx(D);
  2064. 2044 UnLockFile(D.ID);
  2065. 2045 CallErr(D,FileError,'Add');
  2066. 2046 RETURN;
  2067. 2047 END;
  2068. 2048 FIOx.Write(D.ID^.FHandle,Buf^,Size);
  2069. 2049 IOabort('Add');
  2070. 2050 iH := NextIndx;
  2071. 2051 LOOP
  2072. 2052 WHILE iH.ID#NIL DO
  2073. 2053 iH.ID^.Id[iH.In].KeyFct(ADR(Key),ADR(Data));
  2074. 2054 AddIndex(iH,Key,LastDataRef);
  2075. 2055 IF LastError(iH)#OK THEN
  2076. 2056 SetErr(D,LastError(iH));
  2077. 2057 LOOP
  2078. 2058 tH := NextIndx;
  2079. 2059 WHILE tH#iH DO
  2080. 2060 tH.ID^.Id[tH.In].KeyFct(ADR(Key),ADR(Data));
  2081. 2061 DeleteIndex(tH,Key,LastDataRef);
  2082. 2062 IF LastError(tH)#OK THEN
  2083. 2063 ClearErr(D);
  2084. 2064 SetErr(D,LastError(tH));
  2085. 2065 EXIT;
  2086. 2066 END;
  2087. 2067 FollowNextIndx(tH);
  2088. 2068 END;
  2089. 2069 EXIT;
  2090. 2070 END;
  2091. 2071 IF iwr^.RecordSize=0 THEN
  2092. 2072 FreeBlock(D.ID,LONGCARD(Size+SIZE(Size)),LastDataRef-SIZE(Size));
  2093. 2073 ELSE
  2094. 2074 FreeBlock(D.ID,LONGCARD(Size),LastDataRef);
  2095. 2075 END;
  2096. 2076 EXIT;
  2097. 2077 END;
  2098. 2078 FollowNextIndx(iH);
  2099. 2079 END;
  2100. 2080 EXIT;
  2101. 2081 END;
  2102. 2082 IF LastError(D)=OK THEN
  2103. 2083 INC(iwr^.RecordCnt);
  2104. 2084 END;
  2105. 2085 UnLockIx(D);
  2106. 2086 END;
  2107. 2087 UnLockFile(D.ID);
  2108. 2088 ELSE
  2109. 2089 SetErr(D,Locked);
  2110. 2090 END;
  2111. 2091 END;
  2112. 2092 END Add;
  2113. 2093
  2114. 2094
  2115. 2095 PROCEDURE Change(D: IHandle; Data: ARRAY OF BYTE; Length: CARDINAL);
  2116. 2096 VAR
  2117. 2097 BPos : LONGCARD;
  2118. 2098 size : CARDINAL;
  2119. 2099 t : CARDINAL;
  2120. 2100 iH : IHandle;
  2121. 2101 err : Errors;
  2122. 2102 OldKey,
  2123. 2103 NewKey : KeyType;
  2124. 2104 BEGIN
  2125. 2105 ClearErr(D);
  2126. 2106 IF NOT IsData(D) THEN
  2127. 2107 CallErr(D,NotData,'Change');
  2128. 2108 RETURN;
  2129. 2109 END;
  2130. 2110 IF D.ID^.ReadOnly THEN
  2131. 2111 CallErr(D,BadWrite,'Change with ReadOnly');
  2132. 2112 RETURN;
  2133. 2113 END;
  2134. 2114 IF (D.ID^.Id[D.In].iwr^.RecordSize=0) AND (D.ID^.fwr^.Mode=Compress) THEN
  2135. 2115 CallErr(D,BadSize,'Change');
  2136. 2116 RETURN;
  2137. 2117 END;
  2138. 2118 IF D.ID^.Id[D.In].LastDataRef=Nil THEN
  2139. 2119 CallErr(D,BadIndex,'Change');
  2140. 2120 RETURN;
  2141. 2121 END;
  2142. 2122 IF NOT cLocked(D,D.ID^.Id[D.In].LastDataRef) THEN
  2143. 2123 CallErr(D,NotLocked,'Change');
  2144. 2124 RETURN;
  2145. 2125 END;
  2146. 2126 LoadRec(D,D.ID^.Id[D.In].LastDataRef,BPos,size);
  2147. 2127 IF size#Length THEN
  2148. 2128 CallErr(D,BadSize,'Change');
  2149. 2129 RETURN;
  2150. 2130 END;
  2151. 2131 err := OK;
  2152. 2132 iH := D.ID^.Id[D.In].NextIndx;
  2153. 2133 LOOP
  2154. 2134 IF iH=Null THEN
  2155. 2135 EXIT;
  2156. 2136 END;
  2157. 2137 WITH iH.ID^.Id[iH.In] DO
  2158. 2138 KeyFct(ADR(OldKey),D.ID^.Id[D.In].bufPtr);
  2159. 2139 KeyFct(ADR(NewKey),ADR(Data));
  2160. 2140 IF CompFct(ADR(OldKey),ADR(NewKey))#Eq THEN
  2161. 2141 err := BadIndex;
  2162. 2142 EXIT;
  2163. 2143 END;
  2164. 2144 iH := NextIndx;
  2165. 2145 END;
  2166. 2146 END;
  2167. 2147 CallErr(D,err,'Change');
  2168. 2148 IF err=OK THEN
  2169. 2149 FIOx.Seek(D.ID^.FHandle,D.ID^.Id[D.In].LastDataRef);
  2170. 2150 IOabort('Change');
  2171. 2151 FIOx.Write(D.ID^.FHandle,Data,size);
  2172. 2152 IOabort('Change');
  2173. 2153 END;
  2174. 2154 END Change;
  2175. 2155
  2176. 2156
  2177. 2157 PROCEDURE SyncIx(iH: IHandle; rec: ARRAY OF BYTE);
  2178. 2158 VAR
  2179. 2159 tH : IHandle;
  2180. 2160 BEGIN
  2181. 2161 tH := iH.ID^.Id[iH.In].DataPtr;
  2182. 2162 IF tH.ID^.Id[tH.In].Sync THEN
  2183. 2163 LOOP
  2184. 2164 FollowNextIndx(tH);
  2185. 2165 IF tH=Null THEN
  2186. 2166 EXIT;
  2187. 2167 END;
  2188. 2168 IF tH#iH THEN
  2189. 2169 WITH tH.ID^.Id[tH.In] DO
  2190. 2170 LastKeyRef := iH.ID^.Id[iH.In].LastDataRef;
  2191. 2171 KeyFct(ADR(LastKey),ADR(rec));
  2192. 2172 LastKeyOK := TRUE;
  2193. 2173 PageLevel := 0;
  2194. 2174 END;
  2195. 2175 END;
  2196. 2176 END;
  2197. 2177 END;
  2198. 2178 END SyncIx;
  2199. 2179
  2200. 2180
  2201. 2181 PROCEDURE Search(I: IHandle; Key: ARRAY OF BYTE;
  2202. 2182 VAR Data: ARRAY OF BYTE): BOOLEAN;
  2203. 2183 VAR
  2204. 2184 r : BOOLEAN;
  2205. 2185 t : CARDINAL;
  2206. 2186 BEGIN
  2207. 2187 ClearErr(I);
  2208. 2188 IF NOT IsIndex(I) THEN
  2209. 2189 CallErr(I,NotIndex,'Search');
  2210. 2190 RETURN FALSE;
  2211. 2191 END;
  2212. 2192 Release(I);
  2213. 2193 IF cLockIHandle(I,Implicit) THEN
  2214. 2194 r := SearchIndex(I,Key,I.ID^.Id[I.In].LastDataRef);
  2215. 2195 WITH I.ID^.Id[I.In] DO
  2216. 2196 IF NOT r THEN
  2217. 2197 DataPtr.ID^.Id[DataPtr.In].LastDataRef := Nil;
  2218. 2198 ELSE
  2219. 2199 IF LockDat(I,LastDataRef) THEN
  2220. 2200 DataPtr.ID^.Id[DataPtr.In].LastDataRef := LastDataRef;
  2221. 2201 ReadRec(DataPtr,LastDataRef,Data);
  2222. 2202 (*
  2223. 2203 l := DataPtr.ID^.Id[DataPtr.In].iwr^.RecordSize;
  2224. 2204 IF l=0 THEN
  2225. 2205 FIOx.Seek(DataPtr.ID^.FHandle,LastDataRef-2);
  2226. 2206 IOabort('Search');
  2227. 2207 FIOx.Read(DataPtr.ID^.FHandle,l,2);
  2228. 2208 IOabort('Search');
  2229. 2209 ELSE
  2230. 2210 FIOx.Seek(DataPtr.ID^.FHandle,LastDataRef);
  2231. 2211 IOabort('Search');
  2232. 2212 END;
  2233. 2213 FIOx.Read(DataPtr.ID^.FHandle,Data,l);
  2234. 2214 IOabort('Search');
  2235. 2215 *)
  2236. 2216 SyncIx(I,Data);
  2237. 2217 ELSE
  2238. 2218 r := FALSE;
  2239. 2219 END;
  2240. 2220 END;
  2241. 2221 END;
  2242. 2222 cUnLockIHandle(I,Implicit);
  2243. 2223 RETURN r;
  2244. 2224 ELSE
  2245. 2225 RETURN FALSE;
  2246. 2226 END;
  2247. 2227 END Search;
  2248. 2228
  2249. 2229
  2250. 2230 PROCEDURE Find(I: IHandle; Key: ARRAY OF BYTE;
  2251. 2231 VAR Data: ARRAY OF BYTE): BOOLEAN;
  2252. 2232 VAR
  2253. 2233 r : BOOLEAN;
  2254. 2234 t : CARDINAL;
  2255. 2235 BEGIN
  2256. 2236 ClearErr(I);
  2257. 2237 IF NOT IsIndex(I) THEN
  2258. 2238 CallErr(I,NotIndex,'Find');
  2259. 2239 RETURN FALSE;
  2260. 2240 END;
  2261. 2241 Release(I);
  2262. 2242 IF cLockIHandle(I,Implicit) THEN
  2263. 2243 r := FindIndex(I,Key,I.ID^.Id[I.In].LastDataRef);
  2264. 2244 WITH I.ID^.Id[I.In] DO
  2265. 2245 IF r THEN
  2266. 2246 IF LockDat(I,LastDataRef) THEN
  2267. 2247 DataPtr.ID^.Id[DataPtr.In].LastDataRef := LastDataRef;
  2268. 2248 ReadRec(DataPtr,LastDataRef,Data);
  2269. 2249 (*
  2270. 2250 l := DataPtr.ID^.Id[DataPtr.In].iwr^.RecordSize;
  2271. 2251 IF l=0 THEN
  2272. 2252 FIOx.Seek(DataPtr.ID^.FHandle,LastDataRef-2);
  2273. 2253 IOabort('Find');
  2274. 2254 FIOx.Read(DataPtr.ID^.FHandle,l,2);
  2275. 2255 IOabort('Find');
  2276. 2256 ELSE
  2277. 2257 FIOx.Seek(DataPtr.ID^.FHandle,LastDataRef);
  2278. 2258 IOabort('Find');
  2279. 2259 END;
  2280. 2260 FIOx.Read(DataPtr.ID^.FHandle,Data,l);
  2281. 2261 IOabort('Find');
  2282. 2262 *)
  2283. 2263 SyncIx(I,Data);
  2284. 2264 ELSE
  2285. 2265 r := FALSE;
  2286. 2266 END;
  2287. 2267 ELSE
  2288. 2268 DataPtr.ID^.Id[DataPtr.In].LastDataRef := Nil;
  2289. 2269 END;
  2290. 2270 END;
  2291. 2271 cUnLockIHandle(I,Implicit);
  2292. 2272 RETURN r;
  2293. 2273 ELSE
  2294. 2274 RETURN FALSE;
  2295. 2275 END;
  2296. 2276 END Find;
  2297. 2277
  2298. 2278
  2299. 2279 PROCEDURE Next(I: IHandle; VAR Data: ARRAY OF BYTE): BOOLEAN;
  2300. 2280 VAR
  2301. 2281 SerKey : IndexItem;
  2302. 2282 Loc : LONGCARD;
  2303. 2283 r : CARDINAL;
  2304. 2284 ok : BOOLEAN;
  2305. 2285 BEGIN
  2306. 2286 ClearErr(I);
  2307. 2287 IF NOT IsIndex(I) THEN
  2308. 2288 CallErr(I,NotIndex,'Next');
  2309. 2289 RETURN FALSE;
  2310. 2290 END;
  2311. 2291 IF cLockIHandle(I,Implicit) THEN
  2312. 2292 WITH I.ID^.Id[I.In] DO
  2313. 2293 IF NextIndex(I,Loc) THEN
  2314. 2294 IF LockDat(I,Loc) THEN
  2315. 2295 DataPtr.ID^.Id[DataPtr.In].LastDataRef := Loc;
  2316. 2296 ReadRec(DataPtr,Loc,Data);
  2317. 2297 (*
  2318. 2298 l := DataPtr.ID^.Id[DataPtr.In].iwr^.RecordSize;
  2319. 2299 IF l=0 THEN
  2320. 2300 FIOx.Seek(DataPtr.ID^.FHandle,Loc-2);
  2321. 2301 IOabort('Next');
  2322. 2302 FIOx.Read(DataPtr.ID^.FHandle,l,2);
  2323. 2303 IOabort('Next');
  2324. 2304 ELSE
  2325. 2305 FIOx.Seek(DataPtr.ID^.FHandle,Loc);
  2326. 2306 IOabort('Next');
  2327. 2307 END;
  2328. 2308 FIOx.Read(DataPtr.ID^.FHandle,Data,l);
  2329. 2309 IOabort('Next');
  2330. 2310 *)
  2331. 2311 SyncIx(I,Data);
  2332. 2312 LastKeyOK := FALSE;
  2333. 2313 ok := TRUE;
  2334. 2314 ELSE
  2335. 2315 PageLevel := 0;
  2336. 2316 ok := FALSE;
  2337. 2317 END;
  2338. 2318 ELSE
  2339. 2319 ok := FALSE;
  2340. 2320 END;
  2341. 2321 END;
  2342. 2322 cUnLockIHandle(I,Implicit);
  2343. 2323 RETURN ok;
  2344. 2324 ELSE
  2345. 2325 RETURN FALSE;
  2346. 2326 END;
  2347. 2327 END Next;
  2348. 2328
  2349. 2329
  2350. 2330 PROCEDURE Prev(I: IHandle; VAR Data: ARRAY OF BYTE): BOOLEAN;
  2351. 2331 VAR
  2352. 2332 SerKey : IndexItem;
  2353. 2333 Loc : LONGCARD;
  2354. 2334 r : CARDINAL;
  2355. 2335 ok : BOOLEAN;
  2356. 2336 BEGIN
  2357. 2337 ClearErr(I);
  2358. 2338 IF NOT IsIndex(I) THEN
  2359. 2339 CallErr(I,NotIndex,'Prev');
  2360. 2340 RETURN FALSE;
  2361. 2341 END;
  2362. 2342 IF cLockIHandle(I,Implicit) THEN
  2363. 2343 WITH I.ID^.Id[I.In] DO
  2364. 2344 IF PrevIndex(I,Loc) THEN
  2365. 2345 IF LockDat(I,Loc) THEN
  2366. 2346 DataPtr.ID^.Id[DataPtr.In].LastDataRef := Loc;
  2367. 2347 ReadRec(DataPtr,Loc,Data);
  2368. 2348 (*
  2369. 2349 l := DataPtr.ID^.Id[DataPtr.In].iwr^.RecordSize;
  2370. 2350 IF l=0 THEN
  2371. 2351 FIOx.Seek(DataPtr.ID^.FHandle,Loc-2);
  2372. 2352 IOabort('Prev');
  2373. 2353 FIOx.Read(DataPtr.ID^.FHandle,l,2);
  2374. 2354 IOabort('Prev');
  2375. 2355 ELSE
  2376. 2356 FIOx.Seek(DataPtr.ID^.FHandle,Loc);
  2377. 2357 IOabort('Prev');
  2378. 2358 END;
  2379. 2359 FIOx.Read(DataPtr.ID^.FHandle,Data,l);
  2380. 2360 IOabort('Prev');
  2381. 2361 *)
  2382. 2362 SyncIx(I,Data);
  2383. 2363 LastKeyOK := FALSE;
  2384. 2364 ok := TRUE;
  2385. 2365 ELSE
  2386. 2366 PageLevel := 0;
  2387. 2367 ok := FALSE;
  2388. 2368 END;
  2389. 2369 ELSE
  2390. 2370 ok := FALSE;
  2391. 2371 END;
  2392. 2372 END;
  2393. 2373 cUnLockIHandle(I,Implicit);
  2394. 2374 RETURN ok;
  2395. 2375 ELSE
  2396. 2376 RETURN FALSE;
  2397. 2377 END;
  2398. 2378 END Prev;
  2399. 2379
  2400. 2380
  2401. 2381 PROCEDURE Reset(H: IHandle);
  2402. 2382 VAR
  2403. 2383 iH : IHandle;
  2404. 2384 BEGIN
  2405. 2385 ClearErr(H);
  2406. 2386 IF NOT IsIHandle(H) THEN
  2407. 2387 CallFErr(H.ID,NotIHandle,'Reset');
  2408. 2388 RETURN;
  2409. 2389 END;
  2410. 2390 IF IsData(H) THEN
  2411. 2391 iH := H.ID^.Id[H.In].NextIndx;
  2412. 2392 WHILE iH.ID#NIL DO
  2413. 2393 Reset(iH);
  2414. 2394 FollowNextIndx(iH);
  2415. 2395 END;
  2416. 2396 ELSE
  2417. 2397 H.ID^.Id[H.In].PageLevel := 0;
  2418. 2398 H.ID^.Id[H.In].LastKeyOK := FALSE;
  2419. 2399 Release(H);
  2420. 2400 END;
  2421. 2401 H.ID^.Id[H.In].LastDataRef := Nil;
  2422. 2402 END Reset;
  2423. 2403
  2424. 2404
  2425. 2405 PROCEDURE UpdateSlot(iH: IHandle);
  2426. 2406 BEGIN
  2427. 2407 FIOx.Seek(iH.ID^.FHandle,iH.ID^.Id[iH.In].ihLock.Position);
  2428. 2408 IOabort('UpdateSlot');
  2429. 2409 FIOx.Write(iH.ID^.FHandle,iH.ID^.Id[iH.In].iwr^,IndexDataWrSize);
  2430. 2410 IOabort('UpdateSlot');
  2431. 2411 END UpdateSlot;
  2432. 2412
  2433. 2413
  2434. 2414 PROCEDURE OpenIx(VAR iH: IHandle; CmpFct: CompareFunction; KeSize: CARDINAL;
  2435. 2415 DpKey: BOOLEAN; Create: BOOLEAN);
  2436. 2416 VAR
  2437. 2417 t : TPage;
  2438. 2418 i,
  2439. 2419 r : CARDINAL;
  2440. 2420 BEGIN
  2441. 2421 WITH iH.ID^.Id[iH.In] DO
  2442. 2422 LastDataRef := Nil;
  2443. 2423 NextIndx := Null;
  2444. 2424 LastErr := OK;
  2445. 2425 ErrorNest := 0;
  2446. 2426 DataPtr := Null;
  2447. 2427 PageLevel := 0;
  2448. 2428 CompFct := CmpFct;
  2449. 2429 KeyFct := NULLPROC;
  2450. 2430 LastKeyOK := FALSE;
  2451. 2431 IF Create THEN
  2452. 2432 OldWriteCnt := 0;
  2453. 2433 AllocMem(PageRefs,VSIZE(PageRef.Height)+10*SIZE(PageRefRec));
  2454. 2434 Die(PageRefs=NIL,OutOfMemory);
  2455. 2435 PageRefs^.Height := 10;
  2456. 2436 iwr^.RecordCnt := 0;
  2457. 2437 iwr^.WriteCnt := 0;
  2458. 2438 IF iH.In=0 THEN
  2459. 2439 iwr^.TopPage := iH.ID^.fwr^.FileSize;
  2460. 2440 INC(iH.ID^.fwr^.FileSize,PageSize);
  2461. 2441 ELSE
  2462. 2442 iwr^.TopPage := AllocateBlock(iH.ID,PageSize);
  2463. 2443 END;
  2464. 2444 iwr^.Depth := 1;
  2465. 2445 iwr^.KeySize := KeSize;
  2466. 2446 iwr^.N2 := N2Eval(KeSize);
  2467. 2447 IF iwr^.N2=MAX(CARDINAL) THEN
  2468. 2448 SetFErr(iH.ID,KeyTooBig);
  2469. 2449 RETURN;
  2470. 2450 END;
  2471. 2451 iwr^.N22 := iwr^.N2 DIV 2;
  2472. 2452 iwr^.DupKey := DpKey;
  2473. 2453 (* create empty Root Page *)
  2474. 2454 t.ICount := 0;
  2475. 2455 t.IItem.IP := Nil;
  2476. 2456 iwr^.Ft := IndexSlot;
  2477. 2457 FIOx.Seek(iH.ID^.FHandle,iwr^.TopPage);
  2478. 2458 IOabort('OpenIx');
  2479. 2459 FIOx.Write(iH.ID^.FHandle,t,SIZE(t));
  2480. 2460 IOabort('OpenIx');
  2481. 2461 UpdateSlot(iH);
  2482. 2462 ELSE
  2483. 2463 IF (iwr^.Ft#IndexSlot) OR (iwr^.KeySize#KeSize) OR (iwr^.DupKey#DpKey) THEN
  2484. 2464 CallFErr(iH.ID,BadIndex,'OpenIx');
  2485. 2465 RETURN;
  2486. 2466 END;
  2487. 2467 OldWriteCnt := iwr^.WriteCnt;
  2488. 2468 i := 10;
  2489. 2469 IF i+2 < iwr^.Depth THEN
  2490. 2470 i := (iwr^.Depth-i)*2+i;
  2491. 2471 END;
  2492. 2472 AllocMem(PageRefs,VSIZE(PageRef.Height)+i*SIZE(PageRefRec));
  2493. 2473 Die(PageRefs=NIL,OutOfMemory);
  2494. 2474 PageRefs^.Height := i;
  2495. 2475 END;
  2496. 2476 Ft := IndexSlot;
  2497. 2477 END;
  2498. 2478 END OpenIx;
  2499. 2479
  2500. 2480
  2501. 2481 (*# save *)
  2502. 2482 (*%T _fcall *) (*# call(near_call=>off) *) (*%E *)
  2503. 2483 PROCEDURE SizeCmp4(VAR a,b: LONGCARD): CmpRes;
  2504. 2484 BEGIN
  2505. 2485 IF a < b THEN
  2506. 2486 RETURN Less;
  2507. 2487 ELSIF a = b THEN
  2508. 2488 RETURN Eq;
  2509. 2489 ELSE
  2510. 2490 RETURN Greater;
  2511. 2491 END;
  2512. 2492 END SizeCmp4;
  2513. 2493 (*# restore *)
  2514. 2494
  2515. 2495
  2516. 2496 (*# save *)
  2517. 2497 (*%T _fcall *) (*# call(near_call=>off) *) (*%E *)
  2518. 2498 PROCEDURE SizeCmp2(VAR a,b: CARDINAL): CmpRes;
  2519. 2499 BEGIN
  2520. 2500 IF a < b THEN
  2521. 2501 RETURN Less;
  2522. 2502 ELSIF a = b THEN
  2523. 2503 RETURN Eq;
  2524. 2504 ELSE
  2525. 2505 RETURN Greater;
  2526. 2506 END;
  2527. 2507 END SizeCmp2;
  2528. 2508 (*# restore *)
  2529. 2509
  2530. 2510
  2531. 2511 PROCEDURE Open(Name: ARRAY OF CHAR; MaxIHandle: CARDINAL; AMode : AccessMode;
  2532. 2512 readOnly, shared, Create: BOOLEAN): FHandle;
  2533. 2513
  2534. 2514 VAR
  2535. 2515 iH : IHandle;
  2536. 2516 h,
  2537. 2517 r,
  2538. 2518 i : CARDINAL;
  2539. 2519 lck : FIOx.LockRec;
  2540. 2520
  2541. 2521 (*# save *)
  2542. 2522 (*# call(o_a_size=>on) *)
  2543. 2523 PROCEDURE Abort(str : ARRAY OF CHAR);
  2544. 2524 BEGIN
  2545. 2525 IF iH.ID # NIL THEN
  2546. 2526 IF iH.ID^.FHandle#MAX(CARDINAL) THEN
  2547. 2527 FIOx.Close(iH.ID^.FHandle);
  2548. 2528 IOabort('Open.Abort');
  2549. 2529 END;
  2550. 2530 FreeMem(iH.ID);
  2551. 2531 END;
  2552. 2532 CallErr(Null,BadOpen,str);
  2553. 2533 END Abort;
  2554. 2534 (*# restore *)
  2555. 2535
  2556. 2536 BEGIN
  2557. 2537 IF (AMode=Compress) AND NOT Packing() THEN
  2558. 2538 CallErr(Null,BadOpen,'Compress w/o PACK');
  2559. 2539 RETURN NIL;
  2560. 2540 END;
  2561. 2541 IF readOnly AND Create THEN
  2562. 2542 CallErr(Null,BadOpen,'ReadOnly with Create');
  2563. 2543 RETURN NIL;
  2564. 2544 END;
  2565. 2545 IF shared AND Create THEN
  2566. 2546 CallErr(Null,BadOpen,'Shared with Create');
  2567. 2547 END;
  2568. 2548 r := FIOx.Open(Name,shared,readOnly,Create);
  2569. 2549 IF r=MAX(CARDINAL) THEN
  2570. 2550 CallErr(Null,FileError,'Create');
  2571. 2551 RETURN NIL;
  2572. 2552 END;
  2573. 2553 h := SIZE(IndexDataWr)*MaxIHandle+SIZE(IndexFileWr);
  2574. 2554 IF h MOD SectorSize#0 THEN
  2575. 2555 h := h+SectorSize-(h MOD SectorSize);
  2576. 2556 END;
  2577. 2557 i := IndexDataSize*MaxIHandle+IndexFileSize+h;
  2578. 2558 AllocMem(iH.ID,i);
  2579. 2559 Die(iH.ID=NIL,OutOfMemory);
  2580. 2560 iH.In := 0;
  2581. 2561 WITH iH.ID^ DO
  2582. 2562 ReadOnly := readOnly;
  2583. 2563 Buffered := NOT shared OR readOnly OR NOT FIOx.MultiFile(r);
  2584. 2564 WriteThru := FALSE;
  2585. 2565 FOR i := 0 TO LockQSize-1 DO
  2586. 2566 Locks[i] := LockRec(Nil,0,0,Null);
  2587. 2567 END;
  2588. 2568 fhLock := LockRec(0,0,0,Null);
  2589. 2569 FHandle := r;
  2590. 2570 fwr := AddAddr(iH.ID,IndexFileSize+IndexDataSize*MaxIHandle);
  2591. 2571 FOR i := 0 TO MaxIHandle DO
  2592. 2572 WITH Id[i] DO
  2593. 2573 ihLock := LockRec(0,0,0,Null);
  2594. 2574 ihLock.Position := SIZE(IndexFileWr)+SIZE(IndexDataWr)*VAL(LONGCARD,i);
  2595. 2575 Ft := FreeSlot;
  2596. 2576 iwr := AddAddr(fwr,VAL(CARDINAL,ihLock.Position));
  2597. 2577 END;
  2598. 2578 END;
  2599. 2579 IF Create THEN
  2600. 2580 fwr^.HeaderSize := h;
  2601. 2581 fwr^.FileSize := VAL(LONGCARD,h);
  2602. 2582 fwr^.Version := ThisVersion;
  2603. 2583 fwr^.FreeList := Nil;
  2604. 2584 fwr^.IndexCount :=MaxIHandle;
  2605. 2585 fwr^.Mode := AMode;
  2606. 2586 fwr^.PageSz := PageSize;
  2607. 2587 fwr^.MaxKeySz := MaxKeySize;
  2608. 2588 FOR i := 0 TO MaxIHandle DO
  2609. 2589 Id[i].iwr^.Ft := FreeSlot;
  2610. 2590 END;
  2611. 2591 FIOx.Write(FHandle,fwr^,fwr^.HeaderSize);
  2612. 2592 IOabort('Open');
  2613. 2593 ELSE
  2614. 2594 lck.pos := 0;
  2615. 2595 lck.len := SIZE(fwr^.HeaderSize);
  2616. 2596 IF NOT Buffered AND NOT FIOx.Lock(FHandle,lck) THEN
  2617. 2597 Abort('Lock failure');
  2618. 2598 RETURN NIL;
  2619. 2599 END;
  2620. 2600 FIOx.Read(FHandle,fwr^.HeaderSize,SIZE(fwr^.HeaderSize));
  2621. 2601 IF NOT Buffered THEN
  2622. 2602 FIOx.UnLock(FHandle,lck);
  2623. 2603 END;
  2624. 2604 IF FIOx.Error()#FIOx.PAST_EOF THEN
  2625. 2605 IOabort('Open');
  2626. 2606 END;
  2627. 2607 IF (FIOx.Error()=FIOx.PAST_EOF) OR (h#fwr^.HeaderSize) THEN
  2628. 2608 Abort('HeaderSize');
  2629. 2609 RETURN NIL;
  2630. 2610 END;
  2631. 2611 lck.pos := 0;
  2632. 2612 lck.len := VAL(LONGCARD,fwr^.HeaderSize);
  2633. 2613 IF NOT Buffered AND NOT FIOx.Lock(FHandle,lck) THEN
  2634. 2614 Abort('Lock failure(2)');
  2635. 2615 END;
  2636. 2616 FIOx.Read(FHandle,fwr^.FileSize,fwr^.HeaderSize-SIZE(fwr^.HeaderSize));
  2637. 2617 IF NOT Buffered THEN
  2638. 2618 FIOx.UnLock(FHandle,lck);
  2639. 2619 END;
  2640. 2620 IF FIOx.Error()#FIOx.PAST_EOF THEN
  2641. 2621 IOabort('Open');
  2642. 2622 END;
  2643. 2623 IF FIOx.Error()=FIOx.PAST_EOF THEN
  2644. 2624 Abort('I/O Error');
  2645. 2625 RETURN NIL;
  2646. 2626 ELSIF (fwr^.Version DIV 10) # (ThisVersion DIV 10) THEN
  2647. 2627 Abort('Version'); (* The version number's ones digit isn't tested! *)
  2648. 2628 RETURN NIL;
  2649. 2629 ELSIF fwr^.Mode#AMode THEN
  2650. 2630 Abort('Accessmode');
  2651. 2631 RETURN NIL;
  2652. 2632 ELSIF fwr^.IndexCount#MaxIHandle THEN
  2653. 2633 Abort('MaxIHandle');
  2654. 2634 RETURN NIL;
  2655. 2635 ELSIF fwr^.PageSz#PageSize THEN
  2656. 2636 Abort('PageSize');
  2657. 2637 RETURN NIL;
  2658. 2638 ELSIF fwr^.MaxKeySz#MaxKeySize THEN
  2659. 2639 Abort('MaxKeySize');
  2660. 2640 RETURN NIL;
  2661. 2641 END;
  2662. 2642 END;
  2663. 2643 IF AMode=Size32 THEN
  2664. 2644 OpenIx(iH,CompareFunction(SizeCmp4),4,TRUE,Create);
  2665. 2645 ELSE
  2666. 2646 OpenIx(iH,CompareFunction(SizeCmp2),2,TRUE,Create);
  2667. 2647 END;
  2668. 2648 IF iH=Null THEN
  2669. 2649 Abort('Unknown error');
  2670. 2650 RETURN NIL;
  2671. 2651 END;
  2672. 2652 END;
  2673. 2653 iH.ID^.G1 := GuardV1;
  2674. 2654 iH.ID^.G2 := GuardV2;
  2675. 2655 ClearFErr(iH.ID);
  2676. 2656 RETURN iH.ID;
  2677. 2657 END Open;
  2678. 2658
  2679. 2659
  2680. 2660 PROCEDURE OpenIndex(F: FHandle; D: IHandle; I: CARDINAL;
  2681. 2661 CmpFct: CompareFunction; KeFct: KeyFunction;
  2682. 2662 KeSize: CARDINAL; DpKey,New: BOOLEAN): IHandle;
  2683. 2663 VAR
  2684. 2664 iH : IHandle;
  2685. 2665 idx : CARDINAL;
  2686. 2666 BEGIN
  2687. 2667 ClearFErr(F);
  2688. 2668 IF NOT IsFHandle(F) THEN
  2689. 2669 CallFErr(F,NotFHandle,'OpenIndex');
  2690. 2670 RETURN Null;
  2691. 2671 END;
  2692. 2672 IF (D#Null) AND NOT IsData(D) THEN
  2693. 2673 CallFErr(F,NotData,'OpenIndex');
  2694. 2674 RETURN Null;
  2695. 2675 END;
  2696. 2676 IF New AND NOT F^.Buffered THEN
  2697. 2677 CallFErr(F,BadOpen,'New with Sharing');
  2698. 2678 RETURN Null;
  2699. 2679 END;
  2700. 2680 IF (F^.fwr^.IndexCount<I) OR ((F^.Id[I].iwr^.Ft#FreeSlot)=New) THEN
  2701. 2681 CallFErr(F,NoSlot,'Index');
  2702. 2682 RETURN Null;
  2703. 2683 END;
  2704. 2684 IF New AND F^.ReadOnly THEN
  2705. 2685 CallFErr(F,BadOpen,'New with ReadOnly');
  2706. 2686 RETURN Null;
  2707. 2687 END;
  2708. 2688 iH.ID := F;
  2709. 2689 iH.In := I;
  2710. 2690 OpenIx(iH,CmpFct,KeSize,DpKey,New);
  2711. 2691 IF iH#Null THEN
  2712. 2692 WITH iH.ID^.Id[I] DO
  2713. 2693 IF (KeFct#NULLPROC) AND (D#Null) THEN
  2714. 2694 KeyFct := KeFct;
  2715. 2695 NextIndx := D.ID^.Id[D.In].NextIndx;
  2716. 2696 D.ID^.Id[D.In].NextIndx := iH;
  2717. 2697 DataPtr := D;
  2718. 2698 END;
  2719. 2699 END;
  2720. 2700 END;
  2721. 2701 RETURN iH;
  2722. 2702 END OpenIndex;
  2723. 2703
  2724. 2704
  2725. 2705 PROCEDURE OpenData(F: FHandle; I,RSize: CARDINAL; New: BOOLEAN): IHandle;
  2726. 2706 VAR
  2727. 2707 dH : IHandle;
  2728. 2708 BEGIN
  2729. 2709 ClearFErr(F);
  2730. 2710 IF NOT IsFHandle(F) THEN
  2731. 2711 CallFErr(F,NotFHandle,'OpenData');
  2732. 2712 RETURN Null;
  2733. 2713 END;
  2734. 2714 IF New AND NOT F^.Buffered THEN
  2735. 2715 CallFErr(F,BadOpen,'New with Sharing');
  2736. 2716 RETURN Null;
  2737. 2717 END;
  2738. 2718 IF (F^.fwr^.IndexCount<I) OR ((F^.Id[I].iwr^.Ft#FreeSlot)=New) THEN
  2739. 2719 CallFErr(F,NoSlot,'Data');
  2740. 2720 RETURN Null;
  2741. 2721 END;
  2742. 2722 IF (RSize=0) AND (F^.fwr^.Mode=FixSize) THEN
  2743. 2723 CallFErr(F,BadOpen,'OpenData');
  2744. 2724 RETURN Null;
  2745. 2725 END;
  2746. 2726 IF New AND F^.ReadOnly THEN
  2747. 2727 CallFErr(F,BadOpen,'New with ReadOnly');
  2748. 2728 END;
  2749. 2729 dH.ID := F;
  2750. 2730 dH.In := I;
  2751. 2731 WITH dH.ID^.Id[dH.In] DO
  2752. 2732 LastDataRef := Nil;
  2753. 2733 NextIndx := Null;
  2754. 2734 LastErr := OK;
  2755. 2735 ErrorNest := 0;
  2756. 2736 Sync := FALSE;
  2757. 2737 bufSize := RSize;
  2758. 2738 IF RSize=0 THEN
  2759. 2739 bufPtr := NIL;
  2760. 2740 ELSE
  2761. 2741 AllocMem(bufPtr,RSize);
  2762. 2742 Die(bufPtr=NIL,OutOfMemory);
  2763. 2743 END;
  2764. 2744 IF New THEN
  2765. 2745 iwr^.Ft := DataSlot;
  2766. 2746 iwr^.RecordSize := RSize;
  2767. 2747 iwr^.RecordCnt := 0;
  2768. 2748 UpdateSlot(dH);
  2769. 2749 ELSE
  2770. 2750 IF iwr^.Ft # DataSlot THEN
  2771. 2751 CallFErr(F,NotData,'OpenData');
  2772. 2752 RETURN Null;
  2773. 2753 ELSIF iwr^.RecordSize # RSize THEN
  2774. 2754 CallFErr(F,BadSize,'OpenData');
  2775. 2755 RETURN Null;
  2776. 2756 END;
  2777. 2757 END;
  2778. 2758 Ft := DataSlot;
  2779. 2759 END;
  2780. 2760 RETURN dH;
  2781. 2761 END OpenData;
  2782. 2762
  2783. 2763
  2784. 2764 PROCEDURE FreeIHandle(VAR H: IHandle);
  2785. 2765 VAR
  2786. 2766 dH : IHandle;
  2787. 2767 iH : IHandle;
  2788. 2768 BEGIN
  2789. 2769 ClearErr(H);
  2790. 2770 ClearFErr(H.ID);
  2791. 2771 IF NOT IsIHandle(H) THEN
  2792. 2772 CallFErr(H.ID,NotIHandle,'FreeIHandle');
  2793. 2773 RETURN;
  2794. 2774 END;
  2795. 2775 IF NOT H.ID^.Buffered AND IsIndex(H) AND (H.ID^.Id[H.In].DataPtr#Null) THEN
  2796. 2776 CallErr(H,BadFree,'FreeIHandle');
  2797. 2777 RETURN;
  2798. 2778 END;
  2799. 2779 IF IsData(H) THEN
  2800. 2780 dH := H.ID^.Id[H.In].NextIndx;
  2801. 2781 WHILE dH # Null DO
  2802. 2782 iH := dH;
  2803. 2783 FollowNextIndx(dH);
  2804. 2784 iH.ID^.Id[iH.In].NextIndx := Null;
  2805. 2785 iH.ID^.Id[iH.In].DataPtr := Null;
  2806. 2786 FreeIHandle(iH);
  2807. 2787 END;
  2808. 2788 ELSE
  2809. 2789 dH := H.ID^.Id[H.In].DataPtr;
  2810. 2790 LOOP
  2811. 2791 IF dH.ID=NIL THEN
  2812. 2792 EXIT;
  2813. 2793 END;
  2814. 2794 iH := dH.ID^.Id[dH.In].NextIndx;
  2815. 2795 IF iH=H THEN
  2816. 2796 dH.ID^.Id[dH.In].NextIndx := iH.ID^.Id[iH.In].NextIndx;
  2817. 2797 EXIT;
  2818. 2798 END;
  2819. 2799 FollowNextIndx(dH);
  2820. 2800 END;
  2821. 2801 END;
  2822. 2802 WITH H.ID^.Id[H.In] DO
  2823. 2803 CASE Ft OF
  2824. 2804 IndexSlot : FreeMem(PageRefs);
  2825. 2805 SaveBuffers(H);
  2826. 2806 ClearBuffers(H);
  2827. 2807 | DataSlot : FreeMem(bufPtr);
  2828. 2808 ELSE
  2829. 2809 (* ignore *)
  2830. 2810 END;
  2831. 2811 Ft := FreeSlot;
  2832. 2812 DataPtr := Null;
  2833. 2813 END;
  2834. 2814 H := Null;
  2835. 2815 END FreeIHandle;
  2836. 2816
  2837. 2817
  2838. 2818 PROCEDURE ClearIndex(VAR I: IHandle);
  2839. 2819
  2840. 2820 VAR
  2841. 2821 TP : TPage;
  2842. 2822
  2843. 2823 TYPE
  2844. 2824 IPtr = POINTER Seg(TP) TO IndexItem;
  2845. 2825 A2 = ARRAY[0..1] OF SHORTCARD;
  2846. 2826
  2847. 2827 (*# save *)
  2848. 2828 (*# call(inline=>on) *)
  2849. 2829 (*# call(reg_param=>(ax,cx),reg_saved=>(bx,cx,dx,si,di,ds,es,st1,st2,st3,st4,st5,st6)) *)
  2850. 2830 PROCEDURE AddIPtr(A: IPtr; I: CARDINAL): IPtr=A2(003H,0C1H);(*add ax,cx*)
  2851. 2831 (*# restore *)
  2852. 2832
  2853. 2833 PROCEDURE Free(Page: LONGCARD; Level: CARDINAL);
  2854. 2834 VAR
  2855. 2835 i : CARDINAL;
  2856. 2836 IP : IPtr;
  2857. 2837 BEGIN
  2858. 2838 WITH I.ID^.Id[I.In] DO
  2859. 2839 IF Level=iwr^.Depth THEN
  2860. 2840 ClearPage(I,Page);
  2861. 2841 FreeBlock(I.ID,PageSize,Page);
  2862. 2842 ELSE
  2863. 2843 i := 0;
  2864. 2844 IP := IPtr(Ofs((TP.IItem)));
  2865. 2845 LOOP
  2866. 2846 ReadPage(I,Page,TP);
  2867. 2847 IF i>TP.ICount THEN
  2868. 2848 EXIT;
  2869. 2849 END;
  2870. 2850 Free(IP^.IP,Level+1);
  2871. 2851 INC(i);
  2872. 2852 IncAddr(IP,8+iwr^.KeySize);
  2873. 2853 END;
  2874. 2854 ClearPage(I,Page);
  2875. 2855 FreeBlock(I.ID,PageSize,Page);
  2876. 2856 END;
  2877. 2857 END;
  2878. 2858 END Free;
  2879. 2859
  2880. 2860 BEGIN
  2881. 2861 ClearErr(I);
  2882. 2862 ClearFErr(I.ID);
  2883. 2863 IF NOT IsIndex(I) THEN
  2884. 2864 CallErr(I,NotIndex,'ClearIndex');
  2885. 2865 RETURN;
  2886. 2866 END;
  2887. 2867 IF NOT I.ID^.Buffered THEN
  2888. 2868 CallErr(I,BadFree,'ClearIndex');
  2889. 2869 RETURN;
  2890. 2870 END;
  2891. 2871 IF I.ID^.ReadOnly THEN
  2892. 2872 CallErr(I,BadWrite,'ClearIndex with ReadOnly');
  2893. 2873 END;
  2894. 2874 Free(I.ID^.Id[I.In].iwr^.TopPage,1);
  2895. 2875 FreeIHandle(I);
  2896. 2876 END ClearIndex;
  2897. 2877
  2898. 2878
  2899. 2879 PROCEDURE Close(VAR F: FHandle);
  2900. 2880 VAR
  2901. 2881 idx : CARDINAL;
  2902. 2882 iH : IHandle;
  2903. 2883 BEGIN
  2904. 2884 ClearFErr(F);
  2905. 2885 IF NOT IsFHandle(F) THEN
  2906. 2886 CallFErr(F,NotFHandle,'Close');
  2907. 2887 RETURN;
  2908. 2888 END;
  2909. 2889 iH.ID := F;
  2910. 2890 iH.In := MAX(CARDINAL);
  2911. 2891 SaveBuffers(iH);
  2912. 2892 ClearBuffers(iH);
  2913. 2893 Flush(F);
  2914. 2894 iH.In := 0;
  2915. 2895 WITH F^ DO
  2916. 2896 IF NOT Buffered THEN
  2917. 2897 FOR idx := 0 TO LockQSize-1 DO
  2918. 2898 IF Locks[idx].Position#Nil THEN
  2919. 2899 ccUnLock(iH,Locks[idx],AllLocks);
  2920. 2900 END;
  2921. 2901 END;
  2922. 2902 END;
  2923. 2903 FOR idx := 0 TO F^.fwr^.IndexCount DO
  2924. 2904 WITH Id[idx] DO
  2925. 2905 IF NOT Buffered AND ((ihLock.ICnt#0) OR (ihLock.ECnt#0)) THEN
  2926. 2906 ccUnLock(iH,ihLock,AllLocks);
  2927. 2907 END;
  2928. 2908 CASE Ft OF
  2929. 2909 IndexSlot : FreeMem(PageRefs);
  2930. 2910 | DataSlot : FreeMem(bufPtr);
  2931. 2911 ELSE
  2932. 2912 (* ignore *)
  2933. 2913 END;
  2934. 2914 END;
  2935. 2915 END;
  2936. 2916 IF NOT Buffered AND ((fhLock.ICnt#0) OR (fhLock.ECnt#0)) THEN
  2937. 2917 ccUnLock(iH,fhLock,AllLocks);
  2938. 2918 END;
  2939. 2919 FIOx.Close(FHandle);
  2940. 2920 END;
  2941. 2921 F^.G1 := 0;
  2942. 2922 F^.G2 := 0;
  2943. 2923 FreeMem(F);
  2944. 2924 END Close;
  2945. 2925
  2946. 2926
  2947. 2927 PROCEDURE Allocate(F: FHandle; Length: LONGCARD): LONGCARD;
  2948. 2928 VAR
  2949. 2929 Pos : LONGCARD;
  2950. 2930 iH : IHandle;
  2951. 2931 ok : BOOLEAN;
  2952. 2932 BEGIN
  2953. 2933 ClearFErr(F);
  2954. 2934 IF NOT IsFHandle(F) THEN
  2955. 2935 CallFErr(F,NotFHandle,'Allocate');
  2956. 2936 RETURN MAX(LONGCARD);
  2957. 2937 END;
  2958. 2938 IF F^.ReadOnly THEN
  2959. 2939 CallFErr(F,BadWrite,'Allocate with ReadOnly');
  2960. 2940 RETURN MAX(LONGCARD);
  2961. 2941 END;
  2962. 2942 IF LockFile(F) THEN
  2963. 2943 Pos := AllocateBlock(F,Length+4);
  2964. 2944 IF Pos=Nil THEN
  2965. 2945 CallFErr(F,FileError,'Allocate');
  2966. 2946 RETURN Nil;
  2967. 2947 END;
  2968. 2948 FIOx.Seek(F^.FHandle,Pos);
  2969. 2949 IOabort('Allocate');
  2970. 2950 FIOx.Write(F^.FHandle,Length+4,4);
  2971. 2951 IOabort('Allocate');
  2972. 2952 iH.ID := F;
  2973. 2953 iH.In := 0;
  2974. 2954 ok := cLock(iH,Pos+4,Explicit);
  2975. 2955 UnLockFile(F);
  2976. 2956 RETURN Pos+4;
  2977. 2957 ELSE
  2978. 2958 RETURN MAX(LONGCARD);
  2979. 2959 END;
  2980. 2960 END Allocate;
  2981. 2961
  2982. 2962
  2983. 2963 PROCEDURE DeAllocate(F: FHandle; Position: LONGCARD);
  2984. 2964 VAR
  2985. 2965 Len : LONGCARD;
  2986. 2966 r : CARDINAL;
  2987. 2967 iH : IHandle;
  2988. 2968 BEGIN
  2989. 2969 ClearFErr(F);
  2990. 2970 IF NOT IsFHandle(F) THEN
  2991. 2971 CallFErr(F,NotFHandle,'DeAllocate');
  2992. 2972 RETURN;
  2993. 2973 END;
  2994. 2974 IF F^.ReadOnly THEN
  2995. 2975 CallFErr(F,BadWrite,'DeAllocate with ReadOnly');
  2996. 2976 RETURN;
  2997. 2977 END;
  2998. 2978 iH.ID := F;
  2999. 2979 iH.In := 0;
  3000. 2980 IF NOT cLocked(iH,Position) THEN
  3001. 2981 CallFErr(F,NotLocked,'Write');
  3002. 2982 END;
  3003. 2983 SetFErr(F,OK);
  3004. 2984 IF LockFile(F) THEN
  3005. 2985 FIOx.Seek(F^.FHandle,Position-4);
  3006. 2986 IOabort('DeAllocate');
  3007. 2987 FIOx.Read(F^.FHandle,Len,4);
  3008. 2988 IOabort('DeAllocate');
  3009. 2989 FreeBlock(F,Len,Position-4);
  3010. 2990 cUnLock(iH,Position,AllLocks);
  3011. 2991 UnLockFile(F);
  3012. 2992 END;
  3013. 2993 END DeAllocate;
  3014. 2994
  3015. 2995
  3016. 2996 PROCEDURE Read(F: FHandle; Position: LONGCARD; Length: CARDINAL;
  3017. 2997 VAR Data: ARRAY OF BYTE);
  3018. 2998 VAR
  3019. 2999 iH : IHandle;
  3020. 3000 BEGIN
  3021. 3001 ClearFErr(F);
  3022. 3002 IF NOT IsFHandle(F) THEN
  3023. 3003 CallFErr(F,NotFHandle,'Read');
  3024. 3004 RETURN;
  3025. 3005 END;
  3026. 3006 iH.ID := F;
  3027. 3007 iH.In := 0;
  3028. 3008 IF NOT cLocked(iH,Position) THEN
  3029. 3009 CallFErr(F,NotLocked,'Read');
  3030. 3010 END;
  3031. 3011 SetFErr(F,OK);
  3032. 3012 FIOx.Seek(F^.FHandle,Position);
  3033. 3013 IOabort('Read');
  3034. 3014 FIOx.Read(F^.FHandle,Data,Length);
  3035. 3015 IOabort('Read');
  3036. 3016 END Read;
  3037. 3017
  3038. 3018
  3039. 3019 PROCEDURE Write(F: FHandle; Position: LONGCARD; Length: CARDINAL;
  3040. 3020 Data: ARRAY OF BYTE);
  3041. 3021 VAR
  3042. 3022 iH : IHandle;
  3043. 3023 BEGIN
  3044. 3024 ClearFErr(F);
  3045. 3025 IF NOT IsFHandle(F) THEN
  3046. 3026 CallFErr(F,NotFHandle,'Write');
  3047. 3027 RETURN;
  3048. 3028 END;
  3049. 3029 IF F^.ReadOnly THEN
  3050. 3030 CallFErr(F,BadWrite,'Write with ReadOnly');
  3051. 3031 RETURN;
  3052. 3032 END;
  3053. 3033 iH.ID := F;
  3054. 3034 iH.In := 0;
  3055. 3035 IF NOT cLocked(iH,Position) THEN
  3056. 3036 CallFErr(F,NotLocked,'Write');
  3057. 3037 END;
  3058. 3038 FIOx.Seek(F^.FHandle,Position);
  3059. 3039 IOabort('Write');
  3060. 3040 FIOx.Write(F^.FHandle,Data,Length);
  3061. 3041 IOabort('Write');
  3062. 3042 END Write;
  3063. 3043
  3064. 3044
  3065. 3045 PROCEDURE Flush(F: FHandle);
  3066. 3046 VAR
  3067. 3047 idx : CARDINAL;
  3068. 3048 iH : IHandle;
  3069. 3049 BEGIN
  3070. 3050 ClearFErr(F);
  3071. 3051 IF NOT IsFHandle(F) THEN
  3072. 3052 CallFErr(F,NotFHandle,'Flush');
  3073. 3053 RETURN;
  3074. 3054 END;
  3075. 3055 iH.ID := F;
  3076. 3056 IF F^.Buffered THEN
  3077. 3057 FOR idx := 0 TO F^.fwr^.IndexCount DO
  3078. 3058 iH.In := idx;
  3079. 3059 FlushIHandle(iH);
  3080. 3060 END;
  3081. 3061 FlushFHandle(F);
  3082. 3062 ELSE
  3083. 3063 FOR idx := 0 TO F^.fwr^.IndexCount DO
  3084. 3064 WITH F^.Id[idx] DO
  3085. 3065 IF (Ft#FreeSlot) AND ((ihLock.ECnt#0) OR (ihLock.ICnt#0)) THEN
  3086. 3066 iH.In := idx;
  3087. 3067 FlushIHandle(iH);
  3088. 3068 END;
  3089. 3069 END;
  3090. 3070 END;
  3091. 3071 IF (F^.fhLock.ECnt#0) OR (F^.fhLock.ICnt#0) THEN
  3092. 3072 FlushFHandle(F);
  3093. 3073 END;
  3094. 3074 END;
  3095. 3075 FIOx.Flush(F^.FHandle);
  3096. 3076 END Flush;
  3097. 3077
  3098. 3078
  3099. 3079 PROCEDURE AddIndex(I: IHandle; Key: ARRAY OF BYTE; DataLoc: LONGCARD);
  3100. 3080
  3101. 3081 VAR
  3102. 3082 TP : xTPage;
  3103. 3083
  3104. 3084 TYPE
  3105. 3085 IPtr = POINTER Seg(TP) TO IndexItem;
  3106. 3086 A2 = ARRAY[0..1] OF SHORTCARD;
  3107. 3087
  3108. 3088 (*# save *)
  3109. 3089 (*# call(inline=>on) *)
  3110. 3090 (*# call(reg_param=>(ax,cx),reg_saved=>(bx,cx,dx,si,di,ds,es,st1,st2,st3,st4,st5,st6)) *)
  3111. 3091 PROCEDURE AddIPtr(A: IPtr; I: CARDINAL): IPtr=A2(003H,0C1H);(*add ax,cx*)
  3112. 3092 (*# restore *)
  3113. 3093
  3114. 3094 VAR
  3115. 3095 InsKey : IndexItem;
  3116. 3096 C : CmpRes;
  3117. 3097 r,
  3118. 3098 Level : CARDINAL;
  3119. 3099 b : BOOLEAN;
  3120. 3100 ItemSize : CARDINAL;
  3121. 3101 Index : CARDINAL;
  3122. 3102 Page,
  3123. 3103 PageTmp : LONGCARD;
  3124. 3104 IP,
  3125. 3105 NP,
  3126. 3106 XP : IPtr;
  3127. 3107
  3128. 3108 BEGIN
  3129. 3109 ClearErr(I);
  3130. 3110 IF NOT IsIndex(I) THEN
  3131. 3111 CallErr(I,NotIndex,'AddIndex');
  3132. 3112 RETURN;
  3133. 3113 END;
  3134. 3114 IF I.ID^.ReadOnly THEN
  3135. 3115 CallErr(I,BadWrite,'AddIndex with ReadOnly');
  3136. 3116 RETURN;
  3137. 3117 END;
  3138. 3118 IF LockFile(I.ID) THEN
  3139. 3119 IF cLockIHandle(I,Implicit) THEN
  3140. 3120 WITH I.ID^.Id[I.In] DO
  3141. 3121 ItemSize := 8+iwr^.KeySize;
  3142. 3122 InsKey.IP := Nil;
  3143. 3123 InsKey.DP := DataLoc;
  3144. 3124 MemFastMove(ADR(Key),ADR(InsKey.Key),iwr^.KeySize);
  3145. 3125 b := FindIx(I,InsKey.Key,DataLoc,Ins);
  3146. 3126 IF LastError(I)=OK THEN
  3147. 3127 Level := PageLevel;
  3148. 3128 Index := PageRefs^.Refs[Level].Rec;
  3149. 3129 Page := PageRefs^.Refs[Level].Page;
  3150. 3130 ReadPage(I,Page,TPage(TP));
  3151. 3131 IF TP.ICount=iwr^.N2 THEN
  3152. 3132 FIOx.Truncate(I.ID^.FHandle,I.ID^.fwr^.FileSize+VAL(LONGCARD,PageRefs^.Refs[PageLevel].Cnt)*PageSize);
  3153. 3133 IF FIOx.Error()#FIOx.NO_ERROR THEN
  3154. 3134 FIOx.Truncate(I.ID^.FHandle,I.ID^.fwr^.FileSize);
  3155. 3135 IOabort('AddIndex');
  3156. 3136 cUnLockIHandle(I,Implicit);
  3157. 3137 UnLockFile(I.ID);
  3158. 3138 CallErr(I,FileError,'AddIndex');
  3159. 3139 RETURN;
  3160. 3140 END;
  3161. 3141 IOabort('AddIndex');
  3162. 3142 END;
  3163. 3143 LOOP
  3164. 3144 IP := AddIPtr(IPtr(Ofs((TP.IItem))),Index*ItemSize);
  3165. 3145 XP := AddIPtr(IP,ItemSize);
  3166. 3146 INC(TP.ICount);
  3167. 3147 MemMove(ADR(IP^),ADR(XP^),ItemSize*(TP.ICount-(Index+1))+4);
  3168. 3148 MemFastMove(ADR(InsKey),ADR(IP^),ItemSize);
  3169. 3149 IF TP.ICount<=iwr^.N2 THEN
  3170. 3150 EXIT;
  3171. 3151 ELSE
  3172. 3152 NP := AddIPtr(IPtr(Ofs((TP.IItem))),ItemSize*iwr^.N22);
  3173. 3153 MemFastMove(ADR(NP^),ADR(InsKey),ItemSize);
  3174. 3154 TP.ICount := iwr^.N22;
  3175. 3155 IncAddr(NP,ItemSize);
  3176. 3156 IF I.In=0 THEN
  3177. 3157 InsKey.IP := AllocateFreeBlock(I.ID);
  3178. 3158 ELSE
  3179. 3159 InsKey.IP := AllocateBlock(I.ID,PageSize);
  3180. 3160 END;
  3181. 3161 WritePage(I,InsKey.IP,TPage(TP));
  3182. 3162 MemFastMove(ADR(NP^),ADR(TP.IItem),ItemSize*iwr^.N22+4);
  3183. 3163 WritePage(I,Page,TPage(TP));
  3184. 3164 DEC(Level);
  3185. 3165 IF Level=0 THEN
  3186. 3166 TP.ICount := 1;
  3187. 3167 MemFastMove(ADR(InsKey),ADR(TP.IItem),ItemSize);
  3188. 3168 IP := AddIPtr(IPtr(Ofs((TP.IItem))),ItemSize);
  3189. 3169 IP^.IP := iwr^.TopPage;
  3190. 3170 IF I.In=0 THEN
  3191. 3171 iwr^.TopPage := AllocateFreeBlock(I.ID);
  3192. 3172 ELSE
  3193. 3173 iwr^.TopPage := AllocateBlock(I.ID,PageSize);
  3194. 3174 END;
  3195. 3175 Page := iwr^.TopPage;
  3196. 3176 INC(iwr^.Depth);
  3197. 3177 IF iwr^.Depth>PageRefs^.Height THEN
  3198. 3178 FreeMem(PageRefs);
  3199. 3179 r := iwr^.Depth+1;
  3200. 3180 AllocMem(PageRefs,VSIZE(PageRef.Height)+r*SIZE(PageRefRec));
  3201. 3181 Die(PageRefs=NIL,OutOfMemory);
  3202. 3182 PageRefs^.Height := r;
  3203. 3183 END;
  3204. 3184 EXIT;
  3205. 3185 END;
  3206. 3186 END;
  3207. 3187 Index := PageRefs^.Refs[Level].Rec;
  3208. 3188 Page := PageRefs^.Refs[Level].Page;
  3209. 3189 ReadPage(I,Page,TPage(TP));
  3210. 3190 END;
  3211. 3191 WritePage(I,Page,TPage(TP));
  3212. 3192 PageLevel := 0;
  3213. 3193 END;
  3214. 3194 IF LastError(I)=OK THEN
  3215. 3195 INC(iwr^.RecordCnt);
  3216. 3196 END;
  3217. 3197 END;
  3218. 3198 cUnLockIHandle(I,Implicit);
  3219. 3199 END;
  3220. 3200 FIOx.Truncate(I.ID^.FHandle,I.ID^.fwr^.FileSize);
  3221. 3201 UnLockFile(I.ID);
  3222. 3202 ELSE
  3223. 3203 SetErr(I,Locked);
  3224. 3204 END;
  3225. 3205 END AddIndex;
  3226. 3206
  3227. 3207
  3228. 3208 PROCEDURE DeleteIndex(I: IHandle; Key: ARRAY OF BYTE; DataLoc: LONGCARD);
  3229. 3209
  3230. 3210 VAR
  3231. 3211 TP : TPage;
  3232. 3212
  3233. 3213 TYPE
  3234. 3214 IPtr = POINTER Seg(TP) TO IndexItem;
  3235. 3215 A2 = ARRAY[0..1] OF SHORTCARD;
  3236. 3216
  3237. 3217 (*# save *)
  3238. 3218 (*# call(inline=>on) *)
  3239. 3219 (*# call(reg_param=>(ax,cx),reg_saved=>(bx,cx,dx,si,di,ds,es,st1,st2,st3,st4,st5,st6)) *)
  3240. 3220 PROCEDURE AddIPtr(A: IPtr; I: CARDINAL): IPtr=A2(003H,0C1H);(*add ax,cx*)
  3241. 3221 (*# restore *)
  3242. 3222
  3243. 3223 VAR
  3244. 3224 QP,
  3245. 3225 RP : TPage;
  3246. 3226 DelKey : IndexItem;
  3247. 3227 Level : CARDINAL;
  3248. 3228 ItemSize : CARDINAL;
  3249. 3229 Page,
  3250. 3230 RPage : LONGCARD;
  3251. 3231 IP,
  3252. 3232 JP,
  3253. 3233 NP : IPtr;
  3254. 3234
  3255. 3235 (* 07/23/90 DWD - This procedure has not yet been optimized
  3256. 3236 by using MemFastMove() *)
  3257. 3237 BEGIN
  3258. 3238 ClearErr(I);
  3259. 3239 IF NOT IsIndex(I) THEN
  3260. 3240 CallErr(I,NotIndex,'DeleteIndex');
  3261. 3241 RETURN;
  3262. 3242 END;
  3263. 3243 IF I.ID^.ReadOnly THEN
  3264. 3244 CallErr(I,BadWrite,'DeleteIndex with ReadOnly');
  3265. 3245 RETURN;
  3266. 3246 END;
  3267. 3247 IF LockFile(I.ID) THEN
  3268. 3248 IF cLockIHandle(I,Implicit) THEN
  3269. 3249 WITH I.ID^.Id[I.In] DO
  3270. 3250 LOOP
  3271. 3251 ItemSize := 8+iwr^.KeySize;
  3272. 3252 DelKey.DP := DataLoc;
  3273. 3253 MemFastMove(ADR(Key),ADR(DelKey.Key),iwr^.KeySize);
  3274. 3254 IF NOT FindIx(I,DelKey.Key,DataLoc,Idx) THEN
  3275. 3255 CallErr(I,BadIndex,'DelIndex');
  3276. 3256 EXIT;
  3277. 3257 END;
  3278. 3258 Level := PageLevel;
  3279. 3259 Page := PageRefs^.Refs[PageLevel].Page;
  3280. 3260 ReadPage(I,Page,TP);
  3281. 3261 IP := AddIPtr(IPtr(Ofs((TP.IItem))),ItemSize*PageRefs^.Refs[PageLevel].Rec);
  3282. 3262 IF PageLevel#iwr^.Depth THEN
  3283. 3263 INC(Level);
  3284. 3264 NP := IP;
  3285. 3265 IncAddr(NP,ItemSize);
  3286. 3266 INC(PageRefs^.Refs[PageLevel].Rec);
  3287. 3267 Page := NP^.IP;
  3288. 3268 LOOP
  3289. 3269 ReadPage(I,Page,QP);
  3290. 3270 PageRefs^.Refs[Level].Rec := 0;
  3291. 3271 PageRefs^.Refs[Level].Page := Page;
  3292. 3272 IF Level=iwr^.Depth THEN
  3293. 3273 EXIT;
  3294. 3274 END;
  3295. 3275 Page := QP.IItem.IP;
  3296. 3276 INC(Level);
  3297. 3277 END;
  3298. 3278 MemFastMove(ADR(QP.IItem.DP),ADR(IP^.DP),iwr^.KeySize+4);
  3299. 3279 WritePage(I,PageRefs^.Refs[PageLevel].Page,TP);
  3300. 3280 TP:=QP;
  3301. 3281 PageLevel := iwr^.Depth;
  3302. 3282 IP := AddIPtr(IPtr(Ofs((TP.IItem))),ItemSize*PageRefs^.Refs[PageLevel].Rec)
  3303. 3283 END;
  3304. 3284 NP := IP;
  3305. 3285 IncAddr(NP,ItemSize);
  3306. 3286 DEC(TP.ICount);
  3307. 3287 MemFastMove(ADR(NP^),ADR(IP^),ItemSize*(TP.ICount-PageRefs^.Refs[PageLevel].Rec));
  3308. 3288 WHILE (TP.ICount<iwr^.N22) AND (PageLevel#1) DO
  3309. 3289 IF PageRefs^.Refs[PageLevel-1].Rec=0 THEN
  3310. 3290 (* Has got a right sibling *)
  3311. 3291 ReadPage(I,PageRefs^.Refs[PageLevel-1].Page,QP);
  3312. 3292 IP := AddIPtr(IPtr(Ofs((TP.IItem))),ItemSize*TP.ICount);
  3313. 3293 JP := AddIPtr(IPtr(Ofs((QP.IItem))),ItemSize*(PageRefs^.Refs[PageLevel-1].Rec+1));
  3314. 3294 RPage := JP^.IP;
  3315. 3295 DecAddr(JP,ItemSize);
  3316. 3296 ReadPage(I,RPage,RP);
  3317. 3297 MemFastMove(ADR(JP^.DP),ADR(IP^.DP),iwr^.KeySize+4);
  3318. 3298 INC(TP.ICount);
  3319. 3299 IF RP.ICount>iwr^.N22 THEN
  3320. 3300 IncAddr(IP,ItemSize);
  3321. 3301 IP^.IP := RP.IItem.IP;
  3322. 3302 MemFastMove(ADR(RP.IItem.DP),ADR(JP^.DP),iwr^.KeySize+4);
  3323. 3303 DEC(RP.ICount);
  3324. 3304 IP := AddIPtr(IPtr(Ofs((RP.IItem))),ItemSize);
  3325. 3305 MemFastMove(ADR(IP^),ADR(RP.IItem),ItemSize*RP.ICount+4);
  3326. 3306 WritePage(I,RPage,RP);
  3327. 3307 WritePage(I,PageRefs^.Refs[PageLevel].Page,TP);
  3328. 3308 WritePage(I,PageRefs^.Refs[PageLevel-1].Page,QP);
  3329. 3309 PageLevel :=0;
  3330. 3310 EXIT;
  3331. 3311 END;
  3332. 3312 IncAddr(IP,ItemSize);
  3333. 3313 MemFastMove(ADR(RP.IItem),ADR(IP^),ItemSize*iwr^.N22+4);
  3334. 3314 TP.ICount := iwr^.N2;
  3335. 3315 IP := JP;
  3336. 3316 IncAddr(IP,ItemSize);
  3337. 3317 DEC(QP.ICount);
  3338. 3318 MemFastMove(ADR(IP^.DP),ADR(JP^.DP),ItemSize*(QP.ICount-PageRefs^.Refs[PageLevel-1].Rec));
  3339. 3319 WritePage(I,PageRefs^.Refs[PageLevel].Page,TP);
  3340. 3320 ClearPage(I,RPage);
  3341. 3321 IF I.In=0 THEN
  3342. 3322 FreeFreeBlock(I.ID,RPage);
  3343. 3323 ELSE
  3344. 3324 FreeBlock(I.ID,PageSize,RPage);
  3345. 3325 END;
  3346. 3326 DEC(PageLevel);
  3347. 3327 TP := QP;
  3348. 3328 ELSE
  3349. 3329 (* Has got a left sibling *)
  3350. 3330 ReadPage(I,PageRefs^.Refs[PageLevel-1].Page,QP);
  3351. 3331 IP := AddIPtr(IPtr(Ofs((TP.IItem))),ItemSize);
  3352. 3332 MemMove(ADR(TP.IItem),ADR(IP^),ItemSize*TP.ICount+4);
  3353. 3333 JP := AddIPtr(IPtr(Ofs((QP.IItem))),ItemSize*(PageRefs^.Refs[PageLevel-1].Rec-1));
  3354. 3334 RPage := JP^.IP;
  3355. 3335 ReadPage(I,RPage,RP);
  3356. 3336 MemFastMove(ADR(JP^.DP),ADR(TP.IItem.DP),iwr^.KeySize+4);
  3357. 3337 INC(TP.ICount);
  3358. 3338 IF RP.ICount>iwr^.N22 THEN
  3359. 3339 NP := AddIPtr(IPtr(Ofs((RP.IItem))),ItemSize*RP.ICount);
  3360. 3340 TP.IItem.IP:= NP^.IP;
  3361. 3341 DecAddr(NP,ItemSize);
  3362. 3342 MemFastMove(ADR(NP^.DP),ADR(JP^.DP),iwr^.KeySize+4);
  3363. 3343 DEC(RP.ICount);
  3364. 3344 WritePage(I,RPage,RP);
  3365. 3345 WritePage(I,PageRefs^.Refs[PageLevel].Page,TP);
  3366. 3346 WritePage(I,PageRefs^.Refs[PageLevel-1].Page,QP);
  3367. 3347 PageLevel := 0;
  3368. 3348 EXIT;
  3369. 3349 END;
  3370. 3350 IP := AddIPtr(IPtr(Ofs((TP.IItem))),ItemSize*iwr^.N22);
  3371. 3351 MemFastMove(ADR(TP.IItem.DP),ADR(IP^.DP),ItemSize*iwr^.N22);
  3372. 3352 MemFastMove(ADR(RP.IItem),ADR(TP.IItem),ItemSize*iwr^.N22+4);
  3373. 3353 TP.ICount := iwr^.N2;
  3374. 3354 IP := JP;
  3375. 3355 IncAddr(IP,ItemSize);
  3376. 3356 MemFastMove(ADR(IP^),ADR(JP^),ItemSize*(QP.ICount-PageRefs^.Refs[PageLevel-1].Rec)+4);
  3377. 3357 DEC(QP.ICount);
  3378. 3358 WritePage(I,PageRefs^.Refs[PageLevel].Page,TP);
  3379. 3359 ClearPage(I,RPage);
  3380. 3360 IF I.In=0 THEN
  3381. 3361 FreeFreeBlock(I.ID,RPage);
  3382. 3362 ELSE
  3383. 3363 FreeBlock(I.ID,PageSize,RPage);
  3384. 3364 END;
  3385. 3365 DEC(PageLevel);
  3386. 3366 TP := QP;
  3387. 3367 END;
  3388. 3368 END;
  3389. 3369 IF (TP.ICount=0) AND (iwr^.Depth>1) THEN
  3390. 3370 DEC(iwr^.Depth);
  3391. 3371 iwr^.TopPage := TP.IItem.IP;
  3392. 3372 ELSE
  3393. 3373 WritePage(I,PageRefs^.Refs[PageLevel].Page,TP);
  3394. 3374 END;
  3395. 3375 PageLevel :=0;
  3396. 3376 EXIT;
  3397. 3377 END;
  3398. 3378 IF LastError(I)=OK THEN
  3399. 3379 DEC(iwr^.RecordCnt);
  3400. 3380 END;
  3401. 3381 END;
  3402. 3382 cUnLockIHandle(I,Implicit);
  3403. 3383 END;
  3404. 3384 UnLockFile(I.ID);
  3405. 3385 ELSE
  3406. 3386 SetErr(I,Locked);
  3407. 3387 END;
  3408. 3388 END DeleteIndex;
  3409. 3389
  3410. 3390
  3411. 3391 PROCEDURE FindIndex(I: IHandle; Key: ARRAY OF BYTE;
  3412. 3392 VAR DataLoc: LONGCARD): BOOLEAN;
  3413. 3393 VAR
  3414. 3394 res : BOOLEAN;
  3415. 3395 BEGIN
  3416. 3396 ClearErr(I);
  3417. 3397 IF NOT IsIndex(I) THEN
  3418. 3398 CallErr(I,NotIndex,'FindIndex');
  3419. 3399 RETURN FALSE;
  3420. 3400 END;
  3421. 3401 Release(I);
  3422. 3402 IF cLockIHandle(I,Implicit) THEN
  3423. 3403 IF FindIx(I,Key,Nil,Fnd) THEN
  3424. 3404 DataLoc := I.ID^.Id[I.In].LastDataRef;
  3425. 3405 res := TRUE;
  3426. 3406 ELSE
  3427. 3407 res := FALSE;
  3428. 3408 END;
  3429. 3409 I.ID^.Id[I.In].LastKeyOK := FALSE;
  3430. 3410 cUnLockIHandle(I,Implicit);
  3431. 3411 RETURN res;
  3432. 3412 ELSE
  3433. 3413 RETURN FALSE;
  3434. 3414 END;
  3435. 3415 END FindIndex;
  3436. 3416
  3437. 3417
  3438. 3418 PROCEDURE SearchIndex(I: IHandle; Key: ARRAY OF BYTE;
  3439. 3419 VAR DataLoc: LONGCARD): BOOLEAN;
  3440. 3420 VAR
  3441. 3421 res : BOOLEAN;
  3442. 3422 BEGIN
  3443. 3423 ClearErr(I);
  3444. 3424 IF NOT IsIndex(I) THEN
  3445. 3425 CallErr(I,NotIndex,'SearchIndex');
  3446. 3426 RETURN FALSE;
  3447. 3427 END;
  3448. 3428 Release(I);
  3449. 3429 IF cLockIHandle(I,Implicit) THEN
  3450. 3430 IF FindIx(I,Key,Nil,Src) THEN
  3451. 3431 DataLoc := I.ID^.Id[I.In].LastDataRef;
  3452. 3432 res := TRUE;
  3453. 3433 ELSE
  3454. 3434 res := FALSE;
  3455. 3435 END;
  3456. 3436 I.ID^.Id[I.In].LastKeyOK := FALSE;
  3457. 3437 cUnLockIHandle(I,Implicit);
  3458. 3438 RETURN res;
  3459. 3439 ELSE
  3460. 3440 RETURN FALSE;
  3461. 3441 END;
  3462. 3442 END SearchIndex;
  3463. 3443
  3464. 3444
  3465. 3445 PROCEDURE Recover(iH: IHandle) : BOOLEAN;
  3466. 3446 BEGIN
  3467. 3447 WITH iH.ID^ DO
  3468. 3448 WITH Id[iH.In] DO
  3469. 3449 IF (PageLevel=0) AND LastKeyOK THEN
  3470. 3450 RETURN FindIx(iH,LastKey,LastKeyRef,Rec);
  3471. 3451 ELSIF PageLevel#0 THEN
  3472. 3452 SetLastKey(iH);
  3473. 3453 END;
  3474. 3454 END;
  3475. 3455 END;
  3476. 3456 RETURN TRUE;
  3477. 3457 END Recover;
  3478. 3458
  3479. 3459
  3480. 3460 PROCEDURE NextIndex(I: IHandle; VAR DataLoc: LONGCARD): BOOLEAN;
  3481. 3461 VAR
  3482. 3462 res : BOOLEAN;
  3483. 3463 BEGIN
  3484. 3464 ClearErr(I);
  3485. 3465 IF NOT IsIndex(I) THEN
  3486. 3466 CallErr(I,NotIndex,'NextIndex');
  3487. 3467 RETURN FALSE;
  3488. 3468 END;
  3489. 3469 Release(I);
  3490. 3470 IF cLockIHandle(I,Implicit) THEN
  3491. 3471 WITH I.ID^.Id[I.In] DO
  3492. 3472 IF Recover(I) THEN
  3493. 3473 WalkIx(I,Forward);
  3494. 3474 END;
  3495. 3475 res := PageLevel#0;
  3496. 3476 cUnLockIHandle(I,Implicit);
  3497. 3477 IF res THEN
  3498. 3478 DataLoc := LastDataRef;
  3499. 3479 END;
  3500. 3480 RETURN res;
  3501. 3481 END;
  3502. 3482 ELSE
  3503. 3483 RETURN FALSE;
  3504. 3484 END;
  3505. 3485 END NextIndex;
  3506. 3486
  3507. 3487
  3508. 3488 PROCEDURE PrevIndex(I: IHandle; VAR DataLoc: LONGCARD): BOOLEAN;
  3509. 3489 VAR
  3510. 3490 res : BOOLEAN;
  3511. 3491 BEGIN
  3512. 3492 ClearErr(I);
  3513. 3493 IF NOT IsIndex(I) THEN
  3514. 3494 CallErr(I,NotIndex,'PrevIndex');
  3515. 3495 RETURN FALSE;
  3516. 3496 END;
  3517. 3497 Release(I);
  3518. 3498 IF cLockIHandle(I,Implicit) THEN
  3519. 3499 res := Recover(I);
  3520. 3500 WITH I.ID^.Id[I.In] DO
  3521. 3501 WalkIx(I,Backward);
  3522. 3502 res := PageLevel#0;
  3523. 3503 cUnLockIHandle(I,Implicit);
  3524. 3504 IF res THEN
  3525. 3505 DataLoc := LastDataRef;
  3526. 3506 END;
  3527. 3507 RETURN res;
  3528. 3508 END;
  3529. 3509 ELSE
  3530. 3510 RETURN FALSE;
  3531. 3511 END;
  3532. 3512 END PrevIndex;
  3533. 3513
  3534. 3514
  3535. 3515 PROCEDURE SetSyncMode(D: IHandle; On: BOOLEAN);
  3536. 3516 BEGIN
  3537. 3517 ClearErr(D);
  3538. 3518 IF NOT IsData(D) THEN
  3539. 3519 CallErr(D,NotData,'SetSyncMode');
  3540. 3520 RETURN;
  3541. 3521 END;
  3542. 3522 D.ID^.Id[D.In].Sync := On;
  3543. 3523 Reset(D);
  3544. 3524 END SetSyncMode;
  3545. 3525
  3546. 3526
  3547. 3527 PROCEDURE LastError(H: IHandle): Errors;
  3548. 3528 BEGIN
  3549. 3529 IF NOT IsFHandle(H.ID) THEN
  3550. 3530 RETURN NotFHandle;
  3551. 3531 ELSIF NOT IsIHandle(H) THEN
  3552. 3532 RETURN NotIHandle;
  3553. 3533 ELSE
  3554. 3534 RETURN H.ID^.Id[H.In].LastErr;
  3555. 3535 END;
  3556. 3536 END LastError;
  3557. 3537
  3558. 3538
  3559. 3539 PROCEDURE LastFError(F: FHandle): Errors;
  3560. 3540 VAR
  3561. 3541 iH : IHandle;
  3562. 3542 BEGIN
  3563. 3543 iH.ID := F;
  3564. 3544 iH.In := 0;
  3565. 3545 RETURN LastError(iH);
  3566. 3546 END LastFError;
  3567. 3547
  3568. 3548
  3569. 3549 PROCEDURE LastRef(I : IHandle) : LONGCARD;
  3570. 3550 BEGIN
  3571. 3551 IF NOT IsIHandle(I) THEN
  3572. 3552 CallErr(I,NotIHandle,'LastRef');
  3573. 3553 RETURN Nil;
  3574. 3554 END;
  3575. 3555 RETURN I.ID^.Id[I.In].LastDataRef;
  3576. 3556 END LastRef;
  3577. 3557
  3578. 3558
  3579. 3559 PROCEDURE RecordCount(I: IHandle): LONGCARD;
  3580. 3560 BEGIN
  3581. 3561 ClearErr(I);
  3582. 3562 IF NOT IsIHandle(I) THEN
  3583. 3563 CallErr(I,NotIHandle,'RecordCount');
  3584. 3564 RETURN Nil;
  3585. 3565 END;
  3586. 3566 WITH I.ID^.Id[I.In] DO
  3587. 3567 IF NOT I.ID^.Buffered AND (ihLock.ICnt=0) AND (ihLock.ECnt=0) THEN
  3588. 3568 CallErr(I,NotLocked,'RecordCount');
  3589. 3569 RETURN Nil;
  3590. 3570 END;
  3591. 3571 RETURN iwr^.RecordCnt;
  3592. 3572 END;
  3593. 3573 END RecordCount;
  3594. 3574
  3595. 3575
  3596. 3576 (*# save *)
  3597. 3577 (*%T _fcall *) (*# call(near_call=>off) *) (*%E *)
  3598. 3578 (*# call(o_a_size=>on) *)
  3599. 3579 PROCEDURE Err(err: Errors; str: ARRAY OF CHAR);
  3600. 3580 VAR s : ARRAY[0..79] OF CHAR;
  3601. 3581 BEGIN
  3602. 3582 Str.Concat(s,CHR(13)+CHR(10),str);
  3603. 3583 Lib.FatalError(s);
  3604. 3584 END Err;
  3605. 3585 (*# restore *)
  3606. 3586
  3607. 3587
  3608. 3588 MODULE NoPack;
  3609. 3589
  3610. 3590 IMPORT MemFastMove;
  3611. 3591
  3612. 3592 EXPORT QUALIFIED Packer, Unpacker, UnpackedSize, Packing, AdjustBlock;
  3613. 3593
  3614. 3594 PROCEDURE Packer(n: CARDINAL; in: ADDRESS; out: ADDRESS): CARDINAL;
  3615. 3595 BEGIN
  3616. 3596 MemFastMove(in,out,n);
  3617. 3597 RETURN n;
  3618. 3598 END Packer;
  3619. 3599
  3620. 3600 PROCEDURE Unpacker(n: CARDINAL; in: ADDRESS; out: ADDRESS);
  3621. 3601 BEGIN
  3622. 3602 MemFastMove(in,out,n);
  3623. 3603 END Unpacker;
  3624. 3604
  3625. 3605 PROCEDURE UnpackedSize(n: CARDINAL; in: ADDRESS): CARDINAL;
  3626. 3606 BEGIN
  3627. 3607 RETURN n;
  3628. 3608 END UnpackedSize;
  3629. 3609
  3630. 3610 PROCEDURE Packing(): BOOLEAN;
  3631. 3611 BEGIN
  3632. 3612 RETURN FALSE;
  3633. 3613 END Packing;
  3634. 3614
  3635. 3615 PROCEDURE AdjustBlock(rs: CARDINAL): CARDINAL;
  3636. 3616 BEGIN
  3637. 3617 RETURN rs;
  3638. 3618 END AdjustBlock;
  3639. 3619
  3640. 3620 END NoPack;
  3641. 3621
  3642. 3622
  3643. 3623 BEGIN
  3644. 3624 ErrorHandler := Err;
  3645. 3625 Packer := NoPack.Packer;
  3646. 3626 Unpacker := NoPack.Unpacker;
  3647. 3627 UnpackedSize := NoPack.UnpackedSize;
  3648. 3628 Packing := NoPack.Packing;
  3649. 3629 AdjustBlock := NoPack.AdjustBlock;
  3650. 3630 END Btree.
  3651. 19 errors