PostgreSQL Source Code: src/backend/utils/adt/dbsize.c Source File (original) (raw)
1
2
3
4
5
6
7
8
9
10
11
13
14#include <sys/stat.h>
15
33
34
35#define half_rounded(x) (((x) + ((x) < 0 ? -1 : 1)) / 2)
36
37
39{
42
45
46};
47
48
50 {"bytes", 10 * 1024, false, 0},
51 {"kB", 20 * 1024 - 1, true, 10},
52 {"MB", 20 * 1024 - 1, true, 20},
53 {"GB", 20 * 1024 - 1, true, 30},
54 {"TB", 20 * 1024 - 1, true, 40},
55 {"PB", 20 * 1024 - 1, true, 50},
56 {NULL, 0, false, 0}
57};
58
59
61{
63 int unit_index;
64};
65
66
68 {"B", 0},
69 {NULL}
70};
71
72
75{
76 int64 dirsize = 0;
77 struct dirent *direntry;
78 DIR *dirdesc;
80
82
83 if (!dirdesc)
84 return 0;
85
86 while ((direntry = ReadDir(dirdesc, path)) != NULL)
87 {
88 struct stat fst;
89
91
92 if (strcmp(direntry->d_name, ".") == 0 ||
93 strcmp(direntry->d_name, "..") == 0)
94 continue;
95
97
99 {
100 if (errno == ENOENT)
101 continue;
102 else
105 errmsg("could not stat file \"%s\": %m", filename)));
106 }
108 }
109
111 return dirsize;
112}
113
114
115
116
119{
121 DIR *dirdesc;
122 struct dirent *direntry;
126
127
128
129
130
134 {
137 }
138
139
140
141
142 snprintf(pathname, sizeof(pathname), "base/%u", dbOid);
144
145
148
149 while ((direntry = ReadDir(dirdesc, dirpath)) != NULL)
150 {
152
153 if (strcmp(direntry->d_name, ".") == 0 ||
154 strcmp(direntry->d_name, "..") == 0)
155 continue;
156
157 snprintf(pathname, sizeof(pathname), "%s/%s/%s/%u",
160 }
161
163
164 return totalsize;
165}
166
169{
172
173
174
175
176
179 errcode(ERRCODE_UNDEFINED_OBJECT),
180 errmsg("database with OID %u does not exist", dbOid));
181
183
184 if (size == 0)
186
188}
189
192{
196
198
199 if (size == 0)
201
203}
204
205
206
207
208
209
212{
215 int64 totalsize = 0;
216 DIR *dirdesc;
217 struct dirent *direntry;
219
220
221
222
223
224
227 {
232 }
233
234 if (tblspcOid == DEFAULTTABLESPACE_OID)
236 else if (tblspcOid == GLOBALTABLESPACE_OID)
238 else
241
243
244 if (!dirdesc)
245 return -1;
246
247 while ((direntry = ReadDir(dirdesc, tblspcPath)) != NULL)
248 {
249 struct stat fst;
250
252
253 if (strcmp(direntry->d_name, ".") == 0 ||
254 strcmp(direntry->d_name, "..") == 0)
255 continue;
256
257 snprintf(pathname, sizeof(pathname), "%s/%s", tblspcPath, direntry->d_name);
258
259 if (stat(pathname, &fst) < 0)
260 {
261 if (errno == ENOENT)
262 continue;
263 else
266 errmsg("could not stat file \"%s\": %m", pathname)));
267 }
268
271
272 totalsize += fst.st_size;
273 }
274
276
277 return totalsize;
278}
279
282{
285
286
287
288
289
292 errcode(ERRCODE_UNDEFINED_OBJECT),
293 errmsg("tablespace with OID %u does not exist", tblspcOid));
294
296
297 if (size < 0)
299
301}
302
305{
309
311
312 if (size < 0)
314
316}
317
318
319
320
321
322
323
324
327{
328 int64 totalsize = 0;
331 unsigned int segcount = 0;
332
333 relationpath = relpathbackend(*rfn, backend, forknum);
334
335 for (segcount = 0;; segcount++)
336 {
337 struct stat fst;
338
340
341 if (segcount == 0)
343 relationpath.str);
344 else
346 relationpath.str, segcount);
347
348 if (stat(pathname, &fst) < 0)
349 {
350 if (errno == ENOENT)
351 break;
352 else
355 errmsg("could not stat file \"%s\": %m", pathname)));
356 }
357 totalsize += fst.st_size;
358 }
359
360 return totalsize;
361}
362
365{
370
372
373
374
375
376
377
378
379
380 if (rel == NULL)
382
385
387
389}
390
391
392
393
394
397{
402 List *indexlist;
403
405
406
407 for (forkNum = 0; forkNum <= MAX_FORKNUM; forkNum++)
410
411
413
414
415 foreach(lc, indexlist)
416 {
418
421 for (forkNum = 0; forkNum <= MAX_FORKNUM; forkNum++)
424
426 }
429
430 return size;
431}
432
433
434
435
436
437
438
439
440
443{
446
447
448
449
450 for (forkNum = 0; forkNum <= MAX_FORKNUM; forkNum++)
452 forkNum);
453
454
455
456
459
460 return size;
461}
462
463
464
465
466
467
470{
472
473
474
475
476 if (rel->rd_rel->relhasindex)
477 {
480
481 foreach(cell, index_oids)
482 {
486
488
489 for (forkNum = 0; forkNum <= MAX_FORKNUM; forkNum++)
492 forkNum);
493
495 }
496
498 }
499
500 return size;
501}
502
505{
509
511
512 if (rel == NULL)
514
516
518
520}
521
524{
528
530
531 if (rel == NULL)
533
535
537
539}
540
541
542
543
544
547{
549
550
551
552
553
555
556
557
558
560
561 return size;
562}
563
566{
570
572
573 if (rel == NULL)
575
577
579
581}
582
583
584
585
588{
590 char buf[64];
592
594 {
597
598
599
600
601
602 if (unit[1].name == NULL || abs_size < unit->limit)
603 {
606
608 break;
609 }
610
611
612
613
614
615
616
617
618
619
621 + (unit->round == true));
622 size /= ((int64) 1) << bits;
623 }
624
626}
627
628static char *
630{
632
634}
635
636static bool
638{
641
643}
644
647{
650
653}
654
657{
663
667
670 else
672
675}
676
679{
681 Datum divisor_numeric;
683
687}
688
691{
693 char *result = NULL;
695
697 {
698 unsigned int shiftby;
699
700
701 if (unit[1].name == NULL ||
704 {
707
709 break;
710 }
711
712
713
714
715
716
717
718
720 + (unit->round == true));
722 }
723
725}
726
727
728
729
732{
734 char *str,
735 *strptr,
736 *endptr;
737 char saved_char;
740 bool have_digits = false;
741
743
744
745 strptr = str;
746 while (isspace((unsigned char) *strptr))
747 strptr++;
748
749
750 endptr = strptr;
751
752
753 if (*endptr == '-' || *endptr == '+')
754 endptr++;
755
756
757 if (isdigit((unsigned char) *endptr))
758 {
759 have_digits = true;
760 do
761 endptr++;
762 while (isdigit((unsigned char) *endptr));
763 }
764
765
766 if (*endptr == '.')
767 {
768 endptr++;
769 if (isdigit((unsigned char) *endptr))
770 {
771 have_digits = true;
772 do
773 endptr++;
774 while (isdigit((unsigned char) *endptr));
775 }
776 }
777
778
779 if (!have_digits)
781 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
782 errmsg("invalid size: \"%s\"", str)));
783
784
785 if (*endptr == 'e' || *endptr == 'E')
786 {
787 long exponent;
788 char *cp;
789
790
791
792
793
794 exponent = strtol(endptr + 1, &cp, 10);
795 (void) exponent;
796 if (cp > endptr + 1)
797 endptr = cp;
798 }
799
800
801
802
803
804 saved_char = *endptr;
805 *endptr = '\0';
806
811
812 *endptr = saved_char;
813
814
815 strptr = endptr;
816 while (isspace((unsigned char) *strptr))
817 strptr++;
818
819
820 if (*strptr != '\0')
821 {
823 int64 multiplier = 0;
824
825
827
828 while (isspace((unsigned char) *endptr))
829 endptr--;
830
831 endptr++;
832 *endptr = '\0';
833
835 {
836
838 break;
839 }
840
841
842 if (unit->name == NULL)
843 {
845 {
847 {
849 break;
850 }
851 }
852 }
853
854
855 if (unit->name == NULL)
857 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
859 errdetail("Invalid size unit: \"%s\".", strptr),
860 errhint("Valid units are \"bytes\", \"B\", \"kB\", \"MB\", \"GB\", \"TB\", and \"PB\".")));
861
863
864 if (multiplier > 1)
865 {
867
869
873 }
874 }
875
878
880}
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
898{
903
908
909 if (RELKIND_HAS_STORAGE(relform->relkind))
910 {
911 if (relform->relfilenode)
912 result = relform->relfilenode;
913 else
915 relform->relisshared);
916 }
917 else
918 {
919
921 }
922
924
927
929}
930
931
932
933
934
935
936
937
938
939
940
941
942
943
946{
949 Oid heaprel;
950
951
954
956
959 else
961}
962
963
964
965
966
967
970{
977
982
983 if (RELKIND_HAS_STORAGE(relform->relkind))
984 {
985
986 if (relform->reltablespace)
987 rlocator.spcOid = relform->reltablespace;
988 else
990 if (rlocator.spcOid == GLOBALTABLESPACE_OID)
992 else
994 if (relform->relfilenode)
995 rlocator.relNumber = relform->relfilenode;
996 else
998 relform->relisshared);
999 }
1000 else
1001 {
1002
1004
1007 }
1008
1010 {
1013 }
1014
1015
1016 switch (relform->relpersistence)
1017 {
1018 case RELPERSISTENCE_UNLOGGED:
1019 case RELPERSISTENCE_PERMANENT:
1021 break;
1022 case RELPERSISTENCE_TEMP:
1025 else
1026 {
1027
1030 }
1031 break;
1032 default:
1033 elog(ERROR, "invalid relpersistence: %c", relform->relpersistence);
1035 break;
1036 }
1037
1039
1041
1043}
bool has_privs_of_role(Oid member, Oid role)
void aclcheck_error(AclResult aclerr, ObjectType objtype, const char *objectname)
AclResult object_aclcheck(Oid classid, Oid objectid, Oid roleid, AclMode mode)
char * get_tablespace_name(Oid spc_oid)
Oid get_tablespace_oid(const char *tablespacename, bool missing_ok)
Datum numeric_sub(PG_FUNCTION_ARGS)
Numeric int64_to_numeric(int64 val)
Datum numeric_int8(PG_FUNCTION_ARGS)
Datum numeric_ge(PG_FUNCTION_ARGS)
Datum numeric_out(PG_FUNCTION_ARGS)
Datum numeric_div_trunc(PG_FUNCTION_ARGS)
Datum numeric_in(PG_FUNCTION_ARGS)
Datum numeric_lt(PG_FUNCTION_ARGS)
Datum numeric_add(PG_FUNCTION_ARGS)
Datum numeric_abs(PG_FUNCTION_ARGS)
Datum numeric_mul(PG_FUNCTION_ARGS)
#define OidIsValid(objectId)
Oid get_database_oid(const char *dbname, bool missing_ok)
char * get_database_name(Oid dbid)
static int64 calculate_total_relation_size(Relation rel)
static char * numeric_to_cstring(Numeric n)
static bool numeric_is_less(Numeric a, Numeric b)
Datum pg_indexes_size(PG_FUNCTION_ARGS)
Datum pg_size_bytes(PG_FUNCTION_ARGS)
static Numeric numeric_truncated_divide(Numeric n, int64 divisor)
static const struct size_bytes_unit_alias size_bytes_aliases[]
Datum pg_database_size_oid(PG_FUNCTION_ARGS)
Datum pg_total_relation_size(PG_FUNCTION_ARGS)
Datum pg_tablespace_size_name(PG_FUNCTION_ARGS)
static int64 calculate_tablespace_size(Oid tblspcOid)
Datum pg_size_pretty_numeric(PG_FUNCTION_ARGS)
Datum pg_relation_size(PG_FUNCTION_ARGS)
static int64 calculate_indexes_size(Relation rel)
static int64 db_dir_size(const char *path)
Datum pg_database_size_name(PG_FUNCTION_ARGS)
static Numeric numeric_absolute(Numeric n)
Datum pg_size_pretty(PG_FUNCTION_ARGS)
static int64 calculate_database_size(Oid dbOid)
Datum pg_table_size(PG_FUNCTION_ARGS)
Datum pg_tablespace_size_oid(PG_FUNCTION_ARGS)
static Numeric numeric_half_rounded(Numeric n)
Datum pg_relation_filenode(PG_FUNCTION_ARGS)
Datum pg_filenode_relation(PG_FUNCTION_ARGS)
static const struct size_pretty_unit size_pretty_units[]
static int64 calculate_relation_size(RelFileLocator *rfn, ProcNumber backend, ForkNumber forknum)
Datum pg_relation_filepath(PG_FUNCTION_ARGS)
static int64 calculate_toast_table_size(Oid toastrelid)
static int64 calculate_table_size(Relation rel)
int errcode_for_file_access(void)
int errdetail(const char *fmt,...)
int errhint(const char *fmt,...)
int errcode(int sqlerrcode)
int errmsg(const char *fmt,...)
#define ereport(elevel,...)
DIR * AllocateDir(const char *dirname)
struct dirent * ReadDir(DIR *dir, const char *dirname)
#define PG_GETARG_TEXT_PP(n)
#define DirectFunctionCall2(func, arg1, arg2)
#define PG_RETURN_INT64(x)
#define DirectFunctionCall1(func, arg1)
#define PG_GETARG_INT64(n)
#define PG_GETARG_NAME(n)
#define PG_RETURN_TEXT_P(x)
#define DirectFunctionCall3(func, arg1, arg2, arg3)
Assert(PointerIsAligned(start, uint64))
#define HeapTupleIsValid(tuple)
static void * GETSTRUCT(const HeapTupleData *tuple)
void list_free(List *list)
#define CHECK_FOR_INTERRUPTS()
bool isTempOrTempToastNamespace(Oid namespaceId)
ProcNumber GetTempNamespaceProcNumber(Oid namespaceId)
static Numeric DatumGetNumeric(Datum X)
#define PG_GETARG_NUMERIC(n)
static Datum NumericGetDatum(Numeric X)
FormData_pg_class * Form_pg_class
static const char * dbName
int pg_strcasecmp(const char *s1, const char *s2)
static bool DatumGetBool(Datum X)
static int64 DatumGetInt64(Datum X)
static Datum ObjectIdGetDatum(Oid X)
static char * DatumGetCString(Datum X)
static Datum CStringGetDatum(const char *X)
static Datum Int32GetDatum(int32 X)
#define INVALID_PROC_NUMBER
#define ProcNumberForTempRelations()
char * psprintf(const char *fmt,...)
List * RelationGetIndexList(Relation relation)
Oid RelidByRelfilenumber(Oid reltablespace, RelFileNumber relfilenumber)
RelFileNumber RelationMapOidToFilenumber(Oid relationId, bool shared)
ForkNumber forkname_to_number(const char *forkName)
#define InvalidRelFileNumber
#define relpathbackend(rlocator, backend, forknum)
#define TABLESPACE_VERSION_DIRECTORY
#define RelFileNumberIsValid(relnumber)
void relation_close(Relation relation, LOCKMODE lockmode)
Relation try_relation_open(Oid relationId, LOCKMODE lockmode)
Relation relation_open(Oid relationId, LOCKMODE lockmode)
char str[REL_PATH_STR_MAXLEN+1]
RelFileLocator rd_locator
void ReleaseSysCache(HeapTuple tuple)
HeapTuple SearchSysCache1(int cacheId, Datum key1)
#define SearchSysCacheExists1(cacheId, key1)
#define VARSIZE_ANY_EXHDR(PTR)
text * cstring_to_text(const char *s)
char * text_to_cstring(const text *t)