88 *
99 *
1010 * IDENTIFICATION
11- * $PostgreSQL: pgsql/src/backend/libpq/be-fsstubs.c,v 1.81 2006/03/05 15:58:27 momjian Exp $
11+ * $PostgreSQL: pgsql/src/backend/libpq/be-fsstubs.c,v 1.82 2006/04/26 00:34:57 tgl Exp $
1212 *
1313 * NOTES
1414 * This should be moved to a more appropriate place. It is here
1515 * for lack of a better place.
1616 *
17- * These functions operate in a private MemoryContext, which means
18- * that large object descriptors hang around until we destroy the context
19- * at transaction end. It'd be possible to prolong the lifetime
17+ * These functions store LargeObjectDesc structs in a private MemoryContext,
18+ * which means that large object descriptors hang around until we destroy
19+ * the context at transaction end. It'd be possible to prolong the lifetime
2020 * of the context so that LO FDs are good across transactions (for example,
2121 * we could release the context only if we see that no FDs remain open).
2222 * But we'd need additional state in order to do the right thing at the
2929 *
3030 * As of PostgreSQL 8.0, much of the angst expressed above is no longer
3131 * relevant, and in fact it'd be pretty easy to allow LO FDs to stay
32- * open across transactions. However backwards compatibility suggests
33- * that we should stick to the status quo.
32+ * open across transactions. (Snapshot relevancy would still be an issue.)
33+ * However backwards compatibility suggests that we should stick to the
34+ * status quo.
3435 *
3536 *-------------------------------------------------------------------------
3637 */
5657 * LO "FD"s are indexes into the cookies array.
5758 *
5859 * A non-null entry is a pointer to a LargeObjectDesc allocated in the
59- * LO private memory context. The cookies array itself is also dynamically
60- * allocated in that context. Its current allocated size is cookies_len
61- * entries, of which any unused entries will be NULL.
60+ * LO private memory context "fscxt" . The cookies array itself is also
61+ * dynamically allocated in that context. Its current allocated size is
62+ * cookies_len entries, of which any unused entries will be NULL.
6263 */
6364static LargeObjectDesc * * cookies = NULL ;
6465static int cookies_size = 0 ;
@@ -91,21 +92,17 @@ lo_open(PG_FUNCTION_ARGS)
9192 int32 mode = PG_GETARG_INT32 (1 );
9293 LargeObjectDesc * lobjDesc ;
9394 int fd ;
94- MemoryContext currentContext ;
9595
9696#if FSDB
9797 elog (DEBUG4 , "lo_open(%u,%d)" , lobjId , mode );
9898#endif
9999
100100 CreateFSContext ();
101101
102- currentContext = MemoryContextSwitchTo (fscxt );
103-
104- lobjDesc = inv_open (lobjId , mode );
102+ lobjDesc = inv_open (lobjId , mode , fscxt );
105103
106104 if (lobjDesc == NULL )
107105 { /* lookup failed */
108- MemoryContextSwitchTo (currentContext );
109106#if FSDB
110107 elog (DEBUG4 , "could not open large object %u" , lobjId );
111108#endif
@@ -114,16 +111,13 @@ lo_open(PG_FUNCTION_ARGS)
114111
115112 fd = newLOfd (lobjDesc );
116113
117- MemoryContextSwitchTo (currentContext );
118-
119114 PG_RETURN_INT32 (fd );
120115}
121116
122117Datum
123118lo_close (PG_FUNCTION_ARGS )
124119{
125120 int32 fd = PG_GETARG_INT32 (0 );
126- MemoryContext currentContext ;
127121
128122 if (fd < 0 || fd >= cookies_size || cookies [fd ] == NULL )
129123 {
@@ -136,15 +130,10 @@ lo_close(PG_FUNCTION_ARGS)
136130 elog (DEBUG4 , "lo_close(%d)" , fd );
137131#endif
138132
139- Assert (fscxt != NULL );
140- currentContext = MemoryContextSwitchTo (fscxt );
141-
142133 inv_close (cookies [fd ]);
143134
144135 deleteLOfd (fd );
145136
146- MemoryContextSwitchTo (currentContext );
147-
148137 PG_RETURN_INT32 (0 );
149138}
150139
@@ -160,7 +149,6 @@ lo_close(PG_FUNCTION_ARGS)
160149int
161150lo_read (int fd , char * buf , int len )
162151{
163- MemoryContext currentContext ;
164152 int status ;
165153
166154 if (fd < 0 || fd >= cookies_size || cookies [fd ] == NULL )
@@ -171,20 +159,14 @@ lo_read(int fd, char *buf, int len)
171159 return -1 ;
172160 }
173161
174- Assert (fscxt != NULL );
175- currentContext = MemoryContextSwitchTo (fscxt );
176-
177162 status = inv_read (cookies [fd ], buf , len );
178163
179- MemoryContextSwitchTo (currentContext );
180-
181164 return status ;
182165}
183166
184167int
185168lo_write (int fd , char * buf , int len )
186169{
187- MemoryContext currentContext ;
188170 int status ;
189171
190172 if (fd < 0 || fd >= cookies_size || cookies [fd ] == NULL )
@@ -201,13 +183,8 @@ lo_write(int fd, char *buf, int len)
201183 errmsg ("large object descriptor %d was not opened for writing" ,
202184 fd )));
203185
204- Assert (fscxt != NULL );
205- currentContext = MemoryContextSwitchTo (fscxt );
206-
207186 status = inv_write (cookies [fd ], buf , len );
208187
209- MemoryContextSwitchTo (currentContext );
210-
211188 return status ;
212189}
213190
@@ -218,7 +195,6 @@ lo_lseek(PG_FUNCTION_ARGS)
218195 int32 fd = PG_GETARG_INT32 (0 );
219196 int32 offset = PG_GETARG_INT32 (1 );
220197 int32 whence = PG_GETARG_INT32 (2 );
221- MemoryContext currentContext ;
222198 int status ;
223199
224200 if (fd < 0 || fd >= cookies_size || cookies [fd ] == NULL )
@@ -229,49 +205,40 @@ lo_lseek(PG_FUNCTION_ARGS)
229205 PG_RETURN_INT32 (-1 );
230206 }
231207
232- Assert (fscxt != NULL );
233- currentContext = MemoryContextSwitchTo (fscxt );
234-
235208 status = inv_seek (cookies [fd ], offset , whence );
236209
237- MemoryContextSwitchTo (currentContext );
238-
239210 PG_RETURN_INT32 (status );
240211}
241212
242213Datum
243214lo_creat (PG_FUNCTION_ARGS )
244215{
245216 Oid lobjId ;
246- MemoryContext currentContext ;
247217
248- /* do we actually need fscxt for this? */
218+ /*
219+ * We don't actually need to store into fscxt, but create it anyway to
220+ * ensure that AtEOXact_LargeObject knows there is state to clean up
221+ */
249222 CreateFSContext ();
250223
251- currentContext = MemoryContextSwitchTo (fscxt );
252-
253224 lobjId = inv_create (InvalidOid );
254225
255- MemoryContextSwitchTo (currentContext );
256-
257226 PG_RETURN_OID (lobjId );
258227}
259228
260229Datum
261230lo_create (PG_FUNCTION_ARGS )
262231{
263232 Oid lobjId = PG_GETARG_OID (0 );
264- MemoryContext currentContext ;
265233
266- /* do we actually need fscxt for this? */
234+ /*
235+ * We don't actually need to store into fscxt, but create it anyway to
236+ * ensure that AtEOXact_LargeObject knows there is state to clean up
237+ */
267238 CreateFSContext ();
268239
269- currentContext = MemoryContextSwitchTo (fscxt );
270-
271240 lobjId = inv_create (lobjId );
272241
273- MemoryContextSwitchTo (currentContext );
274-
275242 PG_RETURN_OID (lobjId );
276243}
277244
@@ -288,10 +255,6 @@ lo_tell(PG_FUNCTION_ARGS)
288255 PG_RETURN_INT32 (-1 );
289256 }
290257
291- /*
292- * We assume we do not need to switch contexts for inv_tell. That is true
293- * for now, but is probably more than this module ought to assume...
294- */
295258 PG_RETURN_INT32 (inv_tell (cookies [fd ]));
296259}
297260
@@ -305,10 +268,8 @@ lo_unlink(PG_FUNCTION_ARGS)
305268 */
306269 if (fscxt != NULL )
307270 {
308- MemoryContext currentContext ;
309271 int i ;
310272
311- currentContext = MemoryContextSwitchTo (fscxt );
312273 for (i = 0 ; i < cookies_size ; i ++ )
313274 {
314275 if (cookies [i ] != NULL && cookies [i ]-> id == lobjId )
@@ -317,13 +278,11 @@ lo_unlink(PG_FUNCTION_ARGS)
317278 deleteLOfd (i );
318279 }
319280 }
320- MemoryContextSwitchTo (currentContext );
321281 }
322282
323283 /*
324- * inv_drop does not need a context switch, indeed it doesn't touch any
325- * LO-specific data structures at all. (Again, that's probably more than
326- * this module ought to be assuming.)
284+ * inv_drop does not create a need for end-of-transaction cleanup and
285+ * hence we don't need to have created fscxt.
327286 */
328287 PG_RETURN_INT32 (inv_drop (lobjId ));
329288}
@@ -391,10 +350,6 @@ lo_import(PG_FUNCTION_ARGS)
391350 errhint ("Anyone can use the client-side lo_import() provided by libpq." )));
392351#endif
393352
394- /*
395- * We don't actually need to switch into fscxt, but create it anyway to
396- * ensure that AtEOXact_LargeObject knows there is state to clean up
397- */
398353 CreateFSContext ();
399354
400355 /*
@@ -420,7 +375,7 @@ lo_import(PG_FUNCTION_ARGS)
420375 /*
421376 * read in from the filesystem and write to the inversion object
422377 */
423- lobj = inv_open (lobjOid , INV_WRITE );
378+ lobj = inv_open (lobjOid , INV_WRITE , fscxt );
424379
425380 while ((nbytes = FileRead (fd , buf , BUFSIZE )) > 0 )
426381 {
@@ -465,16 +420,12 @@ lo_export(PG_FUNCTION_ARGS)
465420 errhint ("Anyone can use the client-side lo_export() provided by libpq." )));
466421#endif
467422
468- /*
469- * We don't actually need to switch into fscxt, but create it anyway to
470- * ensure that AtEOXact_LargeObject knows there is state to clean up
471- */
472423 CreateFSContext ();
473424
474425 /*
475426 * open the inversion object (no need to test for failure)
476427 */
477- lobj = inv_open (lobjId , INV_READ );
428+ lobj = inv_open (lobjId , INV_READ , fscxt );
478429
479430 /*
480431 * open the file to be written to
@@ -524,13 +475,10 @@ void
524475AtEOXact_LargeObject (bool isCommit )
525476{
526477 int i ;
527- MemoryContext currentContext ;
528478
529479 if (fscxt == NULL )
530480 return ; /* no LO operations in this xact */
531481
532- currentContext = MemoryContextSwitchTo (fscxt );
533-
534482 /*
535483 * Close LO fds and clear cookies array so that LO fds are no longer good.
536484 * On abort we skip the close step.
@@ -549,8 +497,6 @@ AtEOXact_LargeObject(bool isCommit)
549497 cookies = NULL ;
550498 cookies_size = 0 ;
551499
552- MemoryContextSwitchTo (currentContext );
553-
554500 /* Release the LO memory context to prevent permanent memory leaks. */
555501 MemoryContextDelete (fscxt );
556502 fscxt = NULL ;
@@ -623,8 +569,7 @@ newLOfd(LargeObjectDesc *lobjCookie)
623569 i = 0 ;
624570 newsize = 64 ;
625571 cookies = (LargeObjectDesc * * )
626- palloc (newsize * sizeof (LargeObjectDesc * ));
627- MemSet (cookies , 0 , newsize * sizeof (LargeObjectDesc * ));
572+ MemoryContextAllocZero (fscxt , newsize * sizeof (LargeObjectDesc * ));
628573 cookies_size = newsize ;
629574 }
630575 else
0 commit comments