Age Owner TLA Line data Source code
1 : /*-------------------------------------------------------------------------
2 : *
3 : * sharedfileset.c
4 : * Shared temporary file management.
5 : *
6 : * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group
7 : * Portions Copyright (c) 1994, Regents of the University of California
8 : *
9 : * IDENTIFICATION
10 : * src/backend/storage/file/sharedfileset.c
11 : *
12 : * SharedFileSets provide a temporary namespace (think directory) so that
13 : * files can be discovered by name, and a shared ownership semantics so that
14 : * shared files survive until the last user detaches.
15 : *
16 : *-------------------------------------------------------------------------
17 : */
18 :
19 : #include "postgres.h"
20 :
21 : #include <limits.h>
22 :
23 : #include "catalog/pg_tablespace.h"
24 : #include "commands/tablespace.h"
25 : #include "common/hashfn.h"
26 : #include "miscadmin.h"
27 : #include "storage/dsm.h"
28 : #include "storage/ipc.h"
29 : #include "storage/sharedfileset.h"
30 : #include "utils/builtins.h"
31 :
32 : static void SharedFileSetOnDetach(dsm_segment *segment, Datum datum);
33 :
34 : /*
35 : * Initialize a space for temporary files that can be opened by other backends.
36 : * Other backends must attach to it before accessing it. Associate this
37 : * SharedFileSet with 'seg'. Any contained files will be deleted when the
38 : * last backend detaches.
39 : *
40 : * Under the covers the set is one or more directories which will eventually
41 : * be deleted.
42 : */
43 : void
1955 andres 44 CBC 160 : SharedFileSetInit(SharedFileSet *fileset, dsm_segment *seg)
45 : {
46 : /* Initialize the shared fileset specific members. */
47 160 : SpinLockInit(&fileset->mutex);
48 160 : fileset->refcnt = 1;
49 :
50 : /* Initialize the fileset. */
587 akapila 51 160 : FileSetInit(&fileset->fs);
52 :
53 : /* Register our cleanup callback. */
956 54 160 : if (seg)
55 160 : on_dsm_detach(seg, SharedFileSetOnDetach, PointerGetDatum(fileset));
1955 andres 56 160 : }
57 :
58 : /*
59 : * Attach to a set of directories that was created with SharedFileSetInit.
60 : */
61 : void
62 250 : SharedFileSetAttach(SharedFileSet *fileset, dsm_segment *seg)
63 : {
64 : bool success;
65 :
66 250 : SpinLockAcquire(&fileset->mutex);
67 250 : if (fileset->refcnt == 0)
1955 andres 68 UBC 0 : success = false;
69 : else
70 : {
1955 andres 71 CBC 250 : ++fileset->refcnt;
72 250 : success = true;
73 : }
74 250 : SpinLockRelease(&fileset->mutex);
75 :
76 250 : if (!success)
1955 andres 77 UBC 0 : ereport(ERROR,
78 : (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
79 : errmsg("could not attach to a SharedFileSet that is already destroyed")));
80 :
81 : /* Register our cleanup callback. */
1955 andres 82 CBC 250 : on_dsm_detach(seg, SharedFileSetOnDetach, PointerGetDatum(fileset));
83 250 : }
84 :
85 : /*
86 : * Delete all files in the set.
87 : */
88 : void
89 24 : SharedFileSetDeleteAll(SharedFileSet *fileset)
90 : {
587 akapila 91 24 : FileSetDeleteAll(&fileset->fs);
1955 andres 92 24 : }
93 :
94 : /*
95 : * Callback function that will be invoked when this backend detaches from a
96 : * DSM segment holding a SharedFileSet that it has created or attached to. If
97 : * we are the last to detach, then try to remove the directories and
98 : * everything in them. We can't raise an error on failures, because this runs
99 : * in error cleanup paths.
100 : */
101 : static void
102 410 : SharedFileSetOnDetach(dsm_segment *segment, Datum datum)
103 : {
104 410 : bool unlink_all = false;
105 410 : SharedFileSet *fileset = (SharedFileSet *) DatumGetPointer(datum);
106 :
107 410 : SpinLockAcquire(&fileset->mutex);
108 410 : Assert(fileset->refcnt > 0);
109 410 : if (--fileset->refcnt == 0)
110 160 : unlink_all = true;
111 410 : SpinLockRelease(&fileset->mutex);
112 :
113 : /*
114 : * If we are the last to detach, we delete the directory in all
115 : * tablespaces. Note that we are still actually attached for the rest of
116 : * this function so we can safely access its data.
117 : */
118 410 : if (unlink_all)
587 akapila 119 160 : FileSetDeleteAll(&fileset->fs);
1955 andres 120 410 : }
|