home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / unix / volume26 / db-1.6 / part07 < prev    next >
Encoding:
Text File  |  1993-07-05  |  75.8 KB  |  2,496 lines

  1. Newsgroups: comp.sources.unix
  2. From: bostic@cs.berkeley.edu (Keith Bostic)
  3. Subject: v26i286: db-1.6 - A New Hashing Package for UNIX(tm) (updates dbm/ndbm), Part07/09
  4. Sender: unix-sources-moderator@gw.home.vix.com
  5. Approved: vixie@gw.home.vix.com
  6.  
  7. Submitted-By: bostic@cs.berkeley.edu (Keith Bostic)
  8. Posting-Number: Volume 26, Issue 286
  9. Archive-Name: db-1.6/part07
  10.  
  11. #! /bin/sh
  12. # This is a shell archive.  Remove anything before this line, then unpack
  13. # it by saving it into a file and typing "sh file".  To overwrite existing
  14. # files, type "sh file -c".  You can also feed this as standard input via
  15. # unshar, or by typing "sh <file", e.g..  If this archive is complete, you
  16. # will see the following message at the end:
  17. #        "End of archive 7 (of 9)."
  18. # Contents:  doc/dbopen.3.ps hash/hash.c hash/hash_page.c
  19. # Wrapped by vixie@gw.home.vix.com on Mon Jul  5 15:27:28 1993
  20. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  21. if test -f 'doc/dbopen.3.ps' -a "${1}" != "-c" ; then 
  22.   echo shar: Will not clobber existing file \"'doc/dbopen.3.ps'\"
  23. else
  24. echo shar: Extracting \"'doc/dbopen.3.ps'\" \(25656 characters\)
  25. sed "s/^X//" >'doc/dbopen.3.ps' <<'END_OF_FILE'
  26. X%!PS-Adobe-3.0
  27. X%%Creator: groff version 1.08
  28. X%%DocumentNeededResources: font Times-Roman
  29. X%%+ font Times-Bold
  30. X%%+ font Times-Italic
  31. X%%DocumentSuppliedResources: procset grops 1.08 0
  32. X%%Pages: 4
  33. X%%PageOrder: Ascend
  34. X%%Orientation: Portrait
  35. X%%EndComments
  36. X%%BeginProlog
  37. X%%BeginResource: procset grops 1.08 0
  38. X/setpacking where{
  39. Xpop
  40. Xcurrentpacking
  41. Xtrue setpacking
  42. X}if
  43. X/grops 120 dict dup begin
  44. X/SC 32 def
  45. X/A/show load def
  46. X/B{0 SC 3 -1 roll widthshow}bind def
  47. X/C{0 exch ashow}bind def
  48. X/D{0 exch 0 SC 5 2 roll awidthshow}bind def
  49. X/E{0 rmoveto show}bind def
  50. X/F{0 rmoveto 0 SC 3 -1 roll widthshow}bind def
  51. X/G{0 rmoveto 0 exch ashow}bind def
  52. X/H{0 rmoveto 0 exch 0 SC 5 2 roll awidthshow}bind def
  53. X/I{0 exch rmoveto show}bind def
  54. X/J{0 exch rmoveto 0 SC 3 -1 roll widthshow}bind def
  55. X/K{0 exch rmoveto 0 exch ashow}bind def
  56. X/L{0 exch rmoveto 0 exch 0 SC 5 2 roll awidthshow}bind def
  57. X/M{rmoveto show}bind def
  58. X/N{rmoveto 0 SC 3 -1 roll widthshow}bind def
  59. X/O{rmoveto 0 exch ashow}bind def
  60. X/P{rmoveto 0 exch 0 SC 5 2 roll awidthshow}bind def
  61. X/Q{moveto show}bind def
  62. X/R{moveto 0 SC 3 -1 roll widthshow}bind def
  63. X/S{moveto 0 exch ashow}bind def
  64. X/T{moveto 0 exch 0 SC 5 2 roll awidthshow}bind def
  65. X/SF{
  66. Xfindfont exch
  67. X[exch dup 0 exch 0 exch neg 0 0]makefont
  68. Xdup setfont
  69. X[exch/setfont cvx]cvx bind def
  70. X}bind def
  71. X/MF{
  72. Xfindfont
  73. X[5 2 roll
  74. X0 3 1 roll 
  75. Xneg 0 0]makefont
  76. Xdup setfont
  77. X[exch/setfont cvx]cvx bind def
  78. X}bind def
  79. X/level0 0 def
  80. X/RES 0 def
  81. X/PL 0 def
  82. X/LS 0 def
  83. X/PLG{
  84. Xgsave newpath clippath pathbbox grestore
  85. Xexch pop add exch pop
  86. X}bind def
  87. X/BP{
  88. X/level0 save def
  89. X1 setlinecap
  90. X1 setlinejoin
  91. X72 RES div dup scale
  92. XLS{
  93. X90 rotate
  94. X}{
  95. X0 PL translate
  96. X}ifelse
  97. X1 -1 scale
  98. X}bind def
  99. X/EP{
  100. Xlevel0 restore
  101. Xshowpage
  102. X}bind def
  103. X/DA{
  104. Xnewpath arcn stroke
  105. X}bind def
  106. X/SN{
  107. Xtransform
  108. X.25 sub exch .25 sub exch
  109. Xround .25 add exch round .25 add exch
  110. Xitransform
  111. X}bind def
  112. X/DL{
  113. XSN
  114. Xmoveto
  115. XSN
  116. Xlineto stroke
  117. X}bind def
  118. X/DC{
  119. Xnewpath 0 360 arc closepath
  120. X}bind def
  121. X/TM matrix def
  122. X/DE{
  123. XTM currentmatrix pop
  124. Xtranslate scale newpath 0 0 .5 0 360 arc closepath
  125. XTM setmatrix
  126. X}bind def
  127. X/RC/rcurveto load def
  128. X/RL/rlineto load def
  129. X/ST/stroke load def
  130. X/MT/moveto load def
  131. X/CL/closepath load def
  132. X/FL{
  133. Xcurrentgray exch setgray fill setgray
  134. X}bind def
  135. X/BL/fill load def
  136. X/LW/setlinewidth load def
  137. X/RE{
  138. Xfindfont
  139. Xdup maxlength 1 index/FontName known not{1 add}if dict begin
  140. X{
  141. X1 index/FID ne{def}{pop pop}ifelse
  142. X}forall
  143. X/Encoding exch def
  144. Xdup/FontName exch def
  145. Xcurrentdict end definefont pop
  146. X}bind def
  147. X/DEFS 0 def
  148. X/EBEGIN{
  149. Xmoveto
  150. XDEFS begin
  151. X}bind def
  152. X/EEND/end load def
  153. X/CNT 0 def
  154. X/level1 0 def
  155. X/PBEGIN{
  156. X/level1 save def
  157. Xtranslate
  158. Xdiv 3 1 roll div exch scale
  159. Xneg exch neg exch translate
  160. X0 setgray
  161. X0 setlinecap
  162. X1 setlinewidth
  163. X0 setlinejoin
  164. X10 setmiterlimit
  165. X[]0 setdash
  166. X/setstrokeadjust where{
  167. Xpop
  168. Xfalse setstrokeadjust
  169. X}if
  170. X/setoverprint where{
  171. Xpop
  172. Xfalse setoverprint
  173. X}if
  174. Xnewpath
  175. X/CNT countdictstack def
  176. Xuserdict begin
  177. X/showpage{}def
  178. X}bind def
  179. X/PEND{
  180. Xclear
  181. Xcountdictstack CNT sub{end}repeat
  182. Xlevel1 restore
  183. X}bind def
  184. Xend def
  185. X/setpacking where{
  186. Xpop
  187. Xsetpacking
  188. X}if
  189. X%%EndResource
  190. X%%IncludeResource: font Times-Roman
  191. X%%IncludeResource: font Times-Bold
  192. X%%IncludeResource: font Times-Italic
  193. Xgrops begin/DEFS 1 dict def DEFS begin/u{.001 mul}bind def end/RES 72 def/PL
  194. X792 def/LS false def/ENC0[/asciicircum/asciitilde/Scaron/Zcaron/scaron/zcaron
  195. X/Ydieresis/trademark/quotesingle/.notdef/.notdef/.notdef/.notdef/.notdef
  196. X/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef
  197. X/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/space
  198. X/exclam/quotedbl/numbersign/dollar/percent/ampersand/quoteright/parenleft
  199. X/parenright/asterisk/plus/comma/hyphen/period/slash/zero/one/two/three/four
  200. X/five/six/seven/eight/nine/colon/semicolon/less/equal/greater/question/at/A/B/C
  201. X/D/E/F/G/H/I/J/K/L/M/N/O/P/Q/R/S/T/U/V/W/X/Y/Z/bracketleft/backslash
  202. X/bracketright/circumflex/underscore/quoteleft/a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/q
  203. X/r/s/t/u/v/w/x/y/z/braceleft/bar/braceright/tilde/.notdef/quotesinglbase
  204. X/guillemotleft/guillemotright/bullet/florin/fraction/perthousand/dagger
  205. X/daggerdbl/endash/emdash/ff/fi/fl/ffi/ffl/dotlessi/dotlessj/grave/hungarumlaut
  206. X/dotaccent/breve/caron/ring/ogonek/quotedblleft/quotedblright/oe/lslash
  207. X/quotedblbase/OE/Lslash/.notdef/exclamdown/cent/sterling/currency/yen/brokenbar
  208. X/section/dieresis/copyright/ordfeminine/guilsinglleft/logicalnot/minus
  209. X/registered/macron/degree/plusminus/twosuperior/threesuperior/acute/mu
  210. X/paragraph/periodcentered/cedilla/onesuperior/ordmasculine/guilsinglright
  211. X/onequarter/onehalf/threequarters/questiondown/Agrave/Aacute/Acircumflex/Atilde
  212. X/Adieresis/Aring/AE/Ccedilla/Egrave/Eacute/Ecircumflex/Edieresis/Igrave/Iacute
  213. X/Icircumflex/Idieresis/Eth/Ntilde/Ograve/Oacute/Ocircumflex/Otilde/Odieresis
  214. X/multiply/Oslash/Ugrave/Uacute/Ucircumflex/Udieresis/Yacute/Thorn/germandbls
  215. X/agrave/aacute/acircumflex/atilde/adieresis/aring/ae/ccedilla/egrave/eacute
  216. X/ecircumflex/edieresis/igrave/iacute/icircumflex/idieresis/eth/ntilde/ograve
  217. X/oacute/ocircumflex/otilde/odieresis/divide/oslash/ugrave/uacute/ucircumflex
  218. X/udieresis/yacute/thorn/ydieresis]def/Times-Italic@0 ENC0/Times-Italic RE
  219. X/Times-Bold@0 ENC0/Times-Bold RE/Times-Roman@0 ENC0/Times-Roman RE
  220. X%%EndProlog
  221. X%%Page: 1 1
  222. X%%BeginPageSetup
  223. XBP
  224. X%%EndPageSetup
  225. X/F0 10/Times-Roman@0 SF 169.84(DBOPEN\(3\) 1993 DBOPEN\(3\))72 48 R/F1 9
  226. X/Times-Bold@0 SF -.18(NA)72 84 S(ME).18 E F0
  227. X(dbopen \255 database access methods)108 96 Q F1(SYNOPSIS)72 112.8 Q/F2 10
  228. X/Times-Bold@0 SF(#include <sys/types.h>)108 124.8 Q(#include <limits.h>)108
  229. X136.8 Q(#include <db)108 148.8 Q(.h>)-.4 E(DB *)108 172.8 Q
  230. X(dbopen\(const char *\214le, int \215ags, int mode, DBTYPE type,)108 184.8 Q
  231. X(const v)158 196.8 Q(oid *openinf)-.1 E(o\);)-.25 E F1(DESCRIPTION)72 213.6 Q
  232. X/F3 10/Times-Italic@0 SF(Dbopen)108 225.6 Q F0 .032(is the library interf)2.532
  233. XF .031(ace to database \214les.)-.1 F .031
  234. X(The supported \214le formats are btree, hashed and UNIX \214le)5.031 F 2.82
  235. X(oriented. The)108 237.6 R .32
  236. X(btree format is a representation of a sorted, balanced tree structure.)2.82 F
  237. X.321(The hashed format is an)5.321 F -.15(ex)108 249.6 S .424
  238. X(tensible, dynamic hashing scheme.).15 F .423
  239. X(The \215at-\214le format is a byte stream \214le with \214x)5.423 F .423
  240. X(ed or v)-.15 F .423(ariable length)-.25 F 2.906(records. The)108 261.6 R .407
  241. X(formats and \214le format speci\214c information are described in detail in t\
  242. Xheir respecti)2.906 F .707 -.15(ve m)-.25 H(anual).15 E(pages)108 273.6 Q F3
  243. X(btr)2.5 E(ee)-.37 E F0(\(3\),).18 E F3(hash)2.5 E F0(\(3\) and).28 E F3 -.37
  244. X(re)2.5 G(cno).37 E F0(\(3\).).18 E .433(Dbopen opens)108 290.4 R F3(\214le)
  245. X2.933 E F0 .433(for reading and/or writing.)2.933 F .433(Files ne)5.433 F -.15
  246. X(ve)-.25 G 2.933(ri).15 G .433(ntended to be preserv)346.737 290.4 R .433
  247. X(ed on disk may be created)-.15 F(by setting the \214le parameter to NULL.)108
  248. X302.4 Q(The)108 319.2 Q F3<8d61>4.661 E(gs)-.1 E F0(and)4.661 E F3 2.161
  249. X(mode ar)4.661 F(guments)-.37 E F0 2.161(are as speci\214ed to the)4.661 F F3
  250. X(open)4.661 E F0 2.162(\(2\) routine, ho).24 F(we)-.25 E -.15(ve)-.25 G 2.962
  251. X-.4(r, o).15 H 2.162(nly the O_CREA).4 F -.74(T,)-1.11 G 2.597
  252. X(O_EXCL, O_EXLOCK, O_RDONL)108 331.2 R 5.177 -1.29(Y, O)-1 H(_RD)1.29 E 2.597
  253. X(WR, O_SHLOCK and O_TR)-.3 F 2.596(UNC \215ags are meaningful.)-.4 F
  254. X(\(Note, opening a database \214le O_WR)108 343.2 Q(ONL)-.4 E 2.5(Yi)-1 G 2.5
  255. X(sn)289.62 343.2 S(ot possible.\))301.01 343.2 Q(The)108 360 Q F3(type)5.337 E
  256. XF0(ar)5.337 E 2.837(gument is of type DBTYPE \(as de\214ned in the <db)-.18 F
  257. X2.838(.h> include \214le\) and may be set to)-.4 F
  258. X(DB_BTREE, DB_HASH or DB_RECNO.)108 372 Q(The)108 388.8 Q F3(openinfo)2.85 E F0
  259. X(ar)2.85 E .349(gument is a pointer to an access method speci\214c structure d\
  260. Xescribed in the access method')-.18 F(s)-.55 E .03(manual page.)108 400.8 R(If)
  261. X5.03 E F3(openinfo)2.53 E F0 .031(is NULL, each access method will use def)2.53
  262. XF .031(aults appropriate for the system and the)-.1 F(access method.)108 412.8
  263. XQ F3(Dbopen)108 429.6 Q F0 .416
  264. X(returns a pointer to a DB structure on success and NULL on error)2.917 F 5.416
  265. X(.T)-.55 G .416(he DB structure is de\214ned in)423.21 429.6 R(the <db)108
  266. X441.6 Q(.h> include \214le, and contains at least the follo)-.4 E
  267. X(wing \214elds:)-.25 E(typedef struct {)108 465.6 Q(DBTYPE type;)144 477.6 Q
  268. X(int \(*close\)\(const DB *db\);)144 489.6 Q
  269. X(int \(*del\)\(const DB *db, const DBT *k)144 501.6 Q -.15(ey)-.1 G 2.5(,u)-.5
  270. XG(_int \215ags\);)318.92 501.6 Q(int \(*fd\)\(const DB *db\);)144 513.6 Q
  271. X(int \(*get\)\(const DB *db, DBT *k)144 525.6 Q -.15(ey)-.1 G 2.5(,D)-.5 G
  272. X(BT *data, u_int \215ags\);)297.53 525.6 Q(int \(*put\)\(const DB *db, DBT *k)
  273. X144 537.6 Q -.15(ey)-.1 G 2.5(,c)-.5 G(onst DBT *data,)295.31 537.6 Q
  274. X(u_int \215ags\);)194 549.6 Q(int \(*sync\)\(const DB *db, u_int \215ags\);)144
  275. X561.6 Q(int \(*seq\)\(const DB *db, DBT *k)144 573.6 Q -.15(ey)-.1 G 2.5(,D)-.5
  276. XG(BT *data, u_int \215ags\);)298.64 573.6 Q 2.5(}D)108 585.6 S(B;)122.52 585.6
  277. XQ .101
  278. X(These elements describe a database type and a set of functions performing v)
  279. X108 602.4 R .101(arious actions.)-.25 F .101(These functions)5.101 F(tak)108
  280. X614.4 Q 3.039(eap)-.1 G .539(ointer to a structure as returned by)140.078 614.4
  281. XR F3(dbopen)3.038 E F0 3.038(,a).24 G .538
  282. X(nd sometimes one or more pointers to k)323.196 614.4 R -.15(ey)-.1 G .538
  283. X(/data struc-).15 F(tures and a \215ag v)108 626.4 Q(alue.)-.25 E 16.28
  284. X(type The)108 643.2 R
  285. X(type of the underlying access method \(and \214le format\).)2.5 E 12.95
  286. X(close A)108 660 R .988(pointer to a routine to \215ush an)3.488 F 3.489(yc)
  287. X-.15 G .989(ached information to disk, free an)293.968 660 R 3.489(ya)-.15 G
  288. X.989(llocated resources, and)446.662 660 R .112
  289. X(close the underlying \214le\(s\).)144 672 R .111(Since k)5.112 F -.15(ey)-.1 G
  290. X.111(/data pairs may be cached in memory).15 F 2.611(,f)-.65 G .111
  291. X(ailing to sync the \214le)455.666 672 R .494(with a)144 684 R F3(close)2.994 E
  292. XF0(or)2.994 E F3(sync)2.994 E F0 .495
  293. X(function may result in inconsistent or lost information.)2.994 F F3(Close)
  294. X5.495 E F0 .495(routines return)2.995 F(-1 on error \(setting)144 696 Q F3
  295. X(errno)2.5 E F0 2.5(\)a).18 G(nd 0 on success.)254.43 696 Q 21.28(del A)108
  296. X712.8 R(pointer to a routine to remo)2.5 E .3 -.15(ve k)-.15 H -.15(ey).05 G
  297. X(/data pairs from the database.).15 E 209.835(24, May)72 768 R(1)535 768 Q EP
  298. X%%Page: 2 2
  299. X%%BeginPageSetup
  300. XBP
  301. X%%EndPageSetup
  302. X/F0 10/Times-Roman@0 SF 169.84(DBOPEN\(3\) 1993 DBOPEN\(3\))72 48 R
  303. X(The parameter)144 84 Q/F1 10/Times-Italic@0 SF<8d61>2.5 E(g)-.1 E F0
  304. X(may be set to the follo)2.5 E(wing v)-.25 E(alue:)-.25 E(R_CURSOR)144 100.8 Q
  305. X.289(Delete the record referenced by the cursor)180 112.8 R 5.288(.T)-.55 G
  306. X.288(he cursor must ha)363.342 112.8 R .588 -.15(ve p)-.2 H(re).15 E .288
  307. X(viously been initial-)-.25 F(ized.)180 124.8 Q F1(Delete)144 141.6 Q F0 .03
  308. X(routines return -1 on error \(setting)2.53 F F1(errno)2.53 E F0 .03
  309. X(\), 0 on success, and 1 if the speci\214ed).18 F F1 -.1(ke)2.53 G(y)-.2 E F0
  310. X-.1(wa)2.53 G 2.53(sn).1 G .03(ot in)521.91 141.6 R(the \214le.)144 153.6 Q
  311. X25.17(fd A)108 170.4 R .451
  312. X(pointer to a routine which returns a \214le descriptor representati)2.951 F
  313. X.75 -.15(ve o)-.25 H 2.95(ft).15 G .45(he underlying database.)431.73 170.4 R
  314. X(A)5.45 E .942(\214le descriptor referencing the same \214le will be returned \
  315. Xto all processes which call)144 182.4 R F1(dbopen)3.442 E F0(with)3.442 E 1.629
  316. X(the same)144 194.4 R F1(\214le)4.129 E F0 4.129(name. This)4.129 F 1.628
  317. X(\214le descriptor may be safely used as a ar)4.128 F 1.628(gument to the)-.18
  318. XF F1(fcntl)4.128 E F0 1.628(\(2\) and).51 F F1(\215oc)144 206.4 Q(k)-.2 E F0
  319. X.425(\(2\) locking functions.).67 F .425
  320. X(The \214le descriptor is not necessarily associated with an)5.425 F 2.925(yo)
  321. X-.15 G 2.925(ft)492.7 206.4 S .425(he under)501.735 206.4 R(-)-.2 E .198
  322. X(lying \214les used by the access method.)144 218.4 R .198
  323. X(No \214le descriptor is a)5.198 F -.25(va)-.2 G .198
  324. X(ilable for in memory databases.).25 F F1(Fd)5.198 E F0
  325. X(routines return -1 on error \(setting)144 230.4 Q F1(errno)2.5 E F0
  326. X(\), and the \214le descriptor on success.).18 E 21.28(get A)108 247.2 R
  327. X(pointer to a routine which is the interf)2.5 E .001(ace for k)-.1 F -.15(ey)
  328. X-.1 G .001(ed retrie).15 F -.25(va)-.25 G 2.501(lf).25 G .001
  329. X(rom the database.)399.755 247.2 R .001(The address and)5.001 F .061
  330. X(length of the data associated with the speci\214ed)144 259.2 R F1 -.1(ke)2.561
  331. XG(y)-.2 E F0 .06(are returned in the structure referenced by)2.561 F F1(data)
  332. X2.56 E F0(.).26 E F1(Get)144 271.2 Q F0(routines return -1 on error \(setting)
  333. X2.5 E F1(errno)2.5 E F0(\), 0 on success, and 1 if the).18 E F1 -.1(ke)2.5 G(y)
  334. X-.2 E F0 -.1(wa)2.5 G 2.5(sn).1 G(ot in the \214le.)471.66 271.2 Q 20.72(put A)
  335. X108 288 R(pointer to a routine to store k)2.5 E -.15(ey)-.1 G
  336. X(/data pairs in the database.).15 E(The parameter)144 304.8 Q F1<8d61>2.5 E(g)
  337. X-.1 E F0(may be set to one of the follo)2.5 E(wing v)-.25 E(alues:)-.25 E
  338. X(R_CURSOR)144 321.6 Q .051(Replace the k)180 333.6 R -.15(ey)-.1 G .051
  339. X(/data pair referenced by the cursor).15 F 5.052(.T)-.55 G .052
  340. X(he cursor must ha)393.98 333.6 R .352 -.15(ve p)-.2 H(re).15 E .052
  341. X(viously been)-.25 F(initialized.)180 345.6 Q(R_IAFTER)144 362.4 Q 1.165
  342. X(Append the data immediately after the data referenced by)180 374.4 R F1 -.1
  343. X(ke)3.664 G(y)-.2 E F0 3.664(,c).32 G 1.164(reating a ne)446.758 374.4 R 3.664
  344. X(wk)-.25 G -.15(ey)511.27 374.4 S(/data).15 E(pair)180 386.4 Q 6.065(.T)-.55 G
  345. X1.065(he record number of the appended k)209.675 386.4 R -.15(ey)-.1 G 1.065
  346. X(/data pair is returned in the).15 F F1 -.1(ke)3.565 G(y)-.2 E F0(structure.)
  347. X3.565 E(\(Applicable only to the DB_RECNO access method.\))180 398.4 Q
  348. X(R_IBEFORE)144 415.2 Q 1.293
  349. X(Insert the data immediately before the data referenced by)180 427.2 R F1 -.1
  350. X(ke)3.793 G(y)-.2 E F0 3.793(,c).32 G 1.293(reating a ne)446.371 427.2 R 3.793
  351. X(wk)-.25 G -.15(ey)511.27 427.2 S(/data).15 E(pair)180 439.2 Q 6.54(.T)-.55 G
  352. X1.54(he record number of the inserted k)210.15 439.2 R -.15(ey)-.1 G 1.541
  353. X(/data pair is returned in the).15 F F1 -.1(ke)4.041 G(y)-.2 E F0(structure.)
  354. X4.041 E(\(Applicable only to the DB_RECNO access method.\))180 451.2 Q(R_NOO)
  355. X144 468 Q(VER)-.5 E(WRITE)-.55 E(Enter the ne)180 480 Q 2.5(wk)-.25 G -.15(ey)
  356. X242.69 480 S(/data pair only if the k).15 E .3 -.15(ey d)-.1 H(oes not pre).15
  357. XE(viously e)-.25 E(xist.)-.15 E(R_SETCURSOR)144 496.8 Q 1.36(Store the k)180
  358. X508.8 R -.15(ey)-.1 G 1.36(/data pair).15 F 3.86(,s)-.4 G 1.359
  359. X(etting or initializing the position of the cursor to reference it.)283.94
  360. X508.8 R(\(Applicable only to the DB_BTREE and DB_RECNO access methods.\))180
  361. X520.8 Q .563(R_SETCURSOR is a)144 537.6 R -.25(va)-.2 G .564
  362. X(ilable only for the DB_BTREE and DB_RECNO access methods because).25 F
  363. X(it implies that the k)144 549.6 Q -.15(ey)-.1 G 2.5(sh).15 G -2.25 -.2(av e)
  364. X241.81 549.6 T(an inherent order which does not change.)2.7 E .416
  365. X(R_IAFTER and R_IBEFORE are a)144 566.4 R -.25(va)-.2 G .416
  366. X(ilable only for the DB_RECNO access method because the).25 F(y)-.15 E 1.221
  367. X(each imply that the access method is able to create ne)144 578.4 R 3.722(wk)
  368. X-.25 G -.15(ey)385.644 578.4 S 3.722(s. This).15 F 1.222(is only true if the k)
  369. X3.722 F -.15(ey)-.1 G 3.722(sa).15 G(re)532.23 578.4 Q
  370. X(ordered and independent, record numbers for e)144 590.4 Q(xample.)-.15 E .289
  371. X(The def)144 607.2 R .289(ault beha)-.1 F .289(vior of the)-.2 F F1(put)2.789 E
  372. XF0 .289(routines is to enter the ne)2.789 F 2.789(wk)-.25 G -.15(ey)388.998
  373. X607.2 S .288(/data pair).15 F 2.788(,r)-.4 G .288(eplacing an)444.284 607.2 R
  374. X2.788(yp)-.15 G(re)503.03 607.2 Q(viously)-.25 E -.15(ex)144 619.2 S(isting k)
  375. X.15 E -.15(ey)-.1 G(.)-.5 E F1(Put)144 636 Q F0 .37
  376. X(routines return -1 on error \(setting)2.87 F F1(errno)2.87 E F0 .37
  377. X(\), 0 on success, and 1 if the R_NOO).18 F(VER)-.5 E(WRITE)-.55 E F1<8d61>2.87
  378. XE(g)-.1 E F0 -.1(wa)144 648 S 2.5(ss).1 G(et and the k)165.84 648 Q .3 -.15
  379. X(ey a)-.1 H(lready e).15 E(xists in the \214le.)-.15 E 20.17(seq A)108 664.8 R
  380. X.002(pointer to a routine which is the interf)2.502 F .002
  381. X(ace for sequential retrie)-.1 F -.25(va)-.25 G 2.502(lf).25 G .002
  382. X(rom the database.)416.694 664.8 R .001(The address)5.001 F .219
  383. X(and length of the k)144 676.8 R .519 -.15(ey a)-.1 H .219
  384. X(re returned in the structure referenced by).15 F F1 -.1(ke)2.72 G(y)-.2 E F0
  385. X2.72(,a).32 G .22(nd the address and length of)426.42 676.8 R
  386. X(the data are returned in the structure referenced by)144 688.8 Q F1(data)2.5 E
  387. XF0(.).26 E .937(Sequential k)144 705.6 R -.15(ey)-.1 G .937(/data pair retrie)
  388. X.15 F -.25(va)-.25 G 3.437(lm).25 G .936(ay be)289.748 705.6 R .936(gin at an)
  389. X-.15 F 3.436(yt)-.15 G .936(ime, and the position of the `)359.292 705.6 R
  390. X(`cursor')-.74 E 3.436('i)-.74 G 3.436(sn)519.894 705.6 S(ot)532.22 705.6 Q(af)
  391. X144 717.6 Q 1.585(fected by calls to the)-.25 F F1(del)4.085 E F0(,).51 E F1
  392. X-.1(ge)4.085 G(t).1 E F0(,).68 E F1(put)4.086 E F0 4.086(,o).68 G(r)308.452
  393. X717.6 Q F1(sync)4.086 E F0 4.086(routines. Modi\214cations)4.086 F 1.586
  394. X(to the database during a)4.086 F 1.404(sequential scan will be re\215ected in\
  395. X the scan, i.e. records inserted behind the cursor will not be)144 729.6 R
  396. X209.835(24, May)72 768 R(2)535 768 Q EP
  397. X%%Page: 3 3
  398. X%%BeginPageSetup
  399. XBP
  400. X%%EndPageSetup
  401. X/F0 10/Times-Roman@0 SF 169.84(DBOPEN\(3\) 1993 DBOPEN\(3\))72 48 R
  402. X(returned while records inserted in front of the cursor will be returned.)144
  403. X84 Q(The \215ag v)144 100.8 Q(alue)-.25 E/F1 10/Times-Bold@0 SF(must)2.5 E F0
  404. X(be set to one of the follo)2.5 E(wing v)-.25 E(alues:)-.25 E(R_CURSOR)144
  405. X117.6 Q .523(The data associated with the speci\214ed k)180 129.6 R .824 -.15
  406. X(ey i)-.1 H 3.024(sr).15 G 3.024(eturned. This)367.236 129.6 R(dif)3.024 E .524
  407. X(fers from the)-.25 F/F2 10/Times-Italic@0 SF -.1(ge)3.024 G(t).1 E F0
  408. X(routines)3.024 E 1.143
  409. X(in that it sets or initializes the cursor to the location of the k)180 141.6 R
  410. X1.443 -.15(ey a)-.1 H 3.642(sw).15 G 3.642(ell. \(Note,)464.924 141.6 R 1.142
  411. X(for the)3.642 F 1.275(DB_BTREE access method, the returned k)180 153.6 R 1.575
  412. X-.15(ey i)-.1 H 3.775(sn).15 G 1.276(ot necessarily an e)386.425 153.6 R 1.276
  413. X(xact match for the)-.15 F .598(speci\214ed k)180 165.6 R -.15(ey)-.1 G 5.598
  414. X(.T)-.5 G .598(he returned k)246.396 165.6 R .898 -.15(ey i)-.1 H 3.098(st).15
  415. XG .598(he smallest k)325.188 165.6 R .898 -.15(ey g)-.1 H .598
  416. X(reater than or equal to the speci\214ed).15 F -.1(ke)180 177.6 S 1.3 -.65
  417. X(y, p)-.05 H(ermitting partial k).65 E .3 -.15(ey m)-.1 H
  418. X(atches and range searches.\)).15 E(R_FIRST)144 194.4 Q 1.043(The \214rst k)180
  419. X206.4 R -.15(ey)-.1 G 1.044(/data pair of the database is returned, and the cu\
  420. Xrsor is set or initialized to).15 F(reference it.)180 218.4 Q(R_LAST)144 235.2
  421. XQ .085(The last k)180 247.2 R -.15(ey)-.1 G .085(/data pair of the database is\
  422. X returned, and the cursor is set or initialized to ref-).15 F(erence it.)180
  423. X259.2 Q(\(Applicable only to the DB_BTREE and DB_RECNO access methods.\))5 E
  424. X(R_NEXT)144 276 Q(Retrie)180 288 Q .604 -.15(ve t)-.25 H .304(he k).15 F -.15
  425. X(ey)-.1 G .304(/data pair immediately after the cursor).15 F 5.304(.I)-.55 G
  426. X2.804(ft)410.622 288 S .305(he cursor is not yet set, this is)419.536 288 R
  427. X(the same as the R_FIRST \215ag.)180 300 Q(R_PREV)144 316.8 Q(Retrie)180 328.8
  428. XQ .755 -.15(ve t)-.25 H .455(he k).15 F -.15(ey)-.1 G .455
  429. X(/data pair immediately before the cursor).15 F 5.455(.I)-.55 G 2.955(ft)419.05
  430. X328.8 S .454(he cursor is not yet set, this)428.115 328.8 R .62
  431. X(is the same as the R_LAST \215ag.)180 340.8 R .621
  432. X(\(Applicable only to the DB_BTREE and DB_RECNO)5.621 F(access methods.\))180
  433. X352.8 Q .911(R_LAST and R_PREV are a)144 369.6 R -.25(va)-.2 G .911
  434. X(ilable only for the DB_BTREE and DB_RECNO access methods).25 F(because the)144
  435. X381.6 Q 2.5(ye)-.15 G(ach imply that the k)202.16 381.6 Q -.15(ey)-.1 G 2.5(sh)
  436. X.15 G -2.25 -.2(av e)302.18 381.6 T(an inherent order which does not change.)
  437. X2.7 E F2(Seq)144 398.4 Q F0 .061(routines return -1 on error \(setting)2.561 F
  438. XF2(errno)2.561 E F0 .061(\), 0 on success and 1 if there are no k).18 F -.15
  439. X(ey)-.1 G .061(/data pairs less).15 F .35
  440. X(than or greater than the speci\214ed or current k)144 410.4 R -.15(ey)-.1 G
  441. X5.349(.I)-.5 G 2.849(ft)346.467 410.4 S .349
  442. X(he DB_RECNO access method is being used,)355.426 410.4 R .025
  443. X(and if the database \214le is a character special \214le and no complete k)144
  444. X422.4 R -.15(ey)-.1 G .025(/data pairs are currently a).15 F -.25(va)-.2 G(il-)
  445. X.25 E(able, the)144 434.4 Q F2(seq)2.5 E F0(routines return 2.)2.5 E 15.17
  446. X(sync A)108 451.2 R .458(pointer to a routine to \215ush an)2.958 F 2.957(yc)
  447. X-.15 G .457(ached information to disk.)289.72 451.2 R .457
  448. X(If the database is in memory only)5.457 F(,)-.65 E(the)144 463.2 Q F2(sync)2.5
  449. XE F0(routine has no ef)2.5 E(fect and will al)-.25 E -.1(wa)-.1 G(ys succeed.)
  450. X.1 E(The \215ag v)144 480 Q(alue may be set to the follo)-.25 E(wing v)-.25 E
  451. X(alue:)-.25 E(R_RECNOSYNC)144 496.8 Q .077(If the DB_RECNO access method is be\
  452. Xing used, this \215ag causes the sync routine to apply)180 508.8 R .75(to the \
  453. Xbtree \214le which underlies the recno \214le, not the recno \214le itself.)180
  454. X520.8 R .75(\(See the)5.75 F F2(bfname)3.25 E F0(\214eld of the)180 532.8 Q F2
  455. X-.37(re)2.5 G(cno).37 E F0(\(3\) manual page for more information.\)).18 E F2
  456. X(Sync)144 549.6 Q F0(routines return -1 on error \(setting)2.5 E F2(errno)2.5 E
  457. XF0 2.5(\)a).18 G(nd 0 on success.)336.91 549.6 Q/F3 9/Times-Bold@0 SF(KEY/D)72
  458. X566.4 Q -1.35 -.855(AT A)-.315 H -.666(PA)3.105 G(IRS).666 E F0 .134
  459. X(Access to all \214le types is based on k)108 578.4 R -.15(ey)-.1 G .134
  460. X(/data pairs.).15 F .134(Both k)5.134 F -.15(ey)-.1 G 2.634(sa).15 G .134
  461. X(nd data are represented by the follo)359.078 578.4 R .135(wing data)-.25 F
  462. X(structure:)108 590.4 Q(typedef struct {)108 607.2 Q -.2(vo)144 619.2 S
  463. X(id *data;).2 E(size_t size;)144 631.2 Q 2.5(}D)108 643.2 S(BT)122.52 643.2 Q
  464. X(;)-.55 E(The elements of the DBT structure are de\214ned as follo)108 660 Q
  465. X(ws:)-.25 E 16.84(data A)108 676.8 R(pointer to a byte string.)2.5 E 17.95
  466. X(size The)108 693.6 R(length of the byte string.)2.5 E -2.15 -.25(Ke y)108
  467. X710.4 T .829(and data byte strings may reference strings of essentially unlimi\
  468. Xted length although an)3.579 F 3.328(yt)-.15 G 1.028 -.1(wo o)492.894 710.4 T
  469. X3.328(ft).1 G(hem)522.78 710.4 Q 1.133(must \214t into a)108 722.4 R -.25(va)
  470. X-.2 G 1.134(ilable memory at the same time.).25 F 1.134
  471. X(It should be noted that the access methods pro)6.134 F 1.134(vide no)-.15 F
  472. X209.835(24, May)72 768 R(3)535 768 Q EP
  473. X%%Page: 4 4
  474. X%%BeginPageSetup
  475. XBP
  476. X%%EndPageSetup
  477. X/F0 10/Times-Roman@0 SF 169.84(DBOPEN\(3\) 1993 DBOPEN\(3\))72 48 R
  478. X(guarantees about byte string alignment.)108 84 Q/F1 9/Times-Bold@0 SF(ERR)72
  479. X100.8 Q(ORS)-.27 E F0(The)108 112.8 Q/F2 10/Times-Italic@0 SF(dbopen)3.389 E F0
  480. X.889(routine may f)3.389 F .889(ail and set)-.1 F F2(errno)3.388 E F0 .888
  481. X(for an)3.388 F 3.388(yo)-.15 G 3.388(ft)324.376 112.8 S .888
  482. X(he errors speci\214ed for the library routines)333.874 112.8 R F2(open)3.388 E
  483. XF0(\(2\)).24 E(and)108 124.8 Q F2(malloc)2.5 E F0(\(3\) or the follo).31 E
  484. X(wing:)-.25 E([EFTYPE])108 141.6 Q 2.5<418c>144 153.6 S
  485. X(le is incorrectly formatted.)159.28 153.6 Q([EINV)108 170.4 Q(AL])-1.35 E
  486. X2.812(Ap)144 182.4 S .313(arameter has been speci\214ed \(hash function, pad b\
  487. Xyte etc.\) that is incompatible with the current)159.032 182.4 R .406
  488. X(\214le speci\214cation or which is not meaningful for the function \(for e)144
  489. X194.4 R .405(xample, use of the cursor with-)-.15 F .099
  490. X(out prior initialization\) or there is a mismatch between the v)144 206.4 R .1
  491. X(ersion number of \214le and the softw)-.15 F(are.)-.1 E(The)108 223.2 Q F2
  492. X(close)3.469 E F0 .969(routines may f)3.469 F .969(ail and set)-.1 F F2(errno)
  493. X3.469 E F0 .969(for an)3.469 F 3.469(yo)-.15 G 3.469(ft)320.18 223.2 S .969
  494. X(he errors speci\214ed for the library routines)329.759 223.2 R F2(close)3.468
  495. XE F0(\(2\),).18 E F2 -.37(re)108 235.2 S(ad).37 E F0(\(2\),).77 E F2(write)2.5
  496. XE F0(\(2\),).18 E F2(fr)2.5 E(ee)-.37 E F0(\(3\), or).18 E F2(fsync)2.5 E F0
  497. X(\(2\).).31 E(The)108 252 Q F2(del)2.969 E F0(,).51 E F2 -.1(ge)2.969 G(t).1 E
  498. XF0(,).68 E F2(put)2.969 E F0(and)2.969 E F2(seq)2.969 E F0 .469(routines may f)
  499. X2.969 F .469(ail and set)-.1 F F2(errno)2.97 E F0 .47(for an)2.97 F 2.97(yo)
  500. X-.15 G 2.97(ft)377.59 252 S .47(he errors speci\214ed for the library rou-)
  501. X386.67 252 R(tines)108 264 Q F2 -.37(re)2.5 G(ad).37 E F0(\(2\),).77 E F2
  502. X(write)2.5 E F0(\(2\),).18 E F2(fr)2.5 E(ee)-.37 E F0(\(3\) or).18 E F2(malloc)
  503. X2.5 E F0(\(3\).).31 E(The)108 280.8 Q F2(fd)2.5 E F0(routines will f)2.5 E
  504. X(ail and set)-.1 E F2(errno)2.5 E F0(to ENOENT for in memory databases.)2.5 E
  505. X(The)108 297.6 Q F2(sync)2.5 E F0(routines may f)2.5 E(ail and set)-.1 E F2
  506. X(errno)2.5 E F0(for an)2.5 E 2.5(yo)-.15 G 2.5(ft)307.71 297.6 S
  507. X(he errors speci\214ed for the library routine)316.32 297.6 Q F2(fsync)2.5 E F0
  508. X(\(2\).).31 E F1(SEE ALSO)72 314.4 Q F2(btr)108 326.4 Q(ee)-.37 E F0(\(3\),).18
  509. XE F2(hash)2.5 E F0(\(3\),).28 E F2(mpool)2.5 E F0(\(3\),).51 E F2 -.37(re)2.5 G
  510. X(cno).37 E F0(\(3\)).18 E F1 -.09(BU)72 343.2 S(GS).09 E F0 .399
  511. X(The typedef DBT is a mnemonic for `)108 355.2 R .399(`data base thang')-.74 F
  512. X.399(', and w)-.74 F .399(as used because noone could think of a rea-)-.1 F
  513. X(sonable name that w)108 367.2 Q(asn')-.1 E 2.5(ta)-.18 G(lready used.)216.03
  514. X367.2 Q(The \214le descriptor interf)108 384 Q
  515. X(ace is a kluge and will be deleted in a future v)-.1 E(ersion of the interf)
  516. X-.15 E(ace.)-.1 E(None of the access methods pro)108 400.8 Q(vide an)-.15 E 2.5
  517. X(yf)-.15 G(orm of concurrent access, locking, or transactions.)275.16 400.8 Q
  518. X209.835(24, May)72 768 R(4)535 768 Q EP
  519. X%%Trailer
  520. Xend
  521. X%%EOF
  522. END_OF_FILE
  523. if test 25656 -ne `wc -c <'doc/dbopen.3.ps'`; then
  524.     echo shar: \"'doc/dbopen.3.ps'\" unpacked with wrong size!
  525. fi
  526. # end of 'doc/dbopen.3.ps'
  527. fi
  528. if test -f 'hash/hash.c' -a "${1}" != "-c" ; then 
  529.   echo shar: Will not clobber existing file \"'hash/hash.c'\"
  530. else
  531. echo shar: Extracting \"'hash/hash.c'\" \(23885 characters\)
  532. sed "s/^X//" >'hash/hash.c' <<'END_OF_FILE'
  533. X/*-
  534. X * Copyright (c) 1990, 1993
  535. X *    The Regents of the University of California.  All rights reserved.
  536. X *
  537. X * This code is derived from software contributed to Berkeley by
  538. X * Margo Seltzer.
  539. X *
  540. X * Redistribution and use in source and binary forms, with or without
  541. X * modification, are permitted provided that the following conditions
  542. X * are met:
  543. X * 1. Redistributions of source code must retain the above copyright
  544. X *    notice, this list of conditions and the following disclaimer.
  545. X * 2. Redistributions in binary form must reproduce the above copyright
  546. X *    notice, this list of conditions and the following disclaimer in the
  547. X *    documentation and/or other materials provided with the distribution.
  548. X * 3. All advertising materials mentioning features or use of this software
  549. X *    must display the following acknowledgement:
  550. X *    This product includes software developed by the University of
  551. X *    California, Berkeley and its contributors.
  552. X * 4. Neither the name of the University nor the names of its contributors
  553. X *    may be used to endorse or promote products derived from this software
  554. X *    without specific prior written permission.
  555. X *
  556. X * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  557. X * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  558. X * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  559. X * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  560. X * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  561. X * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  562. X * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  563. X * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  564. X * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  565. X * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  566. X * SUCH DAMAGE.
  567. X */
  568. X
  569. X#if defined(LIBC_SCCS) && !defined(lint)
  570. Xstatic char sccsid[] = "@(#)hash.c    8.1 (Berkeley) 6/6/93";
  571. X#endif /* LIBC_SCCS and not lint */
  572. X
  573. X#include <sys/param.h>
  574. X#include <sys/stat.h>
  575. X
  576. X#include <errno.h>
  577. X#include <fcntl.h>
  578. X#include <stdio.h>
  579. X#include <stdlib.h>
  580. X#include <string.h>
  581. X#include <unistd.h>
  582. X#ifdef DEBUG
  583. X#include <assert.h>
  584. X#endif
  585. X
  586. X#include <db.h>
  587. X#include "hash.h"
  588. X#include "page.h"
  589. X#include "extern.h"
  590. X
  591. Xstatic int   alloc_segs __P((HTAB *, int));
  592. Xstatic int   flush_meta __P((HTAB *));
  593. Xstatic int   hash_access __P((HTAB *, ACTION, DBT *, DBT *));
  594. Xstatic int   hash_close __P((DB *));
  595. Xstatic int   hash_delete __P((const DB *, const DBT *, u_int));
  596. Xstatic int   hash_fd __P((const DB *));
  597. Xstatic int   hash_get __P((const DB *, const DBT *, DBT *, u_int));
  598. Xstatic int   hash_put __P((const DB *, DBT *, const DBT *, u_int));
  599. Xstatic void *hash_realloc __P((SEGMENT **, int, int));
  600. Xstatic int   hash_seq __P((const DB *, DBT *, DBT *, u_int));
  601. Xstatic int   hash_sync __P((const DB *, u_int));
  602. Xstatic int   hdestroy __P((HTAB *));
  603. Xstatic HTAB *init_hash __P((HTAB *, const char *, HASHINFO *));
  604. Xstatic int   init_htab __P((HTAB *, int));
  605. X#if BYTE_ORDER == LITTLE_ENDIAN
  606. Xstatic void  swap_header __P((HTAB *));
  607. Xstatic void  swap_header_copy __P((HASHHDR *, HASHHDR *));
  608. X#endif
  609. X
  610. X/* Fast arithmetic, relying on powers of 2, */
  611. X#define MOD(x, y)        ((x) & ((y) - 1))
  612. X
  613. X#define RETURN_ERROR(ERR, LOC)    { save_errno = ERR; goto LOC; }
  614. X
  615. X/* Return values */
  616. X#define    SUCCESS     (0)
  617. X#define    ERROR    (-1)
  618. X#define    ABNORMAL (1)
  619. X
  620. X#ifdef HASH_STATISTICS
  621. Xlong hash_accesses, hash_collisions, hash_expansions, hash_overflows;
  622. X#endif
  623. X
  624. X/************************** INTERFACE ROUTINES ***************************/
  625. X/* OPEN/CLOSE */
  626. X
  627. Xextern DB *
  628. X__hash_open(file, flags, mode, info)
  629. X    const char *file;
  630. X    int flags, mode;
  631. X    const HASHINFO *info;    /* Special directives for create */
  632. X{
  633. X    HTAB *hashp;
  634. X    struct stat statbuf;
  635. X    DB *dbp;
  636. X    int bpages, hdrsize, new_table, nsegs, save_errno;
  637. X
  638. X    if ((flags & O_ACCMODE) == O_WRONLY) {
  639. X        errno = EINVAL;
  640. X        return (NULL);
  641. X    }
  642. X
  643. X    if (!(hashp = calloc(1, sizeof(HTAB))))
  644. X        return (NULL);
  645. X    hashp->fp = -1;
  646. X    /*
  647. X     * Select flags relevant to us. Even if user wants write only, we need
  648. X     * to be able to read the actual file, so we need to open it read/write.
  649. X     * But, the field in the hashp structure needs to be accurate so that
  650. X     * we can check accesses.
  651. X     */
  652. X    hashp->flags = flags = flags & __USE_OPEN_FLAGS;
  653. X
  654. X    new_table = 0;
  655. X    if (!file || (flags & O_TRUNC) ||
  656. X        (stat(file, &statbuf) && (errno == ENOENT))) {
  657. X        if (errno == ENOENT)
  658. X            errno = 0; /* Just in case someone looks at errno */
  659. X        new_table = 1;
  660. X    }
  661. X    if (file) {
  662. X        if ((hashp->fp = open(file, flags, mode)) == -1)
  663. X            RETURN_ERROR(errno, error0);
  664. X        (void)fcntl(hashp->fp, F_SETFD, 1);
  665. X    }
  666. X    if (new_table) {
  667. X        if (!(hashp = init_hash(hashp, file, (HASHINFO *)info)))
  668. X            RETURN_ERROR(errno, error1);
  669. X    } else {
  670. X        /* Table already exists */
  671. X        if (info && info->hash)
  672. X            hashp->hash = info->hash;
  673. X        else
  674. X            hashp->hash = __default_hash;
  675. X
  676. X        hdrsize = read(hashp->fp, &hashp->hdr, sizeof(HASHHDR));
  677. X#if BYTE_ORDER == LITTLE_ENDIAN
  678. X        swap_header(hashp);
  679. X#endif
  680. X        if (hdrsize == -1)
  681. X            RETURN_ERROR(errno, error1);
  682. X        if (hdrsize != sizeof(HASHHDR))
  683. X            RETURN_ERROR(EFTYPE, error1);
  684. X        /* Verify file type, versions and hash function */
  685. X        if (hashp->MAGIC != HASHMAGIC)
  686. X            RETURN_ERROR(EFTYPE, error1);
  687. X        if (hashp->VERSION != HASHVERSION)
  688. X            RETURN_ERROR(EFTYPE, error1);
  689. X        if (hashp->hash(CHARKEY, sizeof(CHARKEY)) != hashp->H_CHARKEY)
  690. X            RETURN_ERROR(EFTYPE, error1);
  691. X        /*
  692. X         * Figure out how many segments we need.  Max_Bucket is the
  693. X         * maximum bucket number, so the number of buckets is
  694. X         * max_bucket + 1.
  695. X         */
  696. X        nsegs = (hashp->MAX_BUCKET + 1 + hashp->SGSIZE - 1) /
  697. X             hashp->SGSIZE;
  698. X        hashp->nsegs = 0;
  699. X        if (alloc_segs(hashp, nsegs))
  700. X            /*
  701. X             * If alloc_segs fails, table will have been destroyed
  702. X             * and errno will have been set.
  703. X             */
  704. X            return (NULL);
  705. X        /* Read in bitmaps */
  706. X        bpages = (hashp->SPARES[hashp->OVFL_POINT] +
  707. X            (hashp->BSIZE << BYTE_SHIFT) - 1) >>
  708. X            (hashp->BSHIFT + BYTE_SHIFT);
  709. X
  710. X        hashp->nmaps = bpages;
  711. X        (void)memset(&hashp->mapp[0], 0, bpages * sizeof(u_long *));
  712. X    }
  713. X
  714. X    /* Initialize Buffer Manager */
  715. X    if (info && info->cachesize)
  716. X        __buf_init(hashp, info->cachesize);
  717. X    else
  718. X        __buf_init(hashp, DEF_BUFSIZE);
  719. X
  720. X    hashp->new_file = new_table;
  721. X    hashp->save_file = file && (hashp->flags & O_RDWR);
  722. X    hashp->cbucket = -1;
  723. X    if (!(dbp = malloc(sizeof(DB)))) {
  724. X        save_errno = errno;
  725. X        hdestroy(hashp);
  726. X        errno = save_errno;
  727. X        return (NULL);
  728. X    }
  729. X    dbp->internal = hashp;
  730. X    dbp->close = hash_close;
  731. X    dbp->del = hash_delete;
  732. X    dbp->fd = hash_fd;
  733. X    dbp->get = hash_get;
  734. X    dbp->put = hash_put;
  735. X    dbp->seq = hash_seq;
  736. X    dbp->sync = hash_sync;
  737. X    dbp->type = DB_HASH;
  738. X
  739. X#ifdef DEBUG
  740. X    (void)fprintf(stderr,
  741. X"%s\n%s%x\n%s%d\n%s%d\n%s%d\n%s%d\n%s%d\n%s%d\n%s%d\n%s%d\n%s%d\n%s%x\n%s%x\n%s%d\n%s%d\n",
  742. X        "init_htab:",
  743. X        "TABLE POINTER   ", hashp,
  744. X        "BUCKET SIZE     ", hashp->BSIZE,
  745. X        "BUCKET SHIFT    ", hashp->BSHIFT,
  746. X        "DIRECTORY SIZE  ", hashp->DSIZE,
  747. X        "SEGMENT SIZE    ", hashp->SGSIZE,
  748. X        "SEGMENT SHIFT   ", hashp->SSHIFT,
  749. X        "FILL FACTOR     ", hashp->FFACTOR,
  750. X        "MAX BUCKET      ", hashp->MAX_BUCKET,
  751. X        "OVFL POINT         ", hashp->OVFL_POINT,
  752. X        "LAST FREED      ", hashp->LAST_FREED,
  753. X        "HIGH MASK       ", hashp->HIGH_MASK,
  754. X        "LOW  MASK       ", hashp->LOW_MASK,
  755. X        "NSEGS           ", hashp->nsegs,
  756. X        "NKEYS           ", hashp->NKEYS);
  757. X#endif
  758. X#ifdef HASH_STATISTICS
  759. X    hash_overflows = hash_accesses = hash_collisions = hash_expansions = 0;
  760. X#endif
  761. X    return (dbp);
  762. X
  763. Xerror1:
  764. X    if (hashp != NULL)
  765. X        (void)close(hashp->fp);
  766. X
  767. Xerror0:
  768. X    free(hashp);
  769. X    errno = save_errno;
  770. X    return (NULL);
  771. X}
  772. X
  773. Xstatic int
  774. Xhash_close(dbp)
  775. X    DB *dbp;
  776. X{
  777. X    HTAB *hashp;
  778. X    int retval;
  779. X
  780. X    if (!dbp)
  781. X        return (ERROR);
  782. X
  783. X    hashp = (HTAB *)dbp->internal;
  784. X    retval = hdestroy(hashp);
  785. X    free(dbp);
  786. X    return (retval);
  787. X}
  788. X
  789. Xstatic int
  790. Xhash_fd(dbp)
  791. X    const DB *dbp;
  792. X{
  793. X    HTAB *hashp;
  794. X
  795. X    if (!dbp)
  796. X        return (ERROR);
  797. X
  798. X    hashp = (HTAB *)dbp->internal;
  799. X    if (hashp->fp == -1) {
  800. X        errno = ENOENT;
  801. X        return (-1);
  802. X    }
  803. X    return (hashp->fp);
  804. X}
  805. X
  806. X/************************** LOCAL CREATION ROUTINES **********************/
  807. Xstatic HTAB *
  808. Xinit_hash(hashp, file, info)
  809. X    HTAB *hashp;
  810. X    const char *file;
  811. X    HASHINFO *info;
  812. X{
  813. X    struct stat statbuf;
  814. X    int nelem;
  815. X
  816. X    nelem = 1;
  817. X    hashp->NKEYS = 0;
  818. X    hashp->LORDER = BYTE_ORDER;
  819. X    hashp->BSIZE = DEF_BUCKET_SIZE;
  820. X    hashp->BSHIFT = DEF_BUCKET_SHIFT;
  821. X    hashp->SGSIZE = DEF_SEGSIZE;
  822. X    hashp->SSHIFT = DEF_SEGSIZE_SHIFT;
  823. X    hashp->DSIZE = DEF_DIRSIZE;
  824. X    hashp->FFACTOR = DEF_FFACTOR;
  825. X    hashp->hash = __default_hash;
  826. X    memset(hashp->SPARES, 0, sizeof(hashp->SPARES));
  827. X    memset(hashp->BITMAPS, 0, sizeof (hashp->BITMAPS));
  828. X
  829. X    /* Fix bucket size to be optimal for file system */
  830. X    if (file != NULL) {
  831. X        if (stat(file, &statbuf))
  832. X            return (NULL);
  833. X        hashp->BSIZE = statbuf.st_blksize;
  834. X        hashp->BSHIFT = __log2(hashp->BSIZE);
  835. X    }
  836. X
  837. X    if (info) {
  838. X        if (info->bsize) {
  839. X            /* Round pagesize up to power of 2 */
  840. X            hashp->BSHIFT = __log2(info->bsize);
  841. X            hashp->BSIZE = 1 << hashp->BSHIFT;
  842. X            if (hashp->BSIZE > MAX_BSIZE) {
  843. X                errno = EINVAL;
  844. X                return (NULL);
  845. X            }
  846. X        }
  847. X        if (info->ffactor)
  848. X            hashp->FFACTOR = info->ffactor;
  849. X        if (info->hash)
  850. X            hashp->hash = info->hash;
  851. X        if (info->nelem)
  852. X            nelem = info->nelem;
  853. X        if (info->lorder) {
  854. X            if (info->lorder != BIG_ENDIAN &&
  855. X                info->lorder != LITTLE_ENDIAN) {
  856. X                errno = EINVAL;
  857. X                return (NULL);
  858. X            }
  859. X            hashp->LORDER = info->lorder;
  860. X        }
  861. X    }
  862. X    /* init_htab should destroy the table and set errno if it fails */
  863. X    if (init_htab(hashp, nelem))
  864. X        return (NULL);
  865. X    else
  866. X        return (hashp);
  867. X}
  868. X/*
  869. X * This calls alloc_segs which may run out of memory.  Alloc_segs will destroy
  870. X * the table and set errno, so we just pass the error information along.
  871. X *
  872. X * Returns 0 on No Error
  873. X */
  874. Xstatic int
  875. Xinit_htab(hashp, nelem)
  876. X    HTAB *hashp;
  877. X    int nelem;
  878. X{
  879. X    register int nbuckets, nsegs;
  880. X    int l2;
  881. X
  882. X    /*
  883. X     * Divide number of elements by the fill factor and determine a
  884. X     * desired number of buckets.  Allocate space for the next greater
  885. X     * power of two number of buckets.
  886. X     */
  887. X    nelem = (nelem - 1) / hashp->FFACTOR + 1;
  888. X
  889. X    l2 = __log2(MAX(nelem, 2));
  890. X    nbuckets = 1 << l2;
  891. X
  892. X    hashp->SPARES[l2] = l2 + 1;
  893. X    hashp->SPARES[l2 + 1] = l2 + 1;
  894. X    hashp->OVFL_POINT = l2;
  895. X    hashp->LAST_FREED = 2;
  896. X
  897. X    /* First bitmap page is at: splitpoint l2 page offset 1 */
  898. X    if (__init_bitmap(hashp, OADDR_OF(l2, 1), l2 + 1, 0))
  899. X        return (-1);
  900. X
  901. X    hashp->MAX_BUCKET = hashp->LOW_MASK = nbuckets - 1;
  902. X    hashp->HIGH_MASK = (nbuckets << 1) - 1;
  903. X    hashp->HDRPAGES = ((MAX(sizeof(HASHHDR), MINHDRSIZE) - 1) >>
  904. X        hashp->BSHIFT) + 1;
  905. X
  906. X    nsegs = (nbuckets - 1) / hashp->SGSIZE + 1;
  907. X    nsegs = 1 << __log2(nsegs);
  908. X
  909. X    if (nsegs > hashp->DSIZE)
  910. X        hashp->DSIZE = nsegs;
  911. X    return (alloc_segs(hashp, nsegs));
  912. X}
  913. X
  914. X/********************** DESTROY/CLOSE ROUTINES ************************/
  915. X
  916. X/*
  917. X * Flushes any changes to the file if necessary and destroys the hashp
  918. X * structure, freeing all allocated space.
  919. X */
  920. Xstatic int
  921. Xhdestroy(hashp)
  922. X    HTAB *hashp;
  923. X{
  924. X    int i, save_errno;
  925. X
  926. X    save_errno = 0;
  927. X
  928. X#ifdef HASH_STATISTICS
  929. X    (void)fprintf(stderr, "hdestroy: accesses %ld collisions %ld\n",
  930. X        hash_accesses, hash_collisions);
  931. X    (void)fprintf(stderr, "hdestroy: expansions %ld\n",
  932. X        hash_expansions);
  933. X    (void)fprintf(stderr, "hdestroy: overflows %ld\n",
  934. X        hash_overflows);
  935. X    (void)fprintf(stderr, "keys %ld maxp %d segmentcount %d\n",
  936. X        hashp->NKEYS, hashp->MAX_BUCKET, hashp->nsegs);
  937. X
  938. X    for (i = 0; i < NCACHED; i++)
  939. X        (void)fprintf(stderr,
  940. X            "spares[%d] = %d\n", i, hashp->SPARES[i]);
  941. X#endif
  942. X    /*
  943. X     * Call on buffer manager to free buffers, and if required,
  944. X     * write them to disk.
  945. X     */
  946. X    if (__buf_free(hashp, 1, hashp->save_file))
  947. X        save_errno = errno;
  948. X    if (hashp->dir) {
  949. X        free(*hashp->dir);    /* Free initial segments */
  950. X        /* Free extra segments */
  951. X        while (hashp->exsegs--)
  952. X            free(hashp->dir[--hashp->nsegs]);
  953. X        free(hashp->dir);
  954. X    }
  955. X    if (flush_meta(hashp) && !save_errno)
  956. X        save_errno = errno;
  957. X    /* Free Bigmaps */
  958. X    for (i = 0; i < hashp->nmaps; i++)
  959. X        if (hashp->mapp[i])
  960. X            free(hashp->mapp[i]);
  961. X
  962. X    if (hashp->fp != -1)
  963. X        (void)close(hashp->fp);
  964. X
  965. X    if (save_errno) {
  966. X        errno = save_errno;
  967. X        return (ERROR);
  968. X    }
  969. X    return (SUCCESS);
  970. X}
  971. X/*
  972. X * Write modified pages to disk
  973. X *
  974. X * Returns:
  975. X *     0 == OK
  976. X *    -1 ERROR
  977. X */
  978. Xstatic int
  979. Xhash_sync(dbp, flags)
  980. X    const DB *dbp;
  981. X    u_int flags;
  982. X{
  983. X    HTAB *hashp;
  984. X
  985. X    if (flags != 0) {
  986. X        errno = EINVAL;
  987. X        return (ERROR);
  988. X    }
  989. X
  990. X    if (!dbp)
  991. X        return (ERROR);
  992. X
  993. X    hashp = (HTAB *)dbp->internal;
  994. X    if (!hashp->save_file)
  995. X        return (0);
  996. X    if (__buf_free(hashp, 0, 1) || flush_meta(hashp))
  997. X        return (ERROR);
  998. X    hashp->new_file = 0;
  999. X    return (0);
  1000. X}
  1001. X
  1002. X/*
  1003. X * Returns:
  1004. X *     0 == OK
  1005. X *    -1 indicates that errno should be set
  1006. X */
  1007. Xstatic int
  1008. Xflush_meta(hashp)
  1009. X    HTAB *hashp;
  1010. X{
  1011. X    HASHHDR *whdrp;
  1012. X#if BYTE_ORDER == LITTLE_ENDIAN
  1013. X    HASHHDR whdr;
  1014. X#endif
  1015. X    int fp, i, wsize;
  1016. X
  1017. X    if (!hashp->save_file)
  1018. X        return (0);
  1019. X    hashp->MAGIC = HASHMAGIC;
  1020. X    hashp->VERSION = HASHVERSION;
  1021. X    hashp->H_CHARKEY = hashp->hash(CHARKEY, sizeof(CHARKEY));
  1022. X
  1023. X    fp = hashp->fp;
  1024. X    whdrp = &hashp->hdr;
  1025. X#if BYTE_ORDER == LITTLE_ENDIAN
  1026. X    whdrp = &whdr;
  1027. X    swap_header_copy(&hashp->hdr, whdrp);
  1028. X#endif
  1029. X    if ((lseek(fp, (off_t)0, SEEK_SET) == -1) ||
  1030. X        ((wsize = write(fp, whdrp, sizeof(HASHHDR))) == -1))
  1031. X        return (-1);
  1032. X    else
  1033. X        if (wsize != sizeof(HASHHDR)) {
  1034. X            errno = EFTYPE;
  1035. X            hashp->errno = errno;
  1036. X            return (-1);
  1037. X        }
  1038. X    for (i = 0; i < NCACHED; i++)
  1039. X        if (hashp->mapp[i])
  1040. X            if (__put_page(hashp, (char *)hashp->mapp[i],
  1041. X                hashp->BITMAPS[i], 0, 1))
  1042. X                return (-1);
  1043. X    return (0);
  1044. X}
  1045. X
  1046. X/*******************************SEARCH ROUTINES *****************************/
  1047. X/*
  1048. X * All the access routines return
  1049. X *
  1050. X * Returns:
  1051. X *     0 on SUCCESS
  1052. X *     1 to indicate an external ERROR (i.e. key not found, etc)
  1053. X *    -1 to indicate an internal ERROR (i.e. out of memory, etc)
  1054. X */
  1055. Xstatic int
  1056. Xhash_get(dbp, key, data, flag)
  1057. X    const DB *dbp;
  1058. X    const DBT *key;
  1059. X    DBT *data;
  1060. X    u_int flag;
  1061. X{
  1062. X    HTAB *hashp;
  1063. X
  1064. X    hashp = (HTAB *)dbp->internal;
  1065. X    if (flag) {
  1066. X        hashp->errno = errno = EINVAL;
  1067. X        return (ERROR);
  1068. X    }
  1069. X    return (hash_access(hashp, HASH_GET, (DBT *)key, data));
  1070. X}
  1071. X
  1072. Xstatic int
  1073. Xhash_put(dbp, key, data, flag)
  1074. X    const DB *dbp;
  1075. X    DBT *key;
  1076. X    const DBT *data;
  1077. X    u_int flag;
  1078. X{
  1079. X    HTAB *hashp;
  1080. X
  1081. X    hashp = (HTAB *)dbp->internal;
  1082. X    if (flag && flag != R_NOOVERWRITE) {
  1083. X        hashp->errno = errno = EINVAL;
  1084. X        return (ERROR);
  1085. X    }
  1086. X    if ((hashp->flags & O_ACCMODE) == O_RDONLY) {
  1087. X        hashp->errno = errno = EPERM;
  1088. X        return (ERROR);
  1089. X    }
  1090. X    return (hash_access(hashp, flag == R_NOOVERWRITE ?
  1091. X        HASH_PUTNEW : HASH_PUT, (DBT *)key, (DBT *)data));
  1092. X}
  1093. X
  1094. Xstatic int
  1095. Xhash_delete(dbp, key, flag)
  1096. X    const DB *dbp;
  1097. X    const DBT *key;
  1098. X    u_int flag;        /* Ignored */
  1099. X{
  1100. X    HTAB *hashp;
  1101. X
  1102. X    hashp = (HTAB *)dbp->internal;
  1103. X    if (flag && flag != R_CURSOR) {
  1104. X        hashp->errno = errno = EINVAL;
  1105. X        return (ERROR);
  1106. X    }
  1107. X    if ((hashp->flags & O_ACCMODE) == O_RDONLY) {
  1108. X        hashp->errno = errno = EPERM;
  1109. X        return (ERROR);
  1110. X    }
  1111. X    return (hash_access(hashp, HASH_DELETE, (DBT *)key, NULL));
  1112. X}
  1113. X
  1114. X/*
  1115. X * Assume that hashp has been set in wrapper routine.
  1116. X */
  1117. Xstatic int
  1118. Xhash_access(hashp, action, key, val)
  1119. X    HTAB *hashp;
  1120. X    ACTION action;
  1121. X    DBT *key, *val;
  1122. X{
  1123. X    register BUFHEAD *rbufp;
  1124. X    BUFHEAD *bufp, *save_bufp;
  1125. X    register u_short *bp;
  1126. X    register int n, ndx, off, size;
  1127. X    register char *kp;
  1128. X    u_short pageno;
  1129. X
  1130. X#ifdef HASH_STATISTICS
  1131. X    hash_accesses++;
  1132. X#endif
  1133. X
  1134. X    off = hashp->BSIZE;
  1135. X    size = key->size;
  1136. X    kp = (char *)key->data;
  1137. X    rbufp = __get_buf(hashp, __call_hash(hashp, kp, size), NULL, 0);
  1138. X    if (!rbufp)
  1139. X        return (ERROR);
  1140. X    save_bufp = rbufp;
  1141. X
  1142. X    /* Pin the bucket chain */
  1143. X    rbufp->flags |= BUF_PIN;
  1144. X    for (bp = (u_short *)rbufp->page, n = *bp++, ndx = 1; ndx < n;)
  1145. X        if (bp[1] >= REAL_KEY) {
  1146. X            /* Real key/data pair */
  1147. X            if (size == off - *bp &&
  1148. X                memcmp(kp, rbufp->page + *bp, size) == 0)
  1149. X                goto found;
  1150. X            off = bp[1];
  1151. X#ifdef HASH_STATISTICS
  1152. X            hash_collisions++;
  1153. X#endif
  1154. X            bp += 2;
  1155. X            ndx += 2;
  1156. X        } else if (bp[1] == OVFLPAGE) {
  1157. X            rbufp = __get_buf(hashp, *bp, rbufp, 0);
  1158. X            if (!rbufp) {
  1159. X                save_bufp->flags &= ~BUF_PIN;
  1160. X                return (ERROR);
  1161. X            }
  1162. X            /* FOR LOOP INIT */
  1163. X            bp = (u_short *)rbufp->page;
  1164. X            n = *bp++;
  1165. X            ndx = 1;
  1166. X            off = hashp->BSIZE;
  1167. X        } else if (bp[1] < REAL_KEY) {
  1168. X            if ((ndx =
  1169. X                __find_bigpair(hashp, rbufp, ndx, kp, size)) > 0)
  1170. X                goto found;
  1171. X            if (ndx == -2) {
  1172. X                bufp = rbufp;
  1173. X                if (!(pageno =
  1174. X                    __find_last_page(hashp, &bufp))) {
  1175. X                    ndx = 0;
  1176. X                    rbufp = bufp;
  1177. X                    break;    /* FOR */
  1178. X                }
  1179. X                rbufp = __get_buf(hashp, pageno, bufp, 0);
  1180. X                if (!rbufp) {
  1181. X                    save_bufp->flags &= ~BUF_PIN;
  1182. X                    return (ERROR);
  1183. X                }
  1184. X                /* FOR LOOP INIT */
  1185. X                bp = (u_short *)rbufp->page;
  1186. X                n = *bp++;
  1187. X                ndx = 1;
  1188. X                off = hashp->BSIZE;
  1189. X            } else {
  1190. X                save_bufp->flags &= ~BUF_PIN;
  1191. X                return (ERROR);
  1192. X            }
  1193. X        }
  1194. X
  1195. X    /* Not found */
  1196. X    switch (action) {
  1197. X    case HASH_PUT:
  1198. X    case HASH_PUTNEW:
  1199. X        if (__addel(hashp, rbufp, key, val)) {
  1200. X            save_bufp->flags &= ~BUF_PIN;
  1201. X            return (ERROR);
  1202. X        } else {
  1203. X            save_bufp->flags &= ~BUF_PIN;
  1204. X            return (SUCCESS);
  1205. X        }
  1206. X    case HASH_GET:
  1207. X    case HASH_DELETE:
  1208. X    default:
  1209. X        save_bufp->flags &= ~BUF_PIN;
  1210. X        return (ABNORMAL);
  1211. X    }
  1212. X
  1213. Xfound:
  1214. X    switch (action) {
  1215. X    case HASH_PUTNEW:
  1216. X        save_bufp->flags &= ~BUF_PIN;
  1217. X        return (ABNORMAL);
  1218. X    case HASH_GET:
  1219. X        bp = (u_short *)rbufp->page;
  1220. X        if (bp[ndx + 1] < REAL_KEY) {
  1221. X            if (__big_return(hashp, rbufp, ndx, val, 0))
  1222. X                return (ERROR);
  1223. X        } else {
  1224. X            val->data = (u_char *)rbufp->page + (int)bp[ndx + 1];
  1225. X            val->size = bp[ndx] - bp[ndx + 1];
  1226. X        }
  1227. X        break;
  1228. X    case HASH_PUT:
  1229. X        if ((__delpair(hashp, rbufp, ndx)) ||
  1230. X            (__addel(hashp, rbufp, key, val))) {
  1231. X            save_bufp->flags &= ~BUF_PIN;
  1232. X            return (ERROR);
  1233. X        }
  1234. X        break;
  1235. X    case HASH_DELETE:
  1236. X        if (__delpair(hashp, rbufp, ndx))
  1237. X            return (ERROR);
  1238. X        break;
  1239. X    default:
  1240. X        abort();
  1241. X    }
  1242. X    save_bufp->flags &= ~BUF_PIN;
  1243. X    return (SUCCESS);
  1244. X}
  1245. X
  1246. Xstatic int
  1247. Xhash_seq(dbp, key, data, flag)
  1248. X    const DB *dbp;
  1249. X    DBT *key, *data;
  1250. X    u_int flag;
  1251. X{
  1252. X    register u_int bucket;
  1253. X    register BUFHEAD *bufp;
  1254. X    HTAB *hashp;
  1255. X    u_short *bp, ndx;
  1256. X
  1257. X    hashp = (HTAB *)dbp->internal;
  1258. X    if (flag && flag != R_FIRST && flag != R_NEXT) {
  1259. X        hashp->errno = errno = EINVAL;
  1260. X        return (ERROR);
  1261. X    }
  1262. X#ifdef HASH_STATISTICS
  1263. X    hash_accesses++;
  1264. X#endif
  1265. X    if ((hashp->cbucket < 0) || (flag == R_FIRST)) {
  1266. X        hashp->cbucket = 0;
  1267. X        hashp->cndx = 1;
  1268. X        hashp->cpage = NULL;
  1269. X    }
  1270. X
  1271. X    for (bp = NULL; !bp || !bp[0]; ) {
  1272. X        if (!(bufp = hashp->cpage)) {
  1273. X            for (bucket = hashp->cbucket;
  1274. X                bucket <= hashp->MAX_BUCKET;
  1275. X                bucket++, hashp->cndx = 1) {
  1276. X                bufp = __get_buf(hashp, bucket, NULL, 0);
  1277. X                if (!bufp)
  1278. X                    return (ERROR);
  1279. X                hashp->cpage = bufp;
  1280. X                bp = (u_short *)bufp->page;
  1281. X                if (bp[0])
  1282. X                    break;
  1283. X            }
  1284. X            hashp->cbucket = bucket;
  1285. X            if (hashp->cbucket > hashp->MAX_BUCKET) {
  1286. X                hashp->cbucket = -1;
  1287. X                return (ABNORMAL);
  1288. X            }
  1289. X        } else
  1290. X            bp = (u_short *)hashp->cpage->page;
  1291. X
  1292. X#ifdef DEBUG
  1293. X        assert(bp);
  1294. X        assert(bufp);
  1295. X#endif
  1296. X        while (bp[hashp->cndx + 1] == OVFLPAGE) {
  1297. X            bufp = hashp->cpage =
  1298. X                __get_buf(hashp, bp[hashp->cndx], bufp, 0);
  1299. X            if (!bufp)
  1300. X                return (ERROR);
  1301. X            bp = (u_short *)(bufp->page);
  1302. X            hashp->cndx = 1;
  1303. X        }
  1304. X        if (!bp[0]) {
  1305. X            hashp->cpage = NULL;
  1306. X            ++hashp->cbucket;
  1307. X        }
  1308. X    }
  1309. X    ndx = hashp->cndx;
  1310. X    if (bp[ndx + 1] < REAL_KEY) {
  1311. X        if (__big_keydata(hashp, bufp, key, data, 1))
  1312. X            return (ERROR);
  1313. X    } else {
  1314. X        key->data = (u_char *)hashp->cpage->page + bp[ndx];
  1315. X        key->size = (ndx > 1 ? bp[ndx - 1] : hashp->BSIZE) - bp[ndx];
  1316. X        data->data = (u_char *)hashp->cpage->page + bp[ndx + 1];
  1317. X        data->size = bp[ndx] - bp[ndx + 1];
  1318. X        ndx += 2;
  1319. X        if (ndx > bp[0]) {
  1320. X            hashp->cpage = NULL;
  1321. X            hashp->cbucket++;
  1322. X            hashp->cndx = 1;
  1323. X        } else
  1324. X            hashp->cndx = ndx;
  1325. X    }
  1326. X    return (SUCCESS);
  1327. X}
  1328. X
  1329. X/********************************* UTILITIES ************************/
  1330. X
  1331. X/*
  1332. X * Returns:
  1333. X *     0 ==> OK
  1334. X *    -1 ==> Error
  1335. X */
  1336. Xextern int
  1337. X__expand_table(hashp)
  1338. X    HTAB *hashp;
  1339. X{
  1340. X    u_int old_bucket, new_bucket;
  1341. X    int dirsize, new_segnum, spare_ndx;
  1342. X
  1343. X#ifdef HASH_STATISTICS
  1344. X    hash_expansions++;
  1345. X#endif
  1346. X    new_bucket = ++hashp->MAX_BUCKET;
  1347. X    old_bucket = (hashp->MAX_BUCKET & hashp->LOW_MASK);
  1348. X
  1349. X    new_segnum = new_bucket >> hashp->SSHIFT;
  1350. X
  1351. X    /* Check if we need a new segment */
  1352. X    if (new_segnum >= hashp->nsegs) {
  1353. X        /* Check if we need to expand directory */
  1354. X        if (new_segnum >= hashp->DSIZE) {
  1355. X            /* Reallocate directory */
  1356. X            dirsize = hashp->DSIZE * sizeof(SEGMENT *);
  1357. X            if (!hash_realloc(&hashp->dir, dirsize, dirsize << 1))
  1358. X                return (-1);
  1359. X            hashp->DSIZE = dirsize << 1;
  1360. X        }
  1361. X        if (!(hashp->dir[new_segnum] =
  1362. X            calloc(hashp->SGSIZE, sizeof(SEGMENT))))
  1363. X            return (-1);
  1364. X        hashp->exsegs++;
  1365. X        hashp->nsegs++;
  1366. X    }
  1367. X    /*
  1368. X     * If the split point is increasing (MAX_BUCKET's log base 2
  1369. X     * * increases), we need to copy the current contents of the spare
  1370. X     * split bucket to the next bucket.
  1371. X     */
  1372. X    spare_ndx = __log2(hashp->MAX_BUCKET + 1);
  1373. X    if (spare_ndx > hashp->OVFL_POINT) {
  1374. X        hashp->SPARES[spare_ndx] = hashp->SPARES[hashp->OVFL_POINT];
  1375. X        hashp->OVFL_POINT = spare_ndx;
  1376. X    }
  1377. X
  1378. X    if (new_bucket > hashp->HIGH_MASK) {
  1379. X        /* Starting a new doubling */
  1380. X        hashp->LOW_MASK = hashp->HIGH_MASK;
  1381. X        hashp->HIGH_MASK = new_bucket | hashp->LOW_MASK;
  1382. X    }
  1383. X    /* Relocate records to the new bucket */
  1384. X    return (__split_page(hashp, old_bucket, new_bucket));
  1385. X}
  1386. X
  1387. X/*
  1388. X * If realloc guarantees that the pointer is not destroyed if the realloc
  1389. X * fails, then this routine can go away.
  1390. X */
  1391. Xstatic void *
  1392. Xhash_realloc(p_ptr, oldsize, newsize)
  1393. X    SEGMENT **p_ptr;
  1394. X    int oldsize, newsize;
  1395. X{
  1396. X    register void *p;
  1397. X
  1398. X    if (p = malloc(newsize)) {
  1399. X        memmove(p, *p_ptr, oldsize);
  1400. X        memset(p + oldsize, 0, newsize - oldsize);
  1401. X        free(*p_ptr);
  1402. X        *p_ptr = p;
  1403. X    }
  1404. X    return (p);
  1405. X}
  1406. X
  1407. Xextern u_int
  1408. X__call_hash(hashp, k, len)
  1409. X    HTAB *hashp;
  1410. X    char *k;
  1411. X    int len;
  1412. X{
  1413. X    int n, bucket;
  1414. X
  1415. X    n = hashp->hash(k, len);
  1416. X    bucket = n & hashp->HIGH_MASK;
  1417. X    if (bucket > hashp->MAX_BUCKET)
  1418. X        bucket = bucket & hashp->LOW_MASK;
  1419. X    return (bucket);
  1420. X}
  1421. X
  1422. X/*
  1423. X * Allocate segment table.  On error, destroy the table and set errno.
  1424. X *
  1425. X * Returns 0 on success
  1426. X */
  1427. Xstatic int
  1428. Xalloc_segs(hashp, nsegs)
  1429. X    HTAB *hashp;
  1430. X    int nsegs;
  1431. X{
  1432. X    register int i;
  1433. X    register SEGMENT store;
  1434. X
  1435. X    int save_errno;
  1436. X
  1437. X    if (!(hashp->dir = calloc(hashp->DSIZE, sizeof(SEGMENT *)))) {
  1438. X        save_errno = errno;
  1439. X        (void)hdestroy(hashp);
  1440. X        errno = save_errno;
  1441. X        return (-1);
  1442. X    }
  1443. X    /* Allocate segments */
  1444. X    store = calloc(nsegs << hashp->SSHIFT, sizeof(SEGMENT));
  1445. X    if (!store) {
  1446. X        save_errno = errno;
  1447. X        (void)hdestroy(hashp);
  1448. X        errno = save_errno;
  1449. X        return (-1);
  1450. X    }
  1451. X    for (i = 0; i < nsegs; i++, hashp->nsegs++)
  1452. X        hashp->dir[i] = &store[i << hashp->SSHIFT];
  1453. X    return (0);
  1454. X}
  1455. X
  1456. X#if BYTE_ORDER == LITTLE_ENDIAN
  1457. X/*
  1458. X * Hashp->hdr needs to be byteswapped.
  1459. X */
  1460. Xstatic void
  1461. Xswap_header_copy(srcp, destp)
  1462. X    HASHHDR *srcp, *destp;
  1463. X{
  1464. X    int i;
  1465. X
  1466. X    BLSWAP_COPY(srcp->magic, destp->magic);
  1467. X    BLSWAP_COPY(srcp->version, destp->version);
  1468. X    BLSWAP_COPY(srcp->lorder, destp->lorder);
  1469. X    BLSWAP_COPY(srcp->bsize, destp->bsize);
  1470. X    BLSWAP_COPY(srcp->bshift, destp->bshift);
  1471. X    BLSWAP_COPY(srcp->dsize, destp->dsize);
  1472. X    BLSWAP_COPY(srcp->ssize, destp->ssize);
  1473. X    BLSWAP_COPY(srcp->sshift, destp->sshift);
  1474. X    BLSWAP_COPY(srcp->ovfl_point, destp->ovfl_point);
  1475. X    BLSWAP_COPY(srcp->last_freed, destp->last_freed);
  1476. X    BLSWAP_COPY(srcp->max_bucket, destp->max_bucket);
  1477. X    BLSWAP_COPY(srcp->high_mask, destp->high_mask);
  1478. X    BLSWAP_COPY(srcp->low_mask, destp->low_mask);
  1479. X    BLSWAP_COPY(srcp->ffactor, destp->ffactor);
  1480. X    BLSWAP_COPY(srcp->nkeys, destp->nkeys);
  1481. X    BLSWAP_COPY(srcp->hdrpages, destp->hdrpages);
  1482. X    BLSWAP_COPY(srcp->h_charkey, destp->h_charkey);
  1483. X    for (i = 0; i < NCACHED; i++) {
  1484. X        BLSWAP_COPY(srcp->spares[i], destp->spares[i]);
  1485. X        BSSWAP_COPY(srcp->bitmaps[i], destp->bitmaps[i]);
  1486. X    }
  1487. X}
  1488. X
  1489. Xstatic void
  1490. Xswap_header(hashp)
  1491. X    HTAB *hashp;
  1492. X{
  1493. X    HASHHDR *hdrp;
  1494. X    int i;
  1495. X
  1496. X    hdrp = &hashp->hdr;
  1497. X
  1498. X    BLSWAP(hdrp->magic);
  1499. X    BLSWAP(hdrp->version);
  1500. X    BLSWAP(hdrp->lorder);
  1501. X    BLSWAP(hdrp->bsize);
  1502. X    BLSWAP(hdrp->bshift);
  1503. X    BLSWAP(hdrp->dsize);
  1504. X    BLSWAP(hdrp->ssize);
  1505. X    BLSWAP(hdrp->sshift);
  1506. X    BLSWAP(hdrp->ovfl_point);
  1507. X    BLSWAP(hdrp->last_freed);
  1508. X    BLSWAP(hdrp->max_bucket);
  1509. X    BLSWAP(hdrp->high_mask);
  1510. X    BLSWAP(hdrp->low_mask);
  1511. X    BLSWAP(hdrp->ffactor);
  1512. X    BLSWAP(hdrp->nkeys);
  1513. X    BLSWAP(hdrp->hdrpages);
  1514. X    BLSWAP(hdrp->h_charkey);
  1515. X    for (i = 0; i < NCACHED; i++) {
  1516. X        BLSWAP(hdrp->spares[i]);
  1517. X        BSSWAP(hdrp->bitmaps[i]);
  1518. X    }
  1519. X}
  1520. X#endif
  1521. END_OF_FILE
  1522. if test 23885 -ne `wc -c <'hash/hash.c'`; then
  1523.     echo shar: \"'hash/hash.c'\" unpacked with wrong size!
  1524. fi
  1525. # end of 'hash/hash.c'
  1526. fi
  1527. if test -f 'hash/hash_page.c' -a "${1}" != "-c" ; then 
  1528.   echo shar: Will not clobber existing file \"'hash/hash_page.c'\"
  1529. else
  1530. echo shar: Extracting \"'hash/hash_page.c'\" \(23155 characters\)
  1531. sed "s/^X//" >'hash/hash_page.c' <<'END_OF_FILE'
  1532. X/*-
  1533. X * Copyright (c) 1990, 1993
  1534. X *    The Regents of the University of California.  All rights reserved.
  1535. X *
  1536. X * This code is derived from software contributed to Berkeley by
  1537. X * Margo Seltzer.
  1538. X *
  1539. X * Redistribution and use in source and binary forms, with or without
  1540. X * modification, are permitted provided that the following conditions
  1541. X * are met:
  1542. X * 1. Redistributions of source code must retain the above copyright
  1543. X *    notice, this list of conditions and the following disclaimer.
  1544. X * 2. Redistributions in binary form must reproduce the above copyright
  1545. X *    notice, this list of conditions and the following disclaimer in the
  1546. X *    documentation and/or other materials provided with the distribution.
  1547. X * 3. All advertising materials mentioning features or use of this software
  1548. X *    must display the following acknowledgement:
  1549. X *    This product includes software developed by the University of
  1550. X *    California, Berkeley and its contributors.
  1551. X * 4. Neither the name of the University nor the names of its contributors
  1552. X *    may be used to endorse or promote products derived from this software
  1553. X *    without specific prior written permission.
  1554. X *
  1555. X * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  1556. X * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  1557. X * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  1558. X * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  1559. X * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  1560. X * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  1561. X * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  1562. X * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  1563. X * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  1564. X * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  1565. X * SUCH DAMAGE.
  1566. X */
  1567. X
  1568. X#if defined(LIBC_SCCS) && !defined(lint)
  1569. Xstatic char sccsid[] = "@(#)hash_page.c    8.1 (Berkeley) 6/6/93";
  1570. X#endif /* LIBC_SCCS and not lint */
  1571. X
  1572. X/*
  1573. X * PACKAGE:  hashing
  1574. X *
  1575. X * DESCRIPTION:
  1576. X *    Page manipulation for hashing package.
  1577. X *
  1578. X * ROUTINES:
  1579. X *
  1580. X * External
  1581. X *    __get_page
  1582. X *    __add_ovflpage
  1583. X * Internal
  1584. X *    overflow_page
  1585. X *    open_temp
  1586. X */
  1587. X
  1588. X#include <sys/types.h>
  1589. X
  1590. X#include <errno.h>
  1591. X#include <fcntl.h>
  1592. X#include <signal.h>
  1593. X#include <stdio.h>
  1594. X#include <stdlib.h>
  1595. X#include <string.h>
  1596. X#include <unistd.h>
  1597. X#ifdef DEBUG
  1598. X#include <assert.h>
  1599. X#endif
  1600. X
  1601. X#include <db.h>
  1602. X#include "hash.h"
  1603. X#include "page.h"
  1604. X#include "extern.h"
  1605. X
  1606. Xstatic u_long    *fetch_bitmap __P((HTAB *, int));
  1607. Xstatic u_long     first_free __P((u_long));
  1608. Xstatic int     open_temp __P((HTAB *));
  1609. Xstatic u_short     overflow_page __P((HTAB *));
  1610. Xstatic void     putpair __P((char *, const DBT *, const DBT *));
  1611. Xstatic void     squeeze_key __P((u_short *, const DBT *, const DBT *));
  1612. Xstatic int     ugly_split
  1613. X            __P((HTAB *, u_int, BUFHEAD *, BUFHEAD *, int, int));
  1614. X
  1615. X#define    PAGE_INIT(P) { \
  1616. X    ((u_short *)(P))[0] = 0; \
  1617. X    ((u_short *)(P))[1] = hashp->BSIZE - 3 * sizeof(u_short); \
  1618. X    ((u_short *)(P))[2] = hashp->BSIZE; \
  1619. X}
  1620. X
  1621. X/*
  1622. X * This is called AFTER we have verified that there is room on the page for
  1623. X * the pair (PAIRFITS has returned true) so we go right ahead and start moving
  1624. X * stuff on.
  1625. X */
  1626. Xstatic void
  1627. Xputpair(p, key, val)
  1628. X    char *p;
  1629. X    const DBT *key, *val;
  1630. X{
  1631. X    register u_short *bp, n, off;
  1632. X
  1633. X    bp = (u_short *)p;
  1634. X
  1635. X    /* Enter the key first. */
  1636. X    n = bp[0];
  1637. X
  1638. X    off = OFFSET(bp) - key->size;
  1639. X    memmove(p + off, key->data, key->size);
  1640. X    bp[++n] = off;
  1641. X
  1642. X    /* Now the data. */
  1643. X    off -= val->size;
  1644. X    memmove(p + off, val->data, val->size);
  1645. X    bp[++n] = off;
  1646. X
  1647. X    /* Adjust page info. */
  1648. X    bp[0] = n;
  1649. X    bp[n + 1] = off - ((n + 3) * sizeof(u_short));
  1650. X    bp[n + 2] = off;
  1651. X}
  1652. X
  1653. X/*
  1654. X * Returns:
  1655. X *     0 OK
  1656. X *    -1 error
  1657. X */
  1658. Xextern int
  1659. X__delpair(hashp, bufp, ndx)
  1660. X    HTAB *hashp;
  1661. X    BUFHEAD *bufp;
  1662. X    register int ndx;
  1663. X{
  1664. X    register u_short *bp, newoff;
  1665. X    register int n;
  1666. X    u_short pairlen;
  1667. X
  1668. X    bp = (u_short *)bufp->page;
  1669. X    n = bp[0];
  1670. X
  1671. X    if (bp[ndx + 1] < REAL_KEY)
  1672. X        return (__big_delete(hashp, bufp));
  1673. X    if (ndx != 1)
  1674. X        newoff = bp[ndx - 1];
  1675. X    else
  1676. X        newoff = hashp->BSIZE;
  1677. X    pairlen = newoff - bp[ndx + 1];
  1678. X
  1679. X    if (ndx != (n - 1)) {
  1680. X        /* Hard Case -- need to shuffle keys */
  1681. X        register int i;
  1682. X        register char *src = bufp->page + (int)OFFSET(bp);
  1683. X        register char *dst = src + (int)pairlen;
  1684. X        memmove(dst, src, bp[ndx + 1] - OFFSET(bp));
  1685. X
  1686. X        /* Now adjust the pointers */
  1687. X        for (i = ndx + 2; i <= n; i += 2) {
  1688. X            if (bp[i + 1] == OVFLPAGE) {
  1689. X                bp[i - 2] = bp[i];
  1690. X                bp[i - 1] = bp[i + 1];
  1691. X            } else {
  1692. X                bp[i - 2] = bp[i] + pairlen;
  1693. X                bp[i - 1] = bp[i + 1] + pairlen;
  1694. X            }
  1695. X        }
  1696. X    }
  1697. X    /* Finally adjust the page data */
  1698. X    bp[n] = OFFSET(bp) + pairlen;
  1699. X    bp[n - 1] = bp[n + 1] + pairlen + 2 * sizeof(u_short);
  1700. X    bp[0] = n - 2;
  1701. X    hashp->NKEYS--;
  1702. X
  1703. X    bufp->flags |= BUF_MOD;
  1704. X    return (0);
  1705. X}
  1706. X/*
  1707. X * Returns:
  1708. X *     0 ==> OK
  1709. X *    -1 ==> Error
  1710. X */
  1711. Xextern int
  1712. X__split_page(hashp, obucket, nbucket)
  1713. X    HTAB *hashp;
  1714. X    u_int obucket, nbucket;
  1715. X{
  1716. X    register BUFHEAD *new_bufp, *old_bufp;
  1717. X    register u_short *ino;
  1718. X    register char *np;
  1719. X    DBT key, val;
  1720. X    int n, ndx, retval;
  1721. X    u_short copyto, diff, off, moved;
  1722. X    char *op;
  1723. X
  1724. X    copyto = (u_short)hashp->BSIZE;
  1725. X    off = (u_short)hashp->BSIZE;
  1726. X    old_bufp = __get_buf(hashp, obucket, NULL, 0);
  1727. X    if (old_bufp == NULL)
  1728. X        return (-1);
  1729. X    new_bufp = __get_buf(hashp, nbucket, NULL, 0);
  1730. X    if (new_bufp == NULL)
  1731. X        return (-1);
  1732. X
  1733. X    old_bufp->flags |= (BUF_MOD | BUF_PIN);
  1734. X    new_bufp->flags |= (BUF_MOD | BUF_PIN);
  1735. X
  1736. X    ino = (u_short *)(op = old_bufp->page);
  1737. X    np = new_bufp->page;
  1738. X
  1739. X    moved = 0;
  1740. X
  1741. X    for (n = 1, ndx = 1; n < ino[0]; n += 2) {
  1742. X        if (ino[n + 1] < REAL_KEY) {
  1743. X            retval = ugly_split(hashp, obucket, old_bufp, new_bufp,
  1744. X                (int)copyto, (int)moved);
  1745. X            old_bufp->flags &= ~BUF_PIN;
  1746. X            new_bufp->flags &= ~BUF_PIN;
  1747. X            return (retval);
  1748. X
  1749. X        }
  1750. X        key.data = (u_char *)op + ino[n];
  1751. X        key.size = off - ino[n];
  1752. X
  1753. X        if (__call_hash(hashp, key.data, key.size) == obucket) {
  1754. X            /* Don't switch page */
  1755. X            diff = copyto - off;
  1756. X            if (diff) {
  1757. X                copyto = ino[n + 1] + diff;
  1758. X                memmove(op + copyto, op + ino[n + 1],
  1759. X                    off - ino[n + 1]);
  1760. X                ino[ndx] = copyto + ino[n] - ino[n + 1];
  1761. X                ino[ndx + 1] = copyto;
  1762. X            } else
  1763. X                copyto = ino[n + 1];
  1764. X            ndx += 2;
  1765. X        } else {
  1766. X            /* Switch page */
  1767. X            val.data = (u_char *)op + ino[n + 1];
  1768. X            val.size = ino[n] - ino[n + 1];
  1769. X            putpair(np, &key, &val);
  1770. X            moved += 2;
  1771. X        }
  1772. X
  1773. X        off = ino[n + 1];
  1774. X    }
  1775. X
  1776. X    /* Now clean up the page */
  1777. X    ino[0] -= moved;
  1778. X    FREESPACE(ino) = copyto - sizeof(u_short) * (ino[0] + 3);
  1779. X    OFFSET(ino) = copyto;
  1780. X
  1781. X#ifdef DEBUG3
  1782. X    (void)fprintf(stderr, "split %d/%d\n",
  1783. X        ((u_short *)np)[0] / 2,
  1784. X        ((u_short *)op)[0] / 2);
  1785. X#endif
  1786. X    /* unpin both pages */
  1787. X    old_bufp->flags &= ~BUF_PIN;
  1788. X    new_bufp->flags &= ~BUF_PIN;
  1789. X    return (0);
  1790. X}
  1791. X
  1792. X/*
  1793. X * Called when we encounter an overflow or big key/data page during split
  1794. X * handling.  This is special cased since we have to begin checking whether
  1795. X * the key/data pairs fit on their respective pages and because we may need
  1796. X * overflow pages for both the old and new pages.
  1797. X *
  1798. X * The first page might be a page with regular key/data pairs in which case
  1799. X * we have a regular overflow condition and just need to go on to the next
  1800. X * page or it might be a big key/data pair in which case we need to fix the
  1801. X * big key/data pair.
  1802. X *
  1803. X * Returns:
  1804. X *     0 ==> success
  1805. X *    -1 ==> failure
  1806. X */
  1807. Xstatic int
  1808. Xugly_split(hashp, obucket, old_bufp, new_bufp, copyto, moved)
  1809. X    HTAB *hashp;
  1810. X    u_int obucket;    /* Same as __split_page. */
  1811. X    BUFHEAD *old_bufp, *new_bufp;
  1812. X    int copyto;    /* First byte on page which contains key/data values. */
  1813. X    int moved;    /* Number of pairs moved to new page. */
  1814. X{
  1815. X    register BUFHEAD *bufp;    /* Buffer header for ino */
  1816. X    register u_short *ino;    /* Page keys come off of */
  1817. X    register u_short *np;    /* New page */
  1818. X    register u_short *op;    /* Page keys go on to if they aren't moving */
  1819. X
  1820. X    BUFHEAD *last_bfp;    /* Last buf header OVFL needing to be freed */
  1821. X    DBT key, val;
  1822. X    SPLIT_RETURN ret;
  1823. X    u_short n, off, ov_addr, scopyto;
  1824. X    char *cino;        /* Character value of ino */
  1825. X
  1826. X    bufp = old_bufp;
  1827. X    ino = (u_short *)old_bufp->page;
  1828. X    np = (u_short *)new_bufp->page;
  1829. X    op = (u_short *)old_bufp->page;
  1830. X    last_bfp = NULL;
  1831. X    scopyto = (u_short)copyto;    /* ANSI */
  1832. X
  1833. X    n = ino[0] - 1;
  1834. X    while (n < ino[0]) {
  1835. X        if (ino[2] < REAL_KEY && ino[2] != OVFLPAGE) {
  1836. X            /*
  1837. X             * Ov_addr gets set before reaching this point; there's
  1838. X             * always an overflow page before a big key/data page.
  1839. X             */
  1840. X            if (__big_split(hashp, old_bufp,
  1841. X                new_bufp, bufp, ov_addr, obucket, &ret))
  1842. X                return (-1);
  1843. X            old_bufp = ret.oldp;
  1844. X            if (!old_bufp)
  1845. X                return (-1);
  1846. X            op = (u_short *)old_bufp->page;
  1847. X            new_bufp = ret.newp;
  1848. X            if (!new_bufp)
  1849. X                return (-1);
  1850. X            np = (u_short *)new_bufp->page;
  1851. X            bufp = ret.nextp;
  1852. X            if (!bufp)
  1853. X                return (0);
  1854. X            cino = (char *)bufp->page;
  1855. X            ino = (u_short *)cino;
  1856. X            last_bfp = ret.nextp;
  1857. X        } else if (ino[n + 1] == OVFLPAGE) {
  1858. X            ov_addr = ino[n];
  1859. X            /*
  1860. X             * Fix up the old page -- the extra 2 are the fields
  1861. X             * which contained the overflow information.
  1862. X             */
  1863. X            ino[0] -= (moved + 2);
  1864. X            FREESPACE(ino) =
  1865. X                scopyto - sizeof(u_short) * (ino[0] + 3);
  1866. X            OFFSET(ino) = scopyto;
  1867. X
  1868. X            bufp = __get_buf(hashp, ov_addr, bufp, 0);
  1869. X            if (!bufp)
  1870. X                return (-1);
  1871. X
  1872. X            ino = (u_short *)bufp->page;
  1873. X            n = 1;
  1874. X            scopyto = hashp->BSIZE;
  1875. X            moved = 0;
  1876. X
  1877. X            if (last_bfp)
  1878. X                __free_ovflpage(hashp, last_bfp);
  1879. X            last_bfp = bufp;
  1880. X        }
  1881. X        /* Move regular sized pairs of there are any */
  1882. X        off = hashp->BSIZE;
  1883. X        for (n = 1; (n < ino[0]) && (ino[n + 1] >= REAL_KEY); n += 2) {
  1884. X            cino = (char *)ino;
  1885. X            key.data = (u_char *)cino + ino[n];
  1886. X            key.size = off - ino[n];
  1887. X            val.data = (u_char *)cino + ino[n + 1];
  1888. X            val.size = ino[n] - ino[n + 1];
  1889. X            off = ino[n + 1];
  1890. X
  1891. X            if (__call_hash(hashp, key.data, key.size) == obucket) {
  1892. X                /* Keep on old page */
  1893. X                if (PAIRFITS(op, (&key), (&val)))
  1894. X                    putpair((char *)op, &key, &val);
  1895. X                else {
  1896. X                    old_bufp =
  1897. X                        __add_ovflpage(hashp, old_bufp);
  1898. X                    if (!old_bufp)
  1899. X                        return (-1);
  1900. X                    op = (u_short *)old_bufp->page;
  1901. X                    putpair((char *)op, &key, &val);
  1902. X                }
  1903. X                old_bufp->flags |= BUF_MOD;
  1904. X            } else {
  1905. X                /* Move to new page */
  1906. X                if (PAIRFITS(np, (&key), (&val)))
  1907. X                    putpair((char *)np, &key, &val);
  1908. X                else {
  1909. X                    new_bufp =
  1910. X                        __add_ovflpage(hashp, new_bufp);
  1911. X                    if (!new_bufp)
  1912. X                        return (-1);
  1913. X                    np = (u_short *)new_bufp->page;
  1914. X                    putpair((char *)np, &key, &val);
  1915. X                }
  1916. X                new_bufp->flags |= BUF_MOD;
  1917. X            }
  1918. X        }
  1919. X    }
  1920. X    if (last_bfp)
  1921. X        __free_ovflpage(hashp, last_bfp);
  1922. X    return (0);
  1923. X}
  1924. X
  1925. X/*
  1926. X * Add the given pair to the page
  1927. X *
  1928. X * Returns:
  1929. X *    0 ==> OK
  1930. X *    1 ==> failure
  1931. X */
  1932. Xextern int
  1933. X__addel(hashp, bufp, key, val)
  1934. X    HTAB *hashp;
  1935. X    BUFHEAD *bufp;
  1936. X    const DBT *key, *val;
  1937. X{
  1938. X    register u_short *bp, *sop;
  1939. X    int do_expand;
  1940. X
  1941. X    bp = (u_short *)bufp->page;
  1942. X    do_expand = 0;
  1943. X    while (bp[0] && (bp[bp[0]] < REAL_KEY))
  1944. X        /* Exception case */
  1945. X        if (bp[2] < REAL_KEY && bp[bp[0]] != OVFLPAGE) {
  1946. X            /* This is a big-keydata pair */
  1947. X            bufp = __add_ovflpage(hashp, bufp);
  1948. X            if (!bufp)
  1949. X                return (-1);
  1950. X            bp = (u_short *)bufp->page;
  1951. X        } else
  1952. X            /* Try to squeeze key on this page */
  1953. X            if (FREESPACE(bp) > PAIRSIZE(key, val)) {
  1954. X                squeeze_key(bp, key, val);
  1955. X                return (0);
  1956. X            } else {
  1957. X                bufp = __get_buf(hashp, bp[bp[0] - 1], bufp, 0);
  1958. X                if (!bufp)
  1959. X                    return (-1);
  1960. X                bp = (u_short *)bufp->page;
  1961. X            }
  1962. X
  1963. X    if (PAIRFITS(bp, key, val))
  1964. X        putpair(bufp->page, key, val);
  1965. X    else {
  1966. X        do_expand = 1;
  1967. X        bufp = __add_ovflpage(hashp, bufp);
  1968. X        if (!bufp)
  1969. X            return (-1);
  1970. X        sop = (u_short *)bufp->page;
  1971. X
  1972. X        if (PAIRFITS(sop, key, val))
  1973. X            putpair((char *)sop, key, val);
  1974. X        else
  1975. X            if (__big_insert(hashp, bufp, key, val))
  1976. X                return (-1);
  1977. X    }
  1978. X    bufp->flags |= BUF_MOD;
  1979. X    /*
  1980. X     * If the average number of keys per bucket exceeds the fill factor,
  1981. X     * expand the table.
  1982. X     */
  1983. X    hashp->NKEYS++;
  1984. X    if (do_expand ||
  1985. X        (hashp->NKEYS / (hashp->MAX_BUCKET + 1) > hashp->FFACTOR))
  1986. X        return (__expand_table(hashp));
  1987. X    return (0);
  1988. X}
  1989. X
  1990. X/*
  1991. X *
  1992. X * Returns:
  1993. X *    pointer on success
  1994. X *    NULL on error
  1995. X */
  1996. Xextern BUFHEAD *
  1997. X__add_ovflpage(hashp, bufp)
  1998. X    HTAB *hashp;
  1999. X    BUFHEAD *bufp;
  2000. X{
  2001. X    register u_short *sp;
  2002. X    u_short ndx, ovfl_num;
  2003. X#ifdef DEBUG1
  2004. X    int tmp1, tmp2;
  2005. X#endif
  2006. X    sp = (u_short *)bufp->page;
  2007. X
  2008. X    /* Check if we are dynamically determining the fill factor */
  2009. X    if (hashp->FFACTOR == DEF_FFACTOR) {
  2010. X        hashp->FFACTOR = sp[0] >> 1;
  2011. X        if (hashp->FFACTOR < MIN_FFACTOR)
  2012. X            hashp->FFACTOR = MIN_FFACTOR;
  2013. X    }
  2014. X    bufp->flags |= BUF_MOD;
  2015. X    ovfl_num = overflow_page(hashp);
  2016. X#ifdef DEBUG1
  2017. X    tmp1 = bufp->addr;
  2018. X    tmp2 = bufp->ovfl ? bufp->ovfl->addr : 0;
  2019. X#endif
  2020. X    if (!ovfl_num || !(bufp->ovfl = __get_buf(hashp, ovfl_num, bufp, 1)))
  2021. X        return (NULL);
  2022. X    bufp->ovfl->flags |= BUF_MOD;
  2023. X#ifdef DEBUG1
  2024. X    (void)fprintf(stderr, "ADDOVFLPAGE: %d->ovfl was %d is now %d\n",
  2025. X        tmp1, tmp2, bufp->ovfl->addr);
  2026. X#endif
  2027. X    ndx = sp[0];
  2028. X    /*
  2029. X     * Since a pair is allocated on a page only if there's room to add
  2030. X     * an overflow page, we know that the OVFL information will fit on
  2031. X     * the page.
  2032. X     */
  2033. X    sp[ndx + 4] = OFFSET(sp);
  2034. X    sp[ndx + 3] = FREESPACE(sp) - OVFLSIZE;
  2035. X    sp[ndx + 1] = ovfl_num;
  2036. X    sp[ndx + 2] = OVFLPAGE;
  2037. X    sp[0] = ndx + 2;
  2038. X#ifdef HASH_STATISTICS
  2039. X    hash_overflows++;
  2040. X#endif
  2041. X    return (bufp->ovfl);
  2042. X}
  2043. X
  2044. X/*
  2045. X * Returns:
  2046. X *     0 indicates SUCCESS
  2047. X *    -1 indicates FAILURE
  2048. X */
  2049. Xextern int
  2050. X__get_page(hashp, p, bucket, is_bucket, is_disk, is_bitmap)
  2051. X    HTAB *hashp;
  2052. X    char *p;
  2053. X    u_int bucket;
  2054. X    int is_bucket, is_disk, is_bitmap;
  2055. X{
  2056. X    register int fd, page, size;
  2057. X    int rsize;
  2058. X    u_short *bp;
  2059. X
  2060. X    fd = hashp->fp;
  2061. X    size = hashp->BSIZE;
  2062. X
  2063. X    if ((fd == -1) || !is_disk) {
  2064. X        PAGE_INIT(p);
  2065. X        return (0);
  2066. X    }
  2067. X    if (is_bucket)
  2068. X        page = BUCKET_TO_PAGE(bucket);
  2069. X    else
  2070. X        page = OADDR_TO_PAGE(bucket);
  2071. X    if ((lseek(fd, (off_t)page << hashp->BSHIFT, SEEK_SET) == -1) ||
  2072. X        ((rsize = read(fd, p, size)) == -1))
  2073. X        return (-1);
  2074. X    bp = (u_short *)p;
  2075. X    if (!rsize)
  2076. X        bp[0] = 0;    /* We hit the EOF, so initialize a new page */
  2077. X    else
  2078. X        if (rsize != size) {
  2079. X            errno = EFTYPE;
  2080. X            return (-1);
  2081. X        }
  2082. X    if (!is_bitmap && !bp[0]) {
  2083. X        PAGE_INIT(p);
  2084. X    } else
  2085. X        if (hashp->LORDER != BYTE_ORDER) {
  2086. X            register int i, max;
  2087. X
  2088. X            if (is_bitmap) {
  2089. X                max = hashp->BSIZE >> 2; /* divide by 4 */
  2090. X                for (i = 0; i < max; i++)
  2091. X                    BLSWAP(((long *)p)[i]);
  2092. X            } else {
  2093. X                BSSWAP(bp[0]);
  2094. X                max = bp[0] + 2;
  2095. X                for (i = 1; i <= max; i++)
  2096. X                    BSSWAP(bp[i]);
  2097. X            }
  2098. X        }
  2099. X    return (0);
  2100. X}
  2101. X
  2102. X/*
  2103. X * Write page p to disk
  2104. X *
  2105. X * Returns:
  2106. X *     0 ==> OK
  2107. X *    -1 ==>failure
  2108. X */
  2109. Xextern int
  2110. X__put_page(hashp, p, bucket, is_bucket, is_bitmap)
  2111. X    HTAB *hashp;
  2112. X    char *p;
  2113. X    u_int bucket;
  2114. X    int is_bucket, is_bitmap;
  2115. X{
  2116. X    register int fd, page, size;
  2117. X    int wsize;
  2118. X
  2119. X    size = hashp->BSIZE;
  2120. X    if ((hashp->fp == -1) && open_temp(hashp))
  2121. X        return (-1);
  2122. X    fd = hashp->fp;
  2123. X
  2124. X    if (hashp->LORDER != BYTE_ORDER) {
  2125. X        register int i;
  2126. X        register int max;
  2127. X
  2128. X        if (is_bitmap) {
  2129. X            max = hashp->BSIZE >> 2;    /* divide by 4 */
  2130. X            for (i = 0; i < max; i++)
  2131. X                BLSWAP(((long *)p)[i]);
  2132. X        } else {
  2133. X            max = ((u_short *)p)[0] + 2;
  2134. X            for (i = 0; i <= max; i++)
  2135. X                BSSWAP(((u_short *)p)[i]);
  2136. X        }
  2137. X    }
  2138. X    if (is_bucket)
  2139. X        page = BUCKET_TO_PAGE(bucket);
  2140. X    else
  2141. X        page = OADDR_TO_PAGE(bucket);
  2142. X    if ((lseek(fd, (off_t)page << hashp->BSHIFT, SEEK_SET) == -1) ||
  2143. X        ((wsize = write(fd, p, size)) == -1))
  2144. X        /* Errno is set */
  2145. X        return (-1);
  2146. X    if (wsize != size) {
  2147. X        errno = EFTYPE;
  2148. X        return (-1);
  2149. X    }
  2150. X    return (0);
  2151. X}
  2152. X
  2153. X#define BYTE_MASK    ((1 << INT_BYTE_SHIFT) -1)
  2154. X/*
  2155. X * Initialize a new bitmap page.  Bitmap pages are left in memory
  2156. X * once they are read in.
  2157. X */
  2158. Xextern int
  2159. X__init_bitmap(hashp, pnum, nbits, ndx)
  2160. X    HTAB *hashp;
  2161. X    int pnum, nbits, ndx;
  2162. X{
  2163. X    u_long *ip;
  2164. X    int clearbytes, clearints;
  2165. X
  2166. X    if (!(ip = malloc(hashp->BSIZE)))
  2167. X        return (1);
  2168. X    hashp->nmaps++;
  2169. X    clearints = ((nbits - 1) >> INT_BYTE_SHIFT) + 1;
  2170. X    clearbytes = clearints << INT_TO_BYTE;
  2171. X    (void)memset((char *)ip, 0, clearbytes);
  2172. X    (void)memset(((char *)ip) + clearbytes, 0xFF,
  2173. X        hashp->BSIZE - clearbytes);
  2174. X    ip[clearints - 1] = ALL_SET << (nbits & BYTE_MASK);
  2175. X    SETBIT(ip, 0);
  2176. X    hashp->BITMAPS[ndx] = (u_short)pnum;
  2177. X    hashp->mapp[ndx] = ip;
  2178. X    return (0);
  2179. X}
  2180. X
  2181. Xstatic u_long
  2182. Xfirst_free(map)
  2183. X    u_long map;
  2184. X{
  2185. X    register u_long i, mask;
  2186. X
  2187. X    mask = 0x1;
  2188. X    for (i = 0; i < BITS_PER_MAP; i++) {
  2189. X        if (!(mask & map))
  2190. X            return (i);
  2191. X        mask = mask << 1;
  2192. X    }
  2193. X    return (i);
  2194. X}
  2195. X
  2196. Xstatic u_short
  2197. Xoverflow_page(hashp)
  2198. X    HTAB *hashp;
  2199. X{
  2200. X    register u_long *freep;
  2201. X    register int max_free, offset, splitnum;
  2202. X    u_short addr;
  2203. X    int bit, first_page, free_bit, free_page, i, in_use_bits, j;
  2204. X#ifdef DEBUG2
  2205. X    int tmp1, tmp2;
  2206. X#endif
  2207. X    splitnum = hashp->OVFL_POINT;
  2208. X    max_free = hashp->SPARES[splitnum];
  2209. X
  2210. X    free_page = (max_free - 1) >> (hashp->BSHIFT + BYTE_SHIFT);
  2211. X    free_bit = (max_free - 1) & ((hashp->BSIZE << BYTE_SHIFT) - 1);
  2212. X
  2213. X    /* Look through all the free maps to find the first free block */
  2214. X    first_page = hashp->LAST_FREED >>(hashp->BSHIFT + BYTE_SHIFT);
  2215. X    for ( i = first_page; i <= free_page; i++ ) {
  2216. X        if (!(freep = (u_long *)hashp->mapp[i]) &&
  2217. X            !(freep = fetch_bitmap(hashp, i)))
  2218. X            return (NULL);
  2219. X        if (i == free_page)
  2220. X            in_use_bits = free_bit;
  2221. X        else
  2222. X            in_use_bits = (hashp->BSIZE << BYTE_SHIFT) - 1;
  2223. X        
  2224. X        if (i == first_page) {
  2225. X            bit = hashp->LAST_FREED &
  2226. X                ((hashp->BSIZE << BYTE_SHIFT) - 1);
  2227. X            j = bit / BITS_PER_MAP;
  2228. X            bit = bit & ~(BITS_PER_MAP - 1);
  2229. X        } else {
  2230. X            bit = 0;
  2231. X            j = 0;
  2232. X        }
  2233. X        for (; bit <= in_use_bits; j++, bit += BITS_PER_MAP)
  2234. X            if (freep[j] != ALL_SET)
  2235. X                goto found;
  2236. X    }
  2237. X
  2238. X    /* No Free Page Found */
  2239. X    hashp->LAST_FREED = hashp->SPARES[splitnum];
  2240. X    hashp->SPARES[splitnum]++;
  2241. X    offset = hashp->SPARES[splitnum] -
  2242. X        (splitnum ? hashp->SPARES[splitnum - 1] : 0);
  2243. X
  2244. X#define    OVMSG    "HASH: Out of overflow pages.  Increase page size\n"
  2245. X    if (offset > SPLITMASK) {
  2246. X        if (++splitnum >= NCACHED) {
  2247. X            (void)write(STDERR_FILENO, OVMSG, sizeof(OVMSG) - 1);
  2248. X            return (NULL);
  2249. X        }
  2250. X        hashp->OVFL_POINT = splitnum;
  2251. X        hashp->SPARES[splitnum] = hashp->SPARES[splitnum-1];
  2252. X        hashp->SPARES[splitnum-1]--;
  2253. X        offset = 1;
  2254. X    }
  2255. X
  2256. X    /* Check if we need to allocate a new bitmap page */
  2257. X    if (free_bit == (hashp->BSIZE << BYTE_SHIFT) - 1) {
  2258. X        free_page++;
  2259. X        if (free_page >= NCACHED) {
  2260. X            (void)write(STDERR_FILENO, OVMSG, sizeof(OVMSG) - 1);
  2261. X            return (NULL);
  2262. X        }
  2263. X        /*
  2264. X         * This is tricky.  The 1 indicates that you want the new page
  2265. X         * allocated with 1 clear bit.  Actually, you are going to
  2266. X         * allocate 2 pages from this map.  The first is going to be
  2267. X         * the map page, the second is the overflow page we were
  2268. X         * looking for.  The init_bitmap routine automatically, sets
  2269. X         * the first bit of itself to indicate that the bitmap itself
  2270. X         * is in use.  We would explicitly set the second bit, but
  2271. X         * don't have to if we tell init_bitmap not to leave it clear
  2272. X         * in the first place.
  2273. X         */
  2274. X        if (__init_bitmap(hashp, (int)OADDR_OF(splitnum, offset),
  2275. X            1, free_page))
  2276. X            return (NULL);
  2277. X        hashp->SPARES[splitnum]++;
  2278. X#ifdef DEBUG2
  2279. X        free_bit = 2;
  2280. X#endif
  2281. X        offset++;
  2282. X        if (offset > SPLITMASK) {
  2283. X            if (++splitnum >= NCACHED) {
  2284. X                (void)write(STDERR_FILENO, OVMSG,
  2285. X                    sizeof(OVMSG) - 1);
  2286. X                return (NULL);
  2287. X            }
  2288. X            hashp->OVFL_POINT = splitnum;
  2289. X            hashp->SPARES[splitnum] = hashp->SPARES[splitnum-1];
  2290. X            hashp->SPARES[splitnum-1]--;
  2291. X            offset = 0;
  2292. X        }
  2293. X    } else {
  2294. X        /*
  2295. X         * Free_bit addresses the last used bit.  Bump it to address
  2296. X         * the first available bit.
  2297. X         */
  2298. X        free_bit++;
  2299. X        SETBIT(freep, free_bit);
  2300. X    }
  2301. X
  2302. X    /* Calculate address of the new overflow page */
  2303. X    addr = OADDR_OF(splitnum, offset);
  2304. X#ifdef DEBUG2
  2305. X    (void)fprintf(stderr, "OVERFLOW_PAGE: ADDR: %d BIT: %d PAGE %d\n",
  2306. X        addr, free_bit, free_page);
  2307. X#endif
  2308. X    return (addr);
  2309. X
  2310. Xfound:
  2311. X    bit = bit + first_free(freep[j]);
  2312. X    SETBIT(freep, bit);
  2313. X#ifdef DEBUG2
  2314. X    tmp1 = bit;
  2315. X    tmp2 = i;
  2316. X#endif
  2317. X    /*
  2318. X     * Bits are addressed starting with 0, but overflow pages are addressed
  2319. X     * beginning at 1. Bit is a bit addressnumber, so we need to increment
  2320. X     * it to convert it to a page number.
  2321. X     */
  2322. X    bit = 1 + bit + (i * (hashp->BSIZE << BYTE_SHIFT));
  2323. X    if (bit >= hashp->LAST_FREED)
  2324. X        hashp->LAST_FREED = bit - 1;
  2325. X
  2326. X    /* Calculate the split number for this page */
  2327. X    for (i = 0; (i < splitnum) && (bit > hashp->SPARES[i]); i++);
  2328. X    offset = (i ? bit - hashp->SPARES[i - 1] : bit);
  2329. X    if (offset >= SPLITMASK)
  2330. X        return (NULL);    /* Out of overflow pages */
  2331. X    addr = OADDR_OF(i, offset);
  2332. X#ifdef DEBUG2
  2333. X    (void)fprintf(stderr, "OVERFLOW_PAGE: ADDR: %d BIT: %d PAGE %d\n",
  2334. X        addr, tmp1, tmp2);
  2335. X#endif
  2336. X
  2337. X    /* Allocate and return the overflow page */
  2338. X    return (addr);
  2339. X}
  2340. X
  2341. X/*
  2342. X * Mark this overflow page as free.
  2343. X */
  2344. Xextern void
  2345. X__free_ovflpage(hashp, obufp)
  2346. X    HTAB *hashp;
  2347. X    BUFHEAD *obufp;
  2348. X{
  2349. X    register u_short addr;
  2350. X    u_long *freep;
  2351. X    int bit_address, free_page, free_bit;
  2352. X    u_short ndx;
  2353. X
  2354. X    addr = obufp->addr;
  2355. X#ifdef DEBUG1
  2356. X    (void)fprintf(stderr, "Freeing %d\n", addr);
  2357. X#endif
  2358. X    ndx = (((u_short)addr) >> SPLITSHIFT);
  2359. X    bit_address =
  2360. X        (ndx ? hashp->SPARES[ndx - 1] : 0) + (addr & SPLITMASK) - 1;
  2361. X     if (bit_address < hashp->LAST_FREED)
  2362. X        hashp->LAST_FREED = bit_address;
  2363. X    free_page = (bit_address >> (hashp->BSHIFT + BYTE_SHIFT));
  2364. X    free_bit = bit_address & ((hashp->BSIZE << BYTE_SHIFT) - 1);
  2365. X
  2366. X    if (!(freep = hashp->mapp[free_page]))
  2367. X        freep = fetch_bitmap(hashp, free_page);
  2368. X#ifdef DEBUG
  2369. X    /*
  2370. X     * This had better never happen.  It means we tried to read a bitmap
  2371. X     * that has already had overflow pages allocated off it, and we
  2372. X     * failed to read it from the file.
  2373. X     */
  2374. X    if (!freep)
  2375. X        assert(0);
  2376. X#endif
  2377. X    CLRBIT(freep, free_bit);
  2378. X#ifdef DEBUG2
  2379. X    (void)fprintf(stderr, "FREE_OVFLPAGE: ADDR: %d BIT: %d PAGE %d\n",
  2380. X        obufp->addr, free_bit, free_page);
  2381. X#endif
  2382. X    __reclaim_buf(hashp, obufp);
  2383. X}
  2384. X
  2385. X/*
  2386. X * Returns:
  2387. X *     0 success
  2388. X *    -1 failure
  2389. X */
  2390. Xstatic int
  2391. Xopen_temp(hashp)
  2392. X    HTAB *hashp;
  2393. X{
  2394. X    sigset_t set, oset;
  2395. X    static char namestr[] = "_hashXXXXXX";
  2396. X
  2397. X    /* Block signals; make sure file goes away at process exit. */
  2398. X    (void)sigfillset(&set);
  2399. X    (void)sigprocmask(SIG_BLOCK, &set, &oset);
  2400. X    if ((hashp->fp = mkstemp(namestr)) != -1) {
  2401. X        (void)unlink(namestr);
  2402. X        (void)fcntl(hashp->fp, F_SETFD, 1);
  2403. X    }
  2404. X    (void)sigprocmask(SIG_SETMASK, &oset, (sigset_t *)NULL);
  2405. X    return (hashp->fp != -1 ? 0 : -1);
  2406. X}
  2407. X
  2408. X/*
  2409. X * We have to know that the key will fit, but the last entry on the page is
  2410. X * an overflow pair, so we need to shift things.
  2411. X */
  2412. Xstatic void
  2413. Xsqueeze_key(sp, key, val)
  2414. X    u_short *sp;
  2415. X    const DBT *key, *val;
  2416. X{
  2417. X    register char *p;
  2418. X    u_short free_space, n, off, pageno;
  2419. X
  2420. X    p = (char *)sp;
  2421. X    n = sp[0];
  2422. X    free_space = FREESPACE(sp);
  2423. X    off = OFFSET(sp);
  2424. X
  2425. X    pageno = sp[n - 1];
  2426. X    off -= key->size;
  2427. X    sp[n - 1] = off;
  2428. X    memmove(p + off, key->data, key->size);
  2429. X    off -= val->size;
  2430. X    sp[n] = off;
  2431. X    memmove(p + off, val->data, val->size);
  2432. X    sp[0] = n + 2;
  2433. X    sp[n + 1] = pageno;
  2434. X    sp[n + 2] = OVFLPAGE;
  2435. X    FREESPACE(sp) = free_space - PAIRSIZE(key, val);
  2436. X    OFFSET(sp) = off;
  2437. X}
  2438. X
  2439. Xstatic u_long *
  2440. Xfetch_bitmap(hashp, ndx)
  2441. X    HTAB *hashp;
  2442. X    int ndx;
  2443. X{
  2444. X    if (ndx >= hashp->nmaps ||
  2445. X        !(hashp->mapp[ndx] = malloc(hashp->BSIZE)) ||
  2446. X        __get_page(hashp, (char *)hashp->mapp[ndx],
  2447. X        hashp->BITMAPS[ndx], 0, 1, 1))
  2448. X        return (NULL);
  2449. X    return (hashp->mapp[ndx]);
  2450. X}
  2451. X
  2452. X#ifdef DEBUG4
  2453. Xint
  2454. Xprint_chain(addr)
  2455. X    int addr;
  2456. X{
  2457. X    BUFHEAD *bufp;
  2458. X    short *bp, oaddr;
  2459. X
  2460. X    (void)fprintf(stderr, "%d ", addr);
  2461. X    bufp = __get_buf(hashp, addr, NULL, 0);
  2462. X    bp = (short *)bufp->page;
  2463. X    while (bp[0] && ((bp[bp[0]] == OVFLPAGE) ||
  2464. X        ((bp[0] > 2) && bp[2] < REAL_KEY))) {
  2465. X        oaddr = bp[bp[0] - 1];
  2466. X        (void)fprintf(stderr, "%d ", (int)oaddr);
  2467. X        bufp = __get_buf(hashp, (int)oaddr, bufp, 0);
  2468. X        bp = (short *)bufp->page;
  2469. X    }
  2470. X    (void)fprintf(stderr, "\n");
  2471. X}
  2472. X#endif
  2473. END_OF_FILE
  2474. if test 23155 -ne `wc -c <'hash/hash_page.c'`; then
  2475.     echo shar: \"'hash/hash_page.c'\" unpacked with wrong size!
  2476. fi
  2477. # end of 'hash/hash_page.c'
  2478. fi
  2479. echo shar: End of archive 7 \(of 9\).
  2480. cp /dev/null ark7isdone
  2481. MISSING=""
  2482. for I in 1 2 3 4 5 6 7 8 9 ; do
  2483.     if test ! -f ark${I}isdone ; then
  2484.     MISSING="${MISSING} ${I}"
  2485.     fi
  2486. done
  2487. if test "${MISSING}" = "" ; then
  2488.     echo You have unpacked all 9 archives.
  2489.     rm -f ark[1-9]isdone ark[1-9][0-9]isdone
  2490. else
  2491.     echo You still need to unpack the following archives:
  2492.     echo "        " ${MISSING}
  2493. fi
  2494. ##  End of shell archive.
  2495. exit 0
  2496.