CUBRID Engine  latest
locator.c
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  * locator.c - Transaction object locator (Both client & server)
21  */
22 
23 #ident "$Id$"
24 
25 #include "locator.h"
26 
27 #include "config.h"
28 #include "porting.h"
29 #include "memory_alloc.h"
30 #include "oid.h"
31 #include "object_representation.h"
32 #include "error_manager.h"
33 #include "storage_common.h"
34 #if defined(SERVER_MODE)
35 #include "connection_error.h"
36 #endif /* SERVER_MODE */
37 #include "thread_compat.hpp"
38 #if defined(SERVER_MODE)
39 #include "thread_manager.hpp" // for thread_get_thread_entry_info
40 #endif /* SERVER_MODE */
41 
42 #include <stdio.h>
43 #include <string.h>
44 #include <assert.h>
45 
46 #if !defined(SERVER_MODE)
47 #define pthread_mutex_init(a, b)
48 #define pthread_mutex_destroy(a)
49 #define pthread_mutex_lock(a) 0
50 #define pthread_mutex_unlock(a)
51 static int rv;
52 #endif /* !SERVER_MODE */
53 
54 #if defined(SERVER_MODE)
55 #define LOCATOR_NKEEP_LIMIT (50)
56 #else /* SERVER_MODE */
57 #define LOCATOR_NKEEP_LIMIT (2)
58 #endif /* SERVER_MODE */
59 
60 #define LOCATOR_CACHED_COPYAREA_SIZE_LIMIT \
61  (IO_MAX_PAGE_SIZE * 2 + sizeof (LC_COPYAREA))
62 
65 {
67  {
68  int number; /* Num of copy areas that has been kept */
69  LC_COPYAREA *areas[LOCATOR_NKEEP_LIMIT]; /* Array of free copy areas */
70 #if defined(SERVER_MODE)
71  pthread_mutex_t lock;
72 #endif /* SERVER_MODE */
73  } copy_areas;
74 
76  {
77  int number; /* Num of requested areas that has been kept */
78  LC_LOCKSET *areas[LOCATOR_NKEEP_LIMIT]; /* Array of free lockset areas */
79 #if defined(SERVER_MODE)
80  pthread_mutex_t lock;
81 #endif /* SERVER_MODE */
82  } lockset_areas;
83 
85  {
86  int number; /* Num of lockhinted areas that has been kept */
87  LC_LOCKHINT *areas[LOCATOR_NKEEP_LIMIT]; /* Array of free lockhinted */
88 #if defined(SERVER_MODE)
89  pthread_mutex_t lock;
90 #endif /* SERVER_MODE */
92 
94  {
95  int number; /* Num of packed areas that have been kept */
96  LC_COPYAREA *areas[LOCATOR_NKEEP_LIMIT]; /* Array of free packed areas */
97 #if defined(SERVER_MODE)
98  pthread_mutex_t lock;
99 #endif /* SERVER_MODE */
100  } packed_areas;
101 };
102 
104 
106 
107 static bool locator_Is_initialized = false;
108 
109 static char *locator_allocate_packed (int packed_size);
110 static char *locator_reallocate_packed (char *packed, int packed_size);
111 static void locator_free_packed (char *packed_area, int packed_size);
112 #if defined(CUBRID_DEBUG)
113 static void locator_dump_string (FILE * out_fp, char *dump_string, int length);
114 static void locator_dump_copy_area_one_object (FILE * out_fp, LC_COPYAREA_ONEOBJ * obj, int obj_index,
115  const LC_COPYAREA * copyarea, int print_rec);
116 #endif
117 static int locator_initialize_lockset (LC_LOCKSET * lockset, int length, int max_reqobjs, LOCK reqobj_inst_lock,
118  LOCK reqobj_class_lock, int quit_on_errors);
119 #if defined(CUBRID_DEBUG)
120 static void locator_dump_lockset_area_info (FILE * out_fp, LC_LOCKSET * lockset);
121 static void locator_dump_lockset_classes (FILE * out_fp, LC_LOCKSET * lockset);
122 static void locator_dump_lockset_objects (FILE * out_fp, LC_LOCKSET * lockset);
123 #endif
124 static char *locator_pack_lockset_header (char *packed, LC_LOCKSET * lockset);
125 static char *locator_pack_lockset_classes (char *packed, LC_LOCKSET * lockset);
126 static char *locator_pack_lockset_objects (char *packed, LC_LOCKSET * lockset);
127 static char *locator_unpack_lockset_header (char *unpacked, LC_LOCKSET * lockset);
128 static char *locator_unpack_lockset_classes (char *unpacked, LC_LOCKSET * lockset);
129 static char *locator_unpack_lockset_objects (char *unpacked, LC_LOCKSET * lockset);
130 static int locator_initialize_lockhint (LC_LOCKHINT * lockhint, int length, int max_classes, bool quit_on_errors);
131 #if defined(CUBRID_DEBUG)
132 static void locator_dump_lockhint_info (FILE * out_fp, LC_LOCKHINT * lockhint);
133 static void locator_dump_lockhint_classes (FILE * out_fp, LC_LOCKHINT * lockhint);
134 #endif
135 static char *locator_pack_lockhint_header (char *packed, LC_LOCKHINT * lockhint);
136 static char *locator_pack_lockhint_classes (char *packed, LC_LOCKHINT * lockhint);
137 static char *locator_unpack_lockhint_header (char *unpacked, LC_LOCKHINT * lockhint);
138 static char *locator_unpack_lockhint_classes (char *unpacked, LC_LOCKHINT * lockhint);
139 static bool locator_is_hfid_equal (HFID * hfid1_p, HFID * hfid2_p);
140 
141 /*
142  * locator_is_hfid_equal:
143  *
144  * return: bool
145  *
146  * hfid1_p(in):
147  * hfid2_p(in):
148  *
149  * NOTE:
150  */
151 static bool
152 locator_is_hfid_equal (HFID * hfid1_p, HFID * hfid2_p)
153 {
154  return (hfid1_p->vfid.fileid == hfid2_p->vfid.fileid && hfid1_p->vfid.volid == hfid2_p->vfid.volid
155  && hfid1_p->hpgid == hfid2_p->hpgid);
156 }
157 
158 /*
159  * locator_initialize_areas: initialize cache areas
160  *
161  * return: nothing
162  *
163  * NOTE: Initialize all areas.
164  */
165 void
167 {
168  int i;
169 
171  {
172  return;
173  }
174 
175  locator_Keep.copy_areas.number = 0;
176  locator_Keep.lockset_areas.number = 0;
177  locator_Keep.lockhint_areas.number = 0;
178  locator_Keep.packed_areas.number = 0;
179 
180 #if defined(SERVER_MODE)
181  pthread_mutex_init (&locator_Keep.copy_areas.lock, NULL);
182  pthread_mutex_init (&locator_Keep.lockset_areas.lock, NULL);
183  pthread_mutex_init (&locator_Keep.lockhint_areas.lock, NULL);
184  pthread_mutex_init (&locator_Keep.packed_areas.lock, NULL);
185 #endif /* SERVER_MODE */
186 
187  for (i = 0; i < LOCATOR_NKEEP_LIMIT; i++)
188  {
189  locator_Keep.copy_areas.areas[i] = NULL;
190  locator_Keep.lockset_areas.areas[i] = NULL;
191  locator_Keep.lockhint_areas.areas[i] = NULL;
192  locator_Keep.packed_areas.areas[i] = &packed_req_area_ptrs[i];
193  }
194 
195  locator_Is_initialized = true;
196 }
197 
198 /*
199  * locator_free_areas: Free cached areas
200  *
201  * return: nothing
202  *
203  * NOTE: Free all areas that has been cached.
204  */
205 void
207 {
208  int i;
209 
210  if (locator_Is_initialized == false)
211  {
212  return;
213  }
214 
215  for (i = 0; i < locator_Keep.copy_areas.number; i++)
216  {
217  free_and_init (locator_Keep.copy_areas.areas[i]);
218  }
219 
220  for (i = 0; i < locator_Keep.lockset_areas.number; i++)
221  {
222  if (locator_Keep.lockset_areas.areas[i]->packed)
223  {
224  free_and_init (locator_Keep.lockset_areas.areas[i]->packed);
225  }
226  free_and_init (locator_Keep.lockset_areas.areas[i]);
227  }
228 
229  for (i = 0; i < locator_Keep.lockhint_areas.number; i++)
230  {
231  if (locator_Keep.lockhint_areas.areas[i]->packed)
232  {
233  free_and_init (locator_Keep.lockhint_areas.areas[i]->packed);
234  }
235  free_and_init (locator_Keep.lockhint_areas.areas[i]);
236  }
237 
238  for (i = 0; i < locator_Keep.packed_areas.number; i++)
239  {
240  free_and_init (locator_Keep.packed_areas.areas[i]->mem);
241  }
242 
243  locator_Keep.copy_areas.number = 0;
244  locator_Keep.lockset_areas.number = 0;
245  locator_Keep.lockhint_areas.number = 0;
246  locator_Keep.packed_areas.number = 0;
247 
248 #if defined(SERVER_MODE)
249  pthread_mutex_destroy (&locator_Keep.copy_areas.lock);
250  pthread_mutex_destroy (&locator_Keep.lockset_areas.lock);
251  pthread_mutex_destroy (&locator_Keep.lockhint_areas.lock);
252  pthread_mutex_destroy (&locator_Keep.packed_areas.lock);
253 #endif /* SERVER_MODE */
254 
255  locator_Is_initialized = false;
256 }
257 
258 /*
259  *
260  * FETCH/FLUSH COPY AREA
261  *
262  */
263 
264 /*
265  * locator_allocate_packed: allocate an area to pack stuff
266  *
267  * return: char * (pack area)
268  *
269  * packed_size(in): Packed size needed
270  *
271  * NOTE: Allocate an area to pack the stuff such as lockset area
272  * which is sent over the network. The caller needs to free the
273  * packed area.
274  */
275 static char *
276 locator_allocate_packed (int packed_size)
277 {
278  char *packed_area = NULL;
279  int i, tail;
280 #if defined (SERVER_MODE)
281  int rv;
282 #endif /* SERVER_MODE */
283 
284  rv = pthread_mutex_lock (&locator_Keep.packed_areas.lock);
285 
286  for (i = 0; i < locator_Keep.packed_areas.number; i++)
287  {
288  if (locator_Keep.packed_areas.areas[i]->length >= packed_size)
289  {
290  /*
291  * Make sure that the caller is not assuming that the area is
292  * initialized to zeros. That is, make sure caller initialize the area
293  */
294  MEM_REGION_SCRAMBLE (locator_Keep.packed_areas.areas[i]->mem, locator_Keep.packed_areas.areas[i]->length);
295 
296  packed_area = locator_Keep.packed_areas.areas[i]->mem;
297  packed_size = locator_Keep.packed_areas.areas[i]->length;
298 
299  locator_Keep.packed_areas.number--;
300 
301  /* Move the tail to current location */
302  tail = locator_Keep.packed_areas.number;
303 
304  locator_Keep.packed_areas.areas[i]->mem = locator_Keep.packed_areas.areas[tail]->mem;
305  locator_Keep.packed_areas.areas[i]->length = locator_Keep.packed_areas.areas[tail]->length;
306 
307  break;
308  }
309  }
310 
311  pthread_mutex_unlock (&locator_Keep.packed_areas.lock);
312 
313  if (packed_area == NULL)
314  {
315  packed_area = (char *) malloc (packed_size);
316  }
317 
318  return packed_area;
319 }
320 
321 /*
322  * locator_reallocate_packed: Reallocate an area to pack stuff
323  *
324  * return: char * (pack area)
325  *
326  * packed(in): Packed pointer
327  * packed_size(in): New size
328  *
329  * NOTE: Reallocate the given packed area with given size.
330  */
331 static char *
332 locator_reallocate_packed (char *packed, int packed_size)
333 {
334  return (char *) realloc (packed, packed_size);
335 }
336 
337 /*
338  * locator_free_packed: Free a packed area
339  *
340  * return: nothing
341  *
342  * packed_area(in): Area to free
343  * packed_size(in): Size of area to free
344  *
345  * NOTE: Free the given packed area
346  */
347 static void
348 locator_free_packed (char *packed_area, int packed_size)
349 {
350  int tail;
351 #if defined (SERVER_MODE)
352  int rv;
353 #endif /* SERVER_MODE */
354 
355  rv = pthread_mutex_lock (&locator_Keep.packed_areas.lock);
356 
357  if (locator_Keep.packed_areas.number < LOCATOR_NKEEP_LIMIT)
358  {
359  tail = locator_Keep.packed_areas.number;
360 
361  locator_Keep.packed_areas.areas[tail]->mem = packed_area;
362  locator_Keep.packed_areas.areas[tail]->length = packed_size;
363 
364  /*
365  * Scramble the memory, so that the developer detects invalid references
366  * to free'd areas
367  */
368  MEM_REGION_SCRAMBLE (locator_Keep.packed_areas.areas[tail]->mem, locator_Keep.packed_areas.areas[tail]->length);
369  locator_Keep.packed_areas.number++;
370  }
371  else
372  {
373  free_and_init (packed_area);
374  }
375 
376  pthread_mutex_unlock (&locator_Keep.packed_areas.lock);
377 }
378 
379 #if defined (ENABLE_UNUSED_FUNCTION)
380 /*
381  * locator_allocate_copyarea; Allocate a copy area for fetching and flushing
382  *
383  * return: LC_COPYAREA *
384  *
385  * npages(in): Number of needed pages
386  *
387  * NOTE: Allocate a flush/fetch area of the given size.
388  */
389 LC_COPYAREA *
390 locator_allocate_copyarea (DKNPAGES npages)
391 {
393 }
394 #endif
395 
396 /*
397  * locator_allocate_copy_area_by_length: Allocate a copy area for
398  * fetching and flushing purposes.
399  *
400  * return: LC_COPYAREA *
401  *
402  * min_length(in):Length of the copy area
403  *
404  * NOTE: Allocate a flush/fetch area of the given length.
405  */
406 LC_COPYAREA *
408 {
409  LC_COPYAREA *copyarea = NULL;
410  int network_pagesize;
411  int i;
412 #if defined (SERVER_MODE)
413  int rv;
414 #endif /* SERVER_MODE */
415 
416  /*
417  * Make the min_length to be multiple of NETWORK_PAGESIZE since the
418  * copyareas are used to copy objects to/from server and we would like to
419  * maximize the communication line.
420  */
421  network_pagesize = db_network_page_size ();
422 
423  min_length = DB_ALIGN (min_length, network_pagesize);
424 
425  /*
426  * Do we have an area of given or larger length cached ?
427  */
428 
429  rv = pthread_mutex_lock (&locator_Keep.copy_areas.lock);
430 
431  for (i = 0; i < locator_Keep.copy_areas.number; i++)
432  {
433  if (locator_Keep.copy_areas.areas[i]->length >= min_length)
434  {
435  copyarea = locator_Keep.copy_areas.areas[i];
436  locator_Keep.copy_areas.areas[i] = locator_Keep.copy_areas.areas[--locator_Keep.copy_areas.number];
437  min_length = copyarea->length;
438  /*
439  * Make sure that the caller is not assuming that the area is
440  * initialized to zeros. That is, make sure caller initialize the area
441  */
442  MEM_REGION_SCRAMBLE (copyarea, copyarea->length);
443  break;
444  }
445  }
446 
447  pthread_mutex_unlock (&locator_Keep.copy_areas.lock);
448 
449  if (copyarea == NULL)
450  {
451  copyarea = (LC_COPYAREA *) malloc (min_length + sizeof (*copyarea));
452  if (copyarea == NULL)
453  {
455  (size_t) (min_length + sizeof (*copyarea)));
456  return NULL;
457  }
458  }
459 
460  copyarea->mem = (char *) copyarea + sizeof (*copyarea);
461  copyarea->length = min_length;
462 
463  return copyarea;
464 }
465 
466 LC_COPYAREA *
468 {
469  LC_COPYAREA_MANYOBJS *old_mobjs, *new_mobjs;
470  LC_COPYAREA_ONEOBJ *old_obj, *new_obj;
471  LC_COPYAREA *new_area = NULL;
472  int i, last_obj_offset = -1;
473  int last_obj_length = 0;
474  int old_content_length = 0;
475 
476  if (old_area == NULL)
477  {
478  return NULL;
479  }
480 
481  old_mobjs = LC_MANYOBJS_PTR_IN_COPYAREA (old_area);
482 
483  if (new_length < old_area->length)
484  {
485  return NULL;
486  }
487 
488  new_area = locator_allocate_copy_area_by_length (new_length);
489  if (new_area == NULL)
490  {
491  return NULL;
492  }
493 
494  new_mobjs = LC_MANYOBJS_PTR_IN_COPYAREA (new_area);
495  new_mobjs->num_objs = old_mobjs->num_objs;
496  new_mobjs->multi_update_flags = old_mobjs->multi_update_flags;
497 
498  for (i = 0; i < old_mobjs->num_objs; i++)
499  {
500  old_obj = LC_FIND_ONEOBJ_PTR_IN_COPYAREA (old_mobjs, i);
501  new_obj = LC_FIND_ONEOBJ_PTR_IN_COPYAREA (new_mobjs, i);
502 
503  LC_COPY_ONEOBJ (new_obj, old_obj);
504 
505  if (old_obj->offset > last_obj_offset)
506  {
507  last_obj_offset = old_obj->offset;
508  last_obj_length = old_obj->length;
509  }
510  }
511 
512  if (last_obj_offset != -1)
513  {
514  old_content_length = last_obj_offset + last_obj_length;
515  }
516 
517  memcpy (new_area->mem, old_area->mem, old_content_length);
518 
519  locator_free_copy_area (old_area);
520 
521  return new_area;
522 }
523 
524 /*
525  * locator_free_copy_area: Free a copy area
526  *
527  * return:
528  *
529  * copyarea(in): Area to free
530  *
531  * NOTE: Free the given copy area.
532  */
533 void
535 {
536 #if defined (SERVER_MODE)
537  int rv;
538 #endif /* SERVER_MODE */
539 
540  if (LOCATOR_CACHED_COPYAREA_SIZE_LIMIT < (size_t) copyarea->length)
541  {
542  free_and_init (copyarea);
543  return;
544  }
545 
546  rv = pthread_mutex_lock (&locator_Keep.copy_areas.lock);
547  if (locator_Keep.copy_areas.number < LOCATOR_NKEEP_LIMIT)
548  {
549  /* Scramble the memory, so that the developer detects invalid references to free'd areas */
550  MEM_REGION_SCRAMBLE (copyarea->mem, copyarea->length);
551  locator_Keep.copy_areas.areas[locator_Keep.copy_areas.number++] = copyarea;
552 
553  pthread_mutex_unlock (&locator_Keep.copy_areas.lock);
554  }
555  else
556  {
557  pthread_mutex_unlock (&locator_Keep.copy_areas.lock);
558 
559  free_and_init (copyarea);
560  }
561 }
562 
563 /*
564  * locator_pack_copy_area_descriptor: Pack object descriptors for a copy area
565  *
566  * return: updated pack area pointer
567  *
568  * num_objs(in): Number of objects
569  * copyarea(in): Copy area where objects are placed
570  * desc(in): Packed descriptor array
571  *
572  * NOTE: Pack the desc to be sent over the network from the copy area.
573  * The caller is responsible for determining that desc is large
574  * enough to hold the packed data.
575  */
576 char *
577 locator_pack_copy_area_descriptor (int num_objs, LC_COPYAREA * copyarea, char *desc, int desc_len)
578 {
579  LC_COPYAREA_MANYOBJS *mobjs; /* Describe multiple objects in area */
580  LC_COPYAREA_ONEOBJ *obj; /* Describe on object in area */
581  char *ptr;
582  int i;
583 
584  mobjs = LC_MANYOBJS_PTR_IN_COPYAREA (copyarea);
585 
586  assert (num_objs <= mobjs->num_objs);
587 
588  ptr = desc;
589  for (i = 0, obj = LC_START_ONEOBJ_PTR_IN_COPYAREA (mobjs); i < num_objs;
590  i++, obj = LC_NEXT_ONEOBJ_PTR_IN_COPYAREA (obj))
591  {
592  ptr = or_pack_int (ptr, obj->operation);
593  ptr = or_pack_int (ptr, obj->flag);
594  ptr = or_pack_hfid (ptr, &obj->hfid);
595  ptr = or_pack_oid (ptr, &obj->class_oid);
596  ptr = or_pack_oid (ptr, &obj->oid);
597  ptr = or_pack_int (ptr, obj->length);
598  ptr = or_pack_int (ptr, obj->offset);
599 
600  assert (CAST_BUFLEN (ptr - desc) <= desc_len);
601  }
602  return ptr;
603 }
604 
605 /*
606  * locator_unpack_copy_area_descriptor: Unpack object descriptors for a copy area
607  *
608  * return: updated pack area pointer
609  *
610  * num_objs(in): Number of objects
611  * copyarea(in): Copy area where objects are placed
612  * desc(in): Packed descriptor array
613  *
614  * NOTE: Unpack the desc sent over the network and place them in the
615  * copy area. The caller is responsible for determining that
616  * copyarea is large enough to hold the unpacked data.
617  */
618 char *
619 locator_unpack_copy_area_descriptor (int num_objs, LC_COPYAREA * copyarea, char *desc)
620 {
621  LC_COPYAREA_MANYOBJS *mobjs; /* Describe multiple objects in area */
622  LC_COPYAREA_ONEOBJ *obj; /* Describe on object in area */
623  int ope;
624  int i;
625 
626  mobjs = LC_MANYOBJS_PTR_IN_COPYAREA (copyarea);
627  mobjs->num_objs = num_objs;
628  for (i = 0, obj = LC_START_ONEOBJ_PTR_IN_COPYAREA (mobjs); i < num_objs;
629  i++, obj = LC_NEXT_ONEOBJ_PTR_IN_COPYAREA (obj))
630  {
631  desc = or_unpack_int (desc, &ope);
632  obj->operation = (LC_COPYAREA_OPERATION) ope;
633  desc = or_unpack_int (desc, &obj->flag);
634  desc = or_unpack_hfid (desc, &obj->hfid);
635  desc = or_unpack_oid (desc, &obj->class_oid);
636  desc = or_unpack_oid (desc, &obj->oid);
637  desc = or_unpack_int (desc, &obj->length);
638  desc = or_unpack_int (desc, &obj->offset);
639  }
640  return desc;
641 }
642 
643 /*
644  * locator_send_copy_area: find the active areas to be sent over the net
645  *
646  * return: number of objects in the copy area
647  *
648  * copyarea(in):Copy area where objects are placed
649  * contents_ptr(in):Pointer to content of objects
650  * (Set as a side effect)
651  * contents_length(in):Length of content area
652  * (Set as a side effect)
653  * desc_ptr(in):Pointer to descriptor pointer array
654  * (Set as a side effect)
655  * desc_length(in):Length of descriptor pointer array
656  * (Set as a side effect)
657  *
658  * NOTE: Find the active areas (content and descriptor) to be sent over
659  * the network.
660  * The content is sent as is, but the desc are packed.
661  * The caller needs to free *desc_ptr.
662  */
663 int
664 locator_send_copy_area (LC_COPYAREA * copyarea, char **contents_ptr, int *contents_length, char **desc_ptr,
665  int *desc_length)
666 {
667  LC_COPYAREA_MANYOBJS *mobjs; /* Describe multiple objects in area */
668  LC_COPYAREA_ONEOBJ *obj; /* Describe on object in area */
669  int offset = -1;
670  int i, len;
671  char *end;
672 
673  *contents_ptr = copyarea->mem;
674 
675  mobjs = LC_MANYOBJS_PTR_IN_COPYAREA (copyarea);
676  *desc_length = DB_ALIGN (LC_AREA_ONEOBJ_PACKED_SIZE, MAX_ALIGNMENT) * mobjs->num_objs;
677  *desc_ptr = (char *) malloc (*desc_length);
678 
679  if (*desc_ptr == NULL)
680  {
681  *desc_length = 0;
682  return 0;
683  }
684 
685  /* Find the length of the content area and pack the descriptor area */
686 
687  if (contents_length != NULL)
688  {
689  *contents_length = 0;
690  if (mobjs->num_objs > 0)
691  {
692  obj = &mobjs->objs;
693  obj++;
694  for (i = 0; i < mobjs->num_objs; i++)
695  {
696  obj--;
697  if (obj->offset > offset)
698  {
699  /* To the right */
700  *contents_length = obj->length;
701  offset = obj->offset;
702  }
703  }
704 
705  if (offset != -1)
706  {
707  int len = *contents_length;
708  int aligned_len = DB_ALIGN (len, MAX_ALIGNMENT);
709 
710  *contents_length = aligned_len + offset; // total len
711 
712 #if !defined (NDEBUG)
713  int padded_len = aligned_len - len;
714  if (padded_len > 0)
715  {
716  // make valgrind silent
717  memset (*contents_ptr + *contents_length - padded_len, 0, padded_len);
718  }
719 #endif /* DEBUG */
720  }
721  }
722  }
723 
724  end = locator_pack_copy_area_descriptor (mobjs->num_objs, copyarea, *desc_ptr, *desc_length);
725 
726  len = CAST_BUFLEN (end - *desc_ptr);
727  assert (len <= *desc_length);
728  *desc_length = len;
729 
730  return mobjs->num_objs;
731 }
732 
733 /*
734  * locator_recv_allocate_copyarea: allocate a copy area for reciving a "copy area"
735  * from the net.
736  *
737  * return: copyarea or NULL(in case of error)
738  *
739  * num_objs(in):Number of objects
740  * packed_desc(in):Pointer to packed descriptor array
741  * (Set as a side effect)
742  * packed_desc_length(in):Length of packec descriptor array
743  * contents_ptr(in):Pointer to content of objects
744  * (Set as a side effect)
745  * contents_length(in):Length of content area
746  *
747  * NOTE: Prepare a copy area for receiving a "copyarea" of objects
748  * send by either the client or server.
749  */
750 #if defined(SERVER_MODE)
751 LC_COPYAREA *
752 locator_recv_allocate_copyarea (int num_objs, char **contents_ptr, int contents_length)
753 #else /* SERVER_MODE */
754 LC_COPYAREA *
755 locator_recv_allocate_copyarea (int num_objs, char **packed_desc, int packed_desc_length, char **contents_ptr,
756  int contents_length)
757 #endif /* SERVER_MODE */
758 {
759  LC_COPYAREA *copyarea;
760  int length;
761  int desc_length;
762 
763  if (num_objs > 0)
764  {
765  num_objs--;
766  }
767 
768  desc_length = (sizeof (LC_COPYAREA_MANYOBJS) + sizeof (LC_COPYAREA_ONEOBJ) * (num_objs));
769 
770  length = contents_length + desc_length + sizeof (LC_COPYAREA);
771 
772  copyarea = locator_allocate_copy_area_by_length (length);
773  if (copyarea == NULL)
774  {
775  *contents_ptr = NULL;
776  }
777  else
778  {
779  *contents_ptr = copyarea->mem;
780 
781 #if !defined(SERVER_MODE)
782  *packed_desc = (char *) malloc (packed_desc_length);
783  if (*packed_desc == NULL)
784  {
785  locator_free_copy_area (copyarea);
786  copyarea = NULL;
787  *contents_ptr = NULL;
788  }
789 #endif /* !SERVER_MODE */
790  }
791 
792  return copyarea;
793 }
794 
795 #if defined(CUBRID_DEBUG)
796 /*
797  * locator_dump_string:
798  *
799  * return:
800  *
801  * out_fp(in):output file
802  * dump_string(in):
803  * length(in):
804  *
805  * NOTE:
806  */
807 static void
808 locator_dump_string (FILE * out_fp, char *dump_string, int length)
809 {
810  int i;
811  for (i = 0; i < length; i++)
812  {
813  (void) fputc (dump_string[i], out_fp);
814  }
815 }
816 
817 /*
818  * locator_dump_copy_area_one_object:
819  *
820  * return:
821  *
822  * out_fp(in):output file
823  * obj(in):
824  * copyarea(in):Copy area where objects are placed
825  * print_rec(in):true, if records are printed (in ascii format)
826  *
827  * NOTE:
828  */
829 static void
830 locator_dump_copy_area_one_object (FILE * out_fp, LC_COPYAREA_ONEOBJ * obj, int obj_index, const LC_COPYAREA * copyarea,
831  int print_rec)
832 {
833  const char *str_operation;
834  char *rec;
835 
836  switch (obj->operation)
837  {
838  case LC_FLUSH_INSERT:
840  str_operation = "FLUSH_INSERT";
841  break;
842  case LC_FLUSH_DELETE:
843  str_operation = "FLUSH_DELETE";
844  break;
845  case LC_FLUSH_UPDATE:
847  str_operation = "FLUSH_UPDATE";
848  break;
849  case LC_FETCH:
850  str_operation = "FETCH";
851  break;
852  case LC_FETCH_DELETED:
853  str_operation = "FETCH_DELETED";
854  break;
856  str_operation = "FETCH_DECACHE_LOCK";
857  break;
858  case LC_FETCH_VERIFY_CHN:
859  str_operation = "FETCH_VERIFY_CHN";
860  break;
861  default:
862  str_operation = "UNKNOWN";
863  break;
864  }
865  fprintf (out_fp, "Operation = %s, ", str_operation);
866  fprintf (out_fp, "Object OID (volid = %d, pageid = %d, slotid = %d)\n", obj->oid.volid, obj->oid.pageid,
867  obj->oid.slotid);
868  fprintf (out_fp, " length = %d, offset = %d,\n", obj->length, obj->offset);
869 
870  fprintf (out_fp, " Heap (volid = %d, fileid = %d, Hdr_pageid = %d)\n", obj->hfid.vfid.volid,
871  obj->hfid.vfid.fileid, obj->hfid.hpgid);
872 
873  if (obj->length < 0
874  && (obj->length != -1
875  || (obj->operation != LC_FLUSH_DELETE && obj->operation != LC_FETCH_DELETED
877  {
878  fprintf (out_fp, "Bad length = %d for object num = %d, OID = %d|%d|%d\n", obj->length, obj_index, obj->oid.volid,
879  obj->oid.pageid, obj->oid.slotid);
880  }
881  else if (obj->offset > copyarea->length
882  || (obj->offset < 0
883  && (obj->offset != -1
884  || (obj->operation != LC_FLUSH_DELETE && obj->operation != LC_FETCH_DELETED
885  && obj->operation != LC_FETCH_DECACHE_LOCK))))
886  {
887  fprintf (out_fp, "Bad offset = %d for object num = %d, OID = %d|%d|%d\n", obj->offset, obj_index, obj->oid.volid,
888  obj->oid.pageid, obj->oid.slotid);
889  }
890  else if (print_rec)
891  {
892  rec = (char *) copyarea->mem + obj->offset;
893  locator_dump_string (out_fp, rec, obj->length);
894  fprintf (out_fp, "\n");
895  }
896 }
897 
898 /*
899  * locator_dump_copy_area: dump objects placed in copy area
900  *
901  * return:
902  *
903  * out_fp(in):output file
904  * copyarea(in):Copy area where objects are placed
905  * print_rec(in):true, if records are printed (in ascii format)
906  *
907  * NOTE: Dump the objects placed in area. The function also detects
908  * some inconsistencies with the copy area. The actual data of
909  * the objects is not dumped.
910  * This function is used for DEBUGGING PURPOSES.
911  */
912 void
913 locator_dump_copy_area (FILE * out_fp, const LC_COPYAREA * copyarea, int print_rec)
914 {
915  LC_COPYAREA_MANYOBJS *mobjs; /* Describe multiple objects in area */
916  LC_COPYAREA_ONEOBJ *obj; /* Describe on object in area */
917  int i;
918 
919  mobjs = LC_MANYOBJS_PTR_IN_COPYAREA (copyarea);
920  if (mobjs->num_objs != 0)
921  {
922  fprintf (out_fp, "\n\n***Dumping fetch/flush area for Num_objs = %d*** \n", mobjs->num_objs);
923  obj = &mobjs->objs;
924  obj++;
925  for (i = 0; i < mobjs->num_objs; i++)
926  {
927  obj--;
928  locator_dump_copy_area_one_object (out_fp, obj, i, copyarea, print_rec);
929  }
930  fprintf (out_fp, "\n\n");
931  }
932 }
933 #endif
934 
935 /*
936  *
937  * LOCK FETCH AREAS
938  *
939  */
940 
941 /*
942  * locator_allocate_lockset: allocate a lockset area for requesting objects
943  *
944  * return:
945  *
946  * max_reqobjs(in):Maximum number of requested objects needed
947  * reqobj_inst_lock(in):The instance lock for the requested objects
948  * reqobj_class_lock(in):The class lock for the requested classes
949  * quit_on_errors(in):Flag which indicate wheter to continue in case of
950  * errors
951  *
952  * NOTE: Allocate a flush/fetch area of the given size.
953  */
954 LC_LOCKSET *
955 locator_allocate_lockset (int max_reqobjs, LOCK reqobj_inst_lock, LOCK reqobj_class_lock, int quit_on_errors)
956 {
957  LC_LOCKSET *lockset = NULL; /* Area for requested objects */
958  int length;
959  int i;
960 #if defined (SERVER_MODE)
961  int rv;
962 #endif /* SERVER_MODE */
963 
964  length = (sizeof (*lockset) + (max_reqobjs * (sizeof (*(lockset->classes)) + sizeof (*(lockset->objects)))));
965 
966  /*
967  * Do we have an area cached, as big as the one needed ?
968  */
969 
970  rv = pthread_mutex_lock (&locator_Keep.lockset_areas.lock);
971 
972  for (i = 0; i < locator_Keep.lockset_areas.number; i++)
973  {
974  if (locator_Keep.lockset_areas.areas[i]->length >= length)
975  {
976  lockset = locator_Keep.lockset_areas.areas[i];
977  locator_Keep.lockset_areas.areas[i] = locator_Keep.lockset_areas.areas[--locator_Keep.lockset_areas.number];
978  length = lockset->length;
979  max_reqobjs =
980  ((lockset->length - sizeof (*lockset)) / (sizeof (*(lockset->classes)) + sizeof (*(lockset->objects))));
981 
982  /*
983  * Make sure that the caller is not assuming that the area is
984  * initialized to zeros. That is, make sure caller initialize the area
985  */
986  MEM_REGION_SCRAMBLE (lockset, length);
987 
988  break;
989  }
990  }
991  pthread_mutex_unlock (&locator_Keep.lockset_areas.lock);
992 
993  if (lockset == NULL)
994  {
995  lockset = (LC_LOCKSET *) malloc (length);
996  }
997  if (lockset == NULL)
998  {
999  return NULL;
1000  }
1001 
1002  if (locator_initialize_lockset (lockset, length, max_reqobjs, reqobj_inst_lock, reqobj_class_lock, quit_on_errors) !=
1003  NO_ERROR)
1004  {
1005  return NULL;
1006  }
1007 
1008  return lockset;
1009 }
1010 
1011 /*
1012  * locator_initialize_lockset:
1013  *
1014  * return: error code
1015  *
1016  * lockset(in):
1017  * length(in):
1018  * max_reqobjs(in):Maximum number of requested objects needed
1019  * reqobj_inst_lock(in):The instance lock for the requested objects
1020  * reqobj_class_lock(in):The class lock for the requested classes
1021  * quit_on_errors(in):Flag which indicate wheter to continue in case of
1022  * errors
1023  *
1024  * NOTE:
1025  */
1026 static int
1027 locator_initialize_lockset (LC_LOCKSET * lockset, int length, int max_reqobjs, LOCK reqobj_inst_lock,
1028  LOCK reqobj_class_lock, int quit_on_errors)
1029 {
1030  if (lockset == NULL || length < SSIZEOF (*lockset))
1031  {
1032  return ER_FAILED;
1033  }
1034 
1035  lockset->mem = (char *) lockset;
1036  lockset->length = length;
1037  lockset->first_fetch_lockset_call = true;
1038  lockset->max_reqobjs = max_reqobjs;
1039  lockset->num_reqobjs = 0;
1040  lockset->num_reqobjs_processed = -1;
1041  lockset->last_reqobj_cached = -1;
1042  lockset->reqobj_inst_lock = reqobj_inst_lock;
1043  lockset->reqobj_class_lock = reqobj_class_lock;
1044  lockset->num_classes_of_reqobjs = 0;
1045  lockset->num_classes_of_reqobjs_processed = -1;
1046  lockset->last_classof_reqobjs_cached = -1;
1047  lockset->quit_on_errors = quit_on_errors;
1048  lockset->packed = NULL;
1049  lockset->packed_size = 0;
1050  lockset->classes = ((LC_LOCKSET_CLASSOF *) (lockset->mem + sizeof (*lockset)));
1051  lockset->objects = ((LC_LOCKSET_REQOBJ *) (lockset->classes + max_reqobjs));
1052 
1053  return NO_ERROR;
1054 }
1055 
1056 #if defined (ENABLE_UNUSED_FUNCTION)
1057 /*
1058  * locator_allocate_lockset_by_length: allocate a lockset area for requesting objects
1059  * (the area is not initialized)
1060  *
1061  * return:
1062  *
1063  * length(in):Length of needed area
1064  *
1065  * NOTE: Allocate a lockset area by its length. The area is not fully
1066  * initialized. It must be initialized by the caller.
1067  */
1068 LC_LOCKSET *
1069 locator_allocate_lockset_by_length (int length)
1070 {
1071  LC_LOCKSET *lockset;
1072  int max_reqobjs;
1073 
1074  max_reqobjs = ((length - sizeof (*lockset)) / (sizeof (*(lockset->classes)) + sizeof (*(lockset->objects))));
1075 
1076  return locator_allocate_lockset (max_reqobjs, NULL_LOCK, NULL_LOCK, true);
1077 }
1078 #endif
1079 
1080 /*
1081  * locator_reallocate_lockset: reallocate a lockset area for requesting objects
1082  *
1083  * return: new lockset or NULL
1084  *
1085  * lockset(in):The old area.. This should not be NULL.
1086  * max_reqobjs(in):The new size
1087  *
1088  * NOTE: Allocate a flush/fetch area of the given size.
1089  */
1090 LC_LOCKSET *
1091 locator_reallocate_lockset (LC_LOCKSET * lockset, int max_reqobjs)
1092 {
1093  LC_LOCKSET_REQOBJ *old_reqobjs;
1094  int oldmax_reqobjs;
1095  int length;
1096 
1097  length = (sizeof (*lockset) + (max_reqobjs * (sizeof (*(lockset->classes)) + sizeof (*(lockset->objects)))));
1098 
1099  if (lockset->length < length)
1100  {
1101  lockset = (LC_LOCKSET *) realloc (lockset, length);
1102  if (lockset == NULL)
1103  {
1104  return NULL;
1105  }
1106  }
1107 
1108  /*
1109  * Reset to new areas
1110  */
1111 
1112  oldmax_reqobjs =
1113  ((lockset->length - (sizeof (*lockset))) / (sizeof (*(lockset->classes)) + sizeof (*(lockset->objects))));
1114 
1115  lockset->mem = (char *) lockset;
1116  lockset->length = length;
1117  lockset->max_reqobjs = max_reqobjs;
1118  lockset->classes = ((LC_LOCKSET_CLASSOF *) (lockset->mem + sizeof (*lockset)));
1119  lockset->objects = ((LC_LOCKSET_REQOBJ *) (lockset->classes + max_reqobjs));
1120 
1121  /*
1122  * Need to move the object to the right by the number of positions added
1123  */
1124  old_reqobjs = ((LC_LOCKSET_REQOBJ *) (lockset->classes + oldmax_reqobjs));
1125  memmove (lockset->objects, old_reqobjs, lockset->num_reqobjs * sizeof (*(lockset->objects)));
1126 
1127  return lockset;
1128 }
1129 
1130 /*
1131  * locator_free_lockset : free a lockset area
1132  *
1133  * return: nothing
1134  *
1135  * lockset(in):Request area to free
1136  *
1137  * NOTE: Free a lockset area
1138  */
1139 void
1141 {
1142 #if defined (SERVER_MODE)
1143  int rv;
1144 #endif /* SERVER_MODE */
1145 
1146  if (lockset->packed)
1147  {
1148  locator_free_packed (lockset->packed, lockset->packed_size);
1149  lockset->packed = NULL;
1150  lockset->packed_size = 0;
1151  }
1152 
1153  rv = pthread_mutex_lock (&locator_Keep.lockset_areas.lock);
1154 
1155  if (locator_Keep.lockset_areas.number < LOCATOR_NKEEP_LIMIT)
1156  {
1157  /*
1158  * Scramble the memory, so that the developer detects invalid references
1159  * to free'd areas
1160  */
1161  MEM_REGION_SCRAMBLE ((char *) lockset + sizeof (*lockset), lockset->length - sizeof (*lockset));
1162 
1163  locator_Keep.lockset_areas.areas[locator_Keep.lockset_areas.number++] = lockset;
1164  }
1165  else
1166  {
1167  free_and_init (lockset);
1168  }
1169 
1170  pthread_mutex_unlock (&locator_Keep.lockset_areas.lock);
1171 }
1172 
1173 #if defined(CUBRID_DEBUG)
1174 /*
1175  * locator_dump_lockset : Dump objects in lockset area
1176  *
1177  * return: nothing
1178  *
1179  * out_fp(in):output file
1180  * lockset(in): The lockset area
1181  *
1182  * NOTE:
1183  */
1184 static void
1185 locator_dump_lockset_area_info (FILE * out_fp, LC_LOCKSET * lockset)
1186 {
1187  fprintf (out_fp, "Mem = %p, length = %d, num_reqobjs = %d,", (void *) (lockset->mem), lockset->length,
1188  lockset->num_reqobjs);
1189  fprintf (out_fp, "Reqobj_inst_lock = %s, Reqobj_class_lock = %s,\n",
1191 
1192  fprintf (out_fp, " num_reqobjs_processed = %d, last_reqobj_cached = %d, \n", lockset->num_reqobjs_processed,
1193  lockset->last_reqobj_cached);
1194 
1195  fprintf (out_fp, "num_classes_of_reqobjs = %d, ", lockset->num_classes_of_reqobjs);
1196  fprintf (out_fp, "num_classes_of_reqobjs_processed = %d, ", lockset->num_classes_of_reqobjs_processed);
1197  fprintf (out_fp, "last_classof_reqobj_cached = %d", lockset->last_classof_reqobjs_cached);
1198 
1199  fprintf (out_fp, "quit_on_errors = %s, classes = %p, objects = %p\n", (lockset->quit_on_errors ? "TRUE" : "FALSE"),
1200  (void *) (lockset->classes), (void *) (lockset->objects));
1201 }
1202 
1203 /*
1204  * locator_dump_lockset_classes :
1205  *
1206  * return: nothing
1207  *
1208  * out_fp(in):output file
1209  * lockset(in): The lockset area
1210  *
1211  * NOTE:
1212  */
1213 static void
1214 locator_dump_lockset_classes (FILE * out_fp, LC_LOCKSET * lockset)
1215 {
1216  int i;
1217 
1218  for (i = 0; i < lockset->num_classes_of_reqobjs; i++)
1219  {
1220  fprintf (out_fp, "class_oid = %d|%d|%d, chn = %d\n", lockset->classes[i].oid.volid,
1221  lockset->classes[i].oid.pageid, lockset->classes[i].oid.slotid, lockset->classes[i].chn);
1222  }
1223 }
1224 
1225 /*
1226  * locator_dump_lockset_objects :
1227  *
1228  * return: nothing
1229  *
1230  * out_fp(in):output file
1231  * lockset(in): The lockset area
1232  *
1233  * NOTE:
1234  */
1235 static void
1236 locator_dump_lockset_objects (FILE * out_fp, LC_LOCKSET * lockset)
1237 {
1238  int i;
1239 
1240  for (i = 0; i < lockset->num_reqobjs; i++)
1241  {
1242  fprintf (out_fp, "object_oid = %d|%d|%d, chn = %d, class_index = %d\n", lockset->objects[i].oid.volid,
1243  lockset->objects[i].oid.pageid, lockset->objects[i].oid.slotid, lockset->objects[i].chn,
1244  lockset->objects[i].class_index);
1245  }
1246 }
1247 
1248 /*
1249  * locator_dump_lockset : Dump objects in lockset area
1250  *
1251  * return: nothing
1252  *
1253  * out_fp(in):output file
1254  * lockset(in): The lockset area
1255  *
1256  * NOTE: Dump the lockset area.
1257  */
1258 void
1259 locator_dump_lockset (FILE * out_fp, LC_LOCKSET * lockset)
1260 {
1261  int i;
1262 
1263  i = (sizeof (*lockset) + (lockset->num_reqobjs * (sizeof (*lockset->classes) + sizeof (*lockset->objects))));
1264 
1265  if (lockset->length < i || lockset->classes != ((LC_LOCKSET_CLASSOF *) (lockset->mem + sizeof (*lockset)))
1266  || lockset->objects < ((LC_LOCKSET_REQOBJ *) (lockset->classes + lockset->num_reqobjs)))
1267  {
1268  fprintf (out_fp, "Area is inconsistent: either area is too small %d", lockset->length);
1269  fprintf (out_fp, " (expect at least %d),\n", i);
1270  fprintf (out_fp, " pointer to classes %p (expected %p), or\n", (void *) (lockset->classes),
1271  (void *) (lockset->mem + sizeof (*lockset)));
1272  fprintf (out_fp, " pointer to objects %p (expected >= %p) are incorrect\n", (void *) (lockset->objects),
1273  (void *) (lockset->classes + lockset->num_reqobjs));
1274  return;
1275  }
1276 
1277  fprintf (out_fp, "\n***Dumping lockset area***\n");
1278  locator_dump_lockset_area_info (out_fp, lockset);
1279 
1280  locator_dump_lockset_classes (out_fp, lockset);
1281  locator_dump_lockset_objects (out_fp, lockset);
1282 
1283 }
1284 #endif
1285 
1286 /*
1287  * locator_allocate_and_unpack_lockset: allocate a lockset area and unpack the given
1288  * area onto it
1289  *
1290  * return: lockset area
1291  *
1292  * unpacked(in):Area to unpack
1293  * unpacked_size(in):Size of unpacked area
1294  * unpack_classes(in):whether to unpack classes
1295  * unpack_objects(in):whether to unpack objects
1296  * reg_unpacked(in):Whether the unpacked area is register as part of
1297  * lockset area
1298  *
1299  * NOTE: Allocate a lockset. Then unpack the given area onto it.
1300  */
1301 LC_LOCKSET *
1302 locator_allocate_and_unpack_lockset (char *unpacked, int unpacked_size, bool unpack_classes, bool unpack_objects,
1303  bool reg_unpacked)
1304 {
1305  char *ptr;
1306  LC_LOCKSET *lockset;
1307  int max_reqobjs;
1308 
1309  ptr = unpacked;
1310  ptr = or_unpack_int (ptr, &max_reqobjs); /* Really first call */
1311  ptr = or_unpack_int (ptr, &max_reqobjs);
1312 
1313  lockset = locator_allocate_lockset (max_reqobjs, NULL_LOCK, NULL_LOCK, true);
1314  if (lockset == NULL)
1315  {
1316  return NULL;
1317  }
1318 
1319  lockset->packed = unpacked;
1320  lockset->packed_size = unpacked_size;
1321 
1322  (void) locator_unpack_lockset (lockset, unpack_classes, unpack_objects);
1323 
1324  if (reg_unpacked == false)
1325  {
1326  lockset->packed = NULL;
1327  lockset->packed_size = 0;
1328  }
1329 
1330  return lockset;
1331 }
1332 
1333 /*
1334  * locator_pack_lockset_header : Pack the lockset area header
1335  *
1336  * return:
1337  *
1338  * packed(in):
1339  * lockset(in/out):Lockfetch area to pack
1340  *
1341  * NOTE: that we do not pack several fileds such as: last_reqobj_cached,
1342  * las_classof_reqobjs_cached.
1343  */
1344 static char *
1345 locator_pack_lockset_header (char *packed, LC_LOCKSET * lockset)
1346 {
1347  packed = or_pack_int (packed, lockset->first_fetch_lockset_call ? 1 : 0);
1348  packed = or_pack_int (packed, lockset->max_reqobjs);
1349  packed = or_pack_int (packed, lockset->num_reqobjs);
1350  packed = or_pack_int (packed, lockset->num_reqobjs_processed);
1351  packed = or_pack_int (packed, (int) lockset->reqobj_inst_lock);
1352  packed = or_pack_int (packed, (int) lockset->reqobj_class_lock);
1353  packed = or_pack_int (packed, lockset->num_classes_of_reqobjs);
1354  packed = or_pack_int (packed, lockset->num_classes_of_reqobjs_processed);
1355  packed = or_pack_int (packed, lockset->quit_on_errors);
1356 
1357  return packed;
1358 }
1359 
1360 /*
1361  * locator_pack_lockset_classes : Pack the lockset area classes
1362  *
1363  * return:
1364  *
1365  * packed(in):
1366  * lockset(in/out):Lockfetch area to pack
1367  *
1368  * NOTE:
1369  */
1370 static char *
1371 locator_pack_lockset_classes (char *packed, LC_LOCKSET * lockset)
1372 {
1373  LC_LOCKSET_CLASSOF *class_lockset;
1374  int i;
1375 
1376  for (i = 0, class_lockset = lockset->classes; i < lockset->num_classes_of_reqobjs; i++, class_lockset++)
1377  {
1378  packed = or_pack_oid (packed, &class_lockset->oid);
1379  packed = or_pack_int (packed, class_lockset->chn);
1380  }
1381 
1382  return packed;
1383 }
1384 
1385 /*
1386  * locator_pack_lockset_objects : Pack the lockset area objects
1387  *
1388  * return:
1389  *
1390  * packed(in):
1391  * lockset(in/out):Lockfetch area to pack
1392  *
1393  * NOTE:
1394  */
1395 static char *
1396 locator_pack_lockset_objects (char *packed, LC_LOCKSET * lockset)
1397 {
1398  LC_LOCKSET_REQOBJ *object;
1399  int i;
1400 
1401  for (i = 0, object = lockset->objects; i < lockset->num_reqobjs; i++, object++)
1402  {
1403  packed = or_pack_oid (packed, &object->oid);
1404  packed = or_pack_int (packed, object->chn);
1405  packed = or_pack_int (packed, object->class_index);
1406  }
1407 
1408  return packed;
1409 }
1410 
1411 /*
1412  * locator_pack_lockset : Pack the lockset area
1413  *
1414  * return: number of bytes that were packed
1415  * lockset packed fileds are set as a side effect,
1416  *
1417  * lockset(in/out):Lockfetch area to pack
1418  * pack_classes(in):whether to pack classes
1419  * pack_objects(in):whether to pack objects
1420  *
1421  * NOTE: Allocate an area to pack the lockset area to be sent over the
1422  * network. The address and size of the packed area is left on
1423  * the lockset area as a side effect. If there was an area
1424  * already present, it is used.
1425  * Then, the lockset area is packed onto this area, the amount of
1426  * packing is returned.
1427  */
1428 int
1429 locator_pack_lockset (LC_LOCKSET * lockset, bool pack_classes, bool pack_objects)
1430 {
1431  char *packed;
1432  int packed_size;
1433 
1434  packed_size = LC_LOCKSET_PACKED_SIZE (lockset);
1435 
1436  /*
1437  * Do we have space for packing ?
1438  */
1439 
1440  if (lockset->packed != NULL)
1441  {
1442  /*
1443  * Reuse the current area
1444  */
1445  if (packed_size > lockset->packed_size)
1446  {
1447  /*
1448  * We need to realloc this area
1449  */
1450  packed = locator_reallocate_packed (lockset->packed, packed_size);
1451  if (packed == NULL)
1452  {
1453  return 0;
1454  }
1455 
1456  lockset->packed = packed;
1457  lockset->packed_size = packed_size;
1458  }
1459  packed = lockset->packed;
1460  }
1461  else
1462  {
1463  packed = locator_allocate_packed (packed_size);
1464  if (packed == NULL)
1465  {
1466  return 0;
1467  }
1468  lockset->packed = packed;
1469  lockset->packed_size = packed_size;
1470  }
1471 
1472  packed = locator_pack_lockset_header (packed, lockset);
1473 
1474  /*
1475  * Pack the classes of requested objects
1476  */
1477 
1478  if (pack_classes)
1479  {
1480  packed = locator_pack_lockset_classes (packed, lockset);
1481  }
1482 
1483  /*
1484  * Pack the requested objects
1485  */
1486 
1487  if (pack_objects)
1488  {
1489  packed = locator_pack_lockset_objects (packed, lockset);
1490  }
1491 
1492  return CAST_BUFLEN (packed - lockset->packed);
1493 }
1494 
1495 /*
1496  * locator_pack_lockset_header : Pack the lockset area header
1497  *
1498  * return:
1499  *
1500  * packed(in):
1501  * lockset(in/out):Lockfetch area to pack
1502  *
1503  * NOTE: that we do not pack several fileds such as: last_reqobj_cached,
1504  * las_classof_reqobjs_cached.
1505  */
1506 static char *
1507 locator_unpack_lockset_header (char *unpacked, LC_LOCKSET * lockset)
1508 {
1509  int first_fetch;
1510 
1511  unpacked = or_unpack_int (unpacked, &first_fetch);
1512  lockset->first_fetch_lockset_call = (first_fetch == 1) ? true : false;
1513  unpacked = or_unpack_int (unpacked, &lockset->max_reqobjs);
1514  unpacked = or_unpack_int (unpacked, &lockset->num_reqobjs);
1515  unpacked = or_unpack_int (unpacked, &lockset->num_reqobjs_processed);
1516  unpacked = or_unpack_int (unpacked, (int *) &lockset->reqobj_inst_lock);
1517  unpacked = or_unpack_int (unpacked, (int *) &lockset->reqobj_class_lock);
1518  unpacked = or_unpack_int (unpacked, &lockset->num_classes_of_reqobjs);
1519  unpacked = or_unpack_int (unpacked, &lockset->num_classes_of_reqobjs_processed);
1520  unpacked = or_unpack_int (unpacked, &lockset->quit_on_errors);
1521 
1522  return unpacked;
1523 }
1524 
1525 /*
1526  * locator_pack_lockset_classes : Pack the lockset area classes
1527  *
1528  * return:
1529  *
1530  * packed(in):
1531  * lockset(in/out):Lockfetch area to pack
1532  *
1533  * NOTE:
1534  */
1535 static char *
1536 locator_unpack_lockset_classes (char *unpacked, LC_LOCKSET * lockset)
1537 {
1538  LC_LOCKSET_CLASSOF *class_lockset;
1539  int i;
1540 
1541  for (i = 0, class_lockset = lockset->classes; i < lockset->num_classes_of_reqobjs; i++, class_lockset++)
1542  {
1543  unpacked = or_unpack_oid (unpacked, &class_lockset->oid);
1544  unpacked = or_unpack_int (unpacked, &class_lockset->chn);
1545  }
1546 
1547  return unpacked;
1548 }
1549 
1550 /*
1551  * locator_pack_lockset_objects : Pack the lockset area objects
1552  *
1553  * return:
1554  *
1555  * packed(in):
1556  * lockset(in/out):Lockfetch area to pack
1557  *
1558  * NOTE:
1559  */
1560 static char *
1561 locator_unpack_lockset_objects (char *unpacked, LC_LOCKSET * lockset)
1562 {
1563  LC_LOCKSET_REQOBJ *object;
1564  int i;
1565 
1566  for (i = 0, object = lockset->objects; i < lockset->num_reqobjs; i++, object++)
1567  {
1568  unpacked = or_unpack_oid (unpacked, &object->oid);
1569  unpacked = or_unpack_int (unpacked, &object->chn);
1570  unpacked = or_unpack_int (unpacked, &object->class_index);
1571  }
1572 
1573  return unpacked;
1574 }
1575 
1576 /*
1577  * locator_unpack_lockset : unpack a lockset area
1578  *
1579  * return: number of bytes that were unpacked
1580  *
1581  * lockset(in/out):Request area (set as a side effect)
1582  * unpack_classes(in):whether to unpack classes
1583  * unpack_objects(in):whether to unpack objects
1584  *
1585  * NOTE: Unpack the lockset area which was sent over the network.
1586  */
1587 int
1588 locator_unpack_lockset (LC_LOCKSET * lockset, bool unpack_classes, bool unpack_objects)
1589 {
1590  char *unpacked;
1591 
1592  unpacked = lockset->packed;
1593  unpacked = locator_unpack_lockset_header (unpacked, lockset);
1594 
1595  /*
1596  * Unpack the classes of requested objects
1597  */
1598 
1599  if (unpack_classes)
1600  {
1601  unpacked = locator_unpack_lockset_classes (unpacked, lockset);
1602  }
1603 
1604  /*
1605  * Unpack the requested objects
1606  */
1607 
1608  if (unpack_objects)
1609  {
1610  unpacked = locator_unpack_lockset_objects (unpacked, lockset);
1611  }
1612 
1613  return CAST_BUFLEN (unpacked - lockset->packed);
1614 }
1615 
1616 /*
1617  * locator_allocate_lockhint : allocate a lockhint area for prelocking and prefetching
1618  * classes during parsing
1619  *
1620  * return: LC_LOCKHINT * or NULL
1621  *
1622  * max_classes(in):Maximum number of classes
1623  * quit_on_errors(in):Flag which indicate wheter to continue in case of
1624  * errors
1625  *
1626  * NOTE: Allocate a lockhint areas.
1627  */
1628 LC_LOCKHINT *
1629 locator_allocate_lockhint (int max_classes, bool quit_on_errors)
1630 {
1631  LC_LOCKHINT *lockhint = NULL;
1632  int length;
1633  int i;
1634 #if defined (SERVER_MODE)
1635  int rv;
1636 #endif /* SERVER_MODE */
1637 
1638  length = sizeof (*lockhint) + (max_classes * sizeof (*(lockhint->classes)));
1639 
1640  /* Do we have a lockhint area cached ? */
1641 
1642  rv = pthread_mutex_lock (&locator_Keep.lockhint_areas.lock);
1643 
1644  for (i = 0; i < locator_Keep.lockhint_areas.number; i++)
1645  {
1646  if (locator_Keep.lockhint_areas.areas[i]->length >= length)
1647  {
1648  lockhint = locator_Keep.lockhint_areas.areas[i];
1649  locator_Keep.lockhint_areas.areas[i] =
1650  locator_Keep.lockhint_areas.areas[--locator_Keep.lockhint_areas.number];
1651  length = lockhint->length;
1652  max_classes = ((lockhint->length - sizeof (*lockhint)) / sizeof (*(lockhint->classes)));
1653 
1654  /*
1655  * Make sure that the caller is not assuming that the area is
1656  * initialized to zeros. That is, make sure caller initialize the area
1657  */
1658  MEM_REGION_SCRAMBLE (lockhint, length);
1659 
1660  break;
1661  }
1662  }
1663 
1664  pthread_mutex_unlock (&locator_Keep.lockhint_areas.lock);
1665 
1666  if (lockhint == NULL)
1667  {
1668  lockhint = (LC_LOCKHINT *) malloc (length);
1669  }
1670  if (lockhint == NULL)
1671  {
1672  return NULL;
1673  }
1674 
1675  if (locator_initialize_lockhint (lockhint, length, max_classes, quit_on_errors) != NO_ERROR)
1676  {
1677  return NULL;
1678  }
1679 
1680  return lockhint;
1681 }
1682 
1683 /*
1684  * locator_initialize_lockhint:
1685  *
1686  * return: error code
1687  *
1688  * lockhint(in):
1689  * length(in):
1690  * max_classes(in):Maximum number of classes
1691  * quit_on_errors(in):Flag which indicate wheter to continue in case of
1692  * errors
1693  *
1694  * NOTE:
1695  */
1696 static int
1697 locator_initialize_lockhint (LC_LOCKHINT * lockhint, int length, int max_classes, bool quit_on_errors)
1698 {
1699  if (lockhint == NULL || length < SSIZEOF (*lockhint))
1700  {
1701  return ER_FAILED;
1702  }
1703 
1704  lockhint->mem = (char *) lockhint;
1705  lockhint->length = length;
1706  lockhint->first_fetch_lockhint_call = true;
1707  lockhint->max_classes = max_classes;
1708  lockhint->num_classes = 0;
1709  lockhint->num_classes_processed = -1;
1710  lockhint->quit_on_errors = quit_on_errors;
1711  lockhint->packed = NULL;
1712  lockhint->packed_size = 0;
1713  lockhint->classes = ((struct lc_lockhint_class *) (lockhint->mem + sizeof (*lockhint)));
1714 
1715  return NO_ERROR;
1716 }
1717 
1718 /*
1719  * locator_reallocate_lockhint: reallocate a lockhint area for prelocking and
1720  * prefetching classes during parsing
1721  *
1722  * return: LC_LOCKHINT * or NULL
1723  *
1724  * lockhint(in):The old lockhint area.. This should not be NULL
1725  * max_classes(in):The maximum number of classes
1726  *
1727  * NOTE: Reallocate a lockhint areas for lockhinting and prefetching
1728  * purposes during parsing.
1729  */
1730 LC_LOCKHINT *
1731 locator_reallocate_lockhint (LC_LOCKHINT * lockhint, int max_classes)
1732 {
1733  int length;
1734 
1735  length = sizeof (*lockhint) + (max_classes * sizeof (*(lockhint->classes)));
1736 
1737  if (lockhint->length < length)
1738  {
1739  lockhint = (LC_LOCKHINT *) realloc (lockhint, length);
1740  if (lockhint == NULL)
1741  {
1742  return NULL;
1743  }
1744 
1745  /* Reset to new areas */
1746  lockhint->mem = (char *) lockhint;
1747  lockhint->length = length;
1748  lockhint->max_classes = max_classes;
1749  lockhint->classes = ((struct lc_lockhint_class *) (lockhint->mem + sizeof (*lockhint)));
1750  }
1751 
1752  return lockhint;
1753 }
1754 
1755 /*
1756  * locator_free_lockhint : free a lockhint area
1757  *
1758  * return: nothing
1759  *
1760  * lockhint(in):Hintlock area to free
1761  *
1762  * NOTE: Free a lockhint area
1763  */
1764 void
1766 {
1767 #if defined (SERVER_MODE)
1768  int rv;
1769 #endif /* SERVER_MODE */
1770 
1771  if (lockhint->packed)
1772  {
1773  locator_free_packed (lockhint->packed, lockhint->packed_size);
1774  lockhint->packed = NULL;
1775  lockhint->packed_size = 0;
1776  }
1777 
1778  rv = pthread_mutex_lock (&locator_Keep.lockhint_areas.lock);
1779 
1780  if (locator_Keep.lockhint_areas.number < LOCATOR_NKEEP_LIMIT)
1781  {
1782  /*
1783  * Scramble the memory, so that the developer detects invalid references
1784  * to free'd areas
1785  */
1786  MEM_REGION_SCRAMBLE ((char *) lockhint + sizeof (*lockhint), lockhint->length - sizeof (*lockhint));
1787  locator_Keep.lockhint_areas.areas[locator_Keep.lockhint_areas.number++] = lockhint;
1788  }
1789  else
1790  {
1791  free_and_init (lockhint);
1792  }
1793 
1794  pthread_mutex_unlock (&locator_Keep.lockhint_areas.lock);
1795 }
1796 
1797 #if defined(CUBRID_DEBUG)
1798 /*
1799  * locator_dump_lockhint_info :
1800  *
1801  * return: nothing
1802  *
1803  * out_fp(in): output file
1804  * lockhint(in):Hintlock area to dump
1805  *
1806  * NOTE:
1807  */
1808 static void
1809 locator_dump_lockhint_info (FILE * out_fp, LC_LOCKHINT * lockhint)
1810 {
1811  fprintf (out_fp, "Mem = %p, len = %d, max_classes = %d, num_classes = %d\n", (void *) (lockhint->mem),
1812  lockhint->length, lockhint->max_classes, lockhint->num_classes);
1813 
1814  fprintf (out_fp, " num_classes_processed = %d,\n", lockhint->num_classes_processed);
1815 }
1816 
1817 /*
1818  * locator_dump_lockhint_classes :
1819  *
1820  * return: nothing
1821  *
1822  * out_fp(in): output file
1823  * lockhint(in):Hintlock area to dump
1824  *
1825  * NOTE:
1826  */
1827 static void
1828 locator_dump_lockhint_classes (FILE * out_fp, LC_LOCKHINT * lockhint)
1829 {
1830  int i;
1831 
1832  for (i = 0; i < lockhint->num_classes; i++)
1833  {
1834  fprintf (out_fp, "class_oid = %d|%d|%d, chn = %d, lock = %s, subclasses = %d\n", lockhint->classes[i].oid.volid,
1835  lockhint->classes[i].oid.pageid, lockhint->classes[i].oid.slotid, lockhint->classes[i].chn,
1836  LOCK_TO_LOCKMODE_STRING (lockhint->classes[i].lock), lockhint->classes[i].need_subclasses);
1837  }
1838 }
1839 
1840 /*
1841  * locator_dump_lockhint : dump a lockhint area
1842  *
1843  * return: nothing
1844  *
1845  * out_fp(in): output file
1846  * lockhint(in):Hintlock area to dump
1847  *
1848  * NOTE: Dump the information placed in lockhint area.
1849  * This function is used for DEBUGGING PURPOSES.
1850  */
1851 void
1852 locator_dump_lockhint (FILE * out_fp, LC_LOCKHINT * lockhint)
1853 {
1854  fprintf (out_fp, "\n***Dumping lockhint area***\n");
1855  locator_dump_lockhint_info (out_fp, lockhint);
1856 
1857  locator_dump_lockhint_classes (out_fp, lockhint);
1858 }
1859 #endif
1860 
1861 /*
1862  * locator_allocate_and_unpack_lockhint : allocate a lockhint area and unpack the given
1863  * area onto it
1864  *
1865  * return: LC_LOCKHINT * or NULL
1866  *
1867  * unpacked(in):Area to unpack
1868  * unpacked_size(in):Size of unpacked area
1869  * unpack_classes(in):whether to unpack classes
1870  * reg_unpacked(in):Whether the unpacked area is register as part of
1871  * lockhint area
1872  *
1873  * NOTE: Allocate a lockhint area. Then unpack the given area onto it.
1874  */
1875 LC_LOCKHINT *
1876 locator_allocate_and_unpack_lockhint (char *unpacked, int unpacked_size, bool unpack_classes, bool reg_unpacked)
1877 {
1878  int max_classes;
1879  char *ptr;
1880  LC_LOCKHINT *lockhint = NULL;
1881 
1882  ptr = unpacked;
1883  ptr = or_unpack_int (ptr, &max_classes);
1884 
1885  lockhint = locator_allocate_lockhint (max_classes, true);
1886  if (lockhint == NULL)
1887  {
1888  return NULL;
1889  }
1890 
1891  lockhint->packed = unpacked;
1892  lockhint->packed_size = unpacked_size;
1893 
1894  (void) locator_unpack_lockhint (lockhint, unpack_classes);
1895 
1896  if (reg_unpacked == false)
1897  {
1898  lockhint->packed = NULL;
1899  lockhint->packed_size = 0;
1900  }
1901 
1902  return lockhint;
1903 }
1904 
1905 /*
1906  * locator_pack_lockhint_header :
1907  *
1908  * return:
1909  *
1910  * packed(in):
1911  * lockhint(in/out):Hintlock area to pack
1912  *
1913  * NOTE:
1914  */
1915 static char *
1916 locator_pack_lockhint_header (char *packed, LC_LOCKHINT * lockhint)
1917 {
1918  packed = or_pack_int (packed, lockhint->max_classes);
1919  packed = or_pack_int (packed, lockhint->num_classes);
1920  packed = or_pack_int (packed, lockhint->num_classes_processed);
1921  packed = or_pack_int (packed, lockhint->quit_on_errors);
1922 
1923  return packed;
1924 }
1925 
1926 /*
1927  * locator_pack_lockhint_classes :
1928  *
1929  * return:
1930  *
1931  * packed(in):
1932  * lockhint(in/out):Hintlock area to pack
1933  *
1934  * NOTE:
1935  */
1936 static char *
1937 locator_pack_lockhint_classes (char *packed, LC_LOCKHINT * lockhint)
1938 {
1939  LC_LOCKHINT_CLASS *class_lockhint;
1940  int i;
1941 
1942  for (i = 0, class_lockhint = lockhint->classes; i < lockhint->num_classes; i++, class_lockhint++)
1943  {
1944  packed = or_pack_oid (packed, &class_lockhint->oid);
1945  packed = or_pack_int (packed, class_lockhint->chn);
1946  packed = or_pack_lock (packed, class_lockhint->lock);
1947  packed = or_pack_int (packed, class_lockhint->need_subclasses);
1948  }
1949 
1950  return packed;
1951 }
1952 
1953 /*
1954  * locator_pack_lockhint : pack to lockhint area
1955  *
1956  * return: number of bytes that were packed
1957  * lockhint packed fileds are set as a side effect.
1958  *
1959  * lockhint(in/out):Hintlock area to pack
1960  * pack_classes(in):whether to pack classes
1961  *
1962  * NOTE: Allocate an area to pack the lockhint area to be sent over
1963  * the network. The address and size of the packed area is left
1964  * on the lockhint area as a side effect. If there was an area
1965  * already present, it is used.
1966  * Then, the lockhint area is packed onto this area, the amount
1967  * of packing is returned.
1968  */
1969 int
1970 locator_pack_lockhint (LC_LOCKHINT * lockhint, bool pack_classes)
1971 {
1972  char *packed;
1973  int packed_size;
1974 
1975  packed_size = LC_LOCKHINT_PACKED_SIZE (lockhint);
1976 
1977  /*
1978  * Do we have space for packing ?
1979  */
1980 
1981  if (lockhint->packed != NULL)
1982  {
1983  /*
1984  * Reuse the current area
1985  */
1986  if (packed_size > lockhint->packed_size)
1987  {
1988  /*
1989  * We need to realloc this area
1990  */
1991  packed = locator_reallocate_packed (lockhint->packed, packed_size);
1992  if (packed == NULL)
1993  {
1994  return 0;
1995  }
1996 
1997  lockhint->packed = packed;
1998  lockhint->packed_size = packed_size;
1999  }
2000  packed = lockhint->packed;
2001  }
2002  else
2003  {
2004  packed = locator_allocate_packed (packed_size);
2005  if (packed == NULL)
2006  {
2007  return 0;
2008  }
2009 
2010  lockhint->packed = packed;
2011  lockhint->packed_size = packed_size;
2012  }
2013 
2014  packed = locator_pack_lockhint_header (packed, lockhint);
2015 
2016  if (pack_classes)
2017  {
2018  packed = locator_pack_lockhint_classes (packed, lockhint);
2019  }
2020 
2021  return CAST_BUFLEN (packed - lockhint->packed);
2022 }
2023 
2024 /*
2025  * locator_unpack_lockhint_header :
2026  *
2027  * return:
2028  *
2029  * unpacked(in):
2030  * lockhint(in/out):Hintlock area to pack
2031  *
2032  * NOTE:
2033  */
2034 static char *
2035 locator_unpack_lockhint_header (char *unpacked, LC_LOCKHINT * lockhint)
2036 {
2037  unpacked = or_unpack_int (unpacked, &lockhint->max_classes);
2038  unpacked = or_unpack_int (unpacked, &lockhint->num_classes);
2039  unpacked = or_unpack_int (unpacked, &lockhint->num_classes_processed);
2040  unpacked = or_unpack_int (unpacked, &lockhint->quit_on_errors);
2041 
2042  return unpacked;
2043 }
2044 
2045 /*
2046  * locator_unpack_lockhint_classes :
2047  *
2048  * return:
2049  *
2050  * packed(in):
2051  * lockhint(in/out):Hintlock area to pack
2052  *
2053  * NOTE:
2054  */
2055 static char *
2056 locator_unpack_lockhint_classes (char *unpacked, LC_LOCKHINT * lockhint)
2057 {
2058  LC_LOCKHINT_CLASS *class_lockhint;
2059  int i;
2060 
2061  for (i = 0, class_lockhint = lockhint->classes; i < lockhint->num_classes; i++, class_lockhint++)
2062  {
2063  unpacked = or_unpack_oid (unpacked, &class_lockhint->oid);
2064  unpacked = or_unpack_int (unpacked, &class_lockhint->chn);
2065  unpacked = or_unpack_lock (unpacked, &class_lockhint->lock);
2066  unpacked = or_unpack_int (unpacked, &class_lockhint->need_subclasses);
2067  }
2068 
2069  return unpacked;
2070 }
2071 
2072 /*
2073  * locator_unpack_lockhint : unpack a lockhint area
2074  *
2075  * return: number of bytes that were unpacked
2076  *
2077  * lockhint(in/out):Hintlock area to unpack (set as a side effect)
2078  * unpack_classes(in):whether to unpack classes
2079  *
2080  * NOTE: Unpack the lockhint area which was sent over the network.
2081  */
2082 int
2083 locator_unpack_lockhint (LC_LOCKHINT * lockhint, bool unpack_classes)
2084 {
2085  char *unpacked;
2086 
2087  unpacked = lockhint->packed;
2088 
2089  unpacked = locator_unpack_lockhint_header (unpacked, lockhint);
2090 
2091  if (unpack_classes)
2092  {
2093  unpacked = locator_unpack_lockhint_classes (unpacked, lockhint);
2094  }
2095 
2096  return CAST_BUFLEN (unpacked - lockhint->packed);
2097 }
2098 
2099 /*
2100  *
2101  * LC_OIDSET PACKING
2102  *
2103  */
2104 
2105 /*
2106  * locator_make_oid_set () -
2107  *
2108  * return: new oidset structure
2109  *
2110  * NOTE:
2111  * This creates a root LC_OIDSET structure, intended for incremental
2112  * population using locator_add_oid_set.
2113  * Free it with locator_free_oid_set when you're done.
2114  */
2115 LC_OIDSET *
2117 {
2118  LC_OIDSET *set;
2119 
2120  set = (LC_OIDSET *) db_private_alloc (NULL, sizeof (LC_OIDSET));
2121  if (set == NULL)
2122  {
2123  return NULL;
2124  }
2125 
2126  set->total_oids = 0;
2127  set->num_classes = 0;
2128  set->classes = NULL;
2129  set->is_list = true;
2130 
2131  return set;
2132 }
2133 
2134 /*
2135  * locator_clear_oid_set () -
2136  *
2137  * return: nothing
2138  *
2139  * oidset(in):oidset to clear
2140  *
2141  * NOTE:
2142  * Frees the entries inside an LC_OIDSET but leaves the outer structure
2143  * in place. This could be used in places where we build up a partial
2144  * oidset, flush it, and then fill it up again.
2145  * This is a little complicated as there are two different styles for
2146  * allocation. During incremental LC_OIDSET construction, we'll use
2147  * a linked list but the server will unpack it using arrays. This
2148  * style is maintained in an internal is_list flag in the appropriate
2149  * places.
2150  * This saves having to mess with growing arrays.
2151  */
2152 void
2154 {
2155  LC_CLASS_OIDSET *class_oidset, *c_next;
2156  LC_OIDMAP *oid, *o_next;
2157 
2158  if (oidset != NULL)
2159  {
2160  /* map over the classes */
2161  if (oidset->classes != NULL)
2162  {
2163 #if defined (SERVER_MODE)
2164  if (thread_p == NULL)
2165  {
2166  thread_p = thread_get_thread_entry_info ();
2167  }
2168 #endif // SERVER_MODE
2169 
2170  for (class_oidset = oidset->classes, c_next = NULL; class_oidset != NULL; class_oidset = c_next)
2171  {
2172  c_next = class_oidset->next;
2173 
2174  /* on the client, its important that we NULL out these pointers in case they happen to point to MOPs, we
2175  * don't want to leave GC roots lying around. */
2176  for (oid = class_oidset->oids; oid != NULL; oid = oid->next)
2177  {
2178  oid->mop = NULL;
2179  oid->client_data = NULL;
2180  }
2181 
2182  /* free either the list or array of OID map elements */
2183  if (!class_oidset->is_list)
2184  {
2185  db_private_free_and_init (thread_p, class_oidset->oids);
2186  }
2187  else
2188  {
2189  for (oid = class_oidset->oids, o_next = NULL; oid != NULL; oid = o_next)
2190  {
2191  o_next = oid->next;
2192  db_private_free_and_init (thread_p, oid);
2193  }
2194  }
2195  /* if we have a list of classes, free them as we go */
2196  if (oidset->is_list)
2197  {
2198  db_private_free_and_init (thread_p, class_oidset);
2199  }
2200  }
2201 
2202  /* if we have an array of classes, free it at the end */
2203  if (!oidset->is_list)
2204  {
2205  db_private_free_and_init (thread_p, oidset->classes);
2206  }
2207  }
2208 
2209  oidset->total_oids = 0;
2210  oidset->num_classes = 0;
2211  oidset->classes = NULL;
2212  oidset->is_list = true;
2213  }
2214 }
2215 
2216 /*
2217  * locator_free_oid_set () -
2218  *
2219  * return: nothing
2220  *
2221  * oidset(in):oidset to free
2222  *
2223  * NOTE:
2224  * Frees memory associated with an LC_OIDSET.
2225  */
2226 void
2228 {
2229  if (oidset != NULL)
2230  {
2231  locator_clear_oid_set (thread_p, oidset);
2232  db_private_free_and_init (thread_p, oidset);
2233  }
2234 }
2235 
2236 /*
2237  * locator_add_oid_set () -
2238  *
2239  * return: LC_OIDMAP* or NULL
2240  *
2241  * set(in):oidset to extend
2242  * heap(in):class heap id
2243  * class_oid(in):class OID
2244  * obj_oid(in):the currently temporary object OID
2245  *
2246  * NOTE:
2247  * Adds another temporary OID entry to an LC_OIDSET and returns
2248  * the internal LC_OIDMAP structure associated with that OID.
2249  * NULL is returned on error.
2250  *
2251  * This is normally called by the client with a temporary OID, we check
2252  * to make sure that the same temporary OID is not added twice.
2253  */
2254 LC_OIDMAP *
2255 locator_add_oid_set (THREAD_ENTRY * thread_p, LC_OIDSET * set, HFID * heap, OID * class_oid, OID * obj_oid)
2256 {
2257  LC_CLASS_OIDSET *class_oidset_p;
2258  LC_OIDMAP *oidmap_p;
2259 
2260  oidmap_p = NULL;
2261 
2262  /* sanity test, can't extend into fixed structures */
2263  if (set == NULL || !set->is_list)
2264  {
2265  /* can't have a temporary OID without a cached class */
2267  return NULL;
2268  }
2269 
2270  /* see if we already have an entry for this class */
2271  for (class_oidset_p = set->classes; class_oidset_p != NULL; class_oidset_p = class_oidset_p->next)
2272  {
2273  /* MOP comparison would be faster but makes the structre more complex */
2274  if (locator_is_hfid_equal (heap, &(class_oidset_p->hfid)))
2275  {
2276  break;
2277  }
2278  }
2279 
2280 #if defined (SERVER_MODE)
2281  if (thread_p == NULL)
2282  {
2283  thread_p = thread_get_thread_entry_info ();
2284  }
2285 #endif // SERVER_MODE
2286 
2287  if (class_oidset_p == NULL)
2288  {
2289  /* haven't seen this class yet, add a new entry */
2290  class_oidset_p = (LC_CLASS_OIDSET *) db_private_alloc (thread_p, sizeof (LC_CLASS_OIDSET));
2291  if (class_oidset_p == NULL)
2292  {
2293  return NULL;
2294  }
2295  oidmap_p = (LC_OIDMAP *) db_private_alloc (thread_p, sizeof (LC_OIDMAP));
2296  if (oidmap_p == NULL)
2297  {
2298  db_private_free_and_init (thread_p, class_oidset_p);
2299  return NULL;
2300  }
2301 
2302  oidmap_p->next = NULL;
2303  oidmap_p->oid = *obj_oid;
2304  oidmap_p->est_size = 0;
2305  oidmap_p->mop = NULL;
2306  oidmap_p->client_data = NULL;
2307 
2308  class_oidset_p->class_oid = *class_oid;
2309  class_oidset_p->hfid = *heap;
2310  class_oidset_p->is_list = true;
2311  class_oidset_p->oids = oidmap_p;
2312  class_oidset_p->num_oids = 1;
2313  class_oidset_p->next = set->classes;
2314  set->classes = class_oidset_p;
2315  set->num_classes++;
2316  set->total_oids++;
2317  }
2318  else
2319  {
2320  /* already have a list for this class, add another object if we don't have one already */
2321  for (oidmap_p = class_oidset_p->oids; oidmap_p != NULL; oidmap_p = oidmap_p->next)
2322  {
2323  if (OID_EQ (&oidmap_p->oid, obj_oid))
2324  {
2325  break;
2326  }
2327  }
2328  if (oidmap_p == NULL)
2329  {
2330  /* never seen this particular temp oid, add another entry */
2331  oidmap_p = (LC_OIDMAP *) db_private_alloc (thread_p, sizeof (LC_OIDMAP));
2332  if (oidmap_p == NULL)
2333  {
2334  return NULL;
2335  }
2336  oidmap_p->next = class_oidset_p->oids;
2337  class_oidset_p->oids = oidmap_p;
2338  oidmap_p->oid = *obj_oid;
2339  oidmap_p->est_size = 0;
2340  oidmap_p->mop = NULL;
2341  oidmap_p->client_data = NULL;
2342  class_oidset_p->num_oids++;
2343  set->total_oids++;
2344  }
2345  }
2346 
2347  return oidmap_p;
2348 }
2349 
2350 /*
2351  * locator_get_packed_oid_set_size () -
2352  *
2353  * return: packed size
2354  *
2355  * oidset(in):oidset to ponder
2356  *
2357  * Note:
2358  * Returns the number of bytes it would take to create the packed
2359  * representation of an LC_OIDSET as would be produced by
2360  * locator_pack_oid_set.
2361  */
2362 int
2364 {
2365  LC_CLASS_OIDSET *class_oidset;
2366  int size, count;
2367 
2368  size = OR_INT_SIZE; /* number of classes */
2369  for (class_oidset = oidset->classes, count = 0; class_oidset != NULL; class_oidset = class_oidset->next, count++)
2370  {
2371  size += OR_OID_SIZE;
2372  size += OR_HFID_SIZE;
2373  size += OR_INT_SIZE;
2374  size += class_oidset->num_oids * (OR_OID_SIZE + OR_INT_SIZE);
2375  }
2376 
2377  /* sanity check on count, should set an error or something */
2378  if (count != oidset->num_classes)
2379  {
2380  oidset->num_classes = count;
2381  }
2382 
2383  return size;
2384 }
2385 
2386 /*
2387  * locator_pack_oid_set () -
2388  *
2389  * return: advanced pointer
2390  *
2391  * buffer(in):buffer in which to pack
2392  * oidset(in):oidset to pack
2393  *
2394  * NOTE:
2395  * Packs the flattened representation of an oidset into a buffer.
2396  * The buffer must be of an appropriate size, you should always call
2397  * locator_get_packed_oid_set_size first.
2398  */
2399 char *
2400 locator_pack_oid_set (char *buffer, LC_OIDSET * oidset)
2401 {
2402  LC_CLASS_OIDSET *class_oidset;
2403  LC_OIDMAP *oid;
2404 
2405  buffer = or_pack_int (buffer, oidset->num_classes);
2406  for (class_oidset = oidset->classes; class_oidset != NULL; class_oidset = class_oidset->next)
2407  {
2408  buffer = or_pack_oid (buffer, &class_oidset->class_oid);
2409  buffer = or_pack_hfid (buffer, &class_oidset->hfid);
2410  buffer = or_pack_int (buffer, class_oidset->num_oids);
2411 
2412  for (oid = class_oidset->oids; oid != NULL; oid = oid->next)
2413  {
2414  buffer = or_pack_oid (buffer, &oid->oid);
2415  buffer = or_pack_int (buffer, oid->est_size);
2416  }
2417  }
2418  return buffer;
2419 }
2420 
2421 /*
2422  * locator_unpack_oid_set () -
2423  *
2424  * return: unpacked oidset
2425  *
2426  * buffer(in):buffer containing packed representation
2427  * use(in):existing oidset structure to unpack into
2428  *
2429  * NOTE:
2430  * This unpacks the packed representation of an oidset and either updates
2431  * an existing structure or creates and returns a new one.
2432  * If an existing structure is supplied, it MUST be of exactly the same
2433  * format as the one used to create the packed representation.
2434  * This is intended for use on the client after it has sent an oidset
2435  * over to the server for the permanent OID's to be assigned. The
2436  * thing we get back will be identical with only changes to the packed
2437  * OIDs so we don't have to waste time allocating a new structure, we
2438  * can just unpack into the existing structure.
2439  *
2440  * If we're on the server side, we won't have a "use" structure so we
2441  * just allocate a new one. Note that the server uses arrays for
2442  * the class & oidmap lists rather than linked lists.
2443  */
2444 bool
2446 {
2447  LC_CLASS_OIDSET *class_oidset;
2448  LC_OIDMAP *oid;
2449  LC_OIDSET *set = NULL;
2450  int c, o;
2451  char *ptr;
2452 
2453  ptr = buffer;
2454 
2455  if (use == NULL)
2456  {
2457  return false;
2458  }
2459 
2460  set = use;
2461  /* unpack into an existing structure, it better be large enough */
2462  ptr = or_unpack_int (ptr, &c);
2463  if (c != set->num_classes)
2464  {
2465  goto use_error;
2466  }
2467 
2468  for (class_oidset = set->classes; class_oidset != NULL; class_oidset = class_oidset->next)
2469  {
2470  /* skip these, could check for consistency */
2471  ptr += OR_OID_SIZE;
2472  ptr += OR_HFID_SIZE;
2473  ptr = or_unpack_int (ptr, &o);
2474  if (o != class_oidset->num_oids)
2475  {
2476  goto use_error;
2477  }
2478 
2479  for (oid = class_oidset->oids; oid != NULL; oid = oid->next)
2480  {
2481  /* this is what we came for */
2482  ptr = or_unpack_oid (ptr, &oid->oid);
2483  /* can skip this */
2484  ptr += OR_INT_SIZE;
2485  /* note that we must leave mop & client_data fields untouched !! */
2486  }
2487  }
2488 
2489  /* success */
2490  return true;
2491 
2492 use_error:
2493  /* need something appropriate */
2495  return false;
2496 }
2497 
2498 LC_OIDSET *
2500 {
2501  LC_CLASS_OIDSET *class_oidset;
2502  LC_OIDMAP *oid;
2503  LC_OIDSET *set;
2504  int c, o, total;
2505  char *ptr;
2506 
2507  ptr = buffer;
2508 
2509 #if defined (SERVER_MODE)
2510  if (thread_p == NULL)
2511  {
2512  thread_p = thread_get_thread_entry_info ();
2513  }
2514 #endif // SERVER_MODE
2515 
2516  /* we have to unpack and build a new structure, use arrays */
2517  set = (LC_OIDSET *) db_private_alloc (thread_p, sizeof (LC_OIDSET));
2518  if (set == NULL)
2519  {
2520  goto memory_error;
2521  }
2522 
2523  total = 0;
2524  ptr = or_unpack_int (ptr, &set->num_classes);
2525  if (!set->num_classes)
2526  {
2527  set->classes = NULL;
2528  }
2529  else
2530  {
2531  set->classes = (LC_CLASS_OIDSET *) db_private_alloc (thread_p, sizeof (LC_CLASS_OIDSET) * set->num_classes);
2532  if (set->classes == NULL)
2533  {
2534  goto memory_error;
2535  }
2536  set->is_list = false;
2537 
2538  /* initialize things so we can cleanup easier */
2539  for (c = 0, class_oidset = set->classes; c < set->num_classes; c++, class_oidset++)
2540  {
2541  if (c == set->num_classes - 1)
2542  {
2543  class_oidset->next = NULL;
2544  }
2545  else
2546  {
2547  class_oidset->next = class_oidset + 1;
2548  }
2549  class_oidset->oids = NULL;
2550  }
2551 
2552  /* load the class data */
2553  for (c = 0, class_oidset = set->classes; c < set->num_classes; c++, class_oidset++)
2554  {
2555  ptr = or_unpack_oid (ptr, &class_oidset->class_oid);
2556  ptr = or_unpack_hfid (ptr, &class_oidset->hfid);
2557  ptr = or_unpack_int (ptr, &class_oidset->num_oids);
2558 
2559  class_oidset->oids = (LC_OIDMAP *) db_private_alloc (thread_p, sizeof (LC_OIDMAP) * class_oidset->num_oids);
2560  if (class_oidset->oids == NULL)
2561  {
2562  goto memory_error;
2563  }
2564  class_oidset->is_list = false;
2565 
2566  /* load the oid data */
2567  for (o = 0, oid = class_oidset->oids; o < class_oidset->num_oids; o++, oid++)
2568  {
2569  if (o == class_oidset->num_oids - 1)
2570  {
2571  oid->next = NULL;
2572  }
2573  else
2574  {
2575  oid->next = oid + 1;
2576  }
2577  ptr = or_unpack_oid (ptr, &oid->oid);
2578  ptr = or_unpack_int (ptr, &oid->est_size);
2579  oid->mop = NULL;
2580  oid->client_data = NULL;
2581  total++;
2582  }
2583  }
2584  set->total_oids = total;
2585  }
2586 
2587  /* success */
2588  return set;
2589 
2590 memory_error:
2591  locator_free_oid_set (thread_p, set);
2592 
2593  return NULL;
2594 }
2595 
2596 bool
2598 {
2599  return copyarea->multi_update_flags & muf;
2600 }
2601 
2602 void
2604 {
2605  assert (locator_manyobj_flag_is_set (copyarea, muf));
2606  copyarea->multi_update_flags &= (~muf);
2607 }
2608 
2609 void
2611 {
2612  copyarea->multi_update_flags |= muf;
2613 }
char * locator_pack_oid_set(char *buffer, LC_OIDSET *oidset)
Definition: locator.c:2400
#define LC_LOCKSET_PACKED_SIZE(req)
Definition: locator.h:84
struct lc_copy_area LC_COPYAREA
Definition: locator.h:244
char * or_unpack_oid(char *ptr, OID *oid)
LC_LOCKSET_CLASSOF * classes
Definition: locator.h:303
cubthread::entry * thread_get_thread_entry_info(void)
#define NO_ERROR
Definition: error_code.h:46
#define IO_PAGESIZE
static LOCATOR_GLOBAL locator_Keep
Definition: locator.c:103
LC_LOCKHINT * locator_reallocate_lockhint(LC_LOCKHINT *lockhint, int max_classes)
Definition: locator.c:1731
int locator_get_packed_oid_set_size(LC_OIDSET *oidset)
Definition: locator.c:2363
void locator_free_copy_area(LC_COPYAREA *copyarea)
Definition: locator.c:534
PAGEID DKNPAGES
static char * locator_pack_lockhint_header(char *packed, LC_LOCKHINT *lockhint)
Definition: locator.c:1916
LC_LOCKHINT * locator_allocate_and_unpack_lockhint(char *unpacked, int unpacked_size, bool unpack_classes, bool reg_unpacked)
Definition: locator.c:1876
#define ER_FAILED
Definition: error_code.h:47
#define LC_START_ONEOBJ_PTR_IN_COPYAREA(manyobjs_ptr)
Definition: locator.h:44
char * packed
Definition: locator.h:328
char * locator_unpack_copy_area_descriptor(int num_objs, LC_COPYAREA *copyarea, char *desc)
Definition: locator.c:619
void locator_manyobj_flag_set(LC_COPYAREA_MANYOBJS *copyarea, enum MULTI_UPDATE_FLAG muf)
Definition: locator.c:2610
LC_COPYAREA * locator_reallocate_copy_area_by_length(LC_COPYAREA *old_area, int new_length)
Definition: locator.c:467
char * mem
Definition: locator.h:247
#define OR_HFID_SIZE
char * packed
Definition: locator.h:302
int num_classes_processed
Definition: locator.h:325
int est_size
Definition: locator.h:353
#define LC_FIND_ONEOBJ_PTR_IN_COPYAREA(manyobjs_ptr, obj_num)
Definition: locator.h:51
void locator_free_areas(void)
Definition: locator.c:206
void locator_clear_oid_set(THREAD_ENTRY *thread_p, LC_OIDSET *oidset)
Definition: locator.c:2153
void locator_free_lockhint(LC_LOCKHINT *lockhint)
Definition: locator.c:1765
#define MEM_REGION_SCRAMBLE(region, size)
Definition: memory_alloc.h:113
#define LC_LOCKHINT_PACKED_SIZE(lockhint)
Definition: locator.h:91
INT32 hpgid
#define pthread_mutex_unlock(a)
Definition: locator.c:50
LC_LOCKSET_REQOBJ * objects
Definition: locator.h:305
char * or_pack_oid(char *ptr, const OID *oid)
LC_LOCKHINT * areas[LOCATOR_NKEEP_LIMIT]
Definition: locator.c:87
#define pthread_mutex_lock(a)
Definition: locator.c:49
static char * locator_reallocate_packed(char *packed, int packed_size)
Definition: locator.c:332
void locator_free_lockset(LC_LOCKSET *lockset)
Definition: locator.c:1140
static LC_COPYAREA packed_req_area_ptrs[LOCATOR_NKEEP_LIMIT]
Definition: locator.c:105
static char * locator_unpack_lockset_classes(char *unpacked, LC_LOCKSET *lockset)
Definition: locator.c:1536
#define LC_AREA_ONEOBJ_PACKED_SIZE
Definition: locator.h:35
#define MAX_ALIGNMENT
Definition: memory_alloc.h:70
int packed_size
Definition: locator.h:327
LC_OIDMAP * locator_add_oid_set(THREAD_ENTRY *thread_p, LC_OIDSET *set, HFID *heap, OID *class_oid, OID *obj_oid)
Definition: locator.c:2255
int length
Definition: locator.h:248
LOCK reqobj_inst_lock
Definition: locator.h:292
static int locator_initialize_lockhint(LC_LOCKHINT *lockhint, int length, int max_classes, bool quit_on_errors)
Definition: locator.c:1697
LC_CLASS_OIDSET * classes
Definition: locator.h:386
LC_LOCKHINT * locator_allocate_lockhint(int max_classes, bool quit_on_errors)
Definition: locator.c:1629
void THREAD_ENTRY
char * mem
Definition: locator.h:281
static bool locator_is_hfid_equal(HFID *hfid1_p, HFID *hfid2_p)
Definition: locator.c:152
LOCK
void er_set(int severity, const char *file_name, const int line_no, int err_id, int num_args,...)
char * or_pack_hfid(const char *ptr, const HFID *hfid)
void locator_manyobj_flag_remove(LC_COPYAREA_MANYOBJS *copyarea, enum MULTI_UPDATE_FLAG muf)
Definition: locator.c:2603
static char * locator_pack_lockhint_classes(char *packed, LC_LOCKHINT *lockhint)
Definition: locator.c:1937
#define assert(x)
static char * locator_pack_lockset_classes(char *packed, LC_LOCKSET *lockset)
Definition: locator.c:1371
int32_t fileid
Definition: dbtype_def.h:886
int quit_on_errors
Definition: locator.h:326
#define ER_GENERIC_ERROR
Definition: error_code.h:49
MULTI_UPDATE_FLAG
Definition: locator.h:228
struct lc_copyarea_manyobjs LC_COPYAREA_MANYOBJS
Definition: locator.h:235
struct locator_global::locator_global_copyareas copy_areas
#define ER_OUT_OF_VIRTUAL_MEMORY
Definition: error_code.h:50
char * or_unpack_hfid(char *ptr, HFID *hfid)
char * or_unpack_lock(char *ptr, LOCK *lock)
LC_COPYAREA * locator_allocate_copy_area_by_length(int min_length)
Definition: locator.c:407
#define pthread_mutex_destroy(a)
Definition: locator.c:48
static void locator_free_packed(char *packed_area, int packed_size)
Definition: locator.c:348
LC_LOCKSET * locator_allocate_and_unpack_lockset(char *unpacked, int unpacked_size, bool unpack_classes, bool unpack_objects, bool reg_unpacked)
Definition: locator.c:1302
int length
Definition: locator.h:322
bool first_fetch_lockhint_call
Definition: locator.h:331
static char * locator_pack_lockset_objects(char *packed, LC_LOCKSET *lockset)
Definition: locator.c:1396
static char * locator_unpack_lockhint_header(char *unpacked, LC_LOCKHINT *lockhint)
Definition: locator.c:2035
#define OID_EQ(oidp1, oidp2)
Definition: oid.h:92
LC_LOCKSET * areas[LOCATOR_NKEEP_LIMIT]
Definition: locator.c:78
LC_COPYAREA * areas[LOCATOR_NKEEP_LIMIT]
Definition: locator.c:69
int last_reqobj_cached
Definition: locator.h:290
VFID vfid
void locator_initialize_areas(void)
Definition: locator.c:166
static char * locator_unpack_lockhint_classes(char *unpacked, LC_LOCKHINT *lockhint)
Definition: locator.c:2056
#define LOCK_TO_LOCKMODE_STRING(lock)
LC_COPYAREA * areas[LOCATOR_NKEEP_LIMIT]
Definition: locator.c:96
#define NULL
Definition: freelistheap.h:34
struct lc_oidmap * next
Definition: locator.h:346
#define pthread_mutex_init(a, b)
Definition: locator.c:47
bool locator_unpack_oid_set_to_exist(char *buffer, LC_OIDSET *use)
Definition: locator.c:2445
void * client_data
Definition: locator.h:350
PGLENGTH db_network_page_size(void)
char * mem
Definition: locator.h:321
#define LC_NEXT_ONEOBJ_PTR_IN_COPYAREA(oneobj_ptr)
Definition: locator.h:48
struct lc_class_oidset * next
Definition: locator.h:365
#define db_private_free_and_init(thrd, ptr)
Definition: memory_alloc.h:141
LC_OIDSET * locator_make_oid_set(void)
Definition: locator.c:2116
char * or_unpack_int(char *ptr, int *number)
#define db_private_alloc(thrd, size)
Definition: memory_alloc.h:227
int count(int &result, const cub_regex_object &reg, const std::string &src, const int position, const INTL_CODESET codeset)
int max_classes
Definition: locator.h:323
void locator_free_oid_set(THREAD_ENTRY *thread_p, LC_OIDSET *oidset)
Definition: locator.c:2227
LC_OIDMAP * oids
Definition: locator.h:366
int total_oids
Definition: locator.h:384
int num_reqobjs
Definition: locator.h:287
LC_COPYAREA * locator_recv_allocate_copyarea(int num_objs, char **packed_desc, int packed_desc_length, char **contents_ptr, int contents_length)
Definition: locator.c:755
int num_classes
Definition: locator.h:385
#define CAST_BUFLEN
Definition: porting.h:471
#define LC_COPY_ONEOBJ(new_obj, old_obj)
Definition: locator.h:95
char * or_pack_int(char *ptr, int number)
bool is_list
Definition: locator.h:389
bool locator_manyobj_flag_is_set(LC_COPYAREA_MANYOBJS *copyarea, enum MULTI_UPDATE_FLAG muf)
Definition: locator.c:2597
int quit_on_errors
Definition: locator.h:300
LC_COPYAREA_OPERATION
Definition: locator.h:106
#define ARG_FILE_LINE
Definition: error_manager.h:44
struct locator_global::locator_global_lockset_areas lockset_areas
int locator_pack_lockhint(LC_LOCKHINT *lockhint, bool pack_classes)
Definition: locator.c:1970
#define LOCATOR_CACHED_COPYAREA_SIZE_LIMIT
Definition: locator.c:60
int max_reqobjs
Definition: locator.h:286
int length
Definition: locator.h:283
struct locator_global::locator_global_packed_areas packed_areas
static char * locator_allocate_packed(int packed_size)
Definition: locator.c:276
#define free_and_init(ptr)
Definition: memory_alloc.h:147
#define DB_ALIGN(offset, align)
Definition: memory_alloc.h:84
char * or_pack_lock(char *ptr, LOCK lock)
static int locator_initialize_lockset(LC_LOCKSET *lockset, int length, int max_reqobjs, LOCK reqobj_inst_lock, LOCK reqobj_class_lock, int quit_on_errors)
Definition: locator.c:1027
#define LC_MANYOBJS_PTR_IN_COPYAREA(copy_areaptr)
Definition: locator.h:39
OID oid
Definition: locator.h:352
#define LOCATOR_NKEEP_LIMIT
Definition: locator.c:57
static int rv
Definition: locator.c:51
char * locator_pack_copy_area_descriptor(int num_objs, LC_COPYAREA *copyarea, char *desc, int desc_len)
Definition: locator.c:577
int i
Definition: dynamic_load.c:954
LC_LOCKSET * locator_reallocate_lockset(LC_LOCKSET *lockset, int max_reqobjs)
Definition: locator.c:1091
void * mop
Definition: locator.h:349
int packed_size
Definition: locator.h:301
int locator_unpack_lockset(LC_LOCKSET *lockset, bool unpack_classes, bool unpack_objects)
Definition: locator.c:1588
int num_classes_of_reqobjs_processed
Definition: locator.h:297
static bool locator_Is_initialized
Definition: locator.c:107
struct locator_global::locator_global_lockhint_areas lockhint_areas
short volid
Definition: dbtype_def.h:887
LC_OIDSET * locator_unpack_oid_set_to_new(THREAD_ENTRY *thread_p, char *buffer)
Definition: locator.c:2499
int num_classes_of_reqobjs
Definition: locator.h:296
LOCK reqobj_class_lock
Definition: locator.h:293
int num_reqobjs_processed
Definition: locator.h:289
static char * locator_pack_lockset_header(char *packed, LC_LOCKSET *lockset)
Definition: locator.c:1345
LC_LOCKSET * locator_allocate_lockset(int max_reqobjs, LOCK reqobj_inst_lock, LOCK reqobj_class_lock, int quit_on_errors)
Definition: locator.c:955
static char * locator_unpack_lockset_header(char *unpacked, LC_LOCKSET *lockset)
Definition: locator.c:1507
bool first_fetch_lockset_call
Definition: locator.h:306
int num_classes
Definition: locator.h:324
LC_COPYAREA_ONEOBJ objs
Definition: locator.h:238
LC_COPYAREA_OPERATION operation
Definition: locator.h:219
int locator_unpack_lockhint(LC_LOCKHINT *lockhint, bool unpack_classes)
Definition: locator.c:2083
int last_classof_reqobjs_cached
Definition: locator.h:298
LC_LOCKHINT_CLASS * classes
Definition: locator.h:329
int locator_pack_lockset(LC_LOCKSET *lockset, bool pack_classes, bool pack_objects)
Definition: locator.c:1429
int locator_send_copy_area(LC_COPYAREA *copyarea, char **contents_ptr, int *contents_length, char **desc_ptr, int *desc_length)
Definition: locator.c:664
static char * locator_unpack_lockset_objects(char *unpacked, LC_LOCKSET *lockset)
Definition: locator.c:1561