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