1 /*
2    Copyright (c) 2003, 2021, Oracle and/or its affiliates.
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, version 2.0,
6    as published by the Free Software Foundation.
7 
8    This program is also distributed with certain software (including
9    but not limited to OpenSSL) that is licensed under separate terms,
10    as designated in a particular file or component or in included license
11    documentation.  The authors of MySQL hereby grant you an additional
12    permission to link the program and your derivative works with the
13    separately licensed software that they have included with MySQL.
14 
15    This program is distributed in the hope that it will be useful,
16    but WITHOUT ANY WARRANTY; without even the implied warranty of
17    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18    GNU General Public License, version 2.0, for more details.
19 
20    You should have received a copy of the GNU General Public License
21    along with this program; if not, write to the Free Software
22    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301  USA
23 */
24 
25 #include <SimpleProperties.hpp>
26 #include "LongSignal.hpp"
27 #include "LongSignalImpl.hpp"
28 #include "SimulatedBlock.hpp"
29 
30 #define JAM_FILE_ID 224
31 
32 
SimplePropertiesSectionReader(struct SegmentedSectionPtr & ptr,class SectionSegmentPool & pool)33 SimplePropertiesSectionReader::SimplePropertiesSectionReader
34 (struct SegmentedSectionPtr & ptr, class SectionSegmentPool & pool)
35   : m_pool(pool)
36 {
37   if(ptr.p == 0){
38     m_pos = 0;
39     m_len = 0;
40     m_head = 0;
41     m_currentSegment = 0;
42   } else {
43     m_pos = 0;
44     m_len = ptr.p->m_sz;
45     m_head = ptr.p;
46     m_currentSegment = ptr.p;
47   }
48   first();
49 }
50 
51 void
reset()52 SimplePropertiesSectionReader::reset(){
53   m_pos = 0;
54   m_currentSegment = m_head;
55 }
56 
57 bool
step(Uint32 len)58 SimplePropertiesSectionReader::step(Uint32 len){
59   if(m_pos + len >= m_len) {
60     m_pos++;
61     return false;
62   }
63   while(len > SectionSegment::DataLength){
64     m_currentSegment = m_pool.getPtr(m_currentSegment->m_nextSegment);
65 
66     len -= SectionSegment::DataLength;
67     m_pos += SectionSegment::DataLength;
68   }
69 
70   Uint32 ind = m_pos % SectionSegment::DataLength;
71   while(len > 0){
72     len--;
73     m_pos++;
74 
75     ind++;
76     if(ind == SectionSegment::DataLength){
77       ind = 0;
78       m_currentSegment = m_pool.getPtr(m_currentSegment->m_nextSegment);
79     }
80   }
81   return true;
82 }
83 
84 bool
getWord(Uint32 * dst)85 SimplePropertiesSectionReader::getWord(Uint32 * dst){
86   if (peekWord(dst)) {
87     step(1);
88     return true;
89   }
90   return false;
91 }
92 
93 bool
peekWord(Uint32 * dst) const94 SimplePropertiesSectionReader::peekWord(Uint32 * dst) const {
95   if(m_pos < m_len){
96     Uint32 ind = m_pos % SectionSegment::DataLength;
97     * dst = m_currentSegment->theData[ind];
98     return true;
99   }
100   return false;
101 }
102 
103 bool
peekWords(Uint32 * dst,Uint32 len) const104 SimplePropertiesSectionReader::peekWords(Uint32 * dst, Uint32 len) const {
105   if(m_pos + len > m_len){
106     return false;
107   }
108   Uint32 ind = (m_pos % SectionSegment::DataLength);
109   Uint32 left = (SectionSegment::DataLength - ind);
110   SectionSegment * p = m_currentSegment;
111 
112   while(len > left){
113     memcpy(dst, &p->theData[ind], 4 * left);
114     dst += left;
115     len -= left;
116     ind = 0;
117     left = SectionSegment::DataLength;
118     p = m_pool.getPtr(p->m_nextSegment);
119   }
120 
121   memcpy(dst, &p->theData[ind], 4 * len);
122   return true;
123 }
124 
125 bool
getWords(Uint32 * dst,Uint32 len)126 SimplePropertiesSectionReader::getWords(Uint32 * dst, Uint32 len){
127   if(peekWords(dst, len)){
128     step(len);
129     return true;
130   }
131   return false;
132 }
133 
SimplePropertiesSectionWriter(class SimulatedBlock & block)134 SimplePropertiesSectionWriter::SimplePropertiesSectionWriter(class SimulatedBlock & block)
135   : m_pool(block.getSectionSegmentPool()), m_block(block)
136 {
137   m_pos = -1;
138   m_head = 0;
139   m_currentSegment = 0;
140   m_prevPtrI = RNIL;
141   reset();
142 }
143 
~SimplePropertiesSectionWriter()144 SimplePropertiesSectionWriter::~SimplePropertiesSectionWriter()
145 {
146   release();
147 }
148 
149 #ifdef NDBD_MULTITHREADED
150 #define SP_POOL_ARG f_section_lock, *m_block.m_sectionPoolCache,
151 #else
152 #define SP_POOL_ARG
153 #endif
154 
155 void
release()156 SimplePropertiesSectionWriter::release()
157 {
158   if (m_head)
159   {
160     if (m_sz)
161     {
162       SegmentedSectionPtr ptr;
163       ptr.p = m_head;
164       ptr.i = m_head->m_lastSegment;
165       ptr.sz = m_sz;
166       m_head->m_sz = m_sz;
167       m_head->m_lastSegment = m_currentSegment->m_lastSegment;
168 
169       if((m_pos % SectionSegment::DataLength) == 0){
170         m_pool.release(SP_POOL_ARG m_currentSegment->m_lastSegment);
171         m_head->m_lastSegment = m_prevPtrI;
172       }
173       m_block.release(ptr);
174     }
175     else
176     {
177       m_pool.release(SP_POOL_ARG m_head->m_lastSegment);
178     }
179   }
180   m_pos = -1;
181   m_head = 0;
182   m_currentSegment = 0;
183   m_prevPtrI = RNIL;
184 }
185 
186 bool
reset()187 SimplePropertiesSectionWriter::reset()
188 {
189   release();
190   Ptr<SectionSegment> first;
191   if(m_pool.seize(SP_POOL_ARG first)){
192     ;
193   } else {
194     m_pos = -1;
195     m_head = 0;
196     m_currentSegment = 0;
197     m_prevPtrI = RNIL;
198     return false;
199   }
200   m_sz = 0;
201   m_pos = 0;
202   m_head = first.p;
203   m_head->m_lastSegment = first.i;
204   m_currentSegment = first.p;
205   m_prevPtrI = RNIL;
206   return false;
207 }
208 
209 bool
putWord(Uint32 val)210 SimplePropertiesSectionWriter::putWord(Uint32 val){
211   return putWords(&val, 1);
212 }
213 
214 bool
putWords(const Uint32 * src,Uint32 len)215 SimplePropertiesSectionWriter::putWords(const Uint32 * src, Uint32 len){
216   Uint32 left = SectionSegment::DataLength - m_pos;
217 
218   while(len >= left){
219     memcpy(&m_currentSegment->theData[m_pos], src, 4 * left);
220     Ptr<SectionSegment> next;
221     if(m_pool.seize(SP_POOL_ARG next)){
222 
223       m_prevPtrI = m_currentSegment->m_lastSegment;
224       m_currentSegment->m_nextSegment = next.i;
225       next.p->m_lastSegment = next.i;
226       m_currentSegment = next.p;
227 
228       len -= left;
229       src += left;
230       m_sz += left;
231 
232       left = SectionSegment::DataLength;
233       m_pos = 0;
234     } else {
235       abort();
236       return false;
237     }
238   }
239 
240   memcpy(&m_currentSegment->theData[m_pos], src, 4 * len);
241   m_sz += len;
242   m_pos += len;
243 
244   assert(m_pos < (int)SectionSegment::DataLength);
245 
246   return true;
247 }
248 
getWordsUsed() const249 Uint32 SimplePropertiesSectionWriter::getWordsUsed() const
250 {
251   return m_sz;
252 }
253 
254 void
getPtr(struct SegmentedSectionPtr & dst)255 SimplePropertiesSectionWriter::getPtr(struct SegmentedSectionPtr & dst){
256   // Set last ptr and size
257   if(m_pos >= 0){
258     dst.p = m_head;
259     dst.i = m_head->m_lastSegment;
260     dst.sz = m_sz;
261     m_head->m_sz = m_sz;
262     m_head->m_lastSegment = m_currentSegment->m_lastSegment;
263 
264     if((m_pos % SectionSegment::DataLength) == 0){
265       m_pool.release(SP_POOL_ARG m_currentSegment->m_lastSegment);
266       m_head->m_lastSegment = m_prevPtrI;
267     }
268 
269     m_sz = 0;
270     m_pos = -1;
271     m_head = m_currentSegment = 0;
272     m_prevPtrI = RNIL;
273     return ;
274   }
275   dst.p = 0;
276   dst.sz = 0;
277   dst.i = RNIL;
278 
279   if (m_head)
280   {
281     m_pool.release(SP_POOL_ARG m_head->m_lastSegment);
282   }
283 
284   m_sz = 0;
285   m_pos = -1;
286   m_head = m_currentSegment = 0;
287   m_prevPtrI = RNIL;
288 }
289 
290 /**
291  * #undef is needed since this file is included by
292  * SimplePropertiesSection_nonmt.cpp and SimplePropertiesSection_mt.cpp
293  */
294 #undef JAM_FILE_ID
295