Coverage Report

Created: 2026-08-13 07:12

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/postgres/src/backend/storage/file/sharedfileset.c
Line
Count
Source
1
/*-------------------------------------------------------------------------
2
 *
3
 * sharedfileset.c
4
 *    Shared temporary file management.
5
 *
6
 * Portions Copyright (c) 1996-2026, 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 "storage/dsm.h"
24
#include "storage/sharedfileset.h"
25
26
static void SharedFileSetOnDetach(dsm_segment *segment, Datum datum);
27
28
/*
29
 * Initialize a space for temporary files that can be opened by other backends.
30
 * Other backends must attach to it before accessing it.  Associate this
31
 * SharedFileSet with 'seg'.  Any contained files will be deleted when the
32
 * last backend detaches.
33
 *
34
 * Under the covers the set is one or more directories which will eventually
35
 * be deleted.
36
 */
37
void
38
SharedFileSetInit(SharedFileSet *fileset, dsm_segment *seg)
39
0
{
40
  /* Initialize the shared fileset specific members. */
41
0
  SpinLockInit(&fileset->mutex);
42
0
  fileset->refcnt = 1;
43
44
  /* Initialize the fileset. */
45
0
  FileSetInit(&fileset->fs);
46
47
  /* Register our cleanup callback. */
48
0
  if (seg)
49
0
    on_dsm_detach(seg, SharedFileSetOnDetach, PointerGetDatum(fileset));
50
0
}
51
52
/*
53
 * Attach to a set of directories that was created with SharedFileSetInit.
54
 */
55
void
56
SharedFileSetAttach(SharedFileSet *fileset, dsm_segment *seg)
57
0
{
58
0
  bool    success;
59
60
0
  SpinLockAcquire(&fileset->mutex);
61
0
  if (fileset->refcnt == 0)
62
0
    success = false;
63
0
  else
64
0
  {
65
0
    ++fileset->refcnt;
66
0
    success = true;
67
0
  }
68
0
  SpinLockRelease(&fileset->mutex);
69
70
0
  if (!success)
71
0
    ereport(ERROR,
72
0
        (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
73
0
         errmsg("could not attach to a SharedFileSet that is already destroyed")));
74
75
  /* Register our cleanup callback. */
76
0
  on_dsm_detach(seg, SharedFileSetOnDetach, PointerGetDatum(fileset));
77
0
}
78
79
/*
80
 * Delete all files in the set.
81
 */
82
void
83
SharedFileSetDeleteAll(SharedFileSet *fileset)
84
0
{
85
0
  FileSetDeleteAll(&fileset->fs);
86
0
}
87
88
/*
89
 * Callback function that will be invoked when this backend detaches from a
90
 * DSM segment holding a SharedFileSet that it has created or attached to.  If
91
 * we are the last to detach, then try to remove the directories and
92
 * everything in them.  We can't raise an error on failures, because this runs
93
 * in error cleanup paths.
94
 */
95
static void
96
SharedFileSetOnDetach(dsm_segment *segment, Datum datum)
97
0
{
98
0
  bool    unlink_all = false;
99
0
  SharedFileSet *fileset = (SharedFileSet *) DatumGetPointer(datum);
100
101
0
  SpinLockAcquire(&fileset->mutex);
102
0
  Assert(fileset->refcnt > 0);
103
0
  if (--fileset->refcnt == 0)
104
0
    unlink_all = true;
105
0
  SpinLockRelease(&fileset->mutex);
106
107
  /*
108
   * If we are the last to detach, we delete the directory in all
109
   * tablespaces.  Note that we are still actually attached for the rest of
110
   * this function so we can safely access its data.
111
   */
112
0
  if (unlink_all)
113
0
    FileSetDeleteAll(&fileset->fs);
114
0
}