GnuCOBOL  2.0
A free COBOL compiler
vbindexio.c
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2003 Trevor van Bremen
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public License
6  * as published by the Free Software Foundation; either version 2.1,
7  * or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12  * GNU Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with this library; see the file COPYING.LIB. If
16  * not, write to the Free Software Foundation, 51 Franklin Street, Fifth Floor
17  * Boston, MA 02110-1301 USA
18  */
19 
20 #include "isinternal.h"
21 
22 static char cvbnodetmp[VB_NODE_MAX];
23 
24 /* Local functions */
25 
26 static off_t
27 tvbdatacountgetnext (const int ihandle)
28 {
29  struct DICTINFO *psvbptr;
30  off_t tvalue;
31 
32  psvbptr = psvbfile[ihandle];
33  iserrno = EBADARG;
34  if (!psvbptr->iisdictlocked) {
35  return -1;
36  }
37  iserrno = 0;
38 
39  tvalue = inl_ldquad (psvbptr->sdictnode.cdatacount) + 1;
40  inl_stquad (tvalue, psvbptr->sdictnode.cdatacount);
41  psvbptr->iisdictlocked |= 0x02;
42  return tvalue;
43 }
44 
45 /* Global functions */
46 
47 off_t
48 tvbnodecountgetnext (const int ihandle)
49 {
50  struct DICTINFO *psvbptr;
51  off_t tvalue;
52 
53  psvbptr = psvbfile[ihandle];
54  iserrno = EBADARG;
55  if (!psvbptr->iisdictlocked) {
56  return -1;
57  }
58  iserrno = 0;
59 
60  tvalue = inl_ldquad (psvbptr->sdictnode.cnodecount) + 1;
61  inl_stquad (tvalue, psvbptr->sdictnode.cnodecount);
62  psvbptr->iisdictlocked |= 0x02;
63  return tvalue;
64 }
65 
66 int
67 ivbnodefree (const int ihandle, const off_t tnodenumber)
68 {
69  struct DICTINFO *psvbptr;
70  off_t theadnode;
71  int ilengthused, iresult;
72  char cvbnodetmp2[VB_NODE_MAX];
73 
74  /* Sanity check - Is ihandle a currently open table? */
75  iserrno = ENOTOPEN;
76  psvbptr = psvbfile[ihandle];
77  if (!psvbptr) {
78  return -1;
79  }
80  iserrno = EBADARG;
81  if (!psvbptr->iisdictlocked) {
82  return -1;
83  }
84  iserrno = 0;
85 
86  memset (cvbnodetmp2, 0, (size_t) psvbptr->inodesize);
87  inl_stint (INTSIZE, cvbnodetmp2);
88 
89  theadnode = inl_ldquad (psvbptr->sdictnode.cnodefree);
90  /* If the list is empty, node tnodenumber becomes the whole list */
91  if (theadnode == 0) {
92  inl_stint (INTSIZE + QUADSIZE, cvbnodetmp2);
93  inl_stquad ((off_t)0, cvbnodetmp2 + INTSIZE);
94  cvbnodetmp2[psvbptr->inodesize - 2] = 0x7f;
95  cvbnodetmp2[psvbptr->inodesize - 3] = -2;
96  iresult = ivbblockwrite (ihandle, 1, tnodenumber, cvbnodetmp2);
97  if (iresult) {
98  return iresult;
99  }
100  inl_stquad (tnodenumber, psvbptr->sdictnode.cnodefree);
101  psvbptr->iisdictlocked |= 0x02;
102  return 0;
103  }
104 
105  /* Read in the head of the current free list */
106  iresult = ivbblockread (ihandle, 1, theadnode, cvbnodetmp);
107  if (iresult) {
108  return iresult;
109  }
110 /* C-ISAM is not 100% C-ISAM compatible */
111 #if ISAMMODE == 1
112  if (cvbnodetmp[psvbptr->inodesize - 2] != 0x7f) {
113  return EBADFILE;
114  }
115 #endif
116  if (cvbnodetmp[psvbptr->inodesize - 3] != -2) {
117  return EBADFILE;
118  }
119  ilengthused = inl_ldint (cvbnodetmp);
120  if (ilengthused >= psvbptr->inodesize - (QUADSIZE + 3)) {
121  /* If there was no space left, tnodenumber becomes the head */
122  cvbnodetmp2[psvbptr->inodesize - 2] = 0x7f;
123  cvbnodetmp2[psvbptr->inodesize - 3] = -2;
124  inl_stint (INTSIZE + QUADSIZE, cvbnodetmp2);
125  inl_stquad (theadnode, &cvbnodetmp2[INTSIZE]);
126  iresult = ivbblockwrite (ihandle, 1, tnodenumber, cvbnodetmp2);
127  if (!iresult) {
128  inl_stquad (tnodenumber, psvbptr->sdictnode.cnodefree);
129  psvbptr->iisdictlocked |= 0x02;
130  }
131  return iresult;
132  }
133 
134  /* If we got here, there's space left in the theadnode to store it */
135  cvbnodetmp2[psvbptr->inodesize - 2] = 0x7f;
136  cvbnodetmp2[psvbptr->inodesize - 3] = -2;
137  iresult = ivbblockwrite (ihandle, 1, tnodenumber, cvbnodetmp2);
138  if (iresult) {
139  return iresult;
140  }
141  inl_stquad (tnodenumber, &cvbnodetmp[ilengthused]);
142  ilengthused += QUADSIZE;
143  inl_stint (ilengthused, cvbnodetmp);
144  iresult = ivbblockwrite (ihandle, 1, theadnode, cvbnodetmp);
145 
146  return iresult;
147 }
148 
149 int
150 ivbdatafree (const int ihandle, const off_t trownumber)
151 {
152  struct DICTINFO *psvbptr;
153  off_t theadnode, tnodenumber;
154  int ilengthused, iresult;
155 
156  /* Sanity check - Is ihandle a currently open table? */
157  iserrno = ENOTOPEN;
158  psvbptr = psvbfile[ihandle];
159  if (!psvbptr) {
160  return -1;
161  }
162  iserrno = EBADARG;
163  if (!psvbptr->iisdictlocked) {
164  return -1;
165  }
166  iserrno = 0;
167 
168  if (inl_ldquad (psvbptr->sdictnode.cdatacount) == trownumber) {
169  inl_stquad (trownumber - 1, psvbptr->sdictnode.cdatacount);
170  psvbptr->iisdictlocked |= 0x02;
171  return 0;
172  }
173 
174  theadnode = inl_ldquad (psvbptr->sdictnode.cdatafree);
175  if (theadnode != 0) {
176  iresult = ivbblockread (ihandle, 1, theadnode, cvbnodetmp);
177  if (iresult) {
178  return iresult;
179  }
180 /* C-ISAM is not 100% C-ISAM compatible */
181 #if ISAMMODE == 1
182  if (cvbnodetmp[psvbptr->inodesize - 2] != 0x7f) {
183  return EBADFILE;
184  }
185 #endif
186  if (cvbnodetmp[psvbptr->inodesize - 3] != -1) {
187  return EBADFILE;
188  }
189  ilengthused = inl_ldint (cvbnodetmp);
190  if (ilengthused < psvbptr->inodesize - (QUADSIZE + 3)) {
191  /* We need to add trownumber to the current node */
192  inl_stquad ((off_t) trownumber, cvbnodetmp + ilengthused);
193  ilengthused += QUADSIZE;
194  inl_stint (ilengthused, cvbnodetmp);
195  iresult = ivbblockwrite (ihandle, 1, theadnode, cvbnodetmp);
196  return iresult;
197  }
198  }
199  /* We need to allocate a new row-free node! */
200  /* We append any existing nodes using the next pointer from the new node */
201  tnodenumber = tvbnodeallocate (ihandle);
202  if (tnodenumber == (off_t)-1) {
203  return iserrno;
204  }
205  memset (cvbnodetmp, 0, VB_NODE_MAX);
206  cvbnodetmp[psvbptr->inodesize - 2] = 0x7f;
207  cvbnodetmp[psvbptr->inodesize - 3] = -1;
208  inl_stint (INTSIZE + (2 * QUADSIZE), cvbnodetmp);
209  inl_stquad (theadnode, &cvbnodetmp[INTSIZE]);
210  inl_stquad (trownumber, &cvbnodetmp[INTSIZE + QUADSIZE]);
211  iresult = ivbblockwrite (ihandle, 1, tnodenumber, cvbnodetmp);
212  if (iresult) {
213  return iresult;
214  }
215  inl_stquad (tnodenumber, psvbptr->sdictnode.cdatafree);
216  psvbptr->iisdictlocked |= 0x02;
217  return 0;
218 }
219 
220 off_t
221 tvbnodeallocate (const int ihandle)
222 {
223  struct DICTINFO *psvbptr;
224  off_t theadnode, tvalue;
225  int ilengthused;
226 
227  /* Sanity check - Is ihandle a currently open table? */
228  iserrno = ENOTOPEN;
229  psvbptr = psvbfile[ihandle];
230  if (!psvbptr) {
231  return -1;
232  }
233  iserrno = EBADARG;
234  if (!psvbptr->iisdictlocked) {
235  return -1;
236  }
237  iserrno = 0;
238 
239  /* If there's *ANY* nodes in the free list, use them first! */
240  theadnode = inl_ldquad (psvbptr->sdictnode.cnodefree);
241  if (theadnode != 0) {
242  iserrno = ivbblockread (ihandle, 1, theadnode, cvbnodetmp);
243  if (iserrno) {
244  return -1;
245  }
246  iserrno = EBADFILE;
247 /* C-ISAM is not 100% C-ISAM compatible */
248 #if ISAMMODE == 1
249  if (cvbnodetmp[psvbptr->inodesize - 2] != 0x7f) {
250  return -1;
251  }
252 #endif
253  if (cvbnodetmp[psvbptr->inodesize - 3] != -2) {
254  return -1;
255  }
256  ilengthused = inl_ldint (cvbnodetmp);
257  if (ilengthused > (INTSIZE + QUADSIZE)) {
258  tvalue = inl_ldquad (cvbnodetmp + INTSIZE + QUADSIZE);
259  memcpy (cvbnodetmp + INTSIZE + QUADSIZE,
260  cvbnodetmp + INTSIZE + QUADSIZE + QUADSIZE,
261  (size_t)(ilengthused - (INTSIZE + QUADSIZE + QUADSIZE)));
262  ilengthused -= QUADSIZE;
263  memset (cvbnodetmp + ilengthused, 0, QUADSIZE);
264  inl_stint (ilengthused, cvbnodetmp);
265  iserrno = ivbblockwrite (ihandle, 1, theadnode, cvbnodetmp);
266  if (iserrno) {
267  return -1;
268  }
269  return tvalue;
270  }
271  /* If it's last entry in the node, use the node itself! */
272  tvalue = inl_ldquad (cvbnodetmp + INTSIZE);
273  inl_stquad (tvalue, psvbptr->sdictnode.cnodefree);
274  psvbptr->iisdictlocked |= 0x02;
275  return theadnode;
276  }
277  /* If we get here, we need to allocate a NEW node. */
278  /* Since we already hold a dictionary lock, we don't need another */
279  tvalue = tvbnodecountgetnext (ihandle);
280  return tvalue;
281 }
282 
283 off_t
284 tvbdataallocate (const int ihandle)
285 {
286  struct DICTINFO *psvbptr;
287  off_t theadnode, tnextnode, tvalue;
288  int ilengthused, iresult;
289 
290  psvbptr = psvbfile[ihandle];
291  iserrno = EBADARG;
292  if (!psvbptr->iisdictlocked) {
293  return -1;
294  }
295  iserrno = 0;
296 
297  /* If there's *ANY* rows in the free list, use them first! */
298  theadnode = inl_ldquad (psvbptr->sdictnode.cdatafree);
299  while (theadnode != 0) {
300  iserrno = ivbblockread (ihandle, 1, theadnode, cvbnodetmp);
301  if (iserrno) {
302  return -1;
303  }
304  iserrno = EBADFILE;
305 /* C-ISAM is not 100% C-ISAM compatible */
306 #if ISAMMODE == 1
307  if (cvbnodetmp[psvbptr->inodesize - 2] != 0x7f) {
308  return -1;
309  }
310 #endif
311  if (cvbnodetmp[psvbptr->inodesize - 3] != -1) {
312  return -1;
313  }
314  ilengthused = inl_ldint (cvbnodetmp);
315  if (ilengthused > INTSIZE + QUADSIZE) {
316  psvbptr->iisdictlocked |= 0x02;
317  ilengthused -= QUADSIZE;
318  inl_stint (ilengthused, cvbnodetmp);
319  tvalue = inl_ldquad (&cvbnodetmp[ilengthused]);
320  inl_stquad ((off_t)0, &cvbnodetmp[ilengthused]);
321  if (ilengthused > INTSIZE + QUADSIZE) {
322  iserrno = ivbblockwrite (ihandle, 1, theadnode, cvbnodetmp);
323  if (iserrno) {
324  return -1;
325  }
326  return tvalue;
327  }
328  /* If we're using the last entry in the node, advance */
329  tnextnode = inl_ldquad (&cvbnodetmp[INTSIZE]);
330  iresult = ivbnodefree (ihandle, theadnode);
331  if (iresult) {
332  return -1;
333  }
334  inl_stquad (tnextnode, psvbptr->sdictnode.cdatafree);
335  return tvalue;
336  }
337  /* Ummmm, this is an INTEGRITY ERROR of sorts! */
338  /* However, let's fix it anyway! */
339  tnextnode = inl_ldquad (&cvbnodetmp[INTSIZE]);
340  iresult = ivbnodefree (ihandle, theadnode);
341  if (iresult) {
342  return -1;
343  }
344  inl_stquad (tnextnode, psvbptr->sdictnode.cdatafree);
345  psvbptr->iisdictlocked |= 0x02;
346  theadnode = tnextnode;
347  }
348  /* If we get here, we need to allocate a NEW row number. */
349  /* Since we already hold a dictionary lock, we don't need another */
350  tvalue = tvbdatacountgetnext (ihandle);
351  return tvalue;
352 }
353 
354 int
355 ivbforcedataallocate (const int ihandle, const off_t trownumber)
356 {
357  struct DICTINFO *psvbptr;
358  off_t theadnode, tprevnode, tnextnode;
359  int iloop, ilengthused;
360 
361  /* Sanity check - Is ihandle a currently open table? */
362  iserrno = ENOTOPEN;
363  psvbptr = psvbfile[ihandle];
364  if (!psvbptr) {
365  return -1;
366  }
367  iserrno = EBADARG;
368  if (!psvbptr->iisdictlocked) {
369  return -1;
370  }
371  iserrno = 0;
372 
373  /* Test 1: Is it already beyond EOF (the SIMPLE test) */
374  theadnode = inl_ldquad (psvbptr->sdictnode.cdatacount);
375  if (theadnode < trownumber) {
376  psvbptr->iisdictlocked |= 0x02;
377  inl_stquad (trownumber, psvbptr->sdictnode.cdatacount);
378  theadnode++;
379  while (theadnode < trownumber) {
380  if (theadnode != 0) {
381  ivbdatafree (ihandle, theadnode);
382  }
383  theadnode++;
384  }
385  return 0;
386  }
387  /* <SIGH> It SHOULD be *SOMEWHERE* in the data free list! */
388  tprevnode = 0;
389  theadnode = inl_ldquad (psvbptr->sdictnode.cdatafree);
390  while (theadnode != 0) {
391  iserrno = ivbblockread (ihandle, 1, theadnode, cvbnodetmp);
392  if (iserrno) {
393  return -1;
394  }
395  iserrno = EBADFILE;
396 /* C-ISAM is not 100% C-ISAM compatible */
397 #if ISAMMODE == 1
398  if (cvbnodetmp[psvbptr->inodesize - 2] != 0x7f) {
399  return -1;
400  }
401 #endif
402  if (cvbnodetmp[psvbptr->inodesize - 3] != -1) {
403  return -1;
404  }
405  ilengthused = inl_ldint (cvbnodetmp);
406  for (iloop = INTSIZE + QUADSIZE; iloop < ilengthused; iloop += QUADSIZE) {
407  if (inl_ldquad (&cvbnodetmp[iloop]) == trownumber) { /* Extract it */
408  memcpy (&(cvbnodetmp[iloop]), &(cvbnodetmp[iloop + QUADSIZE]),
409  (size_t)(ilengthused - iloop));
410  ilengthused -= QUADSIZE;
411  if (ilengthused > INTSIZE + QUADSIZE) {
412  inl_stquad ((off_t)0, &cvbnodetmp[ilengthused]);
413  inl_stint (ilengthused, cvbnodetmp);
414  return ivbblockwrite (ihandle, 1, theadnode, cvbnodetmp);
415  } else { /* It was the last one in the node! */
416  tnextnode = inl_ldquad (&cvbnodetmp[INTSIZE]);
417  if (tprevnode) {
418  iserrno =
419  ivbblockread (ihandle, 1, tprevnode,
420  cvbnodetmp);
421  if (iserrno) {
422  return -1;
423  }
424  inl_stquad (tnextnode, &cvbnodetmp[INTSIZE]);
425  return ivbblockwrite
426  (ihandle, 1, tprevnode, cvbnodetmp);
427  } else {
428  psvbptr->iisdictlocked |= 0x02;
429  inl_stquad (tnextnode,
430  psvbptr->sdictnode.cdatafree);
431  }
432  return ivbnodefree (ihandle, theadnode);
433  }
434  }
435  }
436  tprevnode = theadnode;
437  theadnode = inl_ldquad (&cvbnodetmp[INTSIZE]);
438  }
439  /* If we get here, we've got a MAJOR integrity error in that the */
440  /* nominated row number was simply *NOT FREE* */
441  iserrno = EBADFILE;
442  return -1;
443 }
static int inl_ldint(void *pclocation)
Definition: isinternal.h:170
int ivbblockread(const int ihandle, const int iisindex, const off_t tblocknumber, char *cbuffer)
Definition: vblowlevel.c:137
off_t tvbnodeallocate(const int ihandle)
Definition: vbindexio.c:221
char cdatacount[8]
Definition: isinternal.h:375
#define VB_NODE_MAX
Definition: isinternal.h:288
static off_t tvbdatacountgetnext(const int ihandle)
Definition: vbindexio.c:27
static void inl_stint(int ivalue, void *pclocation)
Definition: isinternal.h:190
int ivbforcedataallocate(const int ihandle, const off_t trownumber)
Definition: vbindexio.c:355
unsigned char iisdictlocked
Definition: isinternal.h:427
struct DICTNODE sdictnode
Definition: isinternal.h:444
char cnodecount[8]
Definition: isinternal.h:376
struct DICTINFO * psvbfile[128+1]
Definition: vblowlevel.c:23
#define QUADSIZE
Definition: isinternal.h:108
static char cvbnodetmp[4096]
Definition: vbindexio.c:22
char cnodefree[8]
Definition: isinternal.h:374
char cdatafree[8]
Definition: isinternal.h:373
int ivbblockwrite(const int ihandle, const int iisindex, const off_t tblocknumber, const char *cbuffer)
Definition: vblowlevel.c:167
static void inl_stquad(off_t tvalue, void *pclocation)
Definition: isinternal.h:260
off_t tvbnodecountgetnext(const int ihandle)
Definition: vbindexio.c:48
static off_t inl_ldquad(void *pclocation)
Definition: isinternal.h:238
off_t trownumber
Definition: isinternal.h:416
int ivbdatafree(const int ihandle, const off_t trownumber)
Definition: vbindexio.c:150
off_t tvbdataallocate(const int ihandle)
Definition: vbindexio.c:284
int iserrno
Definition: vbmemio.c:27
int inodesize
Definition: isinternal.h:402
int ivbnodefree(const int ihandle, const off_t tnodenumber)
Definition: vbindexio.c:67