1 /*-
2 * Copyright (c) 2014-2018 MongoDB, Inc.
3 * Copyright (c) 2008-2014 WiredTiger, Inc.
4 * All rights reserved.
5 *
6 * See the file LICENSE for redistribution information.
7 */
8
9 /*
10 * __wt_buf_grow --
11 * Grow a buffer that may be in-use, and ensure that all data is local to
12 * the buffer.
13 */
14 static inline int
__wt_buf_grow(WT_SESSION_IMPL * session,WT_ITEM * buf,size_t size)15 __wt_buf_grow(WT_SESSION_IMPL *session, WT_ITEM *buf, size_t size)
16 {
17 return (size > buf->memsize || !WT_DATA_IN_ITEM(buf) ?
18 __wt_buf_grow_worker(session, buf, size) : 0);
19 }
20
21 /*
22 * __wt_buf_extend --
23 * Grow a buffer that's currently in-use.
24 */
25 static inline int
__wt_buf_extend(WT_SESSION_IMPL * session,WT_ITEM * buf,size_t size)26 __wt_buf_extend(WT_SESSION_IMPL *session, WT_ITEM *buf, size_t size)
27 {
28 /*
29 * The difference between __wt_buf_grow and __wt_buf_extend is that the
30 * latter is expected to be called repeatedly for the same buffer, and
31 * so grows the buffer exponentially to avoid repeated costly calls to
32 * realloc.
33 */
34 return (size > buf->memsize ?
35 __wt_buf_grow(session, buf, WT_MAX(size, 2 * buf->memsize)) : 0);
36 }
37
38 /*
39 * __wt_buf_init --
40 * Create an empty buffer at a specific size.
41 */
42 static inline int
__wt_buf_init(WT_SESSION_IMPL * session,WT_ITEM * buf,size_t size)43 __wt_buf_init(WT_SESSION_IMPL *session, WT_ITEM *buf, size_t size)
44 {
45 /*
46 * The buffer grow function does what we need, but anticipates data
47 * referenced by the buffer. Avoid any data copy by setting data to
48 * reference the buffer's allocated memory, and clearing it.
49 */
50 buf->data = buf->mem;
51 buf->size = 0;
52 return (__wt_buf_grow(session, buf, size));
53 }
54
55 /*
56 * __wt_buf_initsize --
57 * Create an empty buffer at a specific size, and set the data length.
58 */
59 static inline int
__wt_buf_initsize(WT_SESSION_IMPL * session,WT_ITEM * buf,size_t size)60 __wt_buf_initsize(WT_SESSION_IMPL *session, WT_ITEM *buf, size_t size)
61 {
62 WT_RET(__wt_buf_init(session, buf, size));
63
64 buf->size = size; /* Set the data length. */
65
66 return (0);
67 }
68
69 /*
70 * __wt_buf_set --
71 * Set the contents of the buffer.
72 */
73 static inline int
__wt_buf_set(WT_SESSION_IMPL * session,WT_ITEM * buf,const void * data,size_t size)74 __wt_buf_set(
75 WT_SESSION_IMPL *session, WT_ITEM *buf, const void *data, size_t size)
76 {
77 /*
78 * The buffer grow function does what we need, but expects the data to
79 * be referenced by the buffer. If we're copying data from outside the
80 * buffer, set it up so it makes sense to the buffer grow function. (No
81 * test needed, this works if WT_ITEM.data is already set to "data".)
82 */
83 buf->data = data;
84 buf->size = size;
85 return (__wt_buf_grow(session, buf, size));
86 }
87
88 /*
89 * __wt_buf_setstr --
90 * Set the contents of the buffer to a NUL-terminated string.
91 */
92 static inline int
__wt_buf_setstr(WT_SESSION_IMPL * session,WT_ITEM * buf,const char * s)93 __wt_buf_setstr(WT_SESSION_IMPL *session, WT_ITEM *buf, const char *s)
94 {
95 return (__wt_buf_set(session, buf, s, strlen(s) + 1));
96 }
97
98 /*
99 * __wt_buf_free --
100 * Free a buffer.
101 */
102 static inline void
__wt_buf_free(WT_SESSION_IMPL * session,WT_ITEM * buf)103 __wt_buf_free(WT_SESSION_IMPL *session, WT_ITEM *buf)
104 {
105 __wt_free(session, buf->mem);
106
107 memset(buf, 0, sizeof(WT_ITEM));
108 }
109
110 /*
111 * __wt_scr_free --
112 * Release a scratch buffer.
113 */
114 static inline void
__wt_scr_free(WT_SESSION_IMPL * session,WT_ITEM ** bufp)115 __wt_scr_free(WT_SESSION_IMPL *session, WT_ITEM **bufp)
116 {
117 WT_ITEM *buf;
118
119 if ((buf = *bufp) == NULL)
120 return;
121 *bufp = NULL;
122
123 if (session->scratch_cached + buf->memsize >=
124 S2C(session)->session_scratch_max) {
125 __wt_free(session, buf->mem);
126 buf->memsize = 0;
127 } else
128 session->scratch_cached += buf->memsize;
129
130 buf->data = NULL;
131 buf->size = 0;
132 F_CLR(buf, WT_ITEM_INUSE);
133 }
134