home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1992 March / Source_Code_CD-ROM_Walnut_Creek_March_1992.iso / usenet / altsrcs / 2 / 2960 < prev    next >
Encoding:
Internet Message Format  |  1991-03-04  |  46.7 KB

  1. From: lee@sq.sq.com (Liam R. E. Quin)
  2. Newsgroups: alt.sources
  3. Subject: lq-text Full Text Retrieval Database Part 12/13
  4. Message-ID: <1991Mar4.021136.17015@sq.sq.com>
  5. Date: 4 Mar 91 02:11:36 GMT
  6.  
  7. : cut here --- cut here --
  8. : To unbundle, sh this file
  9. #! /bin/sh
  10. : part 12
  11. echo x - lq-text/src/ozmahash/db.3 1>&2
  12. sed 's/^X//' >lq-text/src/ozmahash/db.3 <<'@@@End of lq-text/src/ozmahash/db.3'
  13. X.\" Copyright (c) 1990 The Regents of the University of California.
  14. X.\" All rights reserved.
  15. X.\"
  16. X.\" Redistribution and use in source and binary forms are permitted provided
  17. X.\" that: (1) source distributions retain this entire copyright notice and
  18. X.\" comment, and (2) distributions including binaries display the following
  19. X.\" acknowledgement:  ``This product includes software developed by the
  20. X.\" University of California, Berkeley and its contributors'' in the
  21. X.\" documentation or other materials provided with the distribution and in
  22. X.\" all advertising materials mentioning features or use of this software.
  23. X.\" Neither the name of the University nor the names of its contributors may
  24. X.\" be used to endorse or promote products derived from this software without
  25. X.\" specific prior written permission.
  26. X.\" THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
  27. X.\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
  28. X.\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  29. X.\"
  30. X.\"    @(#)db.3    5.13 (Berkeley) 1/7/91
  31. X.\"
  32. X.TH DB 3  "January 7, 1991"
  33. X.UC 7
  34. X.SH NAME
  35. Xbtree_open, hash_open, recno_open \- database access methods
  36. X.SH SYNOPSIS
  37. X.nf
  38. X.ft B
  39. X#include <sys/types.h>
  40. X#include <db.h>
  41. X
  42. XDB *
  43. Xbtree_open(const char *file, int flags, int mode, const BTREEINFO * openinfo);
  44. X
  45. XDB *
  46. Xhash_open(const char *file, int flags, int mode, const HASHINFO * openinfo);
  47. X
  48. XDB *
  49. Xrecno_open(const char *file, int flags, int mode, const RECNOINFO * openinfo);
  50. X.ft R
  51. X.fi
  52. X.SH DESCRIPTION
  53. X.IR Btree_open ,
  54. X.IR hash_open ,
  55. Xand
  56. X.I recno_open
  57. Xare access method interfaces to database files in btree, hashed, and
  58. Xflat-file formats, respectively.
  59. XThe btree format is a representation of a sorted, balanced tree structure.
  60. XThe hashed format is an extensible, dynamic hashing scheme.
  61. XThe flat-file format is a UNIX file with fixed or variable length
  62. Xlines.
  63. XThese formats are described in more detail below.
  64. X.PP
  65. XAccess to all file types is based on key/data pairs.
  66. X.PP
  67. XEach routine opens
  68. X.I file
  69. Xfor reading and/or writing.
  70. XDatabases never intended to be preserved on disk may be created by setting
  71. Xthe file parameter to NULL.
  72. XThe
  73. X.I flags
  74. Xand
  75. X.I mode arguments
  76. Xare as specified to the
  77. X.IR open (2)
  78. Xroutine, however, only the O_CREAT, O_EXCL, O_RDONLY, O_RDWR, O_TRUNC
  79. Xand O_WRONLY flags are meaningful.
  80. XThe argument
  81. X.I openinfo
  82. Xis a pointer to an access method specific structure described below.
  83. X.PP
  84. XThe open routines return a pointer to a DB structure on success and NULL
  85. Xon error.
  86. XThe DB structure contains at least the following fields:
  87. X.PP
  88. Xtypedef struct {
  89. X.RS
  90. Xvoid *openinfo;
  91. X.br
  92. Xint (*close)(const DB *db);
  93. X.br
  94. Xint (*delete)(const DB *db, const DBT *key, u_long flag);
  95. X.br
  96. Xint (*get)(const DB *db, DBT *key, DBT *data, u_long flag);
  97. X.br
  98. Xint (*put)(const DB *db, const DBT *key, const DBT *data, u_long flag);
  99. X.br
  100. Xint (*seq)(const DB *db, DBT *key, DBT *data, u_long flag);
  101. X.br
  102. Xint (*sync)(const DB *db);
  103. X.RE
  104. X} DB;
  105. X.PP
  106. XThe elements of this structure consist of a pointer to an access method
  107. Xspecific structure and a set of routines which perform various functions.
  108. XAll of these routines take a pointer to a structure as returned by
  109. Xone of the open routines, one or more pointers to key/data structures,
  110. Xand, optionally, a flag value.
  111. X.TP
  112. Xopeninfo
  113. XA pointer to an internal structure specific to the access method.
  114. X.TP
  115. Xclose
  116. XA pointer to a routine to flush any cached information to disk, free any
  117. Xallocated resources, and close the database file.
  118. XSince key/data pairs may be cached in memory, failing to close the
  119. Xfile with a
  120. X.I close
  121. Xroutine may result in inconsistent or lost information.
  122. X.I Close
  123. Xroutines return -1 on error (setting
  124. X.IR errno )
  125. Xand 0 on success.
  126. X.TP
  127. Xdelete
  128. XA pointer to a routine to remove key/data pairs from the database.
  129. X.I Delete
  130. Xroutines return -1 on error (setting
  131. X.IR errno ),
  132. X0 on success, and 1 if the specified
  133. X.I key
  134. Xwas not in the file.
  135. X.TP
  136. Xget
  137. XA pointer to a routine which is the interface for keyed retrieval from
  138. Xthe database.
  139. XThe address and length of the data associated with the specified
  140. X.I key
  141. Xare returned in the structure referenced by
  142. X.IR data .
  143. X.I Get
  144. Xroutines return -1 on error (setting
  145. X.IR errno ),
  146. X0 on success, and 1 if the
  147. X.I key
  148. Xwas not in the file.
  149. X.TP
  150. Xput
  151. XA pointer to a routine to store key/data pairs in the database.
  152. X.IP
  153. XThe parameter
  154. X.I flag
  155. Xmust be set to one of the following values:
  156. X.RS
  157. X.TP
  158. XR_IAFTER
  159. XAppend the data immediately after the data referenced by
  160. X.IR key ,
  161. Xcreating a new key/data pair.
  162. X(This implies that the access method is able to create new keys,
  163. Xi.e. the keys are ordered and independent, for example, record numbers.
  164. XApplicable only to the
  165. X.B RECNO
  166. Xaccess method.)
  167. X.TP
  168. XR_IBEFORE
  169. XInsert the data immediately before the data referenced by
  170. X.IR key ,
  171. Xcreating a new key/data pair.
  172. X(This implies that the access method is able to create new keys,
  173. Xi.e. the keys are ordered and independent, for example, record numbers.
  174. XApplicable only to the
  175. X.B RECNO
  176. Xaccess method.)
  177. X.TP
  178. XR_NOOVERWRITE
  179. XEnter the new key/data pair only if the key does not previously exist.
  180. X.TP
  181. XR_PUT
  182. XEnter the new key/data pair and replace any previously existing key.
  183. X.RE
  184. X.IP
  185. X.I Put
  186. Xroutines return -1 on error (setting
  187. X.IR errno ),
  188. X0 on success, and 1 if the R_NOOVERWRITE
  189. X.I flag
  190. Xwas set and the key already exists in the file.
  191. X.TP
  192. Xseq
  193. XA pointer to a routine which is the interface for sequential
  194. Xretrieval from the database.
  195. XThe address and length of the key are returned in the structure
  196. Xreferenced by
  197. X.IR key ,
  198. Xand the address and length of the data are returned in the
  199. Xstructure referenced
  200. Xby
  201. X.IR data .
  202. X.IP
  203. XSequential key/data pair retrieval may begin at any time, and the
  204. Xposition of the ``cursor'' is not affected by calls to the
  205. X.IR delete ,
  206. X.IR get ,
  207. X.IR put ,
  208. Xor
  209. X.I sync
  210. Xroutines.
  211. XModifications to the database during a sequential scan will be reflected
  212. Xin the scan, i.e. records inserted behind the cursor will not be returned
  213. Xwhile records inserted in front of the cursor will be returned.
  214. X.IP
  215. XThe flag value must be set to one of the following values:
  216. X.RS
  217. X.TP
  218. XR_CURSOR
  219. XThe data associated with the specified key is returned.
  220. XThis differs from the
  221. X.I get
  222. Xroutines in that it sets the ``cursor'' to the location of the
  223. Xkey as well.
  224. X(This implies that the access method has a implicit order which does
  225. Xnot change.
  226. XApplicable only to the
  227. X.B BTREE
  228. Xand
  229. X.B RECNO
  230. Xaccess methods.)
  231. X.TP
  232. XR_FIRST
  233. XThe first key/data pair of the database is returned.
  234. X.TP
  235. XR_LAST
  236. XThe last key/data pair of the database is returned.
  237. X(This implies that the access method has a implicit order which does
  238. Xnot change.
  239. XApplicable only to the
  240. X.B BTREE
  241. Xand
  242. X.B RECNO
  243. Xaccess methods.)
  244. X.TP
  245. XR_NEXT
  246. XRetrieve the key/data pair immediately after the key/data pair most recently
  247. Xretrieved using the
  248. X.I seq
  249. Xroutine.
  250. XThe cursor is moved to the returned key/data pair.
  251. XIf
  252. X.I flag
  253. Xis set to R_NEXT the first time the
  254. X.I seq
  255. Xroutine is called, the first key/data pair of the database is returned.
  256. X.TP
  257. XR_PREV
  258. XRetrieve the key/data pair immediately before the key/data pair most recently
  259. Xretrieved using the
  260. X.I seq
  261. Xroutine.
  262. XThe cursor is moved to the returned key/data pair.
  263. XIf
  264. X.I flag
  265. Xis set to R_PREV the first time the
  266. X.I seq
  267. Xroutine is called, the last key/data pair of the database is returned.
  268. X(This implies that the access method has a implicit order which does
  269. Xnot change.
  270. XApplicable only to the
  271. X.B BTREE
  272. Xand
  273. X.B RECNO
  274. Xaccess methods.)
  275. X.RE
  276. X.IP
  277. X.I Seq
  278. Xroutines return -1 on error (setting
  279. X.IR errno ),
  280. X0 on success, 1 if there are no more key/data pairs available.
  281. XIf the
  282. X.B RECNO
  283. Xaccess method is being used, and if the database file is a character special
  284. Xfile and no complete key/data pairs are currently available, the
  285. X.I seq
  286. Xroutines return 2.
  287. X.TP
  288. Xsync
  289. XA pointer to a routine to flush any cached information to disk.
  290. XIf the database is in memory only, the
  291. X.I sync
  292. Xroutine has no effect and will always succeed.
  293. X.I Sync
  294. Xroutines return -1 on error (setting
  295. X.IR errno )
  296. Xand 0 on success.
  297. X.SH "KEY/DATA PAIRS"
  298. XAccess to all file types is based on key/data pairs.
  299. XBoth keys and data are represented by the following data structure:
  300. X.PP
  301. Xtypedef struct {
  302. X.RS
  303. Xu_char *data;
  304. X.br
  305. Xsize_t size;
  306. X.RE
  307. X} DBT;
  308. X.PP
  309. XThe elements of the DBT structure are defined as follows:
  310. X.TP
  311. Xdata
  312. XA pointer to a byte string.
  313. X.TP
  314. Xsize
  315. XThe length of the byte string.
  316. X.PP
  317. XKey/data strings must fit into available memory.
  318. X.SH BTREE
  319. XOne of the access methods is a btree: a sorted, balanced tree structure
  320. Xwith associated key/data pairs.
  321. X.PP
  322. XThe access method specific data structure provided to
  323. X.I btree_open
  324. Xis as follows:
  325. X.PP
  326. Xtypedef struct {
  327. X.RS
  328. Xu_long flags;
  329. X.br
  330. Xu_int psize;
  331. X.br
  332. Xu_int cachesize;
  333. X.br
  334. Xint (*compare)(const void *, const void *);
  335. X.br
  336. Xint lorder;
  337. X.RE
  338. X} BTREEINFO;
  339. X.PP
  340. XThe elements of this structure are defined as follows:
  341. X.TP
  342. Xflags
  343. XThe flag value is specified by
  344. X.IR or 'ing
  345. Xany of the following values:
  346. X.RS
  347. X.TP
  348. XR_DUP
  349. XOn insertion,
  350. Xif the key to be inserted already exists,
  351. Xpermit insertion anyway.
  352. XThis flag permits duplicate keys in the tree.
  353. XBy default,
  354. Xduplicates are not permitted,
  355. Xand attempts to insert them will fail.
  356. XNote, the order of retrieval of key/data pairs with duplicate keys is
  357. Xundefined.
  358. X.RE
  359. X.TP
  360. Xcachesize
  361. XA suggested maximum size, in bytes, of the memory cache.
  362. XSetting this value to zero specifies that an appropriate amount of memory
  363. Xshould be used.
  364. XSince every search examines the root page of the tree, caching the most
  365. Xrecently used pages substantially improves access time.
  366. XIn addition, physical writes are delayed as long as possible, so a moderate
  367. Xcache can reduce the number of I/O operations significantly.
  368. XObviously, using a cache increases the likelihood of corruption or lost data
  369. Xif the system crashes while a tree is being modified.
  370. XHowever, caching 10
  371. Xpages decreases the creation time of a large tree by between two and three
  372. Xorders of magnitude.
  373. X.TP
  374. Xcompare
  375. XCompare is a user defined comparison function.
  376. XIt must return an integer less than, equal to, or greater than zero if the
  377. Xfirst argument is considered to be respectively less than, equal to, or
  378. Xgreater than the second.
  379. XThe same comparison function must be used on a given tree every time it
  380. Xis opened.
  381. XIf no comparison function is specified,
  382. X.IR strcmp (3)
  383. Xis used.
  384. X.TP
  385. Xlorder
  386. XThe byte order for 4-byte integers in the stored database metadata.
  387. XThe number should represent the order as an integer; for example, 
  388. Xbig endian order would be the number 4,321.
  389. XIf
  390. X.I lorder
  391. Xis 0 (no order is specified) the current host order is used.
  392. XIf the  file already exists, the specified value is ignored and the
  393. Xvalue specified when the tree was created is used.
  394. X(Obviously, portability of the data forming the key/data pairs is the
  395. Xconcern of the application program.)
  396. X.TP
  397. Xpsize
  398. XPage size is the size in bytes of the pages used for nodes in the tree.
  399. XIf the  file already exists, the specified value is ignored and the
  400. Xvalue specified when the tree was created is used.
  401. XIf
  402. X.I psize
  403. Xis zero, an appropriate page size is chosen (based on the system memory
  404. Xand/or file system constraints), but will never be less than 512 bytes.
  405. X.PP
  406. XIf the pointer to the
  407. X.I openinfo
  408. Xdata structure is NULL, the
  409. X.I btree_open
  410. Xroutine will use appropriate values.
  411. X.PP
  412. XIf the database file already exists, and the O_TRUNC flag is not specified
  413. Xto
  414. X.IR btree_open ,
  415. Xthe parameter
  416. X.I psize
  417. Xignored.
  418. X.PP
  419. XKey structures may reference byte strings of slightly less than one-half the
  420. Xtree's page size only (see
  421. X.IR psize ).
  422. XData structures may reference byte strings of essentially unlimited length.
  423. X.PP
  424. XSearches, insertions, and deletions in a btree will all complete in
  425. XO lg N.
  426. X.PP
  427. XForward sequential scans of a tree are from the least key to the greatest.
  428. X.PP
  429. XSpace freed up by deleting key/data pairs from a btree is never reclaimed,
  430. Xalthough it is normally made available for reuse.
  431. XThe exception to this is that space occupied by large data items (those
  432. Xgreater than one quarter the size of a page) is neither reclaimed nor reused.
  433. XThis means that the btree storage structure is grow-only.
  434. XThe only solutions are to avoid excessive deletions, or to create a fresh
  435. Xtree periodically from a scan of an existing one.
  436. X.SH HASH
  437. XOne of the access methods is hashed access and storage.
  438. XThe access method specific data structure provided to
  439. X.I hash_open
  440. Xis as follows:
  441. X.sp
  442. Xtypedef struct {
  443. X.RS
  444. Xint bsize;
  445. X.br
  446. Xu_int cachesize;
  447. X.br
  448. Xint ffactor;
  449. X.br
  450. Xint nelem;
  451. X.br
  452. Xu_long (*hash)(const void *, const size_t);
  453. X.br
  454. Xint lorder;
  455. X.RE
  456. X} HASHINFO;
  457. X.PP
  458. XThe elements of this structure are defined as follows:
  459. X.TP
  460. Xbsize
  461. X.I Bsize
  462. Xdefines the hash table bucket size, and is, by default, 256 bytes.
  463. XIt may be preferable to increase the page size for disk-resident tables and
  464. Xtables with large data items.
  465. X.TP
  466. Xcachesize
  467. XA suggested maximum size, in bytes, of the memory cache.
  468. XSetting this value to zero specifies that an appropriate amount of memory
  469. Xshould be used.
  470. X.TP
  471. Xffactor
  472. X.I Ffactor
  473. Xindicates a desired density within the hash table.
  474. XIt is an approximation of the number of keys allowed to accumulate in any
  475. Xone bucket, determining when the hash table grows or shrinks.
  476. XThe default value is 8.
  477. X.TP
  478. Xhash
  479. X.I Hash
  480. Xis a user defined hash function.
  481. XSince no hash function performs equally well on all possible data, the
  482. Xuser may find that the built-in hash function does poorly on a particular
  483. Xdata set.
  484. XUser specified hash functions must take two arguments (a pointer to a byte
  485. Xstring and a length) and return an u_long to be used as the hash value.
  486. X.TP
  487. Xlorder
  488. XThe byte order for 4-byte integers in the stored database metadata.
  489. XThe number should represent the order as an integer; for example, 
  490. Xbig endian order would be the number 4,321.
  491. XIf
  492. X.I lorder
  493. Xis 0 (no order is specified) the current host order is used.
  494. XIf the  file already exists, the specified value is ignored and the
  495. Xvalue specified when the tree was created is used.
  496. X(Obviously, portability of the data forming the key/data pairs is the
  497. Xconcern of the application program.)
  498. X.TP
  499. Xnelem
  500. X.I Nelem
  501. Xis an estimate of the final size of the hash table.
  502. XIf not set, the default value is 1.
  503. XIf not set or set too low, hash tables will expand gracefully as keys
  504. Xare entered, although a slight performance degradation may be noticed.
  505. X.PP
  506. XIf the pointer to the
  507. X.I openinfo
  508. Xdata structure is NULL, the
  509. X.I hash_open
  510. Xroutine will use appropriate values.
  511. X.PP
  512. XIf the hash table already exists, and the O_TRUNC flag is not
  513. Xspecified to
  514. X.IR hash_open ,
  515. Xthe parameters
  516. X.IR bsize ,
  517. X.IR ffactor ,
  518. Xand
  519. X.I nelem
  520. Xare ignored.
  521. X.PP
  522. XIf a hash function is specified,
  523. X.I hash_open
  524. Xwill attempt to determine if the hash function specified is the same as
  525. Xthe one with which the database was created, and will fail if it is not.
  526. X.PP
  527. XBoth key and data structures may reference byte strings of essentially
  528. Xunlimited length.
  529. X.PP
  530. XBackward compatible interfaces to the routines described in
  531. X.IR dbm (3),
  532. X.IR hsearch (3),
  533. Xand
  534. X.IR ndbm (3)
  535. Xare provided, however, these interfaces are not compatible with
  536. Xprevious file formats.
  537. X.SH RECNO
  538. XOne of the access methods is either variable or fixed-length records,
  539. Xthe former delimited by a specific byte value.
  540. XThe access method specific data structure provided to
  541. X.I recno_open
  542. Xis as follows:
  543. X.sp
  544. Xtypedef struct {
  545. X.RS
  546. Xu_long flags;
  547. X.br
  548. Xu_int cachesize;
  549. X.br
  550. Xsize_t reclen;
  551. X.br
  552. Xu_char bval;
  553. X.RE
  554. X} RECNOINFO;
  555. X.PP
  556. XThe elements of this structure are defined as follows:
  557. X.TP
  558. Xflags
  559. XThe flag value is specified by
  560. X.IR or 'ing
  561. Xany of the following values:
  562. X.RS
  563. X.TP
  564. XR_FIXEDLEN
  565. XThe records are fixed-length, not byte delimited.
  566. XThe structure element
  567. X.I reclen
  568. Xspecifies the length of the record, and the structure element
  569. X.I bval
  570. Xis used as the pad character.
  571. X.TP
  572. XR_SNAPSHOT
  573. XThis flag requires that a snapshot of the file be taken when
  574. X.I recno_open
  575. Xis called, instead of permitting any unmodified records to be
  576. Xread from the original file.
  577. X.RE
  578. X.TP
  579. Xcachesize
  580. XA suggested maximum size, in bytes, of the memory cache.
  581. XSetting this value to zero specifies that an appropriate amount of memory
  582. Xshould be used.
  583. X.TP
  584. Xreclen
  585. XThe length of a fixed-length record.
  586. X.TP
  587. Xbval
  588. XThe delimiting byte to be used to mark the end of a record for
  589. Xvariable-length records, and the pad character for fixed-length
  590. Xrecords.
  591. X.PP
  592. XVariable-length and fixed-length data files require
  593. X.I key
  594. Xstructures to reference the following structure:
  595. X.sp
  596. Xtypedef struct {
  597. X.RS
  598. Xu_long length;
  599. X.br
  600. Xu_long number;
  601. X.br
  602. Xu_long offset;
  603. X.br
  604. Xu_char valid;
  605. X.RE
  606. X} RECNOKEY;
  607. X.PP
  608. XThe elements of this structure are defined as follows:
  609. X.TP
  610. Xlength
  611. XThe length of the record.
  612. X.TP
  613. Xnumber
  614. XThe record number.
  615. X.TP
  616. Xoffset
  617. XThe offset in the file at which the record is located.
  618. X.TP
  619. Xvalid
  620. XA flag value which indicates the validity of the other fields in the
  621. Xstructure.
  622. XThe flag value is specified by
  623. X.IR or 'ing
  624. Xone or more of the following values:
  625. X.RS
  626. X.TP
  627. XR_LENGTH
  628. XThe record length is valid.
  629. X.TP
  630. XR_NUMBER
  631. XThe record number is valid.
  632. X.TP
  633. XR_OFFSET
  634. XThe byte offset is valid.
  635. X.RE
  636. X.PP
  637. XIf the record retrieval is successful, the record number, byte offset and
  638. Xrecord length are set in the RECNOKEY structure referenced by the caller's
  639. X.I key
  640. Xstructure.
  641. X.PP
  642. XData structures may reference byte strings of essentially unlimited length.
  643. X.SH ERRORS
  644. XThe
  645. X.I open
  646. Xroutines may fail and set
  647. X.I errno
  648. Xfor any of the errors specified for the library routines
  649. X.IR open (2)
  650. Xand
  651. X.IR malloc (3)
  652. Xor the following:
  653. X.TP
  654. X[EINVAL]
  655. XA parameter has been specified (hash function, pad byte etc.) that is
  656. Xincompatible with the current file specification or there is a mismatch
  657. Xbetween the version number of file and the software.
  658. X.TP
  659. X[EBADFORMAT]
  660. XA file used by one of the
  661. X.I open
  662. Xroutines is incorrectly formatted.
  663. X.PP
  664. XThe
  665. X.I close
  666. Xroutines may fail and set
  667. X.I errno
  668. Xfor any of the errors specified for the library routines
  669. X.IR close (2),
  670. X.IR read (2),
  671. X.IR write (2),
  672. X.IR free (3),
  673. Xor
  674. X.IR fsync (2).
  675. X.PP
  676. XThe
  677. X.IR delete ,
  678. X.IR get ,
  679. X.I put
  680. Xand
  681. X.I seq
  682. Xroutines may fail and set
  683. X.I errno
  684. Xfor any of the errors specified for the library routines
  685. X.IR read (2),
  686. X.IR write (2),
  687. X.IR free (3)
  688. Xor
  689. X.IR malloc (3).
  690. X.PP
  691. XThe
  692. X.I sync
  693. Xroutines may fail and set
  694. X.I errno
  695. Xfor any of the errors specified for the library routine
  696. X.IR fsync (2).
  697. X.SH "SEE ALSO"
  698. X.IR "Dynamic Hash Tables" ,
  699. XPer-Ake Larson, Communications of the ACM, April 1988.
  700. X.br
  701. X.IR "A New Hash Package for UNIX" ,
  702. XMargo Seltzer, USENIX Proceedings, Winter 1991.
  703. X.SH BUGS
  704. XThe typedef DBT is a mnemonic for ``data base thang'', and was used
  705. Xbecause noone could think of a reasonable name that wasn't already used.
  706. X.PP
  707. XNone of the access methods provide any form of concurrent access,
  708. Xlocking, or transactions.
  709. X.PP
  710. XOnly big and little endian byte order is supported.
  711. @@@End of lq-text/src/ozmahash/db.3
  712. echo x - lq-text/src/ozmahash/db.h 1>&2
  713. sed 's/^X//' >lq-text/src/ozmahash/db.h <<'@@@End of lq-text/src/ozmahash/db.h'
  714. X/*-
  715. X * Copyright (c) 1990 The Regents of the University of California.
  716. X * All rights reserved.
  717. X *
  718. X * This code is derived from software contributed to Berkeley by
  719. X * Margo Seltzer.
  720. X *
  721. X * %sccs.include.redist.c%
  722. X *
  723. X *    %W% (Berkeley) %G%
  724. X */
  725. X
  726. X/* REMOVE THIS WHEN THIS GETS PUT ON A SYSTEM THAT HAS EFTYPE defined */
  727. X#define    EFTYPE    EINVAL
  728. X
  729. X/* Magic Numbers */
  730. X#define    HASHMAGIC    0x61561
  731. X
  732. X/* flags for DB.put() call */
  733. X#define    R_APPEND    1        /* RECNO */
  734. X#define    R_DUP        2        /* BTREE */
  735. X#define    R_INSERT    3        /* RECNO */
  736. X#define    R_NOOVERWRITE    4        /* BTREE, HASH, RECNO */
  737. X
  738. X/* flags for DB.seq() call */
  739. X#define    R_CURSOR    1        /* BTREE, RECNO */
  740. X#define    R_FIRST        2        /* BTREE, HASH, RECNO */
  741. X#define    R_LAST        3        /* BTREE, RECNO */
  742. X#define    R_NEXT        4        /* BTREE, HASH, RECNO */
  743. X#define    R_PREV        5        /* BTREE, RECNO */
  744. X
  745. X/*
  746. X    Swap between big/little endian
  747. X*/
  748. X
  749. X#define BLSWAP(a) { \
  750. X    long _tmp = a; \
  751. X    ((char *)&(a))[0] = ((char *)&_tmp)[3]; \
  752. X    ((char *)&(a))[1] = ((char *)&_tmp)[2]; \
  753. X    ((char *)&(a))[2] = ((char *)&_tmp)[1]; \
  754. X    ((char *)&(a))[3] = ((char *)&_tmp)[0]; \
  755. X}
  756. X
  757. X#define BLSWAP_COPY(a,b) { \
  758. X    ((char *)&(b))[0] = ((char *)&(a))[3]; \
  759. X    ((char *)&(b))[1] = ((char *)&(a))[2]; \
  760. X    ((char *)&(b))[2] = ((char *)&(a))[1]; \
  761. X    ((char *)&(b))[3] = ((char *)&(a))[0]; \
  762. X}
  763. X#define BSSWAP(a) { \
  764. X    u_short _tmp = (a); \
  765. X    ((char *)&(a))[0] = ((char *)&_tmp)[1]; \
  766. X    ((char *)&(a))[1] = ((char *)&_tmp)[0]; \
  767. X}
  768. X#define BSSWAP_COPY(a,b) { \
  769. X    ((char *)&(b))[0] = ((char *)&(a))[1]; \
  770. X    ((char *)&(b))[1] = ((char *)&(a))[0]; \
  771. X}
  772. X
  773. X/* key/data structure -- a data-base thang */
  774. Xtypedef struct {
  775. X    char *data;
  776. X    int size;
  777. X} DBT;
  778. X
  779. X/* access method description structure */
  780. Xtypedef struct {
  781. X    char *internal;        /* access method private; really void * */
  782. X    int (*close)();
  783. X    int (*delete)();
  784. X    int (*get)();
  785. X    int (*put)();
  786. X    int (*seq)();
  787. X    int (*sync)();
  788. X} DB;
  789. X
  790. X/* structure used to pass parameters to the hashing routines */
  791. Xtypedef struct {
  792. X    int bsize;        /* bucket size */
  793. X    int ffactor;        /* fill factor */
  794. X    int nelem;        /* number of elements */
  795. X    int ncached;        /* bytes to cache */
  796. X    int (*hash)();        /* hash function */
  797. X    int lorder;        /* byte order */
  798. X} HASHINFO;
  799. X
  800. X/* structure used to pass parameters to the btree routines */
  801. Xtypedef struct {
  802. X    int cachesize;        /* bytes to cache */
  803. X    int psize;        /* page size */
  804. X    int (*compare);        /* compare function */
  805. X} BTREEINFO;
  806. X
  807. X/* structure used to pass parameters to the record routines */
  808. Xtypedef struct {
  809. X#define    R_FIXEDLEN    0x01    /* fixed-length records */
  810. X    u_long flags;
  811. X    int cachesize;        /* bytes to cache */
  812. X    size_t reclen;        /* record length (fixed-length records) */
  813. X    u_char bval;        /* delimiting byte (variable-length records */
  814. X} RECNOINFO;
  815. X
  816. X/* key structure for the record routines */
  817. Xtypedef struct {
  818. X    u_long number;
  819. X    u_long offset;
  820. X    u_long length;
  821. X#define    R_LENGTH    0x01    /* length is valid */
  822. X#define    R_NUMBER    0x02    /* record number is valid */
  823. X#define    R_OFFSET    0x04    /* offset is valid */
  824. X    u_char valid;
  825. X} RECNOKEY;
  826. X
  827. X#if __STDC__ || c_plusplus
  828. XDB *btree_open(const char *file, int flags, int mode, const BTREEINFO *private);
  829. XDB *hash_open(const char *file, int flags, int mode, const HASHINFO *private);
  830. XDB *recno_open(const char *file, int flags, int mode, const RECNOINFO *private);
  831. X#else
  832. XDB *btree_open();
  833. XDB *hash_open();
  834. XDB *recno_open();
  835. X#endif
  836. @@@End of lq-text/src/ozmahash/db.h
  837. echo x - lq-text/src/ozmahash/dynahash.c 1>&2
  838. sed 's/^X//' >lq-text/src/ozmahash/dynahash.c <<'@@@End of lq-text/src/ozmahash/dynahash.c'
  839. X/*-
  840. X * Copyright (c) 1990 The Regents of the University of California.
  841. X * All rights reserved.
  842. X *
  843. X * This code is derived from software contributed to Berkeley by
  844. X * Margo Seltzer.
  845. X *
  846. X * %sccs.include.redist.c%
  847. X */
  848. X
  849. X#if defined(LIBC_SCCS) && !defined(lint)
  850. Xstatic char sccsid[] = "%W% (Berkeley) %G%";
  851. X#endif /* LIBC_SCCS and not lint */
  852. X
  853. X#include    <sys/types.h>
  854. X#include    <sys/file.h>
  855. X#include    <sys/stat.h>
  856. X#include    <errno.h>
  857. X#include    <assert.h>
  858. X#include    <string.h>
  859. X#include    <db.h>
  860. X#include    <hash.h>
  861. X#include    <stdio.h>
  862. X#include    <endian.h>
  863. X
  864. X/* For systems that do not haev O_ACCMODE */
  865. X#ifndef O_ACCMODE
  866. X#define    O_ACCMODE    (O_RDONLY|O_WRONLY|O_RDWR)
  867. X#endif
  868. X
  869. X/* Fast arithmetic, relying on powers of 2, */
  870. X
  871. X#define MOD(x,y)        ((x) & ((y)-1))
  872. X#define RETURN_ERROR(ERR,LOC)    { save_errno = ERR; goto LOC; }
  873. X
  874. X/* Return values */
  875. X
  876. X#define    SUCCESS    0
  877. X#define    ERROR    -1
  878. X#define    ABNORMAL 1
  879. X
  880. X/* external routines */
  881. Xextern char *calloc();
  882. X
  883. X/* page.c */
  884. Xextern int get_page();
  885. Xextern int split_page();
  886. Xextern int addel();
  887. Xextern int delpair();
  888. Xextern u_long *init_bitmap();
  889. X
  890. X/* big.c */
  891. Xextern void big_return();
  892. Xextern int big_keydata();
  893. Xextern u_short find_last_page();
  894. X
  895. X/* buf.c */
  896. Xextern BUFHEAD    *get_buf();
  897. Xextern void buf_init();
  898. Xextern int buf_free();
  899. X
  900. X/* hash function */
  901. Xextern int (*default_hash)();
  902. X
  903. X/* My externals */
  904. Xextern int expand_table();
  905. Xextern int call_hash();
  906. X
  907. X/* Internal routines */
  908. Xstatic HTAB *init_hash();
  909. Xstatic int hash_access();
  910. Xstatic int flush_meta();
  911. Xstatic int alloc_segs();
  912. Xstatic int init_htab();
  913. Xstatic char *hash_realloc();
  914. Xstatic int hdestroy();
  915. Xstatic int hash_put();
  916. Xstatic int hash_delete();
  917. Xstatic int hash_get();
  918. Xstatic int hash_sync();
  919. Xstatic int hash_close();
  920. Xstatic int hash_seq();
  921. Xstatic void swap_header_copy();
  922. Xstatic void swap_header();
  923. X
  924. X/* Local data */
  925. X
  926. XHTAB *hashp = NULL;
  927. X
  928. X#ifdef HASH_STATISTICS
  929. Xlong hash_accesses, hash_collisions, hash_expansions, hash_overflows;
  930. X#endif
  931. X
  932. X/************************** INTERFACE ROUTINES **********************/
  933. X/* OPEN/CLOSE */
  934. X
  935. Xextern    DB *
  936. Xhash_open ( file, flags, mode, info )
  937. Xchar    *file;
  938. Xint    flags;
  939. Xint    mode;
  940. XHASHINFO    *info;        /* Special directives for create */
  941. X{
  942. X    int        buckets;
  943. X    int        bpages;
  944. X    int        hdrsize;
  945. X    int        i;
  946. X    int        new_table = 0;
  947. X    int        nkey;
  948. X    int        nsegs;
  949. X    int        save_errno;
  950. X    struct    stat statbuf;
  951. X    DB        *dbp;
  952. X
  953. X
  954. X    if ( !(hashp = (HTAB *) calloc( 1, sizeof(HTAB) ))) {
  955. X    /* calloc should set errno */
  956. X    return(0);
  957. X    }
  958. X    /* 
  959. X    Select flags relevant to us.
  960. X    Even if user wants write only, we need to be able to read 
  961. X    the actual file, so we need to open it read/write.  But, the
  962. X    field in the hashp structure needs to be accurate so that
  963. X    we can check accesses.
  964. X    */
  965. X    flags = flags & (O_CREAT | O_EXCL | O_RDONLY | O_RDWR | O_TRUNC | O_WRONLY);
  966. X    hashp->flags = flags;
  967. X    if ( flags & O_WRONLY )  flags = (flags & ~O_WRONLY) | O_RDWR;
  968. X
  969. X    if ( !file || 
  970. X     (flags & O_TRUNC) || 
  971. X     (stat ( file, &statbuf ) && (errno == ENOENT)) ) {
  972. X     new_table = 1;
  973. X    }
  974. X
  975. X    if ( file && ((hashp->fp = open ( file, flags, mode )) == -1)) {
  976. X    RETURN_ERROR (errno, error0);
  977. X    }
  978. X
  979. X    if ( new_table ) {
  980. X    if ( !(hashp = init_hash( info )) ) {
  981. X        RETURN_ERROR(errno,error1);
  982. X    }
  983. X    } else {
  984. X    /* Table already exists */
  985. X    if ( info && info->hash ) hashp->hash = info->hash;
  986. X    else hashp->hash = default_hash;
  987. X
  988. X    hdrsize = read ( hashp->fp, &hashp->hdr, sizeof(HASHHDR) );
  989. X#if BYTE_ORDER == LITTLE_ENDIAN
  990. X    swap_header ( );
  991. X#endif
  992. X    if ( hdrsize == -1 ) {
  993. X        RETURN_ERROR(errno, error1);
  994. X    }
  995. X    if ( hdrsize != sizeof(HASHHDR) ) {
  996. X        RETURN_ERROR(EFTYPE, error1);
  997. X    }
  998. X
  999. X    /* Verify file type, versions and hash function */
  1000. X    if ( hashp->MAGIC != HASHMAGIC ) 
  1001. X        RETURN_ERROR ( EFTYPE, error1 );
  1002. X    if ( hashp->VERSION != VERSION_NO ) 
  1003. X        RETURN_ERROR ( EFTYPE, error1 );
  1004. X    if (hashp->hash ( CHARKEY, sizeof(CHARKEY) ) != hashp->H_CHARKEY ) {
  1005. X        RETURN_ERROR ( EFTYPE, error1 );
  1006. X    }
  1007. X
  1008. X    /* 
  1009. X        Figure out how many segments we need.
  1010. X    */
  1011. X    nsegs = (hashp->MAX_BUCKET + hashp->SGSIZE -1)/ hashp->SGSIZE;
  1012. X    hashp->nsegs = 0;
  1013. X    if (alloc_segs( nsegs )) {    
  1014. X        /* 
  1015. X        If alloc_segs fails, table will have been destroyed 
  1016. X        and errno will have been set.
  1017. X        */
  1018. X        return( (DB *) NULL );
  1019. X    }
  1020. X
  1021. X    /* Read in bitmaps */
  1022. X    bpages = (hashp->SPARES[log2(hashp->MAX_BUCKET)] + 
  1023. X          (hashp->BSIZE << BYTE_SHIFT) - 1) >> 
  1024. X          (hashp->BSHIFT + BYTE_SHIFT);
  1025. X
  1026. X    hashp->mapp[0] = (u_long *)malloc(bpages<<hashp->BSHIFT);
  1027. X    if ( !hashp->mapp[0] ) {
  1028. X        RETURN_ERROR(errno, error2);
  1029. X    }
  1030. X    for ( i = 0; i < bpages; i++ ) {
  1031. X        hashp->mapp[i] = &hashp->mapp[0][i<<hashp->BSHIFT];
  1032. X        if (get_page ((char *)hashp->mapp[i],  hashp->BITMAPS[i], 0, 1, 1)){
  1033. X        RETURN_ERROR(errno, error2);
  1034. X        }
  1035. X    }
  1036. X
  1037. X    }
  1038. X
  1039. X    /* Initialize Buffer Manager */
  1040. X    if ( info && info->ncached ) {
  1041. X    buf_init (info->ncached);
  1042. X    } else {
  1043. X    buf_init (DEF_BUFSIZE);
  1044. X    }
  1045. X
  1046. X    hashp->new_file = new_table;
  1047. X    hashp->save_file = (file != NULL);
  1048. X    hashp->cbucket = -1;
  1049. X    if ( !(dbp = (DB *)malloc ( sizeof (DB) )) ) {
  1050. X    save_errno = errno;
  1051. X    hdestroy();
  1052. X    errno = save_errno;
  1053. X    return ( NULL );
  1054. X    }
  1055. X    dbp->internal = (char *)hashp;
  1056. X    dbp->close = hash_close;
  1057. X    dbp->delete = hash_delete;
  1058. X    dbp->get = hash_get;
  1059. X    dbp->put = hash_put;
  1060. X    dbp->seq = hash_seq;
  1061. X    dbp->sync = hash_sync;
  1062. X
  1063. X#ifdef DEBUG
  1064. X    (void)fprintf(stderr, "%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%x\n%s%x\n%s%d\n%s%d\n",
  1065. X        "init_htab:",
  1066. X        "TABLE POINTER   ", hashp,
  1067. X        "BUCKET SIZE     ", hashp->BSIZE,
  1068. X        "BUCKET SHIFT    ", hashp->BSHIFT,
  1069. X        "DIRECTORY SIZE  ", hashp->DSIZE,
  1070. X        "SEGMENT SIZE    ", hashp->SGSIZE,
  1071. X        "SEGMENT SHIFT   ", hashp->SSHIFT,
  1072. X        "FILL FACTOR     ", hashp->FFACTOR,
  1073. X        "MAX BUCKET      ", hashp->MAX_BUCKET,
  1074. X        "HIGH MASK       ", hashp->HIGH_MASK,
  1075. X        "LOW  MASK       ", hashp->LOW_MASK,
  1076. X        "NSEGS           ", hashp->nsegs,
  1077. X        "NKEYS           ", hashp->NKEYS );
  1078. X#endif
  1079. X#ifdef HASH_STATISTICS
  1080. X    hash_overflows = hash_accesses = hash_collisions = hash_expansions = 0;
  1081. X#endif
  1082. X    return (dbp);
  1083. X
  1084. Xerror2:
  1085. X    (void)hdestroy();
  1086. X    errno = save_errno;
  1087. X    hashp->errno = errno;
  1088. X    return ( (DB *)NULL );
  1089. X
  1090. Xerror1:
  1091. X    (void) close ( hashp->fp );
  1092. X
  1093. Xerror0:
  1094. X    free ( hashp );
  1095. X    errno = save_errno;
  1096. X    hashp->errno = errno;
  1097. X    return ( (DB *) NULL );
  1098. X}
  1099. X
  1100. Xstatic int
  1101. Xhash_close (dbp)
  1102. XDB    *dbp;
  1103. X{
  1104. X    if ( !dbp ) {
  1105. X        return(ERROR);
  1106. X    }
  1107. X    hashp = (HTAB *)dbp->internal;
  1108. X    return (hdestroy());
  1109. X}
  1110. X
  1111. X
  1112. X/************************** LOCAL CREATION ROUTINES **********************/
  1113. Xstatic HTAB * 
  1114. Xinit_hash( info )
  1115. XHASHINFO *info;
  1116. X{
  1117. X    int    nelem;
  1118. X
  1119. X    nelem = 1;
  1120. X
  1121. X    hashp->LORDER    = BYTE_ORDER;
  1122. X    hashp->BSIZE    = DEF_BUCKET_SIZE;
  1123. X    hashp->BSHIFT   = DEF_BUCKET_SHIFT;
  1124. X    hashp->SGSIZE    = DEF_SEGSIZE;
  1125. X    hashp->SSHIFT   = DEF_SEGSIZE_SHIFT;
  1126. X    hashp->DSIZE    = DEF_DIRSIZE;
  1127. X    hashp->FFACTOR  = DEF_FFACTOR;
  1128. X    hashp->hash     = default_hash;
  1129. X    bzero (hashp->SPARES, sizeof (hashp->SPARES));
  1130. X
  1131. X    if ( info ) {
  1132. X        if ( info->bsize )   {
  1133. X        /* Round pagesize up to power of 2 */
  1134. X        hashp->BSHIFT  = log2(info->bsize);
  1135. X        hashp->BSIZE   = 1 << hashp->BSHIFT;
  1136. X        if ( hashp->BSIZE > MAX_BSIZE ) {
  1137. X            errno = EINVAL;
  1138. X            return(0);
  1139. X        }
  1140. X        }
  1141. X        if ( info->ffactor )  hashp->FFACTOR = info->ffactor;
  1142. X        if ( info->hash ) hashp->hash    = info->hash;
  1143. X        if ( info->nelem ) nelem = info->nelem;
  1144. X        if ( info->lorder ) {
  1145. X        if ( info->lorder != BIG_ENDIAN && 
  1146. X             info->lorder != LITTLE_ENDIAN) {
  1147. X            errno = EINVAL;
  1148. X            return(0);
  1149. X        }
  1150. X        hashp->LORDER = info->lorder;
  1151. X        }
  1152. X    }
  1153. X
  1154. X    /* init_htab should destroy the table and set errno if it fails */
  1155. X    if ( init_htab ( nelem ) ) {
  1156. X        return(0);
  1157. X    } else {
  1158. X        return(hashp);
  1159. X    }
  1160. X}
  1161. X
  1162. X/*
  1163. X    This calls alloc_segs which may run out of memory.
  1164. X    Alloc_segs will destroy the table and set errno,
  1165. X    so we just pass the error information along.
  1166. X
  1167. X    Returns 0 on No Error
  1168. X
  1169. X*/
  1170. Xstatic int
  1171. Xinit_htab ( nelem )
  1172. Xint    nelem;
  1173. X{
  1174. X    register SEGMENT    *segp;
  1175. X    register int nbuckets;
  1176. X    register int nsegs;
  1177. X    int    l2;
  1178. X
  1179. X /*
  1180. X  * Divide number of elements by the fill factor and determine a desired
  1181. X  * number of buckets.  Allocate space for the next greater power of
  1182. X  * two number of buckets
  1183. X  */
  1184. X    nelem = (nelem - 1) / hashp->FFACTOR + 1;
  1185. X
  1186. X    l2 = log2(nelem);
  1187. X    nbuckets = 1 << l2;
  1188. X    nbuckets = MAX ( nbuckets, 2 );
  1189. X
  1190. X    hashp->SPARES[l2] = l2 + 1;
  1191. X    hashp->SPARES[l2+1] = l2 + 1;
  1192. X    /* 
  1193. X        First bitmap page is at:
  1194. X        splitpoint l2
  1195. X        page offset 1
  1196. X    */
  1197. X    init_bitmap ( OADDR_OF(l2,1), l2+1, 0 );
  1198. X
  1199. X    hashp->MAX_BUCKET = hashp->LOW_MASK = nbuckets - 1;
  1200. X    hashp->HIGH_MASK = (nbuckets << 1) - 1;
  1201. X    hashp->HDRPAGES = ((MAX(sizeof(HASHHDR),MINHDRSIZE) - 1) >> 
  1202. X              hashp->BSHIFT) + 1;
  1203. X
  1204. X    nsegs = (nbuckets - 1) / hashp->SGSIZE + 1;
  1205. X    nsegs = 1 << log2(nsegs);
  1206. X
  1207. X    if ( nsegs > hashp->DSIZE ) {
  1208. X        hashp->DSIZE  = nsegs;
  1209. X    }
  1210. X
  1211. X    return (alloc_segs ( nsegs ) );
  1212. X}
  1213. X
  1214. X/********************** DESTROY/CLOSE ROUTINES ************************/
  1215. X
  1216. X/*
  1217. X    Flushes any changes to the file if necessary and
  1218. X    destroys the hashp structure, freeing all allocated
  1219. X    space.
  1220. X*/
  1221. Xstatic int
  1222. Xhdestroy()
  1223. X{
  1224. X    int    save_errno;
  1225. X    int    i;
  1226. X
  1227. X    save_errno = 0;
  1228. X
  1229. X    if (hashp != NULL) {
  1230. X#ifdef HASH_STATISTICS
  1231. X     (void)    fprintf(stderr,    "hdestroy: accesses %ld collisions %ld\n",
  1232. X            hash_accesses, hash_collisions);
  1233. X     (void)    fprintf(stderr, "hdestroy: expansions %ld\n",
  1234. X            hash_expansions);
  1235. X     (void)    fprintf(stderr, "hdestroy: overflows %ld\n",
  1236. X            hash_overflows);
  1237. X     (void)    fprintf(stderr,    "keys %ld maxp %d segmentcount %d\n",
  1238. X            hashp->NKEYS, hashp->MAX_BUCKET, hashp->nsegs);
  1239. X
  1240. X    for ( i = 0; i < NCACHED; i++ ) {
  1241. X        (void) fprintf ( stderr, "spares[%d] = %d\n", i, hashp->SPARES[i] );
  1242. X    }
  1243. X#endif
  1244. X
  1245. X        /* 
  1246. X            Call on buffer manager to free buffers, and if
  1247. X            required, write them to disk
  1248. X        */
  1249. X        if (buf_free(1, hashp->save_file)) {
  1250. X            save_errno = errno;
  1251. X        }
  1252. X        if ( hashp->dir ) {
  1253. X            (void)free(*hashp->dir);    /* Free initial segments */
  1254. X            /* Free extra segments */
  1255. X            while ( hashp->exsegs-- ) {
  1256. X            (void)free ( hashp->dir[--hashp->nsegs] );
  1257. X            }
  1258. X            (void)free(hashp->dir);
  1259. X        }
  1260. X        if (flush_meta() && !save_errno) {
  1261. X            save_errno = errno;
  1262. X        }
  1263. X        if ( hashp->save_file ) (void)close (hashp->fp);
  1264. X        (void)free(hashp);
  1265. X        hashp = NULL;
  1266. X    }
  1267. X    if ( save_errno ) {
  1268. X        errno = save_errno;
  1269. X        return(ERROR);
  1270. X    } else {
  1271. X        return(SUCCESS);
  1272. X    }
  1273. X}
  1274. X
  1275. X/* 
  1276. X    Write modified pages to disk 
  1277. X    0 == OK
  1278. X    -1 ERROR
  1279. X*/
  1280. Xstatic int
  1281. Xhash_sync(dbp)
  1282. XDB    *dbp;
  1283. X{
  1284. X    if ( !dbp ) {
  1285. X        return (ERROR);
  1286. X    }
  1287. X
  1288. X    hashp = (HTAB *)dbp->internal;
  1289. X
  1290. X    if (!hashp->save_file) return(0);
  1291. X    if ( buf_free ( 0, 1 )  || flush_meta()) {
  1292. X        return(ERROR);
  1293. X    }
  1294. X    hashp->new_file = 0;
  1295. X    return(0);
  1296. X}
  1297. X
  1298. X/*
  1299. X0 == OK
  1300. X-1 indicates that errno should be set
  1301. X*/
  1302. Xstatic int
  1303. Xflush_meta()
  1304. X{
  1305. X        int    fp;
  1306. X    int    hdrsize;
  1307. X    int    i;
  1308. X    int    wsize;
  1309. X    HASHHDR    *whdrp;
  1310. X    HASHHDR    whdr;
  1311. X
  1312. X    if (!hashp->save_file) return(0);
  1313. X    hashp->MAGIC = HASHMAGIC;
  1314. X    hashp->VERSION = VERSION_NO;
  1315. X    hashp->H_CHARKEY = hashp->hash ( CHARKEY, sizeof(CHARKEY));
  1316. X
  1317. X    fp = hashp->fp;
  1318. X    whdrp = &hashp->hdr;
  1319. X#if BYTE_ORDER == LITTLE_ENDIAN
  1320. X    whdrp = &whdr;
  1321. X    swap_header_copy( &hashp->hdr, whdrp );
  1322. X#endif
  1323. X    if ( (lseek (fp, 0, L_SET) == -1 ) ||
  1324. X         ((wsize = write ( fp, whdrp, sizeof(HASHHDR))) == -1)) {
  1325. X        return(-1);
  1326. X    } else if ( wsize != sizeof(HASHHDR) ) {
  1327. X        errno = EFTYPE;
  1328. X        hashp->errno = errno;
  1329. X        return(-1);
  1330. X    }
  1331. X    for ( i = 0; i < NCACHED; i++ ) {
  1332. X        if ( hashp->mapp[i] ) {
  1333. X        if (!put_page((char *)hashp->mapp[i], hashp->BITMAPS[i], 0, 1)){
  1334. X            return(-1);
  1335. X        }
  1336. X        }
  1337. X    }
  1338. X    return(0);
  1339. X}
  1340. X/*******************************SEARCH ROUTINES *****************************/
  1341. X/*
  1342. X    All the access routines return 
  1343. X    0 on SUCCESS
  1344. X    1 to indicate an external ERROR (i.e. key not found, etc)
  1345. X    -1 to indicate an internal ERROR (i.e. out of memory, etc)
  1346. X*/
  1347. Xstatic int
  1348. Xhash_get ( dbp, key, data )
  1349. XDB    *dbp;
  1350. XDBT *key, *data;
  1351. X{
  1352. X    if ( !dbp ) {
  1353. X    return (ERROR);
  1354. X    }
  1355. X    hashp = (HTAB *)dbp->internal;
  1356. X    if ( hashp->flags & O_WRONLY ) {
  1357. X    errno = EBADF;
  1358. X    hashp->errno = errno;
  1359. X    return ( ERROR );
  1360. X    }
  1361. X    return ( hash_access ( HASH_GET, key, data ) );
  1362. X}
  1363. X
  1364. Xstatic int
  1365. Xhash_put ( dbp, key, data, flag )
  1366. XDB    *dbp;
  1367. XDBT     *key, *data;
  1368. Xint    flag;
  1369. X{
  1370. X    if ( !dbp ) {
  1371. X    return (ERROR);
  1372. X    }
  1373. X    hashp = (HTAB *)dbp->internal;
  1374. X    if ( (hashp->flags & O_ACCMODE) == O_RDONLY ) {
  1375. X    errno = EBADF;
  1376. X    hashp->errno = errno;
  1377. X    return ( ERROR );
  1378. X    }
  1379. X    if ( flag == R_NOOVERWRITE ) {
  1380. X    return ( hash_access ( HASH_PUTNEW, key, data ) );
  1381. X    } else {
  1382. X    return ( hash_access ( HASH_PUT, key, data ) );
  1383. X    }
  1384. X}
  1385. X
  1386. Xstatic int
  1387. Xhash_delete ( dbp, key, flags )
  1388. XDB    *dbp;
  1389. XDBT     *key;
  1390. Xint    flags;        /* Ignored */
  1391. X{
  1392. X    if ( !dbp ) {
  1393. X    return (ERROR);
  1394. X    }
  1395. X    hashp = (HTAB *)dbp->internal;
  1396. X    if ( (hashp->flags & O_ACCMODE) == O_RDONLY ) {
  1397. X    errno = EBADF;
  1398. X    hashp->errno = errno;
  1399. X    return ( ERROR );
  1400. X    }
  1401. X    return ( hash_access ( HASH_DELETE, key, NULL ) );
  1402. X}
  1403. X
  1404. X/*
  1405. X    Assume that hashp has been set in wrapper routine
  1406. X*/
  1407. Xstatic int
  1408. Xhash_access(action, key, val)
  1409. XACTION action;
  1410. XDBT *key, *val;
  1411. X{
  1412. X    register    BUFHEAD    *rbufp;
  1413. X    register    u_short    *bp;
  1414. X    register    int    ndx;
  1415. X    register     int n;
  1416. X    register     int off = hashp->BSIZE;
  1417. X    register    int        size;
  1418. X    register    char    *kp;
  1419. X    BUFHEAD    *bufp;
  1420. X    u_short    pageno;
  1421. X
  1422. X#ifdef HASH_STATISTICS
  1423. X    hash_accesses++;
  1424. X#endif
  1425. X
  1426. X    size = key->size;
  1427. X    kp = key->data;
  1428. X    rbufp = get_buf ( call_hash(key->data, size), NULL, 0 );
  1429. X    if ( !rbufp ) return(ERROR);
  1430. X
  1431. X    for ( bp = (u_short *)rbufp->page, n = *bp++, ndx = 1; ndx < n;  ) {
  1432. X        if ( bp[1] >= REAL_KEY ) {
  1433. X        /* Real key/data pair */
  1434. X        if (size == off - *bp && 
  1435. X            bcmp(kp, rbufp->page + *bp, size) == 0) {
  1436. X            goto found;
  1437. X        }
  1438. X        off = bp[1];
  1439. X#ifdef HASH_STATISTICS
  1440. X        hash_collisions++;
  1441. X#endif
  1442. X            bp += 2; 
  1443. X            ndx += 2;
  1444. X        } else if ( bp[1] == OVFLPAGE ) {
  1445. X        rbufp = get_buf ( *bp, rbufp, 0 );
  1446. X        if ( !rbufp ) return (ERROR);
  1447. X        /* FOR LOOP INIT */
  1448. X        bp = (u_short *)rbufp->page;
  1449. X        n = *bp++;
  1450. X        ndx = 1;
  1451. X        off = hashp->BSIZE;
  1452. X        } else if ( bp[1] < REAL_KEY ) {
  1453. X        if ( (ndx = find_bigpair(rbufp, ndx, kp, size )) > 0 ) {
  1454. X            goto found;
  1455. X        } else if ( ndx == -2 ) {
  1456. X            bufp = rbufp;
  1457. X            if ( !(pageno = find_last_page ( &bufp )) ) {
  1458. X            ndx = 0;
  1459. X            rbufp = bufp;
  1460. X            break;    /* FOR */
  1461. X            }
  1462. X            rbufp = get_buf ( pageno, bufp, 0 );
  1463. X            if ( !rbufp ) return (ERROR);
  1464. X            /* FOR LOOP INIT */
  1465. X            bp = (u_short *)rbufp->page;
  1466. X            n = *bp++;
  1467. X            ndx = 1;
  1468. X            off = hashp->BSIZE;
  1469. X        } else  {
  1470. X            return(ERROR);
  1471. X        }
  1472. X        } 
  1473. X    }
  1474. X
  1475. X    /* Not found */
  1476. X    switch ( action ) {
  1477. X        case HASH_PUT:
  1478. X        case HASH_PUTNEW:
  1479. X        if (addel(rbufp, key, val)) {
  1480. X            return(ERROR);
  1481. X        } else {
  1482. X            return(SUCCESS);
  1483. X        }
  1484. X        case HASH_GET:
  1485. X        return ( ABNORMAL );
  1486. X        case HASH_DELETE:
  1487. X        return ( ABNORMAL );
  1488. X        default:
  1489. X        return(ABNORMAL);
  1490. X    }
  1491. X
  1492. Xfound:
  1493. X    switch (action) {
  1494. X        case HASH_PUTNEW:
  1495. X        return(ABNORMAL);
  1496. X        case HASH_GET:
  1497. X        bp = (u_short *)rbufp->page;
  1498. X        if (bp[ndx+1] < REAL_KEY) big_return(rbufp, ndx, val, 0);
  1499. X        else {
  1500. X            val->data = rbufp->page + (int) bp[ndx + 1];
  1501. X            val->size = bp[ndx] - bp[ndx + 1];
  1502. X        }
  1503. X        break;
  1504. X        case HASH_PUT:
  1505. X        if (delpair (rbufp, ndx))return(ERROR);
  1506. X        if (addel (rbufp, key, val)) return(ERROR);
  1507. X        break;
  1508. X        case HASH_DELETE:
  1509. X        if (delpair (rbufp, ndx))return(ERROR);
  1510. X        break;
  1511. X    }
  1512. X    return (SUCCESS);
  1513. X}
  1514. X
  1515. Xstatic int
  1516. Xhash_seq(dbp, key, data, flag)
  1517. XDB    *dbp;
  1518. XDBT     *key, *data;
  1519. Xint flag;
  1520. X{
  1521. X    register    int bucket;
  1522. X    register    BUFHEAD    *bufp;
  1523. X    u_short    *bp;
  1524. X    u_short    ndx;
  1525. X    u_short    pageno;
  1526. X
  1527. X    if ( !dbp ) {
  1528. X        return (ERROR);
  1529. X    }
  1530. X
  1531. X    hashp = (HTAB *)dbp->internal;
  1532. X    if ( hashp->flags & O_WRONLY ) {
  1533. X        errno = EBADF;
  1534. X        hashp->errno = errno;
  1535. X        return ( ERROR );
  1536. X    }
  1537. X#ifdef HASH_STATISTICS
  1538. X    hash_accesses++;
  1539. X#endif
  1540. X
  1541. X    if ( (hashp->cbucket < 0) || (flag == R_FIRST) ) {
  1542. X        hashp->cbucket = 0;
  1543. X        hashp->cndx = 1;
  1544. X        hashp->cpage = NULL;
  1545. X    }
  1546. X
  1547. X    if ( !(bufp = hashp->cpage) ) {
  1548. X        for (bucket = hashp->cbucket; 
  1549. X         bucket < hashp->MAX_BUCKET; 
  1550. X         bucket++, hashp->cndx = 1 ) {
  1551. X
  1552. X        bufp = get_buf ( bucket, NULL, 0 );
  1553. X        if (!bufp) return(ERROR);
  1554. X        hashp->cpage = bufp;
  1555. X        bp = (u_short *)bufp->page;
  1556. X        if (bp[0]) break;
  1557. X        }
  1558. X        hashp->cbucket = bucket;
  1559. X        if ( hashp->cbucket >= hashp->MAX_BUCKET ) {
  1560. X        hashp->cbucket = -1;
  1561. X        return ( ABNORMAL );
  1562. X        } 
  1563. X    } else {
  1564. X        bp  = (u_short *)hashp->cpage->page;
  1565. X    }
  1566. X    
  1567. X#ifdef DEBUG
  1568. X    assert (bp);
  1569. X    assert (bufp);
  1570. X#endif
  1571. X    while ( bp[hashp->cndx+1] == OVFLPAGE ) {
  1572. X        bufp = hashp->cpage = get_buf ( bp[hashp->cndx], bufp, 0 );
  1573. X        if (!bufp) return(ERROR);
  1574. X        bp = (u_short *)(bufp->page);
  1575. X        hashp->cndx = 1;
  1576. X    }
  1577. X    ndx = hashp->cndx;
  1578. X    if (bp[ndx+1] < REAL_KEY) {
  1579. X        if (big_keydata(bufp, ndx, key, data, 1)) {
  1580. X        return(ERROR);
  1581. X        }
  1582. X    } else {
  1583. X        key->data = hashp->cpage->page + bp[ndx];
  1584. X        key->size = (ndx > 1 ? bp[ndx-1] : hashp->BSIZE) - bp[ndx];
  1585. X        data->data = hashp->cpage->page + bp[ndx + 1];
  1586. X        data->size = bp[ndx] - bp[ndx + 1];
  1587. X        ndx += 2;
  1588. X        if ( ndx > bp[0] ) {
  1589. X        hashp->cpage = NULL;
  1590. X        hashp->cbucket++;
  1591. X        hashp->cndx=1;
  1592. X        } else hashp->cndx = ndx;
  1593. X    }
  1594. X    return (SUCCESS);
  1595. X}
  1596. X
  1597. X/********************************* UTILITIES ************************/
  1598. X/*
  1599. X    0 ==> OK
  1600. X    -1 ==> Error
  1601. X*/
  1602. Xextern int
  1603. Xexpand_table()
  1604. X{
  1605. X    int    old_bucket, new_bucket;
  1606. X    int    new_segnum;
  1607. X    int    dirsize;
  1608. X    int    spare_ndx;
  1609. X    register    char **old, **new;
  1610. X#ifdef HASH_STATISTICS
  1611. X    hash_expansions++;
  1612. X#endif
  1613. X
  1614. X    new_bucket = ++hashp->MAX_BUCKET;
  1615. X    old_bucket = (hashp->MAX_BUCKET & hashp->LOW_MASK);
  1616. X
  1617. X    new_segnum = new_bucket >> hashp->SSHIFT;
  1618. X
  1619. X    /* Check if we need a new segment */
  1620. X    if ( new_segnum >= hashp->nsegs ) {
  1621. X
  1622. X        /* Check if we need to expand directory */
  1623. X        if ( new_segnum >= hashp->DSIZE ) {
  1624. X
  1625. X        /* Reallocate directory */
  1626. X        dirsize = hashp->DSIZE * sizeof ( SEGMENT * );
  1627. X        if (!hash_realloc ( &hashp->dir, dirsize, (dirsize << 1 ) )) {
  1628. X            return(-1);
  1629. X        }
  1630. X        hashp->DSIZE = dirsize << 1;
  1631. X        }
  1632. X        if (!(hashp->dir[new_segnum] = 
  1633. X            (SEGMENT)calloc ( hashp->SGSIZE, sizeof(SEGMENT)))) {
  1634. X            return(-1);
  1635. X        }
  1636. X        hashp->exsegs++;
  1637. X        hashp->nsegs++;
  1638. X    }
  1639. X
  1640. X    /*
  1641. X        If the split point is increasing (MAX_BUCKET's log
  1642. X        base 2 increases), we need to copy the current contents
  1643. X        of the spare split bucket to the next bucket
  1644. X    */
  1645. X    spare_ndx = log2(hashp->MAX_BUCKET);
  1646. X    if ( spare_ndx != (log2(hashp->MAX_BUCKET - 1))) {
  1647. X        hashp->SPARES[spare_ndx] = hashp->SPARES[spare_ndx-1];
  1648. X    }
  1649. X
  1650. X    if ( new_bucket > hashp->HIGH_MASK ) {
  1651. X        /* Starting a new doubling */
  1652. X        hashp->LOW_MASK = hashp->HIGH_MASK;
  1653. X        hashp->HIGH_MASK = new_bucket | hashp->LOW_MASK;
  1654. X    }
  1655. X
  1656. X    /*
  1657. X     * Relocate records to the new bucket
  1658. X     */
  1659. X    return(split_page ( old_bucket, new_bucket ));
  1660. X}
  1661. X/*
  1662. X    If realloc guarantees that the pointer is not destroyed
  1663. X    if the realloc fails, then this routine can go away
  1664. X*/
  1665. Xstatic char * 
  1666. Xhash_realloc ( p_ptr, oldsize, newsize )
  1667. Xchar    **p_ptr;
  1668. Xint    oldsize;
  1669. Xint    newsize;
  1670. X{
  1671. X    register char    *p;
  1672. X
  1673. X    if (p = (char *)malloc ( newsize ) ) {
  1674. X        bcopy ( *p_ptr, p, oldsize );
  1675. X        bzero ( *p_ptr + oldsize, newsize-oldsize );
  1676. X        free(*p_ptr);
  1677. X        *p_ptr = p;
  1678. X    }
  1679. X    return (p);
  1680. X}
  1681. X
  1682. Xextern int
  1683. Xcall_hash ( k, len )
  1684. Xchar    *k;
  1685. Xint    len;
  1686. X{
  1687. X    int    n, bucket;
  1688. X    n = hashp->hash(k, len);
  1689. X
  1690. X    bucket = n & hashp->HIGH_MASK;
  1691. X    if ( bucket > hashp->MAX_BUCKET ) {
  1692. X        bucket = bucket & hashp->LOW_MASK;
  1693. X    }
  1694. X
  1695. X    return(bucket);
  1696. X}
  1697. X
  1698. X/*
  1699. X    Allocate segment table.  On error, destroy the table
  1700. X    and set errno.
  1701. X
  1702. X    Returns 0 on success
  1703. X*/
  1704. Xstatic int
  1705. Xalloc_segs ( nsegs )
  1706. Xint    nsegs;
  1707. X{
  1708. X    register int    i;
  1709. X    register SEGMENT    store;
  1710. X
  1711. X    int    save_errno;
  1712. X
  1713. X    if (!(hashp->dir = (SEGMENT *)calloc(hashp->DSIZE, sizeof(SEGMENT *)))) {
  1714. X    save_errno = errno;
  1715. X    (void)hdestroy();
  1716. X    errno = save_errno;
  1717. X    return(-1);
  1718. X    }
  1719. X
  1720. X    /* Allocate segments */
  1721. X    store = (SEGMENT)calloc ( nsegs << hashp->SSHIFT, sizeof (SEGMENT) );
  1722. X    if ( !store ) {
  1723. X    save_errno = errno;
  1724. X    (void)hdestroy();
  1725. X    errno = save_errno;
  1726. X    return(-1);
  1727. X    }
  1728. X
  1729. X    for ( i=0; i < nsegs; i++, hashp->nsegs++ ) {
  1730. X    hashp->dir[i] = &store[i<<hashp->SSHIFT];
  1731. X    }
  1732. X    return(0);
  1733. X}
  1734. X
  1735. X/*
  1736. X    Hashp->hdr needs to be byteswapped.
  1737. X*/
  1738. Xstatic void
  1739. Xswap_header_copy ( srcp, destp )
  1740. XHASHHDR    *srcp;
  1741. XHASHHDR    *destp;
  1742. X{
  1743. X    int i;
  1744. X
  1745. X    BLSWAP_COPY(srcp->magic, destp->magic);
  1746. X    BLSWAP_COPY(srcp->version, destp->version);
  1747. X    BLSWAP_COPY(srcp->lorder, destp->lorder);
  1748. X    BLSWAP_COPY(srcp->bsize, destp->bsize);
  1749. X    BLSWAP_COPY(srcp->bshift, destp->bshift);
  1750. X    BLSWAP_COPY(srcp->dsize, destp->dsize);
  1751. X    BLSWAP_COPY(srcp->ssize, destp->ssize);
  1752. X    BLSWAP_COPY(srcp->sshift, destp->sshift);
  1753. X    BLSWAP_COPY(srcp->max_bucket, destp->max_bucket);
  1754. X    BLSWAP_COPY(srcp->high_mask, destp->high_mask);
  1755. X    BLSWAP_COPY(srcp->low_mask, destp->low_mask);
  1756. X    BLSWAP_COPY(srcp->ffactor, destp->ffactor);
  1757. X    BLSWAP_COPY(srcp->nkeys, destp->nkeys);
  1758. X    BLSWAP_COPY(srcp->hdrpages, destp->hdrpages);
  1759. X    BLSWAP_COPY(srcp->h_charkey, destp->h_charkey);
  1760. X    for ( i=0; i < NCACHED; i++ ) {
  1761. X    BLSWAP_COPY ( srcp->spares[i] , destp->spares[i]);
  1762. X    BSSWAP_COPY ( srcp->bitmaps[i] , destp->bitmaps[i]);
  1763. X    }
  1764. X    return;
  1765. X}
  1766. X
  1767. Xstatic void
  1768. Xswap_header ( )
  1769. X{
  1770. X    HASHHDR    *hdrp;
  1771. X    int    i;
  1772. X
  1773. X    hdrp = &hashp->hdr;
  1774. X
  1775. X    BLSWAP(hdrp->magic);
  1776. X    BLSWAP(hdrp->version);
  1777. X    BLSWAP(hdrp->lorder);
  1778. X    BLSWAP(hdrp->bsize);
  1779. X    BLSWAP(hdrp->bshift);
  1780. X    BLSWAP(hdrp->dsize);
  1781. X    BLSWAP(hdrp->ssize);
  1782. X    BLSWAP(hdrp->sshift);
  1783. X    BLSWAP(hdrp->max_bucket);
  1784. X    BLSWAP(hdrp->high_mask);
  1785. X    BLSWAP(hdrp->low_mask);
  1786. X    BLSWAP(hdrp->ffactor);
  1787. X    BLSWAP(hdrp->nkeys);
  1788. X    BLSWAP(hdrp->hdrpages);
  1789. X    BLSWAP(hdrp->h_charkey);
  1790. X    for ( i=0; i < NCACHED; i++ ) {
  1791. X    BLSWAP ( hdrp->spares[i] );
  1792. X    BSSWAP ( hdrp->bitmaps[i] );
  1793. X    }
  1794. X    return;
  1795. X}
  1796. @@@End of lq-text/src/ozmahash/dynahash.c
  1797. echo x - lq-text/src/ozmahash/endian.h 1>&2
  1798. sed 's/^X//' >lq-text/src/ozmahash/endian.h <<'@@@End of lq-text/src/ozmahash/endian.h'
  1799. X/*
  1800. X * Copyright (c) 1987 Regents of the University of California.
  1801. X * All rights reserved.
  1802. X *
  1803. X * Redistribution and use in source and binary forms are permitted provided
  1804. X * that: (1) source distributions retain this entire copyright notice and
  1805. X * comment, and (2) distributions including binaries display the following
  1806. X * acknowledgement:  ``This product includes software developed by the
  1807. X * University of California, Berkeley and its contributors'' in the
  1808. X * documentation or other materials provided with the distribution and in
  1809. X * all advertising materials mentioning features or use of this software.
  1810. X * Neither the name of the University nor the names of its contributors may
  1811. X * be used to endorse or promote products derived from this software without
  1812. X * specific prior written permission.
  1813. X * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
  1814. X * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
  1815. X * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  1816. X *
  1817. X *    @(#)endian.h    7.5 (Berkeley) 5/8/90
  1818. X */
  1819. X
  1820. X/*
  1821. X * Definitions for byte order,
  1822. X * according to byte significance from low address to high.
  1823. X */
  1824. X#define    LITTLE_ENDIAN    1234    /* least-significant byte first (vax) */
  1825. X#define    BIG_ENDIAN    4321    /* most-significant byte first (IBM, net) */
  1826. X#define    PDP_ENDIAN    3412    /* LSB first in word, MSW first in long (pdp) */
  1827. X
  1828. X#define    BYTE_ORDER    LITTLE_ENDIAN    /* byte order on DECSTATION */
  1829. X
  1830. X/*
  1831. X * Macros for network/external number representation conversion.
  1832. X */
  1833. X#if BYTE_ORDER == BIG_ENDIAN && !defined(lint)
  1834. X#define    ntohl(x)    (x)
  1835. X#define    ntohs(x)    (x)
  1836. X#define    htonl(x)    (x)
  1837. X#define    htons(x)    (x)
  1838. X
  1839. X#define    NTOHL(x)    (x)
  1840. X#define    NTOHS(x)    (x)
  1841. X#define    HTONL(x)    (x)
  1842. X#define    HTONS(x)    (x)
  1843. X
  1844. X#else
  1845. X
  1846. Xunsigned short    ntohs(), htons();
  1847. Xunsigned long    ntohl(), htonl();
  1848. X
  1849. X#define    NTOHL(x)    (x) = ntohl(x)
  1850. X#define    NTOHS(x)    (x) = ntohs(x)
  1851. X#define    HTONL(x)    (x) = htonl(x)
  1852. X#define    HTONS(x)    (x) = htons(x)
  1853. X#endif
  1854. X
  1855. @@@End of lq-text/src/ozmahash/endian.h
  1856. echo end of part 12
  1857. -- 
  1858. Liam R. E. Quin,  lee@sq.com, SoftQuad Inc., Toronto, +1 (416) 963-8337
  1859.