18
18
*/
19
19
20
20
#include "postgres.h"
21
-
22
21
#include <unistd.h>
23
22
#include <sys/stat.h>
24
23
36
35
#include "catalog/pg_tablespace.h"
37
36
#include "miscadmin.h"
38
37
#include "port/pg_crc32c.h"
38
+ #ifdef PGPRO_EE
39
+ /* For file_is_in_cfs_tablespace() only. */
40
+ #include "common/cfs_common.h"
41
+ #endif
39
42
#include "storage/copydir.h"
40
43
#if PG_VERSION_NUM >= 120000
41
44
#include "storage/md.h"
@@ -91,6 +94,68 @@ ptrack_write_chunk(int fd, pg_crc32c *crc, char *chunk, size_t size)
91
94
}
92
95
}
93
96
97
+ /*
98
+ * Determines a file type which is one of the following:
99
+ * * regular relation file
100
+ * * regular relation file which is a part of a multifile relation
101
+ * * everythong else
102
+ */
103
+ FileType
104
+ file_type_from_path (const char * filename ) {
105
+ ssize_t len = strlen (filename );
106
+ bool met_dot ;
107
+ met_dot = false;
108
+
109
+ // For this length checks we assume that the filename is at least
110
+ // 1 character longer than the corresponding extension ".cfm":
111
+ // strlen(".cfm") == 4 therefore we assume that the filename can't be
112
+ // shorter than 5 bytes, for example: "5.cfm".
113
+ if (len >= 5 && strcmp (& filename [len - 4 ], ".cfm" ) == 0 )
114
+ return FileTypeCFM ;
115
+
116
+ // we expect filename to be ****/12345 or ****/12345.12
117
+ for (ssize_t i = len - 1 ; i >= 0 && filename [i ] != '/' ; i -- ) {
118
+ if (isdigit (filename [i ]) != 0 )
119
+ continue ;
120
+
121
+ // we expect the dot to appear only once
122
+ if (filename [i ] == '.' ) {
123
+ if (met_dot )
124
+ return FileTypeUnknown ;
125
+
126
+ met_dot = true;
127
+ } else
128
+ // met anything except digit and dot => unknown file type
129
+ return FileTypeUnknown ;
130
+ }
131
+
132
+ return met_dot ? FileTypeMainMulti : FileTypeMain ;
133
+ }
134
+
135
+ #ifdef PGPRO_EE
136
+ /*
137
+ * Determines the relation file size specified by fullpath as if it
138
+ * was not compressed.
139
+ */
140
+ off_t
141
+ get_cfs_relation_file_decompressed_size (RelFileNodeBackend rnode , const char * fullpath , ForkNumber forknum ) {
142
+ File fd ;
143
+ int compressor ;
144
+ off_t size ;
145
+
146
+ compressor = md_get_compressor_internal (rnode .node , rnode .backend , forknum );
147
+ fd = PathNameOpenFile (fullpath , O_RDWR | PG_BINARY , compressor );
148
+
149
+ if (fd < 0 )
150
+ return (off_t )- 1 ;
151
+
152
+ size = FileSize (fd );
153
+ FileClose (fd );
154
+
155
+ return size ;
156
+ }
157
+ #endif
158
+
94
159
/*
95
160
* Delete ptrack files when ptrack is disabled.
96
161
*
@@ -498,8 +563,13 @@ assign_ptrack_map_size(int newval, void *extra)
498
563
* For use in functions that copy directories bypassing buffer manager.
499
564
*/
500
565
static void
566
+ #ifdef PGPRO_EE
567
+ ptrack_mark_file (Oid dbOid , Oid tablespaceOid ,
568
+ const char * filepath , const char * filename , bool is_cfs )
569
+ #else
501
570
ptrack_mark_file (Oid dbOid , Oid tablespaceOid ,
502
571
const char * filepath , const char * filename )
572
+ #endif
503
573
{
504
574
RelFileNodeBackend rnode ;
505
575
ForkNumber forknum ;
@@ -508,6 +578,9 @@ ptrack_mark_file(Oid dbOid, Oid tablespaceOid,
508
578
struct stat stat_buf ;
509
579
int oidchars ;
510
580
char oidbuf [OIDCHARS + 1 ];
581
+ #ifdef PGPRO_EE
582
+ off_t rel_size ;
583
+ #endif
511
584
512
585
/* Do not track temporary relations */
513
586
if (looks_like_temp_rel_name (filename ))
@@ -526,6 +599,21 @@ ptrack_mark_file(Oid dbOid, Oid tablespaceOid,
526
599
oidbuf [oidchars ] = '\0' ;
527
600
nodeRel (nodeOf (rnode )) = atooid (oidbuf );
528
601
602
+ #ifdef PGPRO_EE
603
+ // if current tablespace is cfs-compressed and md_get_compressor_internal
604
+ // returns the type of the compressing algorithm for filepath, then it
605
+ // needs to be de-compressed to obtain its size
606
+ if (is_cfs && md_get_compressor_internal (rnode .node , rnode .backend , forknum ) != 0 ) {
607
+ rel_size = get_cfs_relation_file_decompressed_size (rnode , filepath , forknum );
608
+
609
+ if (rel_size == (off_t )- 1 ) {
610
+ elog (WARNING , "ptrack: could not open cfs-compressed relation file: %s" , filepath );
611
+ return ;
612
+ }
613
+
614
+ nblocks = rel_size / BLCKSZ ;
615
+ } else
616
+ #endif
529
617
/* Compute number of blocks based on file size */
530
618
if (stat (filepath , & stat_buf ) == 0 )
531
619
nblocks = stat_buf .st_size / BLCKSZ ;
@@ -546,6 +634,9 @@ ptrack_walkdir(const char *path, Oid tablespaceOid, Oid dbOid)
546
634
{
547
635
DIR * dir ;
548
636
struct dirent * de ;
637
+ #ifdef PGPRO_EE
638
+ bool is_cfs ;
639
+ #endif
549
640
550
641
/* Do not walk during bootstrap and if ptrack is disabled */
551
642
if (ptrack_map_size == 0
@@ -554,6 +645,10 @@ ptrack_walkdir(const char *path, Oid tablespaceOid, Oid dbOid)
554
645
|| InitializingParallelWorker )
555
646
return ;
556
647
648
+ #ifdef PGPRO_EE
649
+ is_cfs = file_is_in_cfs_tablespace (path );
650
+ #endif
651
+
557
652
dir = AllocateDir (path );
558
653
559
654
while ((de = ReadDirExtended (dir , path , LOG )) != NULL )
@@ -581,7 +676,11 @@ ptrack_walkdir(const char *path, Oid tablespaceOid, Oid dbOid)
581
676
}
582
677
583
678
if (S_ISREG (fst .st_mode ))
679
+ #ifdef PGPRO_EE
680
+ ptrack_mark_file (dbOid , tablespaceOid , subpath , de -> d_name , is_cfs );
681
+ #else
584
682
ptrack_mark_file (dbOid , tablespaceOid , subpath , de -> d_name );
683
+ #endif
585
684
}
586
685
587
686
FreeDir (dir ); /* we ignore any error here */
0 commit comments