88 *
99 *
1010 * IDENTIFICATION
11- * $Header: /cvsroot/pgsql/src/backend/libpq/be-fsstubs.c,v 1.55 2000/10/2401:38:26 tgl Exp $
11+ * $Header: /cvsroot/pgsql/src/backend/libpq/be-fsstubs.c,v 1.56 2000/10/2403:14:08 tgl Exp $
1212 *
1313 * NOTES
1414 * This should be moved to a more appropriate place. It is here
4949/* [PA] is Pascal André <andre@via.ecp.fr> */
5050
5151/*#define FSDB 1*/
52- #define MAX_LOBJ_FDS 256
5352#define BUFSIZE 8192
5453
5554/*
56- * LO "FD"s are indexes into this array.
55+ * LO "FD"s are indexes into the cookies array.
56+ *
5757 * A non-null entry is a pointer to a LargeObjectDesc allocated in the
58- * LO private memory context.
58+ * LO private memory context. The cookies array itself is also dynamically
59+ * allocated in that context. Its current allocated size is cookies_len
60+ * entries, of which any unused entries will be NULL.
5961 */
60- static LargeObjectDesc * cookies [MAX_LOBJ_FDS ];
62+ static LargeObjectDesc * * cookies = NULL ;
63+ static int cookies_size = 0 ;
6164
6265static MemoryContext fscxt = NULL ;
6366
@@ -104,14 +107,8 @@ lo_open(PG_FUNCTION_ARGS)
104107
105108fd = newLOfd (lobjDesc );
106109
107- /* switch context back to orig. */
108110MemoryContextSwitchTo (currentContext );
109111
110- #if FSDB
111- if (fd < 0 )/* newLOfd couldn't find a slot */
112- elog (NOTICE ,"Out of space for large object FDs" );
113- #endif
114-
115112PG_RETURN_INT32 (fd );
116113}
117114
@@ -121,15 +118,10 @@ lo_close(PG_FUNCTION_ARGS)
121118int32 fd = PG_GETARG_INT32 (0 );
122119MemoryContext currentContext ;
123120
124- if (fd < 0 || fd >=MAX_LOBJ_FDS )
125- {
126- elog (ERROR ,"lo_close: large obj descriptor (%d) out of range" ,fd );
127- PG_RETURN_INT32 (-2 );
128- }
129- if (cookies [fd ]== NULL )
121+ if (fd < 0 || fd >=cookies_size || cookies [fd ]== NULL )
130122{
131123elog (ERROR ,"lo_close: invalid large obj descriptor (%d)" ,fd );
132- PG_RETURN_INT32 (-3 );
124+ PG_RETURN_INT32 (-1 );
133125}
134126#if FSDB
135127elog (NOTICE ,"lo_close(%d)" ,fd );
@@ -162,15 +154,10 @@ lo_read(int fd, char *buf, int len)
162154MemoryContext currentContext ;
163155int status ;
164156
165- if (fd < 0 || fd >=MAX_LOBJ_FDS )
166- {
167- elog (ERROR ,"lo_read: large obj descriptor (%d) out of range" ,fd );
168- return -2 ;
169- }
170- if (cookies [fd ]== NULL )
157+ if (fd < 0 || fd >=cookies_size || cookies [fd ]== NULL )
171158{
172159elog (ERROR ,"lo_read: invalid large obj descriptor (%d)" ,fd );
173- return -3 ;
160+ return -1 ;
174161}
175162
176163Assert (fscxt != NULL );
@@ -189,15 +176,10 @@ lo_write(int fd, char *buf, int len)
189176MemoryContext currentContext ;
190177int status ;
191178
192- if (fd < 0 || fd >=MAX_LOBJ_FDS )
193- {
194- elog (ERROR ,"lo_write: large obj descriptor (%d) out of range" ,fd );
195- return -2 ;
196- }
197- if (cookies [fd ]== NULL )
179+ if (fd < 0 || fd >=cookies_size || cookies [fd ]== NULL )
198180{
199181elog (ERROR ,"lo_write: invalid large obj descriptor (%d)" ,fd );
200- return -3 ;
182+ return -1 ;
201183}
202184
203185Assert (fscxt != NULL );
@@ -220,15 +202,10 @@ lo_lseek(PG_FUNCTION_ARGS)
220202MemoryContext currentContext ;
221203int status ;
222204
223- if (fd < 0 || fd >=MAX_LOBJ_FDS )
224- {
225- elog (ERROR ,"lo_lseek: large obj descriptor (%d) out of range" ,fd );
226- PG_RETURN_INT32 (-2 );
227- }
228- if (cookies [fd ]== NULL )
205+ if (fd < 0 || fd >=cookies_size || cookies [fd ]== NULL )
229206{
230207elog (ERROR ,"lo_lseek: invalid large obj descriptor (%d)" ,fd );
231- PG_RETURN_INT32 (-3 );
208+ PG_RETURN_INT32 (-1 );
232209}
233210
234211Assert (fscxt != NULL );
@@ -280,15 +257,10 @@ lo_tell(PG_FUNCTION_ARGS)
280257{
281258int32 fd = PG_GETARG_INT32 (0 );
282259
283- if (fd < 0 || fd >=MAX_LOBJ_FDS )
284- {
285- elog (ERROR ,"lo_tell: large object descriptor (%d) out of range" ,fd );
286- PG_RETURN_INT32 (-2 );
287- }
288- if (cookies [fd ]== NULL )
260+ if (fd < 0 || fd >=cookies_size || cookies [fd ]== NULL )
289261{
290262elog (ERROR ,"lo_tell: invalid large object descriptor (%d)" ,fd );
291- PG_RETURN_INT32 (-3 );
263+ PG_RETURN_INT32 (-1 );
292264}
293265
294266/*
@@ -304,13 +276,30 @@ lo_unlink(PG_FUNCTION_ARGS)
304276{
305277Oid lobjId = PG_GETARG_OID (0 );
306278
279+ /*
280+ * If there are any open LO FDs referencing that ID, close 'em.
281+ */
282+ if (fscxt != NULL )
283+ {
284+ MemoryContext currentContext ;
285+ int i ;
286+
287+ currentContext = MemoryContextSwitchTo (fscxt );
288+ for (i = 0 ;i < cookies_size ;i ++ )
289+ {
290+ if (cookies [i ]!= NULL && cookies [i ]-> id == lobjId )
291+ {
292+ inv_close (cookies [i ]);
293+ deleteLOfd (i );
294+ }
295+ }
296+ MemoryContextSwitchTo (currentContext );
297+ }
298+
307299/*
308300 * inv_drop does not need a context switch, indeed it doesn't touch
309301 * any LO-specific data structures at all.(Again, that's probably
310302 * more than this module ought to be assuming.)
311- *
312- * XXX there ought to be some code to clean up any open LO FDs that
313- * reference the specified LO... as is, they remain "open".
314303 */
315304PG_RETURN_INT32 (inv_drop (lobjId ));
316305}
@@ -502,7 +491,7 @@ lo_commit(bool isCommit)
502491 * Clean out still-open index scans (not necessary if aborting) and
503492 * clear cookies array so that LO fds are no longer good.
504493 */
505- for (i = 0 ;i < MAX_LOBJ_FDS ;i ++ )
494+ for (i = 0 ;i < cookies_size ;i ++ )
506495{
507496if (cookies [i ]!= NULL )
508497{
@@ -512,6 +501,10 @@ lo_commit(bool isCommit)
512501}
513502}
514503
504+ /* Needn't actually pfree since we're about to zap context */
505+ cookies = NULL ;
506+ cookies_size = 0 ;
507+
515508MemoryContextSwitchTo (currentContext );
516509
517510/* Release the LO memory context to prevent permanent memory leaks. */
@@ -527,18 +520,45 @@ lo_commit(bool isCommit)
527520static int
528521newLOfd (LargeObjectDesc * lobjCookie )
529522{
530- int i ;
523+ int i ,
524+ newsize ;
531525
532- for (i = 0 ;i < MAX_LOBJ_FDS ;i ++ )
526+ /* Try to find a free slot */
527+ for (i = 0 ;i < cookies_size ;i ++ )
533528{
534-
535529if (cookies [i ]== NULL )
536530{
537531cookies [i ]= lobjCookie ;
538532return i ;
539533}
540534}
541- return -1 ;
535+
536+ /* No free slot, so make the array bigger */
537+ if (cookies_size <=0 )
538+ {
539+ /* First time through, arbitrarily make 64-element array */
540+ i = 0 ;
541+ newsize = 64 ;
542+ cookies = (LargeObjectDesc * * )
543+ palloc (newsize * sizeof (LargeObjectDesc * ));
544+ MemSet (cookies ,0 ,newsize * sizeof (LargeObjectDesc * ));
545+ cookies_size = newsize ;
546+ }
547+ else
548+ {
549+ /* Double size of array */
550+ i = cookies_size ;
551+ newsize = cookies_size * 2 ;
552+ cookies = (LargeObjectDesc * * )
553+ repalloc (cookies ,newsize * sizeof (LargeObjectDesc * ));
554+ MemSet (cookies + cookies_size ,0 ,
555+ (newsize - cookies_size )* sizeof (LargeObjectDesc * ));
556+ cookies_size = newsize ;
557+ }
558+
559+ Assert (cookies [i ]== NULL );
560+ cookies [i ]= lobjCookie ;
561+ return i ;
542562}
543563
544564static void