CUBRID Engine  latest
record_descriptor.cpp
Go to the documentation of this file.
1 /*
2  * Copyright 2008 Search Solution Corporation
3  * Copyright 2016 CUBRID Corporation
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  * http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  *
17  */
18 
19 //
20 // record_descriptor.cpp - extended functionality of recdes
21 //
22 
23 #include "record_descriptor.hpp"
24 
25 #include "error_code.h"
26 #include "memory_alloc.h"
27 #include "packer.hpp"
28 #include "slotted_page.h"
29 
30 #include <cstring>
31 
32 // record_descriptor extends functionality for recdes:
33 //
34 // typedef struct recdes RECDES; /* RECORD DESCRIPTOR */
35 // struct recdes
36 // {
37 // int area_size; /* Length of the allocated area. It includes only the data field. The value is negative
38 // * if data is inside buffer. For example, peeking in a slotted page. */
39 // int length; /* Length of the data. Does not include the length and type fields */
40 // INT16 type; /* Type of record */
41 // char *data; /* The data */
42 // };
43 //
44 
45 record_descriptor::record_descriptor (const cubmem::block_allocator &alloc /* = cubmem::PRIVATE_BLOCK_ALLOCATOR */)
46  : m_recdes ()
47  , m_own_data (alloc)
48  , m_data_source (data_source::INVALID)
49 {
50  m_recdes.area_size = 0;
51  m_recdes.length = 0;
53  m_recdes.data = NULL;
54 }
55 
57  const cubmem::block_allocator &alloc /* = cubmem::PRIVATE_BLOCK_ALLOCATOR */)
58  : record_descriptor (alloc)
59 {
60  set_recdes (rec);
61 }
62 
64 {
65  m_recdes = other.m_recdes;
66  m_own_data = std::move (other.m_own_data);
67  m_data_source = other.m_data_source;
68 
69  other.m_data_source = data_source::INVALID;
70  other.m_recdes.data = NULL;
71  other.m_recdes.type = REC_UNKNOWN;
72 }
73 
74 record_descriptor::record_descriptor (const char *data, std::size_t size)
76 {
77  set_data (data, size);
78 }
79 
81 {
82 }
83 
84 void
86 {
88 
89  m_recdes.type = rec.type;
90  if (rec.length != 0)
91  {
92  // copy content from argument
95  m_own_data.extend_to ((std::size_t) m_recdes.area_size);
97  std::memcpy (m_recdes.data, rec.data, m_recdes.length);
98 
99  m_data_source = data_source::COPIED; // we assume this is a copied record
100  }
101 }
102 
103 int
105 {
106  return get (thread_p, page, slotid, record_get_mode::PEEK_RECORD);
107 }
108 
109 int
111 {
112  return get (thread_p, page, slotid, record_get_mode::COPY_RECORD);
113 }
114 
115 int
117 {
118  int mode_to_int = static_cast<int> (mode);
119  SCAN_CODE sc = spage_get_record (thread_p, page, slotid, &m_recdes, mode_to_int);
120  if (sc == S_SUCCESS)
121  {
123  return NO_ERROR;
124  }
125 
126  if (sc == S_DOESNT_FIT)
127  {
128  // extend and try again
129  assert (m_recdes.length < 0);
131 
132  std::size_t required_size = static_cast<std::size_t> (-m_recdes.length);
133  resize_buffer (required_size);
134 
135  sc = spage_get_record (thread_p, page, slotid, &m_recdes, mode_to_int);
136  if (sc == S_SUCCESS)
137  {
139  return NO_ERROR;
140  }
141  }
142 
143  // failed
144  assert (false);
145  return ER_FAILED;
146 }
147 
148 void
149 record_descriptor::resize_buffer (std::size_t required_size)
150 {
152 
153  if (m_recdes.area_size > 0 && required_size <= (std::size_t) m_recdes.area_size)
154  {
155  // resize not required
156  return;
157  }
158 
159  m_own_data.extend_to (required_size);
160 
162  m_recdes.area_size = (int) required_size;
163 
165  {
167  }
168 }
169 
170 void
172 {
173  switch (mode)
174  {
177  break;
180  break;
181  default:
182  assert (false);
184  break;
185  }
186 }
187 
188 const recdes &
190 {
192  return m_recdes;
193 }
194 
195 const char *
197 {
199  return m_recdes.data;
200 }
201 
202 std::size_t
204 {
206  assert (m_recdes.length > 0);
207  return static_cast<std::size_t> (m_recdes.length);
208 }
209 
210 char *
212 {
214 
215  return m_recdes.data;
216 }
217 
218 void
219 record_descriptor::set_data (const char *data, std::size_t size)
220 {
221  // data is assigned and cannot be changed
223  m_recdes.data = const_cast<char *> (data); // status will protect against changes
224  m_recdes.length = (int) size;
225 }
226 
227 void
229 {
231  assert (m_recdes.area_size >= 0 && length <= (size_t) m_recdes.area_size);
232  m_recdes.length = (int) length;
233 }
234 
235 void
236 record_descriptor::set_type (std::int16_t type)
237 {
239  m_recdes.type = type;
240 }
241 
242 void
243 record_descriptor::set_external_buffer (char *buf, std::size_t buf_size)
244 {
245  m_own_data.freemem ();
246  m_recdes.data = buf;
247  m_recdes.area_size = (int) buf_size;
249 }
250 
251 void
252 record_descriptor::move_data (std::size_t dest_offset, std::size_t source_offset)
253 {
255 
256  // should replace RECORD_MOVE_DATA
257  if (dest_offset == source_offset)
258  {
259  // no moving
260  return;
261  }
262 
263  std::size_t rec_size = get_size ();
264 
265  // safe-guard: source offset cannot be outside record
266  assert (rec_size >= source_offset);
267 
268  std::size_t memmove_size = rec_size - source_offset;
269  std::size_t new_size = rec_size + dest_offset - source_offset;
270 
271  if (dest_offset > source_offset)
272  {
273  // record is being increased; make sure we have enough space
274  resize_buffer (new_size);
275  }
276 
277  if (memmove_size > 0)
278  {
279  std::memmove (m_recdes.data + dest_offset, m_recdes.data + source_offset, memmove_size);
280  }
281  m_recdes.length = static_cast<int> (new_size);
282 }
283 
284 void
285 record_descriptor::modify_data (std::size_t offset, std::size_t old_size, std::size_t new_size, const char *new_data)
286 {
288 
289  // should replace RECORD_REPLACE_DATA
290  move_data (offset + new_size, offset + old_size);
291  if (new_size > 0)
292  {
293  std::memcpy (m_recdes.data + offset, new_data, new_size);
294  }
295 }
296 
297 void
298 record_descriptor::delete_data (std::size_t offset, std::size_t data_size)
299 {
301 
302  // just move data
303  move_data (offset, offset + data_size);
304 }
305 
306 void
307 record_descriptor::insert_data (std::size_t offset, std::size_t new_size, const char *new_data)
308 {
309  modify_data (offset, 0, new_size, new_data);
310 }
311 
312 void
314 {
315  assert (is_mutable ());
316 }
317 
318 bool
320 {
322 }
323 
324 void
326 {
327  packer.pack_short (m_recdes.type);
329 }
330 
331 void
333 {
334  // resize_buffer requires m_data_source to be set
336 
337  unpacker.unpack_short (m_recdes.type);
341 }
342 
343 std::size_t
344 record_descriptor::get_packed_size (cubpacking::packer &packer, std::size_t curr_offset) const
345 {
346  std::size_t entry_size = packer.get_packed_short_size (curr_offset);
347  entry_size += packer.get_packed_buffer_size (m_recdes.data, m_recdes.length, entry_size);
348 
349  return entry_size;
350 }
351 
352 void
353 record_descriptor::release_buffer (char *&data, std::size_t &size)
354 {
355  size = m_own_data.get_size ();
356  data = m_own_data.release_ptr ();
357 }
char * PAGE_PTR
const char * get_data(void) const
#define NO_ERROR
Definition: error_code.h:46
int area_size
char * get_data_for_modify(void)
SCAN_CODE
void set_external_buffer(char *buf, std::size_t buf_size)
void set_recdes(const recdes &rec)
void delete_data(std::size_t offset, std::size_t data_size)
#define ER_FAILED
Definition: error_code.h:47
void set_record_length(std::size_t length)
void pack_buffer_with_length(const char *stream, const std::size_t length)
Definition: packer.cpp:866
void pack_short(const short value)
Definition: packer.cpp:193
char * data
void check_changes_are_permitted(void) const
void insert_data(std::size_t offset, std::size_t new_size, const char *new_data)
void unpack(cubpacking::unpacker &unpacker) override
void set_data(const char *data, std::size_t size)
std::size_t get_size() const
Definition: mem_block.hpp:374
SCAN_CODE spage_get_record(THREAD_ENTRY *thread_p, PAGE_PTR page_p, PGSLOTID slot_id, RECDES *record_descriptor_p, int is_peeking)
std::size_t get_size(void) const
#define assert(x)
void update_source_after_get(record_get_mode mode)
void modify_data(std::size_t offset, std::size_t old_size, std::size_t new_size, const char *new_data)
std::size_t get_packed_buffer_size(const char *stream, const std::size_t length, const std::size_t curr_offset) const
Definition: packer.cpp:851
void release_buffer(char *&data, std::size_t &size)
cubmem::extensible_block m_own_data
static enum scanner_mode mode
record_descriptor(const cubmem::block_allocator &alloc=cubmem::PRIVATE_BLOCK_ALLOCATOR)
int copy(cubthread::entry *thread_p, PAGE_PTR page, PGSLOTID slotid)
int peek(cubthread::entry *thread_p, PAGE_PTR page, PGSLOTID slotid)
#define NULL
Definition: freelistheap.h:34
void unpack_short(short &value)
Definition: packer.cpp:215
bool is_mutable() const
size_t get_packed_short_size(size_t curr_offset)
Definition: packer.cpp:187
void peek_unpack_buffer_length(int &value)
Definition: packer.cpp:884
const recdes & get_recdes(void) const
record_get_mode
INT16 PGSLOTID
void move_data(std::size_t dest_offset, std::size_t source_offset)
void pack(cubpacking::packer &packer) const override
void resize_buffer(std::size_t size)
void extend_to(size_t total_bytes)
Definition: mem_block.hpp:346
INT16 type
std::size_t get_packed_size(cubpacking::packer &packer, std::size_t curr_offset) const override
int get(cubthread::entry *thread_p, PAGE_PTR page, PGSLOTID slotid, record_get_mode mode)
void set_type(std::int16_t type)
void unpack_buffer_with_length(char *stream, const std::size_t max_length)
Definition: packer.cpp:897