GnuCOBOL  2.0
A free COBOL compiler
istrans.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 /* Globals */
23 int ivbintrans = VBNOTRANS; /* If not zero, in a transaction */
24 int ivblogfilehandle = -1; /* Handle of the current logfile */
25 
26 static struct SLOGHDR *psvblogheader;
27 static pid_t tvbpid;
28 static uid_t tvbuid;
29 static char cvbtransbuffer[MAX_BUFFER_LENGTH]; /* Buffer for holding transaction */
30 
31 /* Local functions */
32 
33 static void
35 {
36  static size_t iinitialized = 0;
37 
38  if (iinitialized) {
39  return;
40  }
41  iinitialized = 1;
42 #ifdef _WIN32
43  tvbpid = GetCurrentProcessId();
44  /* No getuid ? */
45  tvbuid = 1;
46 #else
47  tvbpid = getpid ();
48  tvbuid = getuid ();
49 #endif
50 }
51 
52 static void
53 vtranshdr (const char *pctranstype)
54 {
55  vinitpiduid ();
56  psvblogheader = (struct SLOGHDR *)cvbtransbuffer;
57  memcpy (psvblogheader->coperation, pctranstype, 2);
58  inl_stint ((int)tvbpid, psvblogheader->cpid); /* Assumes pid_t is short */
59  inl_stint ((int)tvbuid, psvblogheader->cuid); /* Assumes uid_t is short */
60  inl_stlong (time (NULL), psvblogheader->ctime); /* Assumes time_t is long */
61  inl_stint (0, psvblogheader->crfu1); /* BUG - WTF is this? */
62 }
63 
64 /*
65  * Name:
66  * static int iwritetrans (int itranslength, int irollback);
67  * Arguments:
68  * int itranslength
69  * The length of the transaction to write (exluding hdr/ftr)
70  * int irollback
71  * 0
72  * This transaction CANNOT be rolled back!
73  * 1
74  * Take a wild guess!
75  * Prerequisites:
76  * NONE
77  * Returns:
78  * 0
79  * Success
80  * ELOGWRIT
81  * Ooops, some problem occurred!
82  * Problems:
83  * FUTURE
84  * When we begin to support rows > 32k, the buffer is too small.
85  * In that case, we'll need to perform SEVERAL writes and this means we
86  * will need to implement a crude locking scheme to guarantee atomicity.
87  */
88 static int
89 iwritetrans (int itranslength, const int irollback)
90 {
91  static off_t toffset = 0;
92  static int iprevlen = 0;
93  int iresult;
94 
95  itranslength += sizeof (struct SLOGHDR) + INTSIZE;
96  inl_stint (itranslength, cvbtransbuffer);
97  inl_stint (itranslength, cvbtransbuffer + itranslength - INTSIZE);
98  iresult = ivblock (ivblogfilehandle, (off_t)0, (off_t)1, VBWRLCKW);
99  if (iresult) {
100  return ELOGWRIT;
101  }
102  psvblogheader = (struct SLOGHDR *)cvbtransbuffer;
103  if (irollback) {
104  inl_stint ((int)toffset, psvblogheader->clastposn);
105  inl_stint (iprevlen, psvblogheader->clastlength);
106  toffset = tvblseek (ivblogfilehandle, (off_t)0, SEEK_END);
107  if (toffset == -1) {
108  goto writerr;
109  }
110  iprevlen = itranslength;
111  } else {
112  inl_stint (0, psvblogheader->clastposn);
113  inl_stint (0, psvblogheader->clastlength);
114  if (tvblseek (ivblogfilehandle, (off_t)0, SEEK_END) == -1) {
115  goto writerr;
116  }
117  }
118  if (tvbwrite (ivblogfilehandle, (void *)cvbtransbuffer, (size_t) itranslength) !=
119  (ssize_t) itranslength) {
120  goto writerr;
121  }
122  iresult = ivblock (ivblogfilehandle, (off_t)0, (off_t)1, VBUNLOCK);
123  if (iresult) {
124  return ELOGWRIT;
125  }
126  if (ivbintrans == VBBEGIN) {
128  }
129  return 0;
130 writerr:
131  (void)ivblock (ivblogfilehandle, (off_t)0, (off_t)1, VBUNLOCK);
132  return ELOGWRIT;
133 }
134 
135 static int
137 {
139  return iwritetrans (0, 1);
140 }
141 
142 /*
143  * Name:
144  * static int idemotelocks (void);
145  * Arguments:
146  * NONE
147  * Prerequisites:
148  * NONE
149  * Returns:
150  * 0
151  * Success
152  * EBADFILE
153  * Ooops, some problem occurred!
154  * Problems:
155  * See comments
156  * Comments:
157  * When a transaction is completed, either with an iscommit() or an
158  * isrollback (), *ALL* held locks are released. I'm not quite sure how
159  * valid this really is... Perhaps only the 'transactional' locks should
160  * be released? Or perhaps they should be retained, but demoted to a
161  * non-transactional status? Oh well... C'est la vie!
162  * Caveat:
163  * If the file is exclusively opened (ISEXCLLOCK) or has been locked with
164  * an islock () call, these locks remain in place!
165  */
166 static int
168 {
169  struct DICTINFO *psvbptr;
170  int ihandle, iresult = 0;
171 
172  for (ihandle = 0; ihandle <= ivbmaxusedhandle; ihandle++) {
173  psvbptr = psvbfile[ihandle];
174  if (!psvbptr || psvbptr->iisopen == 2) {
175  continue;
176  }
177  if (psvbptr->iopenmode & ISEXCLLOCK) {
178  continue;
179  }
180  if (psvbptr->iisdatalocked) {
181  continue;
182  }
183  /* Rather a carte-blanche method huh? */
184  if (ivbdatalock (ihandle, VBUNLOCK, (off_t)0)) { /* BUG Only ours? */
185  iresult = -1;
186  }
187  }
188  if (iresult) {
189  iserrno = EBADFILE;
190  }
191  return iresult;
192 }
193 
194 static int
195 ivbrollmeback (off_t toffset, const int iinrecover)
196 {
197  char *pcbuffer, *pcrow;
198  off_t tlength, trownumber;
199  int iloop;
200  int ierrorencountered = 0;
201  int ifoundbegin = 0;
202  int ihandle;
203  int ilocalhandle[VB_MAX_FILES + 1];
204  int isavedhandle[VB_MAX_FILES + 1];
205 
206  for (iloop = 0; iloop <= VB_MAX_FILES; iloop++) {
207  if (psvbfile[iloop]) {
208  ilocalhandle[iloop] = iloop;
209  } else {
210  ilocalhandle[iloop] = -1;
211  }
212  isavedhandle[iloop] = ilocalhandle[iloop];
213  }
214  psvblogheader = (struct SLOGHDR *)(cvbtransbuffer + INTSIZE);
215  pcbuffer = cvbtransbuffer + INTSIZE + sizeof (struct SLOGHDR);
216  /* Begin by reading the footer of the previous transaction */
217  toffset -= INTSIZE;
218  if (tvblseek (ivblogfilehandle, toffset, SEEK_SET) != toffset) {
219  return EBADFILE;
220  }
221  if (tvbread (ivblogfilehandle, cvbtransbuffer, INTSIZE) != INTSIZE) {
222  return EBADFILE;
223  }
224  /* Now, recurse backwards */
225  while (!ifoundbegin) {
226  tlength = inl_ldint (cvbtransbuffer);
227  if (!tlength) {
228  return EBADFILE;
229  }
230  toffset -= tlength;
231  /* Special case: Handle where the FIRST log entry is our BW */
232  if (toffset == -(INTSIZE)) {
233  if (tvblseek (ivblogfilehandle, (off_t)0, SEEK_SET) != 0) {
234  return EBADFILE;
235  }
236  if (tvbread (ivblogfilehandle, cvbtransbuffer + INTSIZE,
237  tlength - INTSIZE) != tlength - INTSIZE) {
238  return EBADFILE;
239  }
240  if (!memcmp (psvblogheader->coperation, VBL_BEGIN, 2)) {
241  break;
242  }
243  return EBADFILE;
244  } else {
245  if (toffset < INTSIZE) {
246  return EBADFILE;
247  }
248  if (tvblseek (ivblogfilehandle, toffset, SEEK_SET) != toffset) {
249  return EBADFILE;
250  }
251  if (tvbread (ivblogfilehandle, cvbtransbuffer, tlength) != tlength) {
252  return EBADFILE;
253  }
254  }
255  /* Is it OURS? */
256  if (inl_ldint (psvblogheader->cpid) != tvbpid) {
257  continue;
258  }
259  if (!memcmp (psvblogheader->coperation, VBL_BEGIN, 2)) {
260  break;
261  }
262  ihandle = inl_ldint (pcbuffer);
263  trownumber = inl_ldquad (pcbuffer + INTSIZE);
264  if (!memcmp (psvblogheader->coperation, VBL_FILECLOSE, 2)) {
265  if (ilocalhandle[ihandle] != -1 && psvbfile[ihandle]->iisopen == 0) {
266  return EBADFILE;
267  }
268  iloop = inl_ldint (pcbuffer + INTSIZE);
269  ilocalhandle[ihandle] =
270  isopen (pcbuffer + INTSIZE + INTSIZE, iloop + ISMANULOCK + ISINOUT);
271  if (ilocalhandle[ihandle] == -1) {
272  return ETOOMANY;
273  }
274  }
275  if (!memcmp (psvblogheader->coperation, VBL_INSERT, 2)) {
276  if (ilocalhandle[ihandle] == -1) {
277  return EBADFILE;
278  }
279  isreclen = inl_ldint (pcbuffer + INTSIZE + QUADSIZE);
280  pcrow = pcbuffer + INTSIZE + QUADSIZE + INTSIZE;
281  memcpy (psvbfile[ilocalhandle[ihandle]]->ppcrowbuffer, pcrow, isreclen);
282  /* BUG? - Should we READ the row first and compare it? */
283  if (isdelrec (ilocalhandle[ihandle], trownumber)) {
284  return iserrno;
285  }
286  }
287  if (!memcmp (psvblogheader->coperation, VBL_UPDATE, 2)) {
288  if (ilocalhandle[ihandle] == -1) {
289  return EBADFILE;
290  }
291  isreclen = inl_ldint (pcbuffer + INTSIZE + QUADSIZE);
292  pcrow = pcbuffer + INTSIZE + QUADSIZE + INTSIZE + INTSIZE;
293  /* BUG? - Should we READ the row first and compare it? */
294  if (isrewrec (ilocalhandle[ihandle], trownumber, pcrow)) {
295  return iserrno;
296  }
297  }
298  if (!memcmp (psvblogheader->coperation, VBL_DELETE, 2)) {
299  if (ilocalhandle[ihandle] == -1) {
300  return EBADFILE;
301  }
302  isreclen = inl_ldint (pcbuffer + INTSIZE + QUADSIZE);
303  pcrow = pcbuffer + INTSIZE + QUADSIZE + INTSIZE;
304  ivbenter (ilocalhandle[ihandle], 1, 0);
305  psvbfile[ilocalhandle[ihandle]]->iisdictlocked |= 0x02;
306  if (iinrecover
307  && ivbforcedataallocate (ilocalhandle[ihandle], trownumber)) {
308  ierrorencountered = EBADFILE;
309  } else {
310  if (ivbwriterow (ilocalhandle[ihandle], pcrow, trownumber)) {
311  ierrorencountered = EDUPL;
312  ivbdatafree (ilocalhandle[ihandle], trownumber);
313  }
314  }
315  ivbexit (ilocalhandle[ihandle]);
316  }
317  if (!memcmp (psvblogheader->coperation, VBL_FILEOPEN, 2)) {
318  if (ilocalhandle[ihandle] == -1) {
319  return EBADFILE;
320  }
321  isclose (ilocalhandle[ihandle]);
322  ilocalhandle[ihandle] = -1;
323  }
324  }
325  for (iloop = 0; iloop <= VB_MAX_FILES; iloop++) {
326  if (isavedhandle[iloop] != -1 && psvbfile[isavedhandle[iloop]]) {
327  isclose (isavedhandle[iloop]);
328  }
329  }
330  return ierrorencountered;
331 }
332 
333 static int
334 ivbrollmeforward (off_t toffset)
335 {
336  char *pcbuffer;
337  off_t tlength, trownumber;
338  int ifoundbegin = 0;
339  int ihandle, iloop;
340  int ilocalhandle[VB_MAX_FILES + 1], isavedhandle[VB_MAX_FILES + 1];
341 
342  vinitpiduid ();
343  for (iloop = 0; iloop <= VB_MAX_FILES; iloop++) {
344  if (psvbfile[iloop]) {
345  ilocalhandle[iloop] = iloop;
346  } else {
347  ilocalhandle[iloop] = -1;
348  }
349  isavedhandle[iloop] = ilocalhandle[iloop];
350  }
351  psvblogheader = (struct SLOGHDR *)(cvbtransbuffer + INTSIZE);
352  pcbuffer = cvbtransbuffer + INTSIZE + sizeof (struct SLOGHDR);
353  /* Begin by reading the footer of the previous transaction */
354  toffset -= INTSIZE;
355  if (tvblseek (ivblogfilehandle, toffset, SEEK_SET) != toffset) {
356  return EBADFILE;
357  }
358  if (tvbread (ivblogfilehandle, cvbtransbuffer, INTSIZE) != INTSIZE) {
359  return EBADFILE;
360  }
361  /* Now, recurse backwards */
362  while (!ifoundbegin) {
363  tlength = inl_ldint (cvbtransbuffer);
364  if (!tlength) {
365  return EBADFILE;
366  }
367  toffset -= tlength;
368  /* Special case: Handle where the FIRST log entry is our BW */
369  if (toffset == -(INTSIZE)) {
370  if (tvblseek (ivblogfilehandle, (off_t)0, SEEK_SET) != 0) {
371  return EBADFILE;
372  }
373  if (tvbread (ivblogfilehandle, cvbtransbuffer + INTSIZE,
374  tlength - INTSIZE) != tlength - INTSIZE) {
375  return EBADFILE;
376  }
377  if (!memcmp (psvblogheader->coperation, VBL_BEGIN, 2)) {
378  break;
379  }
380  return EBADFILE;
381  } else {
382  if (toffset < INTSIZE) {
383  return EBADFILE;
384  }
385  if (tvblseek (ivblogfilehandle, toffset, SEEK_SET) != toffset) {
386  return EBADFILE;
387  }
388  if (tvbread (ivblogfilehandle, cvbtransbuffer, tlength) != tlength) {
389  return EBADFILE;
390  }
391  }
392  /* Is it OURS? */
393  if (inl_ldint (psvblogheader->cpid) != tvbpid) {
394  continue;
395  }
396  if (!memcmp (psvblogheader->coperation, VBL_BEGIN, 2)) {
397  break;
398  }
399  ihandle = inl_ldint (pcbuffer);
400  trownumber = inl_ldquad (pcbuffer + INTSIZE);
401  if (!memcmp (psvblogheader->coperation, VBL_FILECLOSE, 2)) {
402  if (ilocalhandle[ihandle] != -1) {
403  return EBADFILE;
404  }
405  iloop = inl_ldint (pcbuffer + INTSIZE);
406  ilocalhandle[ihandle] =
407  isopen (pcbuffer + INTSIZE + INTSIZE, iloop + ISMANULOCK + ISINOUT);
408  if (ilocalhandle[ihandle] == -1) {
409  return ETOOMANY;
410  }
411  }
412  if (!memcmp (psvblogheader->coperation, VBL_DELETE, 2)) {
413  if (ilocalhandle[ihandle] == -1) {
414  return EBADFILE;
415  }
416  ivbenter (ilocalhandle[ihandle], 1, 0);
417  psvbfile[ilocalhandle[ihandle]]->iisdictlocked |= 0x02;
418  if (trownumber ==
419  inl_ldquad (psvbfile[ilocalhandle[ihandle]]->sdictnode.
420  cdatacount)) {
421  psvbfile[ilocalhandle[ihandle]]->iisdictlocked |= 0x02;
422  inl_stquad (trownumber - 1,
423  psvbfile[ilocalhandle[ihandle]]->sdictnode.
424  cdatacount);
425  } else if (ivbdatafree (ilocalhandle[ihandle], trownumber)) {
426  return EBADFILE;
427  }
428  ivbexit (ilocalhandle[ihandle]);
429  }
430  if (!memcmp (psvblogheader->coperation, VBL_FILEOPEN, 2)) {
431  if (ilocalhandle[ihandle] == -1) {
432  return EBADFILE;
433  }
434  isclose (ilocalhandle[ihandle]);
435  }
436  }
437  for (iloop = 0; iloop <= VB_MAX_FILES; iloop++) {
438  if (isavedhandle[iloop] != -1 && psvbfile[isavedhandle[iloop]]) {
439  isclose (isavedhandle[iloop]);
440  }
441  }
442  return 0;
443 }
444 
445 /* Global functions */
446 
447 int
448 isbegin (void)
449 {
450  if (ivblogfilehandle < 0) {
451  iserrno = ELOGOPEN;
452  return -1;
453  }
454  /* If we're already *IN* a transaction, don't start another! */
455  if (ivbintrans) {
456  return 0;
457  }
458  ivbintrans = VBBEGIN; /* Just flag that we've BEGUN */
459  return 0;
460 }
461 
462 int
463 iscommit (void)
464 {
465  struct DICTINFO *psvbptr;
466  off_t toffset;
467  int iholdstatus = ivbintrans, iloop, iresult = 0;
468 
469  iserrno = 0;
470  if (ivblogfilehandle == -1) {
471  return 0;
472  }
473  if (!ivbintrans) {
474  iserrno = ENOBEGIN;
475  return -1;
476  }
477  vinitpiduid ();
479  if (iholdstatus != VBBEGIN) {
480  toffset = tvblseek (ivblogfilehandle, (off_t)0, SEEK_END);
481  iserrno = ivbrollmeforward (toffset);
482  }
483  for (iloop = 0; iloop <= ivbmaxusedhandle; iloop++) {
484  psvbptr = psvbfile[iloop];
485  if (psvbptr && psvbptr->iisopen == 1) {
486  iresult = iserrno;
487  if (!ivbclose2 (iloop)) {
488  iserrno = iresult;
489  }
490  }
491  }
492  /* Don't write out a 'null' transaction! */
493  if (iholdstatus != VBBEGIN) {
495  iresult = iwritetrans (0, 1);
496  if (iresult) {
497  iserrno = iresult;
498  }
499  idemotelocks ();
500  }
502  if (iserrno) {
503  return -1;
504  }
505  return 0;
506 }
507 
508 int
510 {
511  int iresult = 0;
512 
513  if (ivbintrans == VBNEEDFLUSH) {
514  if (isrollback ()) {
515  iresult = iserrno;
516  }
517  }
519  if (ivblogfilehandle != -1) {
520  if (ivbclose (ivblogfilehandle)) {
521  iresult = errno;
522  }
523  }
524  ivblogfilehandle = -1;
525  return iresult;
526 }
527 
528 int
529 islogopen (const char *pcfilename)
530 {
531  if (ivblogfilehandle != -1) {
532  islogclose (); /* Ignore the return value! */
533  }
534  ivblogfilehandle = ivbopen (pcfilename, O_RDWR | O_BINARY, 0);
535  if (ivblogfilehandle < 0) {
536  iserrno = ELOGOPEN;
537  return -1;
538  }
539  return 0;
540 }
541 
542 int
544 {
545  struct DICTINFO *psvbptr;
546  off_t toffset;
547  int iloop, iresult = 0;
548 
549  if (ivblogfilehandle < 0) {
550  return 0;
551  }
552  if (!ivbintrans) {
553  iserrno = ENOBEGIN;
554  return -1;
555  }
556  vinitpiduid ();
557  /* Don't write out a 'null' transaction! */
558  for (iloop = 0; iloop <= ivbmaxusedhandle; iloop++) {
559  psvbptr = psvbfile[iloop];
560  if (psvbptr && psvbptr->iisopen == 1) {
561  iresult = iserrno;
562  if (!ivbclose2 (iloop)) {
563  iserrno = iresult;
564  }
565  iresult = 0;
566  }
567  }
568  if (ivbintrans == VBBEGIN) {
569  return 0;
570  }
572  toffset = tvblseek (ivblogfilehandle, (off_t)0, SEEK_END);
573  /* Write out the log entry */
575  iserrno = iwritetrans (0, 1);
576  if (!iserrno) {
577  iserrno = ivbrollmeback (toffset, 0);
578  }
579  idemotelocks ();
581  if (iserrno) {
582  return -1;
583  }
584  for (iloop = 0; iloop <= ivbmaxusedhandle; iloop++) {
585  psvbptr = psvbfile[iloop];
586  if (psvbptr && psvbptr->iisopen == 1) {
587  if (ivbclose2 (iloop)) {
588  iresult = iserrno;
589  }
590  }
591  if (psvbptr && psvbptr->iisdictlocked & 0x04) {
592  iresult |= ivbexit (iloop);
593  }
594  }
595  return (iresult ? -1 : 0);
596 }
597 
598 int
599 ivbtransbuild (const char *pcfilename, const int iminrowlen, const int imaxrowlen,
600  struct keydesc *pskeydesc, const int imode)
601 {
602  char *pcbuffer;
603  struct keypart *pskptr;
604  int ilength = 0, ilength2, iloop;
605 
606  if (ivblogfilehandle < 0 || imode & ISNOLOG) {
607  return 0;
608  }
609  /* Don't log transactions if we're in rollback / recover mode */
610  if (ivbintrans > VBNEEDFLUSH) {
611  return 0;
612  }
613  if (ivbintrans == VBBEGIN) {
614  if (iwritebegin ()) {
615  return -1;
616  }
617  }
619  pcbuffer = cvbtransbuffer + sizeof (struct SLOGHDR);
620  inl_stint (imode, pcbuffer);
621  inl_stint (iminrowlen, pcbuffer + INTSIZE);
622  inl_stint (imaxrowlen, pcbuffer + (2 * INTSIZE));
623  inl_stint (pskeydesc->k_flags, pcbuffer + (3 * INTSIZE));
624  inl_stint (pskeydesc->k_nparts, pcbuffer + (4 * INTSIZE));
625  pcbuffer += (INTSIZE * 6);
626  for (iloop = 0; iloop < pskeydesc->k_nparts; iloop++) {
627  pskptr = &pskeydesc->k_part[iloop];
628  inl_stint (pskptr->kp_start, pcbuffer + (iloop * 3 * INTSIZE));
629  inl_stint (pskptr->kp_leng,
630  pcbuffer + INTSIZE + (iloop * 3 * INTSIZE));
631  inl_stint (pskptr->kp_type,
632  pcbuffer + (INTSIZE * 2) + (iloop * 3 * INTSIZE));
633  ilength += pskptr->kp_leng;
634  }
635  inl_stint (ilength, pcbuffer - INTSIZE);
636  ilength = (INTSIZE * 6) + (INTSIZE * 3 * (pskeydesc->k_nparts));
637  ilength2 = strlen (pcfilename) + 1;
638  pcbuffer = cvbtransbuffer + sizeof (struct SLOGHDR) + ilength;
639  memcpy (pcbuffer, pcfilename, (size_t)ilength2);
640  iserrno = iwritetrans (ilength + ilength2, 0);
641  if (iserrno) {
642  return -1;
643  }
644  return 0;
645 }
646 
647 int
648 ivbtranscreateindex (int const ihandle, struct keydesc *pskeydesc)
649 {
650  char *pcbuffer;
651  struct keypart *pskptr;
652  int ilength = 0, iloop;
653 
654  if (ivblogfilehandle < 0 || psvbfile[ihandle]->iopenmode & ISNOLOG) {
655  return 0;
656  }
657  /* Don't log transactions if we're in rollback / recover mode */
658  if (ivbintrans > VBNEEDFLUSH) {
659  return 0;
660  }
661  if (ivbintrans == VBBEGIN) {
662  if (iwritebegin ()) {
663  return -1;
664  }
665  }
667  pcbuffer = cvbtransbuffer + sizeof (struct SLOGHDR);
668  inl_stint (ihandle, pcbuffer);
669  inl_stint (pskeydesc->k_flags, pcbuffer + INTSIZE);
670  inl_stint (pskeydesc->k_nparts, pcbuffer + (2 * INTSIZE));
671  pcbuffer += (INTSIZE * 4);
672  for (iloop = 0; iloop < pskeydesc->k_nparts; iloop++) {
673  pskptr = &pskeydesc->k_part[iloop];
674  inl_stint (pskptr->kp_start, pcbuffer + (iloop * 3 * INTSIZE));
675  inl_stint (pskptr->kp_leng,
676  pcbuffer + INTSIZE + (iloop * 3 * INTSIZE));
677  inl_stint (pskptr->kp_type,
678  pcbuffer + (INTSIZE * 2) + (iloop * 3 * INTSIZE));
679  ilength += pskptr->kp_leng;
680  }
681  inl_stint (ilength, pcbuffer - INTSIZE);
682  ilength = (INTSIZE * 4) + (INTSIZE * 3 * (pskeydesc->k_nparts));
683  iserrno = iwritetrans (ilength, 0);
684  if (iserrno) {
685  return -1;
686  }
687  return 0;
688 }
689 
690 int
692 {
693  /* BUG - Write ivbtranscluster */
694  return 0;
695 }
696 
697 int
698 ivbtransdelete (const int ihandle, off_t trownumber, int irowlength)
699 {
700  struct DICTINFO *psvbptr;
701  char *pcbuffer;
702 
703  psvbptr = psvbfile[ihandle];
704  if (ivblogfilehandle < 0 || psvbptr->iopenmode & ISNOLOG) {
705  return 0;
706  }
707  /* Don't log transactions if we're in rollback / recover mode */
708  if (ivbintrans > VBNEEDFLUSH) {
709  return 0;
710  }
711  if (ivbintrans == VBBEGIN) {
712  if (iwritebegin ()) {
713  return -1;
714  }
715  }
716  if (psvbptr->itransyet == 0) {
717  ivbtransopen (ihandle, psvbptr->cfilename);
718  }
720  pcbuffer = cvbtransbuffer + sizeof (struct SLOGHDR);
721  inl_stint (ihandle, pcbuffer);
722  inl_stquad (trownumber, pcbuffer + INTSIZE);
723  inl_stint (irowlength, pcbuffer + INTSIZE + QUADSIZE);
724  memcpy (pcbuffer + INTSIZE + QUADSIZE + INTSIZE, psvbptr->ppcrowbuffer, (size_t)irowlength);
725  irowlength += (INTSIZE * 2) + QUADSIZE;
726  iserrno = iwritetrans (irowlength, 1);
727  if (iserrno) {
728  return -1;
729  }
730  return 0;
731 }
732 
733 int
734 ivbtransdeleteindex (const int ihandle, struct keydesc *pskeydesc)
735 {
736  char *pcbuffer;
737  struct keypart *pskptr;
738  int ilength = 0, iloop;
739 
740  if (ivblogfilehandle < 0 || psvbfile[ihandle]->iopenmode & ISNOLOG) {
741  return 0;
742  }
743  /* Don't log transactions if we're in rollback / recover mode */
744  if (ivbintrans > VBNEEDFLUSH) {
745  return 0;
746  }
747  if (ivbintrans == VBBEGIN) {
748  if (iwritebegin ()) {
749  return -1;
750  }
751  }
753  pcbuffer = cvbtransbuffer + sizeof (struct SLOGHDR);
754  inl_stint (ihandle, pcbuffer);
755  inl_stint (pskeydesc->k_flags, pcbuffer + INTSIZE);
756  inl_stint (pskeydesc->k_nparts, pcbuffer + (2 * INTSIZE));
757  pcbuffer += (INTSIZE * 4);
758  for (iloop = 0; iloop < pskeydesc->k_nparts; iloop++) {
759  pskptr = &pskeydesc->k_part[iloop];
760  inl_stint (pskptr->kp_start, pcbuffer + (iloop * 3 * INTSIZE));
761  inl_stint (pskptr->kp_leng,
762  pcbuffer + INTSIZE + (iloop * 3 * INTSIZE));
763  inl_stint (pskptr->kp_type,
764  pcbuffer + (INTSIZE * 2) + (iloop * 3 * INTSIZE));
765  ilength += pskptr->kp_leng;
766  }
767  inl_stint (ilength, pcbuffer - INTSIZE);
768  ilength = (INTSIZE * 4) + (INTSIZE * 3 * (pskeydesc->k_nparts));
769  iserrno = iwritetrans (ilength, 0);
770  if (iserrno) {
771  return -1;
772  }
773  return 0;
774 }
775 
776 int
777 ivbtranserase (const char *pcfilename)
778 {
779  char *pcbuffer;
780  int ilength;
781 
782  if (ivblogfilehandle < 0) {
783  return 0;
784  }
785  /* Don't log transactions if we're in rollback / recover mode */
786  if (ivbintrans > VBNEEDFLUSH) {
787  return 0;
788  }
789  if (ivbintrans == VBBEGIN) {
790  if (iwritebegin ()) {
791  return -1;
792  }
793  }
795  ilength = strlen (pcfilename) + 1;
796  pcbuffer = cvbtransbuffer + sizeof (struct SLOGHDR);
797  memcpy (pcbuffer, pcfilename, (size_t)ilength);
798  iserrno = iwritetrans (ilength, 0);
799  if (iserrno) {
800  return -1;
801  }
802  return 0;
803 }
804 
805 int
806 ivbtransclose (const int ihandle, const char *pcfilename)
807 {
808  struct DICTINFO *psvbptr;
809  char *pcbuffer;
810  int ilength;
811 
812  psvbptr = psvbfile[ihandle];
813  if (ivblogfilehandle < 0 || psvbptr->iopenmode & ISNOLOG) {
814  return 0;
815  }
816  /* Don't log transactions if we're in rollback / recover mode */
817  if (ivbintrans > VBROLLBACK) {
818  return 0;
819  }
820  if (psvbptr->itransyet == 0) {
821  return 0;
822  }
823  if (ivbintrans == VBBEGIN) {
824  if (iwritebegin ()) {
825  return -1;
826  }
827  }
829  ilength = strlen (pcfilename) + 1;
830  pcbuffer = cvbtransbuffer + sizeof (struct SLOGHDR);
831  inl_stint (ihandle, pcbuffer);
832  inl_stint (psvbptr->iopenmode & ISVARLEN, pcbuffer + INTSIZE); /* VARLEN flag! */
833  memcpy (pcbuffer + INTSIZE + INTSIZE, pcfilename, (size_t)ilength);
834  ilength += (INTSIZE * 2);
835  iserrno = iwritetrans (ilength, 0);
836  if (iserrno) {
837  return -1;
838  }
839  return 0;
840 }
841 
842 int
843 ivbtransopen (const int ihandle, const char *pcfilename)
844 {
845  struct DICTINFO *psvbptr;
846  char *pcbuffer;
847  int ilength;
848 
849  psvbptr = psvbfile[ihandle];
850  if (ivblogfilehandle < 0 || psvbptr->iopenmode & ISNOLOG) {
851  return 0;
852  }
853  /* Don't log transactions if we're in rollback / recover mode */
854  if (ivbintrans > VBNEEDFLUSH) {
855  return 0;
856  }
857  if (ivbintrans == VBBEGIN) {
858  if (iwritebegin ()) {
859  return -1;
860  }
861  }
862  psvbptr->itransyet = 2;
864  ilength = strlen (pcfilename) + 1;
865  pcbuffer = cvbtransbuffer + sizeof (struct SLOGHDR);
866  inl_stint (ihandle, pcbuffer);
867  inl_stint (psvbptr->iopenmode & ISVARLEN, pcbuffer + INTSIZE); /* VARLEN flag! */
868  memcpy (pcbuffer + INTSIZE + INTSIZE, pcfilename, (size_t)ilength);
869  ilength += (INTSIZE * 2);
870  iserrno = iwritetrans (ilength, 0);
871  if (iserrno) {
872  return -1;
873  }
874  return 0;
875 }
876 
877 int
878 ivbtransinsert (const int ihandle, const off_t trownumber, int irowlength, char *pcrow)
879 {
880  struct DICTINFO *psvbptr;
881  char *pcbuffer;
882 
883  psvbptr = psvbfile[ihandle];
884  if (ivblogfilehandle < 0 || psvbptr->iopenmode & ISNOLOG) {
885  return 0;
886  }
887  /* Don't log transactions if we're in rollback / recover mode */
888  if (ivbintrans > VBNEEDFLUSH) {
889  return 0;
890  }
891  if (ivbintrans == VBBEGIN) {
892  if (iwritebegin ()) {
893  return -1;
894  }
895  }
896  if (psvbptr->itransyet == 0) {
897  ivbtransopen (ihandle, psvbptr->cfilename);
898  }
900  pcbuffer = cvbtransbuffer + sizeof (struct SLOGHDR);
901  inl_stint (ihandle, pcbuffer);
902  inl_stquad (trownumber, pcbuffer + INTSIZE);
903  inl_stint (irowlength, pcbuffer + INTSIZE + QUADSIZE);
904  memcpy (pcbuffer + INTSIZE + QUADSIZE + INTSIZE, pcrow, (size_t)irowlength);
905  irowlength += (INTSIZE * 2) + QUADSIZE;
906  iserrno = iwritetrans (irowlength, 1);
907  if (iserrno) {
908  return -1;
909  }
910  return 0;
911 }
912 
913 int
914 ivbtransrename (char *pcoldname, char *pcnewname)
915 {
916  char *pcbuffer;
917  int ilength, ilength1, ilength2;
918 
919  if (ivblogfilehandle < 0) {
920  return 0;
921  }
922  /* Don't log transactions if we're in rollback / recover mode */
923  if (ivbintrans > VBNEEDFLUSH) {
924  return 0;
925  }
926  if (ivbintrans == VBBEGIN) {
927  if (iwritebegin ()) {
928  return -1;
929  }
930  }
932  pcbuffer = cvbtransbuffer + sizeof (struct SLOGHDR);
933  ilength1 = strlen (pcoldname) + 1;
934  ilength2 = strlen (pcnewname) + 1;
935  inl_stint (ilength1, pcbuffer);
936  inl_stint (ilength2, pcbuffer + INTSIZE);
937  memcpy (pcbuffer + (INTSIZE * 2), pcoldname, (size_t)ilength1);
938  memcpy (pcbuffer + (INTSIZE * 2) + ilength1, pcnewname, (size_t)ilength2);
939  ilength = (INTSIZE * 2) + ilength1 + ilength2;
940  iserrno = iwritetrans (ilength, 0);
941  if (iserrno) {
942  return -1;
943  }
944  return 0;
945 }
946 
947 int
948 ivbtranssetunique (const int ihandle, const off_t tuniqueid)
949 {
950  struct DICTINFO *psvbptr;
951  char *pcbuffer;
952 
953  psvbptr = psvbfile[ihandle];
954  if (ivblogfilehandle < 0 || psvbptr->iopenmode & ISNOLOG) {
955  return 0;
956  }
957  /* Don't log transactions if we're in rollback / recover mode */
958  if (ivbintrans > VBNEEDFLUSH) {
959  return 0;
960  }
961  if (ivbintrans == VBBEGIN) {
962  if (iwritebegin ()) {
963  return -1;
964  }
965  }
966  if (psvbptr->itransyet == 0) {
967  ivbtransopen (ihandle, psvbptr->cfilename);
968  }
970  pcbuffer = cvbtransbuffer + sizeof (struct SLOGHDR);
971  inl_stint (ihandle, pcbuffer);
972  inl_stquad (tuniqueid, pcbuffer + INTSIZE);
973  iserrno = iwritetrans (INTSIZE + QUADSIZE, 0);
974  if (iserrno) {
975  return -1;
976  }
977  return 0;
978 }
979 
980 int
981 ivbtransuniqueid (const int ihandle, const off_t tuniqueid)
982 {
983  struct DICTINFO *psvbptr;
984  char *pcbuffer;
985 
986  psvbptr = psvbfile[ihandle];
987  if (ivblogfilehandle < 0 || (psvbptr->iopenmode & ISNOLOG)) {
988  return 0;
989  }
990  /* Don't log transactions if we're in rollback / recover mode */
991  if (ivbintrans > VBNEEDFLUSH) {
992  return 0;
993  }
994  if (ivbintrans == VBBEGIN) {
995  if (iwritebegin ()) {
996  return -1;
997  }
998  }
999  if (psvbptr->itransyet == 0) {
1000  ivbtransopen (ihandle, psvbptr->cfilename);
1001  }
1003  pcbuffer = cvbtransbuffer + sizeof (struct SLOGHDR);
1004  inl_stint (ihandle, pcbuffer);
1005  inl_stquad (tuniqueid, pcbuffer + INTSIZE);
1006  iserrno = iwritetrans (INTSIZE + QUADSIZE, 0);
1007  if (iserrno) {
1008  return -1;
1009  }
1010  return 0;
1011 }
1012 
1013 int
1014 ivbtransupdate (const int ihandle, const off_t trownumber, const int ioldrowlen, const int inewrowlen, const char *pcrow)
1015 {
1016  struct DICTINFO *psvbptr;
1017  char *pcbuffer;
1018  int ilength;
1019 
1020  psvbptr = psvbfile[ihandle];
1021  if (ivblogfilehandle < 0 || (psvbptr->iopenmode & ISNOLOG)) {
1022  return 0;
1023  }
1024  /* Don't log transactions if we're in rollback / recover mode */
1025  if (ivbintrans > VBNEEDFLUSH) {
1026  return 0;
1027  }
1028  if (ivbintrans == VBBEGIN) {
1029  if (iwritebegin ()) {
1030  return -1;
1031  }
1032  }
1033  if (psvbptr->itransyet == 0) {
1034  ivbtransopen (ihandle, psvbptr->cfilename);
1035  }
1037  pcbuffer = cvbtransbuffer + sizeof (struct SLOGHDR);
1038  inl_stint (ihandle, pcbuffer);
1039  inl_stquad (trownumber, pcbuffer + INTSIZE);
1040  inl_stint (ioldrowlen, pcbuffer + INTSIZE + QUADSIZE);
1041  inl_stint (inewrowlen, pcbuffer + INTSIZE + QUADSIZE + INTSIZE);
1042  memcpy (pcbuffer + INTSIZE + QUADSIZE + INTSIZE + INTSIZE, psvbptr->ppcrowbuffer,
1043  (size_t)ioldrowlen);
1044  memcpy (pcbuffer + INTSIZE + QUADSIZE + INTSIZE + INTSIZE + ioldrowlen, pcrow,
1045  (size_t)inewrowlen);
1046  ilength = INTSIZE + QUADSIZE + (INTSIZE * 2) + ioldrowlen + inewrowlen;
1047  iserrno = iwritetrans (ilength, 1);
1048  if (iserrno) {
1049  return -1;
1050  }
1051  return 0;
1052 }
ssize_t tvbwrite(const int ihandle, const void *pvbuffer, const size_t tcount)
Definition: vblowlevel.c:127
int ivblock(const int ihandle, const off_t toffset, const off_t tlength, const int imode)
Definition: vblowlevel.c:197
int ivbopen(const char *pcfilename, const int iflags, const mode_t tmode)
Definition: vblowlevel.c:32
static void vinitpiduid(void)
Definition: istrans.c:34
#define VBBEGIN
Definition: isinternal.h:307
int ivbtransuniqueid(const int ihandle, const off_t tuniqueid)
Definition: istrans.c:981
int ivbforcedataallocate(const int ihandle, const off_t trownumber)
Definition: vbindexio.c:355
#define VBL_FILEOPEN
Definition: isinternal.h:477
static int inl_ldint(void *pclocation)
Definition: isinternal.h:170
int ivbtransbuild(const char *pcfilename, const int iminrowlen, const int imaxrowlen, struct keydesc *pskeydesc, const int imode)
Definition: istrans.c:599
char cuid[2]
Definition: isinternal.h:489
static int iwritebegin(void)
Definition: istrans.c:136
int ivbtransdelete(const int ihandle, off_t trownumber, int irowlength)
Definition: istrans.c:698
int ivbtransinsert(const int ihandle, const off_t trownumber, int irowlength, char *pcrow)
Definition: istrans.c:878
#define VBL_UPDATE
Definition: isinternal.h:483
#define VBL_COMMIT
Definition: isinternal.h:472
static pid_t tvbpid
Definition: istrans.c:27
#define VBL_BUILD
Definition: isinternal.h:468
static int idemotelocks(void)
Definition: istrans.c:167
int ivbdatafree(const int ihandle, const off_t trownumber)
Definition: vbindexio.c:150
static int ivbrollmeforward(off_t toffset)
Definition: istrans.c:334
int isrewrec(const int ihandle, const long long trownumber, char *pcrow)
Definition: isrewrite.c:298
#define VBCOMMIT
Definition: isinternal.h:309
int isdelrec(const int ihandle, long long trownumber)
Definition: isdelete.c:189
int isreclen
Definition: vbmemio.c:29
static char cvbtransbuffer[65536]
Definition: istrans.c:29
static void inl_stlong(int lvalue, void *pclocation)
Definition: isinternal.h:226
#define VBL_DELETE
Definition: isinternal.h:473
int ivbenter(const int ihandle, const unsigned int imodifying, const unsigned int ispecial)
Definition: vblocking.c:178
static int iwritetrans(int itranslength, const int irollback)
Definition: istrans.c:89
#define VBL_UNIQUEID
Definition: isinternal.h:482
#define VBNOTRANS
Definition: isinternal.h:306
#define O_BINARY
Definition: fileio.c:90
char * cfilename
Definition: isinternal.h:422
char crfu1[2]
Definition: isinternal.h:491
char clastposn[2]
Definition: isinternal.h:492
int ivbmaxusedhandle
Definition: vblocking.c:26
int iisopen
Definition: isinternal.h:407
#define VBL_DELINDEX
Definition: isinternal.h:474
int ivbtranserase(const char *pcfilename)
Definition: istrans.c:777
int ivbtranscluster()
Definition: istrans.c:691
static void inl_stint(int ivalue, void *pclocation)
Definition: isinternal.h:190
#define VBNEEDFLUSH
Definition: isinternal.h:308
#define VBWRLCKW
Definition: isinternal.h:298
unsigned char iisdictlocked
Definition: isinternal.h:427
int isopen(const char *pcfilename, int imode)
Definition: isopen.c:270
EC ARGUMENT EC EC BOUND EC BOUND EC BOUND EC BOUND TABLE EC DATA EC DATA EC DATA PTR NULL
Definition: exception.def:95
static int ivbrollmeback(off_t toffset, const int iinrecover)
Definition: istrans.c:195
int ivbdatalock(const int ihandle, const int imode, const off_t trownumber)
Definition: vblocking.c:432
#define VBL_CREINDEX
Definition: isinternal.h:470
int ivbtranssetunique(const int ihandle, const off_t tuniqueid)
Definition: istrans.c:948
int ivbtransclose(const int ihandle, const char *pcfilename)
Definition: istrans.c:806
int iscommit(void)
Definition: istrans.c:463
#define VBL_FILEERASE
Definition: isinternal.h:475
int isrollback(void)
Definition: istrans.c:543
int ivbwriterow(const int ihandle, char *pcrow, const off_t trownumber)
Definition: iswrite.c:85
#define VB_MAX_FILES
Definition: isinternal.h:120
#define VBL_ROLLBACK
Definition: isinternal.h:480
int isbegin(void)
Definition: istrans.c:448
int ivbtransrename(char *pcoldname, char *pcnewname)
Definition: istrans.c:914
struct DICTINFO * psvbfile[128+1]
Definition: vblowlevel.c:23
#define QUADSIZE
Definition: isinternal.h:108
char coperation[2]
Definition: isinternal.h:487
int ivbtransopen(const int ihandle, const char *pcfilename)
Definition: istrans.c:843
char cpid[2]
Definition: isinternal.h:488
unsigned char iisdatalocked
Definition: isinternal.h:426
int ivblogfilehandle
Definition: istrans.c:24
int ivbclose(const int ihandle)
Definition: vblowlevel.c:93
int ivbexit(const int ihandle)
Definition: vblocking.c:290
int islogclose(void)
Definition: istrans.c:509
#define VBL_INSERT
Definition: isinternal.h:478
int iopenmode
Definition: isinternal.h:412
int isclose(const int ihandle)
Definition: isopen.c:182
static uid_t tvbuid
Definition: istrans.c:28
static void inl_stquad(off_t tvalue, void *pclocation)
Definition: isinternal.h:260
ssize_t tvbread(const int ihandle, void *pvbuffer, const size_t tcount)
Definition: vblowlevel.c:117
#define VBL_FILECLOSE
Definition: isinternal.h:476
int ivbtranscreateindex(int const ihandle, struct keydesc *pskeydesc)
Definition: istrans.c:648
#define VBL_BEGIN
Definition: isinternal.h:469
#define VBROLLBACK
Definition: isinternal.h:310
#define MAX_BUFFER_LENGTH
Definition: isinternal.h:291
static void vtranshdr(const char *pctranstype)
Definition: istrans.c:53
#define VBL_RENAME
Definition: isinternal.h:479
int ivbintrans
Definition: istrans.c:23
#define VBUNLOCK
Definition: isinternal.h:294
#define VBL_SETUNIQUE
Definition: isinternal.h:481
struct keydesc * pskeydesc[32]
Definition: isinternal.h:445
static off_t inl_ldquad(void *pclocation)
Definition: isinternal.h:238
off_t trownumber
Definition: isinternal.h:416
char ctime[4]
Definition: isinternal.h:490
int islogopen(const char *pcfilename)
Definition: istrans.c:529
unsigned char itransyet
Definition: isinternal.h:438
char clastlength[2]
Definition: isinternal.h:493
int ivbtransdeleteindex(const int ihandle, struct keydesc *pskeydesc)
Definition: istrans.c:734
char * ppcrowbuffer
Definition: isinternal.h:423
static int iinitialized
Definition: vblowlevel.c:26
int iserrno
Definition: vbmemio.c:27
static struct SLOGHDR * psvblogheader
Definition: istrans.c:26
int ivbclose2(const int ihandle)
Definition: isopen.c:83
int ivbtransupdate(const int ihandle, const off_t trownumber, const int ioldrowlen, const int inewrowlen, const char *pcrow)
Definition: istrans.c:1014
off_t tvblseek(const int ihandle, off_t toffset, const int iwhence)
Definition: vblowlevel.c:107