MySQL 5.6.14 Source Code Document
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
LongSignal.cpp
1 /* Copyright 2008, 2009 Sun Microsystems, Inc.
2  All rights reserved. Use is subject to license terms.
3 
4  This program is free software; you can redistribute it and/or modify
5  it under the terms of the GNU General Public License as published by
6  the Free Software Foundation; version 2 of the License.
7 
8  This program is distributed in the hope that it will be useful,
9  but WITHOUT ANY WARRANTY; without even the implied warranty of
10  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11  GNU General Public License for more details.
12 
13  You should have received a copy of the GNU General Public License
14  along with this program; if not, write to the Free Software
15  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */
16 
17 #include "LongSignal.hpp"
18 #include "LongSignalImpl.hpp"
19 
25 bool
26 verifySection(Uint32 firstIVal, SectionSegmentPool& thePool)
27 {
28  if (firstIVal == RNIL)
29  return true;
30 
31  /* Get first section ptr (With assertions in getPtr) */
32  SectionSegment* first= thePool.getPtr(firstIVal);
33 
34  assert(first != NULL);
35  Uint32 totalSize= first->m_sz;
36  Uint32 lastSegIVal= first->m_lastSegment;
37 
38  /* Hmm, need to be careful of length == 0
39  * Nature abhors a segmented section with length 0
40  */
41  //assert(totalSize != 0);
42  assert(lastSegIVal != RNIL); /* Should never be == RNIL */
43  /* We ignore m_ownerRef */
44 
45  if (totalSize <= SectionSegment::DataLength)
46  {
47  /* 1 segment */
48  assert(first->m_lastSegment == firstIVal);
49  // m_nextSegment not always set to RNIL on last segment
50  //assert(first->m_nextSegment == RNIL);
51  }
52  else
53  {
54  /* > 1 segment */
55  assert(first->m_nextSegment != RNIL);
56  assert(first->m_lastSegment != firstIVal);
57  Uint32 currIVal= firstIVal;
58  SectionSegment* curr= first;
59 
60  /* Traverse segments to where we think the end should be */
61  while (totalSize > SectionSegment::DataLength)
62  {
63  currIVal= curr->m_nextSegment;
64  curr= thePool.getPtr(currIVal);
65  totalSize-= SectionSegment::DataLength;
66  /* Ignore m_ownerRef, m_sz, m_lastSegment of intermediate
67  * Segments
68  */
69  }
70 
71  /* Once we are here, we are on the last Segment of this Section
72  * Check that last segment is as stated in the first segment
73  */
74  assert(currIVal == lastSegIVal);
75  // m_nextSegment not always set properly on last segment
76  //assert(curr->m_nextSegment == RNIL);
77  /* Ignore m_ownerRef, m_sz, m_lastSegment of last segment */
78  }
79 
80  return true;
81 }
82 
83 void
84 copy(Uint32 * & insertPtr,
85  class SectionSegmentPool & thePool, const SegmentedSectionPtr & _ptr){
86 
87  Uint32 len = _ptr.sz;
88  SectionSegment * ptrP = _ptr.p;
89 
90  assert(verifySection(_ptr.i, thePool));
91 
92  while(len > 60){
93  memcpy(insertPtr, &ptrP->theData[0], 4 * 60);
94  len -= 60;
95  insertPtr += 60;
96  ptrP = thePool.getPtr(ptrP->m_nextSegment);
97  }
98  memcpy(insertPtr, &ptrP->theData[0], 4 * len);
99  insertPtr += len;
100 }
101 
102 void
103 copy(Uint32 * dst, SegmentedSectionPtr src){
104  copy(dst, g_sectionSegmentPool, src);
105 }
106 
107 /* Copy variant which takes an IVal */
108 void
109 copy(Uint32* dst, Uint32 srcFirstIVal)
110 {
112  getSection(p, srcFirstIVal);
113 
114  copy(dst, p);
115 }
116 
117 void
118 print(SectionSegment * s, Uint32 len, FILE* out){
119  for(Uint32 i = 0; i<len; i++){
120  fprintf(out, "H\'0x%.8x ", s->theData[i]);
121  if(((i + 1) % 6) == 0)
122  fprintf(out, "\n");
123  }
124 }
125 
126 void
127 print(SegmentedSectionPtr ptr, FILE* out){
128 
129  ptr.p = g_sectionSegmentPool.getPtr(ptr.i);
130  Uint32 len = ptr.p->m_sz;
131 
132  fprintf(out, "ptr.i = %d(%p) ptr.sz = %d(%d)\n", ptr.i, ptr.p, len, ptr.sz);
133  while(len > SectionSegment::DataLength){
134  print(ptr.p, SectionSegment::DataLength, out);
135 
136  len -= SectionSegment::DataLength;
137  fprintf(out, "ptr.i = %d\n", ptr.p->m_nextSegment);
138  ptr.p = g_sectionSegmentPool.getPtr(ptr.p->m_nextSegment);
139  }
140 
141  print(ptr.p, len, out);
142  fprintf(out, "\n");
143 }
144 
145 bool
146 dupSection(SPC_ARG Uint32& copyFirstIVal, Uint32 srcFirstIVal)
147 {
148  assert(verifySection(srcFirstIVal));
149 
150  SectionSegment* p= g_sectionSegmentPool.getPtr(srcFirstIVal);
151  Uint32 sz= p->m_sz;
152  copyFirstIVal= RNIL;
153  bool ok= true;
154 
155  /* Duplicate bulk of section */
156  while (sz > SectionSegment::DataLength)
157  {
158  ok= appendToSection(SPC_CACHE_ARG copyFirstIVal, &p->theData[0],
159  SectionSegment::DataLength);
160  if (!ok)
161  break;
162 
163  sz-= SectionSegment::DataLength;
164  srcFirstIVal= p->m_nextSegment;
165  p= g_sectionSegmentPool.getPtr(srcFirstIVal);
166  }
167 
168  /* Duplicate last segment */
169  if (ok && (sz > 0))
170  ok= appendToSection(SPC_CACHE_ARG copyFirstIVal, &p->theData[0], sz);
171 
172  if (unlikely(!ok))
173  {
174  releaseSection(SPC_CACHE_ARG copyFirstIVal);
175  copyFirstIVal= RNIL;
176  return false;
177  }
178 
179  assert(verifySection(copyFirstIVal));
180  return true;
181 }
182 
183 bool ErrorImportActive = false;
184 extern int ErrorSignalReceive;
185 extern int ErrorMaxSegmentsToSeize;
186 
206 bool
207 appendToSection(SPC_ARG Uint32& firstSegmentIVal, const Uint32* src, Uint32 len)
208 {
209  Ptr<SectionSegment> firstPtr, currPtr;
210 
211  if (len == 0)
212  return true;
213 
214  Uint32 remain= SectionSegment::DataLength;
215  Uint32 segmentLen= 0;
216 
217  if (firstSegmentIVal == RNIL)
218  {
219 #ifdef ERROR_INSERT
220  /* Simulate running out of segments */
221  if (ErrorImportActive)
222  {
223  if ((ErrorSignalReceive == 1) &&
224  (ErrorMaxSegmentsToSeize == 0))
225  {
226  ndbout_c("append exhausted on first segment");
227  return false;
228  }
229  }
230 #endif
231  /* First data to be added to this section */
232  bool result= g_sectionSegmentPool.seize(SPC_SEIZE_ARG firstPtr);
233 
234  if (!result)
235  return false;
236 
237  firstPtr.p->m_sz= 0;
238  firstPtr.p->m_ownerRef= 0;
239  firstSegmentIVal= firstPtr.i;
240 
241  currPtr= firstPtr;
242  }
243  else
244  {
245  /* Section has at least one segment with data already */
246  g_sectionSegmentPool.getPtr(firstPtr, firstSegmentIVal);
247  g_sectionSegmentPool.getPtr(currPtr, firstPtr.p->m_lastSegment);
248 
249  Uint32 existingLen= firstPtr.p->m_sz;
250  assert(existingLen > 0);
251  segmentLen= existingLen % SectionSegment::DataLength;
252 
253  /* If existingLen % SectionSegment::DataLength == 0
254  * we assume that the last segment is full
255  */
256  segmentLen= segmentLen == 0 ?
257  SectionSegment::DataLength :
258  segmentLen;
259 
260  remain= SectionSegment::DataLength - segmentLen;
261  }
262 
263  firstPtr.p->m_sz+= len;
264 
265 #ifdef ERROR_INSERT
266  Uint32 remainSegs= (Uint32) ErrorMaxSegmentsToSeize - 1;
267 #endif
268 
269  while(len > remain) {
270  /* Fill this segment, and link in another one
271  * Note that we can memcpy to a bad address with size 0
272  */
273  memcpy(&currPtr.p->theData[segmentLen], src, remain << 2);
274  src += remain;
275  len -= remain;
276  Ptr<SectionSegment> prevPtr= currPtr;
277 
278 #ifdef ERROR_INSERT
279  /* Simulate running out of segments */
280  if (ErrorImportActive)
281  {
282  if ((ErrorSignalReceive == 1) &&
283  (0 == remainSegs--))
284  {
285  ndbout_c("Append exhausted on segment %d", ErrorMaxSegmentsToSeize);
286  firstPtr.p->m_lastSegment= prevPtr.i;
287  firstPtr.p->m_sz-= len;
288  return false;
289  }
290  }
291 #endif
292  bool result = g_sectionSegmentPool.seize(SPC_SEIZE_ARG currPtr);
293  if (!result)
294  {
295  /* Failed, ensure segment list is consistent for
296  * freeing later
297  */
298  firstPtr.p->m_lastSegment= prevPtr.i;
299  firstPtr.p->m_sz-= len;
300  return false;
301  }
302  prevPtr.p->m_nextSegment = currPtr.i;
303  currPtr.p->m_sz= 0;
304  currPtr.p->m_ownerRef= 0;
305 
306  segmentLen= 0;
307  remain= SectionSegment::DataLength;
308  }
309 
310  /* Data fits in the current last segment */
311  firstPtr.p->m_lastSegment= currPtr.i;
312  currPtr.p->m_nextSegment= RNIL;
313  memcpy(&currPtr.p->theData[segmentLen], src, len << 2);
314 
315  return true;
316 }
317 
318 bool
319 import(SPC_ARG Ptr<SectionSegment> & first, const Uint32 * src, Uint32 len){
320 
321 #ifdef ERROR_INSERT
322  /* Simulate running out of segments */
323  if (ErrorImportActive)
324  {
325  if ((ErrorSignalReceive == 1) &&
326  (ErrorMaxSegmentsToSeize == 0))
327  {
328  ndbout_c("Import exhausted on first segment");
329  return false;
330  }
331  }
332 #endif
333 
334  first.p = 0;
335  if(g_sectionSegmentPool.seize(SPC_SEIZE_ARG first)){
336  ;
337  } else {
338  ndbout_c("No Segmented Sections for import");
339  return false;
340  }
341 
342  first.p->m_sz = len;
343  first.p->m_ownerRef = 0;
344 
345  Ptr<SectionSegment> currPtr = first;
346 
347 #ifdef ERROR_INSERT
348  Uint32 remainSegs= (Uint32) ErrorMaxSegmentsToSeize - 1;
349 #endif
350 
351  while(len > SectionSegment::DataLength){
352  memcpy(&currPtr.p->theData[0], src, 4 * SectionSegment::DataLength);
353  src += SectionSegment::DataLength;
354  len -= SectionSegment::DataLength;
355  Ptr<SectionSegment> prevPtr = currPtr;
356 
357 #ifdef ERROR_INSERT
358  /* Simulate running out of segments */
359  if (ErrorImportActive)
360  {
361  if ((ErrorSignalReceive == 1) &&
362  (0 == remainSegs--))
363  {
364  ndbout_c("Import exhausted on segment %d",
365  ErrorMaxSegmentsToSeize);
366  first.p->m_lastSegment= prevPtr.i;
367  first.p->m_sz-= len;
368  prevPtr.p->m_nextSegment = RNIL;
369  return false;
370  }
371  }
372 #endif
373 
374  if(g_sectionSegmentPool.seize(SPC_SEIZE_ARG currPtr)){
375  prevPtr.p->m_nextSegment = currPtr.i;
376  ;
377  } else {
378  /* Leave segment chain in ok condition for release */
379  first.p->m_lastSegment = prevPtr.i;
380  first.p->m_sz-= len;
381  prevPtr.p->m_nextSegment = RNIL;
382  ndbout_c("Not enough Segmented Sections during import");
383  return false;
384  }
385  }
386 
387  first.p->m_lastSegment = currPtr.i;
388  currPtr.p->m_nextSegment = RNIL;
389  memcpy(&currPtr.p->theData[0], src, 4 * len);
390 
391  assert(verifySection(first.i));
392  return true;
393 }
394 
395 void
396 release(SPC_ARG SegmentedSectionPtr & ptr)
397 {
398  g_sectionSegmentPool.releaseList(SPC_SEIZE_ARG
399  relSz(ptr.sz),
400  ptr.i,
401  ptr.p->m_lastSegment);
402 }
403 
404 void
405 releaseSection(SPC_ARG Uint32 firstSegmentIVal)
406 {
407  if (firstSegmentIVal != RNIL)
408  {
409  SectionSegment* p = g_sectionSegmentPool.getPtr(firstSegmentIVal);
410 
411  g_sectionSegmentPool.releaseList(SPC_SEIZE_ARG
412  relSz(p->m_sz),
413  firstSegmentIVal,
414  p->m_lastSegment);
415  }
416 }
417 
418 bool
419 writeToSection(Uint32 firstSegmentIVal, Uint32 offset,
420  const Uint32* src,
421  Uint32 len)
422 {
423  Ptr<SectionSegment> segPtr;
424 
425  if (len == 0)
426  return true;
427 
428  if (firstSegmentIVal == RNIL)
429  {
430  return false;
431  }
432  else
433  {
434  /* Section has at least one segment with data already */
435  g_sectionSegmentPool.getPtr(segPtr, firstSegmentIVal);
436 
437  Uint32 existingLen= segPtr.p->m_sz;
438 
439  assert(existingLen > 0);
440  if (offset >= existingLen)
441  return false; /* No sparse sections or extension */
442  if (len > (existingLen - offset))
443  return false; /* Would be extending beyond current length */
444 
445  /* Advance through segments to the one containing the start offset */
446  while (offset >= SectionSegment::DataLength)
447  {
448  g_sectionSegmentPool.getPtr(segPtr, segPtr.p->m_nextSegment);
449  offset-= SectionSegment::DataLength;
450  }
451 
452  /* Now overwrite the words */
453  while (true)
454  {
455  Uint32 wordsToCopy = MIN(len,
456  SectionSegment::DataLength - offset);
457  memcpy(&segPtr.p->theData[offset], src, (wordsToCopy << 2));
458  src+= wordsToCopy;
459  len-= wordsToCopy;
460 
461  if (!len)
462  {
463  return true;
464  }
465 
466  offset = 0;
467  g_sectionSegmentPool.getPtr(segPtr, segPtr.p->m_nextSegment);
468  }
469  }
470 }
471