rec_put.c 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281
  1. /*-
  2. * Copyright (c) 1990, 1993, 1994
  3. * The Regents of the University of California. All rights reserved.
  4. *
  5. * Redistribution and use in source and binary forms, with or without
  6. * modification, are permitted provided that the following conditions
  7. * are met:
  8. * 1. Redistributions of source code must retain the above copyright
  9. * notice, this list of conditions and the following disclaimer.
  10. * 2. Redistributions in binary form must reproduce the above copyright
  11. * notice, this list of conditions and the following disclaimer in the
  12. * documentation and/or other materials provided with the distribution.
  13. * 3. All advertising materials mentioning features or use of this software
  14. * must display the following acknowledgement:
  15. * This product includes software developed by the University of
  16. * California, Berkeley and its contributors.
  17. * 4. Neither the name of the University nor the names of its contributors
  18. * may be used to endorse or promote products derived from this software
  19. * without specific prior written permission.
  20. *
  21. * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  22. * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  23. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  24. * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  25. * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  26. * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  27. * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  28. * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  29. * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  30. * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  31. * SUCH DAMAGE.
  32. */
  33. #if defined(LIBC_SCCS) && !defined(lint)
  34. static char sccsid[] = "@(#)rec_put.c 8.7 (Berkeley) 8/18/94";
  35. #endif /* LIBC_SCCS and not lint */
  36. #include <sys/types.h>
  37. #include <errno.h>
  38. #include <stdio.h>
  39. #include <stdlib.h>
  40. #include <string.h>
  41. #include "../include/db.h"
  42. #include "recno.h"
  43. /*
  44. * __REC_PUT -- Add a recno item to the tree.
  45. *
  46. * Parameters:
  47. * dbp: pointer to access method
  48. * key: key
  49. * data: data
  50. * flag: R_CURSOR, R_IAFTER, R_IBEFORE, R_NOOVERWRITE
  51. *
  52. * Returns:
  53. * RET_ERROR, RET_SUCCESS and RET_SPECIAL if the key is
  54. * already in the tree and R_NOOVERWRITE specified.
  55. */
  56. int
  57. __rec_put(dbp, key, data, flags)
  58. const DB *dbp;
  59. DBT *key;
  60. const DBT *data;
  61. u_int flags;
  62. {
  63. BTREE *t;
  64. DBT fdata, tdata;
  65. recno_t nrec;
  66. int status;
  67. t = dbp->internal;
  68. /* Toss any page pinned across calls. */
  69. if (t->bt_pinned != NULL) {
  70. mpool_put(t->bt_mp, t->bt_pinned, 0);
  71. t->bt_pinned = NULL;
  72. }
  73. /*
  74. * If using fixed-length records, and the record is long, return
  75. * EINVAL. If it's short, pad it out. Use the record data return
  76. * memory, it's only short-term.
  77. */
  78. if (F_ISSET(t, R_FIXLEN) && data->size != t->bt_reclen) {
  79. if (data->size > t->bt_reclen)
  80. goto einval;
  81. if (t->bt_rdata.size < t->bt_reclen) {
  82. t->bt_rdata.data = t->bt_rdata.data == NULL ?
  83. malloc(t->bt_reclen) :
  84. realloc(t->bt_rdata.data, t->bt_reclen);
  85. if (t->bt_rdata.data == NULL)
  86. return (RET_ERROR);
  87. t->bt_rdata.size = t->bt_reclen;
  88. }
  89. memmove(t->bt_rdata.data, data->data, data->size);
  90. memset((char *)t->bt_rdata.data + data->size,
  91. t->bt_bval, t->bt_reclen - data->size);
  92. fdata.data = t->bt_rdata.data;
  93. fdata.size = t->bt_reclen;
  94. } else {
  95. fdata.data = data->data;
  96. fdata.size = data->size;
  97. }
  98. switch (flags) {
  99. case R_CURSOR:
  100. if (!F_ISSET(&t->bt_cursor, CURS_INIT))
  101. goto einval;
  102. nrec = t->bt_cursor.rcursor;
  103. break;
  104. case R_SETCURSOR:
  105. if ((nrec = *(recno_t *)key->data) == 0)
  106. goto einval;
  107. break;
  108. case R_IAFTER:
  109. if ((nrec = *(recno_t *)key->data) == 0) {
  110. nrec = 1;
  111. flags = R_IBEFORE;
  112. }
  113. break;
  114. case 0:
  115. case R_IBEFORE:
  116. if ((nrec = *(recno_t *)key->data) == 0)
  117. goto einval;
  118. break;
  119. case R_NOOVERWRITE:
  120. if ((nrec = *(recno_t *)key->data) == 0)
  121. goto einval;
  122. if (nrec <= t->bt_nrecs)
  123. return (RET_SPECIAL);
  124. break;
  125. default:
  126. einval: errno = EINVAL;
  127. return (RET_ERROR);
  128. }
  129. /*
  130. * Make sure that records up to and including the put record are
  131. * already in the database. If skipping records, create empty ones.
  132. */
  133. if (nrec > t->bt_nrecs) {
  134. if (!F_ISSET(t, R_EOF | R_INMEM) &&
  135. t->bt_irec(t, nrec) == RET_ERROR)
  136. return (RET_ERROR);
  137. if (nrec > t->bt_nrecs + 1) {
  138. if (F_ISSET(t, R_FIXLEN)) {
  139. if ((tdata.data =
  140. (void *)malloc(t->bt_reclen)) == NULL)
  141. return (RET_ERROR);
  142. tdata.size = t->bt_reclen;
  143. memset(tdata.data, t->bt_bval, tdata.size);
  144. } else {
  145. tdata.data = NULL;
  146. tdata.size = 0;
  147. }
  148. while (nrec > t->bt_nrecs + 1)
  149. if (__rec_iput(t,
  150. t->bt_nrecs, &tdata, 0) != RET_SUCCESS)
  151. return (RET_ERROR);
  152. if (F_ISSET(t, R_FIXLEN))
  153. free(tdata.data);
  154. }
  155. }
  156. if ((status = __rec_iput(t, nrec - 1, &fdata, flags)) != RET_SUCCESS)
  157. return (status);
  158. if (flags == R_SETCURSOR)
  159. t->bt_cursor.rcursor = nrec;
  160. F_SET(t, R_MODIFIED);
  161. return (__rec_ret(t, NULL, nrec, key, NULL));
  162. }
  163. /*
  164. * __REC_IPUT -- Add a recno item to the tree.
  165. *
  166. * Parameters:
  167. * t: tree
  168. * nrec: record number
  169. * data: data
  170. *
  171. * Returns:
  172. * RET_ERROR, RET_SUCCESS
  173. */
  174. int
  175. __rec_iput(t, nrec, data, flags)
  176. BTREE *t;
  177. recno_t nrec;
  178. const DBT *data;
  179. u_int flags;
  180. {
  181. DBT tdata;
  182. EPG *e;
  183. PAGE *h;
  184. indx_t idx, nxtindex;
  185. pgno_t pg;
  186. u_int32_t nbytes;
  187. int dflags, status;
  188. char *dest, db[NOVFLSIZE];
  189. /*
  190. * If the data won't fit on a page, store it on indirect pages.
  191. *
  192. * XXX
  193. * If the insert fails later on, these pages aren't recovered.
  194. */
  195. if (data->size > t->bt_ovflsize) {
  196. if (__ovfl_put(t, data, &pg) == RET_ERROR)
  197. return (RET_ERROR);
  198. tdata.data = db;
  199. tdata.size = NOVFLSIZE;
  200. *(pgno_t *)db = pg;
  201. *(u_int32_t *)(db + sizeof(pgno_t)) = data->size;
  202. dflags = P_BIGDATA;
  203. data = &tdata;
  204. } else
  205. dflags = 0;
  206. /* __rec_search pins the returned page. */
  207. if ((e = __rec_search(t, nrec,
  208. nrec > t->bt_nrecs || flags == R_IAFTER || flags == R_IBEFORE ?
  209. SINSERT : SEARCH)) == NULL)
  210. return (RET_ERROR);
  211. h = e->page;
  212. idx = e->index;
  213. /*
  214. * Add the specified key/data pair to the tree. The R_IAFTER and
  215. * R_IBEFORE flags insert the key after/before the specified key.
  216. *
  217. * Pages are split as required.
  218. */
  219. switch (flags) {
  220. case R_IAFTER:
  221. ++idx;
  222. break;
  223. case R_IBEFORE:
  224. break;
  225. default:
  226. if (nrec < t->bt_nrecs &&
  227. __rec_dleaf(t, h, idx) == RET_ERROR) {
  228. mpool_put(t->bt_mp, h, 0);
  229. return (RET_ERROR);
  230. }
  231. break;
  232. }
  233. /*
  234. * If not enough room, split the page. The split code will insert
  235. * the key and data and unpin the current page. If inserting into
  236. * the offset array, shift the pointers up.
  237. */
  238. nbytes = NRLEAFDBT(data->size);
  239. if ((u_int32_t) (h->upper - h->lower) < nbytes + sizeof(indx_t)) {
  240. status = __bt_split(t, h, NULL, data, dflags, nbytes, idx);
  241. if (status == RET_SUCCESS)
  242. ++t->bt_nrecs;
  243. return (status);
  244. }
  245. if (idx < (nxtindex = NEXTINDEX(h)))
  246. memmove(h->linp + idx + 1, h->linp + idx,
  247. (nxtindex - idx) * sizeof(indx_t));
  248. h->lower += sizeof(indx_t);
  249. h->linp[idx] = h->upper -= nbytes;
  250. dest = (char *)h + h->upper;
  251. WR_RLEAF(dest, data, dflags);
  252. ++t->bt_nrecs;
  253. F_SET(t, B_MODIFIED);
  254. mpool_put(t->bt_mp, h, MPOOL_DIRTY);
  255. return (RET_SUCCESS);
  256. }