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