1 /*
2 * Motif
3 *
4 * Copyright (c) 1987-2012, The Open Group. All rights reserved.
5 *
6 * These libraries and programs are free software; you can
7 * redistribute them and/or modify them under the terms of the GNU
8 * Lesser General Public License as published by the Free Software
9 * Foundation; either version 2 of the License, or (at your option)
10 * any later version.
11 *
12 * These libraries and programs are distributed in the hope that
13 * they will be useful, but WITHOUT ANY WARRANTY; without even the
14 * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15 * PURPOSE. See the GNU Lesser General Public License for more
16 * details.
17 *
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with these librararies and programs; if not, write
20 * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
21 * Floor, Boston, MA 02110-1301 USA
22 */
23
24 #ifdef HAVE_CONFIG_H
25 #include <config.h>
26 #endif
27
28
29 #ifdef REV_INFO
30 #ifndef lint
31 static char rcsid[] = "$XConsortium: MrmIbuffer.c /main/16 1996/11/13 13:55:44 drk $"
32 #endif
33 #endif
34
35 /*
36 *++
37 * FACILITY:
38 *
39 * UIL Resource Manager (URM): IDB Facility
40 * Buffer management routines
41 *
42 * ABSTRACT:
43 *
44 * These routines manage the buffer pool for all IDB files, and manage
45 * reading and writing actual file records into these buffers on request.
46 *
47 *--
48 */
49
50
51 /*
52 *
53 * INCLUDE FILES
54 *
55 */
56
57 #include <Mrm/MrmAppl.h>
58 #include <Mrm/Mrm.h>
59 #include <Mrm/IDB.h>
60 #include "MrmMsgI.h"
61
62 /*
63 *
64 * TABLE OF CONTENTS
65 *
66 * Idb__BM_InitBufferVector - Allocates and initializes
67 * the buffer vector
68 *
69 * Idb__BM_GetBuffer - Acquire a free buffer
70 *
71 * Idb__BM_MarkActivity - Mark a buffer as having seen activity
72 *
73 * Idb__BM_MarkModified - Mark a buffer as modified for write
74 *
75 * Idb__BM_GetRecord - Get a record into some buffer
76 *
77 * Idb__BM_InitRecord - Initialize a new record into
78 * some buffer
79 *
80 * Idb__BM_InitDataRecord - Initialize a new data record into
81 * some buffer
82 *
83 * Idb__BM_Decommit - Through with buffer contents
84 *
85 * Idb__BM_DecommitAll - Decommit all buffers for some file
86 */
87
88 /*
89 *
90 * OWN VARIABLE DECLARATIONS
91 *
92 */
93
94 /*
95 * This module manages a pool of buffers for all open IDB files. The pool
96 * is located and managed via the following globals.
97 */
98
99 /*
100 * The following defines the number of buffers in the buffer pool. Once
101 * the pool is initialized, this number is invariant (currently). This
102 * variable will be accessible via currently undefined means for applications
103 * to tailor the buffer pool size at startup.
104 */
105 externaldef(idb__buffer_pool_size) int idb__buffer_pool_size = 8 ;
106
107
108 /*
109 * The following pointer locates a vector of pointers to buffers. This pointer
110 * is initially NULL. The first request for a buffer detects that the buffer
111 * has not been allocated, and does the following:
112 * o Allocate a vector of buffer pointers (IDBRecordBufferPtr) containing
113 * the number of entries specified in idb__buffer_pool_size.
114 *
115 * Thereafter, this vector locates the buffer pool.
116 */
117 static IDBRecordBufferPtr idb__buffer_pool_vec = NULL ;
118
119
120 /*
121 * The following counter is used to maintain the activity count in all
122 * buffers.
123 */
124 static long int idb__buffer_activity_count = 1 ;
125
126
127
128 /*
129 *++
130 *
131 * PROCEDURE DESCRIPTION:
132 *
133 * Idb__BM_InitBufferVector is responsible for initializaing
134 * the buffer pool. This routine allocates the vector of record
135 * buffers, but does not allocate the actual buffer for each
136 * record, which is done on demand.
137 *
138 * FORMAL PARAMETERS:
139 *
140 * IMPLICIT INPUTS:
141 *
142 * IMPLICIT OUTPUTS:
143 *
144 * FUNCTION VALUE:
145 *
146 * MrmSUCCESS operation succeeded
147 * MrmFAILURE some other failure
148 *
149 * SIDE EFFECTS:
150 *
151 *--
152 */
153
154 Cardinal
Idb__BM_InitBufferVector(void)155 Idb__BM_InitBufferVector (void)
156 {
157
158 /*
159 * Local variables
160 */
161 Cardinal ndx ; /* loop variable */
162 IDBRecordBufferPtr bufptr ; /* entry into buffer pool vector */
163
164 idb__buffer_pool_vec = (IDBRecordBufferPtr) XtMalloc
165 (idb__buffer_pool_size*sizeof(IDBRecordBuffer)) ;
166 if ( idb__buffer_pool_vec == NULL )
167 return Urm__UT_Error ("Idb__BM_InitBufferVector", _MrmMMsg_0000,
168 NULL, NULL, MrmFAILURE) ;
169
170 for ( ndx=0,bufptr=idb__buffer_pool_vec ;
171 ndx<idb__buffer_pool_size ;
172 ndx++,bufptr++ )
173 {
174 bufptr->validation = IDBRecordBufferValid;
175 bufptr->activity = 0 ;
176 bufptr->access = 0 ;
177 bufptr->cur_file = NULL ;
178 bufptr->modified = FALSE ;
179 bufptr->IDB_record = NULL ;
180 }
181
182 return MrmSUCCESS;
183
184 }
185
186
187 /*
188 *++
189 *
190 * PROCEDURE DESCRIPTION:
191 *
192 * Idb__BM_GetBuffer acquires a buffer from the buffer pool. The
193 * buffer chosen is some buffer with the lowest activity count. If
194 * necessary, its contents are written to disk. Note that a buffer
195 * which has been decommitted (activity count = 0) may be used
196 * immediately - a search for a buffer with a lower activity count
197 * is not required.
198 *
199 * This routine is responsible for initializaing the buffer pool if
200 * it is not initialized. It is also responsible for acquiring
201 * a record buffer if a buffer pool vector entry is needed but has none.
202 *
203 * FORMAL PARAMETERS:
204 *
205 * file_id Open IDB file
206 * buffer_return Returns a free buffer, contents undefined
207 *
208 * IMPLICIT INPUTS:
209 *
210 * IMPLICIT OUTPUTS:
211 *
212 * FUNCTION VALUE:
213 *
214 * MrmSUCCESS operation succeeded
215 * MrmFAILURE some other failure
216 *
217 * SIDE EFFECTS:
218 *
219 *--
220 */
221
222 Cardinal
Idb__BM_GetBuffer(IDBFile file_id,IDBRecordBufferPtr * buffer_return)223 Idb__BM_GetBuffer (IDBFile file_id,
224 IDBRecordBufferPtr *buffer_return)
225 {
226
227 /*
228 * Local macro to complete allocation of a buffer to a file, and
229 * mark its activity.
230 */
231 #define _IDB_Getbuffer_return() \
232 { \
233 (*buffer_return)->cur_file = file_id; \
234 (*buffer_return)->access = file_id->access; \
235 Idb__BM_MarkActivity (*buffer_return); \
236 return MrmSUCCESS; \
237 }
238
239 /*
240 * Local variables
241 */
242 Cardinal result ; /* function results */
243 int ndx ; /* loop index */
244 long int lowest ; /* lowest activity count found */
245 IDBRecordBufferPtr curbuf ; /* current buffer being examined */
246
247 /*
248 * If the buffer pool is uninitialized, allocate it and
249 * return the first buffer in the pool. Else search the buffer pool for the
250 * buffer with the lowest activity. Decommited/0 activity buffers can
251 * be returned immediately.
252 */
253 if (idb__buffer_pool_vec == NULL)
254 {
255 result = Idb__BM_InitBufferVector () ;
256 if ( result != MrmSUCCESS ) return result ;
257 *buffer_return = idb__buffer_pool_vec ;
258 }
259 else
260 {
261 lowest = idb__buffer_activity_count;
262 for ( ndx=0,curbuf=idb__buffer_pool_vec ;
263 ndx<idb__buffer_pool_size ;
264 ndx++,curbuf++ )
265 {
266 if ( curbuf->activity == 0 )
267 {
268 *buffer_return = curbuf ;
269 break ;
270 }
271 if ( curbuf->activity < lowest )
272 {
273 *buffer_return = curbuf ;
274 lowest = curbuf->activity ;
275 }
276 }
277 }
278
279 /*
280 * Allocate a record buffer if required, and return immediately if
281 * the buffer is decommitted or not yet used.
282 */
283 if ( (*buffer_return)->IDB_record == NULL )
284 {
285 (*buffer_return)->IDB_record =
286 (IDBDummyRecord *) XtMalloc(sizeof(IDBDummyRecord)) ;
287 if ( (*buffer_return)->IDB_record == NULL )
288 return Urm__UT_Error ("Idb__BM_GetBuffer",
289 _MrmMMsg_0001, NULL, NULL, MrmFAILURE) ;
290 _IDB_Getbuffer_return ();
291 }
292 if ( (*buffer_return)->activity == 0 ) _IDB_Getbuffer_return ();
293
294 /*
295 * We have set the buffer pointer. See if it needs to be updated on
296 * disk, and do so if required.
297 */
298 if ( ((*buffer_return)->access == URMWriteAccess) &&
299 ((*buffer_return)->modified) )
300 {
301 result = Idb__BM_Decommit (*buffer_return) ;
302 if ( result != MrmSUCCESS ) return result ;
303 }
304
305 /*
306 * Allocate the buffer to the file, and return.
307 */
308 _IDB_Getbuffer_return ();
309
310 }
311
312
313 /*
314 *++
315 *
316 * PROCEDURE DESCRIPTION:
317 *
318 * Idb__BM_MarkActivity asserts that the buffer has seen some activity,
319 * and updates its activity count. This is done by storing the current
320 * idb__buffer_activity_count++ in the buffer.
321 *
322 * FORMAL PARAMETERS:
323 *
324 * buffer Record buffer to mark as modified
325 *
326 * IMPLICIT INPUTS:
327 *
328 * IMPLICIT OUTPUTS:
329 *
330 * FUNCTION VALUE:
331 *
332 * MrmSUCCESS operation succeeded
333 * MrmFAILURE some other failure
334 *
335 * SIDE EFFECTS:
336 *
337 *--
338 */
339
340 Cardinal
Idb__BM_MarkActivity(IDBRecordBufferPtr buffer)341 Idb__BM_MarkActivity (IDBRecordBufferPtr buffer)
342 {
343
344 if ( ! Idb__BM_Valid(buffer) )
345 return Urm__UT_Error ("Idb__BM_MarkActivity", _MrmMMsg_0002,
346 NULL, NULL, MrmNOT_VALID) ;
347 buffer->activity = idb__buffer_activity_count++ ;
348 return MrmSUCCESS ;
349
350 }
351
352
353
354 /*
355 *++
356 *
357 * PROCEDURE DESCRIPTION:
358 *
359 * Idb__BM_MarkModified asserts that the buffer has been modified,
360 * and sets its modify flag. Its activity count is updated.
361 *
362 * FORMAL PARAMETERS:
363 *
364 * buffer Record buffer to mark as modified
365 *
366 * IMPLICIT INPUTS:
367 *
368 * IMPLICIT OUTPUTS:
369 *
370 * FUNCTION VALUE:
371 *
372 * MrmSUCCESS operation succeeded
373 * MrmFAILURE some other failure
374 *
375 * SIDE EFFECTS:
376 *
377 *--
378 */
379
380 Cardinal
Idb__BM_MarkModified(IDBRecordBufferPtr buffer)381 Idb__BM_MarkModified (IDBRecordBufferPtr buffer)
382
383 {
384
385 if ( ! Idb__BM_Valid(buffer) )
386 return Urm__UT_Error ("Idb__BM_MarkModified", _MrmMMsg_0002,
387 NULL, NULL, MrmNOT_VALID) ;
388 buffer->activity = idb__buffer_activity_count++ ;
389 buffer->modified = TRUE ;
390 return MrmSUCCESS ;
391
392 }
393
394
395
396 /*
397 *++
398 *
399 * PROCEDURE DESCRIPTION:
400 *
401 * Idb__BM_GetRecord reads a record from an open IDB file into a buffer.
402 * If the record is already available in some buffer, then that buffer is
403 * returned without re-reading the record from disk. Otherwise, a buffer is
404 * acquired, the record read into it, and the buffer is returned. The
405 * buffer's activity count is updated.
406 *
407 * FORMAL PARAMETERS:
408 *
409 * file_id Open IDB file
410 * record The desired record number
411 * buffer_return Returns buffer containing record
412 *
413 * IMPLICIT INPUTS:
414 *
415 * IMPLICIT OUTPUTS:
416 *
417 * FUNCTION VALUE:
418 *
419 * MrmSUCCESS operation succeeded
420 * MrmNOT_FOUND record doesn't exist
421 * MrmFAILURE some other failure
422 *
423 * SIDE EFFECTS:
424 *
425 *--
426 */
427
428 Cardinal
Idb__BM_GetRecord(IDBFile file_id,IDBRecordNumber record,IDBRecordBufferPtr * buffer_return)429 Idb__BM_GetRecord (IDBFile file_id,
430 IDBRecordNumber record,
431 IDBRecordBufferPtr *buffer_return)
432 {
433
434 /*
435 * Local variables
436 */
437 Cardinal result ; /* function results */
438 int ndx ; /* loop index */
439 IDBRecordBufferPtr curbuf ; /* current buffer being examined */
440 unsigned char *buf_src; /* tmp pointer to location in uid buffer */
441
442 /*
443 * If buffer pool is unallocated, get a buffer (which WILL allocate it),
444 * and read the record into that. Else see if the record is already in
445 * memory, and return it if so. If the record is not found, get a buffer
446 * to read it into. We exit this if statement with a buffer ready for
447 * the read operation.
448 */
449 if ( idb__buffer_pool_vec == NULL )
450 {
451 result = Idb__BM_GetBuffer (file_id, buffer_return) ;
452 if ( result != MrmSUCCESS ) return result ;
453 }
454 else
455 {
456 for ( ndx=0,curbuf=idb__buffer_pool_vec ;
457 ndx<idb__buffer_pool_size ;
458 ndx++,curbuf++ )
459 {
460 if ( (curbuf->cur_file==file_id) &&
461 (curbuf->IDB_record->header.record_num==record) )
462 {
463 *buffer_return = curbuf ;
464 Idb__BM_MarkActivity (*buffer_return) ;
465 return MrmSUCCESS ;
466 }
467 }
468 result = Idb__BM_GetBuffer (file_id, buffer_return) ;
469 if ( result != MrmSUCCESS ) return result ;
470 }
471
472 /*
473 * Read the record into the buffer.
474 */
475 if ( file_id->in_memory ) {
476 buf_src = file_id->uid_buffer + (record-1)*IDBRecordSize;
477 UrmBCopy(buf_src, (*buffer_return)->IDB_record, IDBRecordSize);
478 result = MrmSUCCESS;
479 }
480 else
481 result = Idb__FU_GetBlock(file_id->lowlevel_id, record,
482 (char*)(*buffer_return)->IDB_record) ;
483
484
485 if ( result != MrmSUCCESS )
486 return Urm__UT_Error ("Idb__BM_GetRecord", _MrmMMsg_0003,
487 file_id, NULL, result) ;
488 file_id->get_count++ ;
489
490 /*
491 * Validate the record, this is the first routine that is called to read
492 * from a newly opened file. If the byte order is different, we find it
493 * here.
494 */
495
496
497 if ( (*buffer_return)->IDB_record->header.validation !=
498 IDBRecordHeaderValid ) {
499 swapbytes( (*buffer_return)->IDB_record->header.validation );
500 if ((*buffer_return)->IDB_record->header.validation == IDBRecordHeaderValid)
501 {
502 /* must be a file needing byte swapping */
503 file_id->byte_swapped = TRUE;
504 Idb__BM_SwapRecordBytes (*buffer_return);
505 Idb__BM_MarkActivity (*buffer_return);
506 return MrmSUCCESS ;
507 }
508 /* byte swapping has done no good, return error */
509 return Urm__UT_Error("Idb__BM_GetRecord", _MrmMMsg_0005,
510 file_id, NULL, MrmNOT_VALID) ;
511 }
512
513 /*
514 * Record successfully read
515 */
516 Idb__BM_MarkActivity (*buffer_return) ;
517 return MrmSUCCESS ;
518
519 }
520
521
522
523 /*
524 *++
525 *
526 * PROCEDURE DESCRIPTION:
527 *
528 * Idb__BM_InitRecord initializes a new record for the file. A buffer
529 * is acquired, and the record number and record type set. The record
530 * number may be specified; if the record number given is <= 0, then the
531 * next available record is taken from the file header. The next
532 * available record number is updated to the new record number if it is
533 * greater than the current value. The record is marked for write access,
534 * and as modified. It is not written to disk. The buffer's activity
535 * count is updated.
536 *
537 * FORMAL PARAMETERS:
538 *
539 * file_id Open IDB file
540 * record The desired record number. This will be a new record in
541 * the file
542 * type The record type, from IDBrt...
543 * buffer_return Returns buffer initialized for record, with type set.
544 * Access is URMWriteAccess, modified.
545 *
546 * IMPLICIT INPUTS:
547 *
548 * IMPLICIT OUTPUTS:
549 *
550 * FUNCTION VALUE:
551 *
552 * MrmSUCCESS operation succeeded
553 * MrmFAILURE some other failure
554 *
555 * SIDE EFFECTS:
556 *
557 *--
558 */
559
560 Cardinal
Idb__BM_InitRecord(IDBFile file_id,IDBRecordNumber record,MrmType type,IDBRecordBufferPtr * buffer_return)561 Idb__BM_InitRecord (IDBFile file_id,
562 IDBRecordNumber record,
563 MrmType type,
564 IDBRecordBufferPtr *buffer_return)
565 {
566
567
568 if ((Idb__BM_GetBuffer (file_id, buffer_return)) != MrmSUCCESS)
569 return MrmFAILURE;
570
571 /*
572 * Set the record number if required. Since the last_record parameter
573 * records the last record currently in use, it must be incremented
574 * before use to give the new last record.
575 */
576 if (record <= 0)
577 record = ++file_id->last_record;
578
579 if (record > file_id->last_record)
580 file_id->last_record = record;
581
582 (*buffer_return)->IDB_record->header.validation = IDBRecordHeaderValid ;
583 (*buffer_return)->IDB_record->header.record_num = record ;
584 (*buffer_return)->IDB_record->header.record_type = type ;
585
586 (*buffer_return)->access = file_id->access ;
587 (*buffer_return)->cur_file = file_id ;
588 (*buffer_return)->modified = TRUE ;
589
590 Idb__BM_MarkActivity (*buffer_return) ;
591
592 /*
593 * Update the record type counter in the file header
594 */
595 file_id->rt_counts[type]++ ;
596
597 /*
598 * Successfully initialized
599 */
600 return MrmSUCCESS ;
601
602 }
603
604
605 /*
606 *++
607 *
608 * PROCEDURE DESCRIPTION:
609 *
610 * Idb__BM_InitDataRecord initializes a new data record for the file.
611 * A buffer is acquired, and the record number and record type set.
612 * The record number may be specified; if the record number given
613 * is <= 0, then the next available record is taken from the file
614 * header. The next available record number is updated to the
615 * new record number if it is greater than the current value. The
616 * record is marked for write access, and as modified. It is not
617 * written to disk. The buffer's activity count is updated. This
618 * routine is nearly identical to InitRecord.
619 *
620 * FORMAL PARAMETERS:
621 *
622 * file_id Open IDB file
623 * buffer_return Returns buffer initialized for record, with type set.
624 * Access is URMWriteAccess, modified.
625 *
626 * IMPLICIT INPUTS:
627 *
628 * IMPLICIT OUTPUTS:
629 *
630 * FUNCTION VALUE:
631 *
632 * MrmSUCCESS operation succeeded
633 * MrmFAILURE some other failure
634 *
635 * SIDE EFFECTS:
636 *
637 *--
638 */
639
640 Cardinal
Idb__BM_InitDataRecord(IDBFile file_id,IDBRecordBufferPtr * buffer_return)641 Idb__BM_InitDataRecord (IDBFile file_id,
642 IDBRecordBufferPtr *buffer_return)
643 {
644
645 /*
646 * Local variables
647 */
648 Cardinal result ; /* function results */
649 IDBDataRecordPtr data_rec; /* data record specific */
650
651
652 /*
653 * Get a new record
654 */
655 result = Idb__BM_InitRecord (file_id, 0, IDBrtData, buffer_return) ;
656 if ( result != MrmSUCCESS ) return result ;
657
658 /*
659 * Set the last data record pointer in the file
660 */
661 file_id->last_data_record = _IdbBufferRecordNumber (*buffer_return) ;
662
663 /*
664 * Initialize the record contents
665 */
666 data_rec = (IDBDataRecord *) (*buffer_return)->IDB_record;
667
668 data_rec->data_header.free_ptr = 0 ;
669 data_rec->data_header.free_count = IDBDataFreeMax ;
670 data_rec->data_header.num_entry = 0 ;
671 data_rec->data_header.last_entry = 0 ;
672 Idb__BM_MarkActivity (*buffer_return) ;
673
674 return MrmSUCCESS ;
675
676 }
677
678
679
680 /*
681 *++
682 *
683 * PROCEDURE DESCRIPTION:
684 *
685 * Idb__BM_Decommit asserts that the buffer contents are no longer
686 * required to be in memory. If the buffer is marked for write access
687 * and as modified, it is written to disk. Then the modified flag is
688 * reset and the activity count set to 0 (least value).
689 *
690 * Note that GetRecord may legally re-acquire a decommitted buffer.
691 *
692 * FORMAL PARAMETERS:
693 *
694 * buffer Record buffer to decommit
695 *
696 * IMPLICIT INPUTS:
697 *
698 * IMPLICIT OUTPUTS:
699 *
700 * FUNCTION VALUE:
701 *
702 * MrmSUCCESS operation succeeded
703 * MrmFAILURE some other failure
704 *
705 * SIDE EFFECTS:
706 *
707 *--
708 */
709
710 Cardinal
Idb__BM_Decommit(IDBRecordBufferPtr buffer)711 Idb__BM_Decommit (IDBRecordBufferPtr buffer)
712 {
713
714 /*
715 * Local variables
716 */
717 Cardinal result ; /* function results */
718
719
720 if ( ! Idb__BM_Valid(buffer) )
721 return Urm__UT_Error ("Idb__BM_Decommit", _MrmMMsg_0002,
722 NULL, NULL, MrmNOT_VALID) ;
723
724 if ((buffer->access == URMWriteAccess) && (buffer->modified == TRUE))
725 {
726 result = Idb__FU_PutBlock (buffer->cur_file->lowlevel_id,
727 buffer->IDB_record->header.record_num,
728 (char*)buffer->IDB_record) ;
729 if ( result != MrmSUCCESS )
730 return Urm__UT_Error ("Idb__BM_Decommit", _MrmMMsg_0004,
731 NULL, NULL, MrmNOT_VALID) ;
732 buffer->cur_file->put_count++ ;
733
734 buffer->activity = 0;
735 buffer->modified = FALSE;
736 }
737
738 return MrmSUCCESS;
739
740 }
741
742
743
744 /*
745 *++
746 *
747 * PROCEDURE DESCRIPTION:
748 *
749 * Idb__BM_DecommitAll decommits all the buffers currently allocated
750 * for a file. It returns an error immediately if there is any
751 * problem decommitting any buffer.
752 *
753 * Since this routine removes all buffers for a file in prepration
754 * for closing it, it also wipes out the file pointer in each buffer.
755 *
756 * FORMAL PARAMETERS:
757 *
758 * file_id IDB file for which to write all modified buffers
759 *
760 * IMPLICIT INPUTS:
761 *
762 * IMPLICIT OUTPUTS:
763 *
764 * FUNCTION VALUE:
765 *
766 * MrmSUCCESS operation succeeded
767 * MrmFAILURE some other failure
768 *
769 * SIDE EFFECTS:
770 *
771 *--
772 */
773
774 Cardinal
Idb__BM_DecommitAll(IDBFile file_id)775 Idb__BM_DecommitAll (IDBFile file_id)
776 {
777
778 /*
779 * Local variables
780 */
781 Cardinal result ; /* function result */
782 Cardinal ndx ; /* loop variable */
783 IDBRecordBufferPtr curbuf ; /* ptr to element in buff pool */
784
785 if ( idb__buffer_pool_vec == NULL )
786 return MrmFAILURE;
787
788 for ( ndx=0,curbuf=idb__buffer_pool_vec ;
789 ndx<idb__buffer_pool_size ;
790 ndx++,curbuf++ )
791 {
792 if (curbuf->cur_file == file_id)
793 {
794 result = Idb__BM_Decommit (curbuf) ;
795 if ( result != MrmSUCCESS ) return result ;
796 curbuf->cur_file = NULL ;
797 }
798 }
799
800 return MrmSUCCESS ;
801
802 }
803
804