diff --git a/src/backend/distributed/Makefile b/src/backend/distributed/Makefile index ea88d1f78..8a28c5b0e 100644 --- a/src/backend/distributed/Makefile +++ b/src/backend/distributed/Makefile @@ -12,7 +12,7 @@ EXTVERSIONS = 5.0 5.0-1 5.0-2 \ 6.1-1 6.1-2 6.1-3 6.1-4 6.1-5 6.1-6 6.1-7 6.1-8 6.1-9 6.1-10 6.1-11 6.1-12 6.1-13 6.1-14 6.1-15 6.1-16 6.1-17 \ 6.2-1 6.2-2 6.2-3 6.2-4 \ 7.0-1 7.0-2 7.0-3 7.0-4 7.0-5 7.0-6 7.0-7 7.0-8 7.0-9 7.0-10 7.0-11 7.0-12 7.0-13 7.0-14 7.0-15 \ - 7.1-1 7.1-2 + 7.1-1 7.1-2 7.1-3 # All citus--*.sql files in the source directory DATA = $(patsubst $(citus_abs_srcdir)/%.sql,%.sql,$(wildcard $(citus_abs_srcdir)/$(EXTENSION)--*--*.sql)) @@ -174,6 +174,8 @@ $(EXTENSION)--7.1-1.sql: $(EXTENSION)--7.0-15.sql $(EXTENSION)--7.0-15--7.1-1.sq cat $^ > $@ $(EXTENSION)--7.1-2.sql: $(EXTENSION)--7.1-1.sql $(EXTENSION)--7.1-1--7.1-2.sql cat $^ > $@ +$(EXTENSION)--7.1-3.sql: $(EXTENSION)--7.1-2.sql $(EXTENSION)--7.1-2--7.1-3.sql + cat $^ > $@ NO_PGXS = 1 diff --git a/src/backend/distributed/citus--7.1-2--7.1-3.sql b/src/backend/distributed/citus--7.1-2--7.1-3.sql new file mode 100644 index 000000000..dcc483c24 --- /dev/null +++ b/src/backend/distributed/citus--7.1-2--7.1-3.sql @@ -0,0 +1,17 @@ +/* citus--7.1-2--7.1-3 */ + +CREATE TABLE citus.pg_dist_node_metadata( + metadata jsonb NOT NULL +); +ALTER TABLE citus.pg_dist_node_metadata SET SCHEMA pg_catalog; +GRANT SELECT ON pg_catalog.pg_dist_node_metadata TO public; + +CREATE FUNCTION pg_catalog.citus_server_id() + RETURNS uuid + LANGUAGE C STRICT + AS 'MODULE_PATHNAME', $$citus_server_id$$; +COMMENT ON FUNCTION citus_server_id() + IS 'generates a random UUID to be used as server identifier'; + +INSERT INTO pg_dist_node_metadata + VALUES (jsonb_build_object('server_id', citus_server_id()::text)); diff --git a/src/backend/distributed/citus.control b/src/backend/distributed/citus.control index 6d0648f0d..0f6cb527a 100644 --- a/src/backend/distributed/citus.control +++ b/src/backend/distributed/citus.control @@ -1,6 +1,6 @@ # Citus extension comment = 'Citus distributed database' -default_version = '7.1-2' +default_version = '7.1-3' module_pathname = '$libdir/citus' relocatable = false schema = pg_catalog diff --git a/src/backend/distributed/utils/metadata_cache.c b/src/backend/distributed/utils/metadata_cache.c index 8b511c1d2..d8392808d 100644 --- a/src/backend/distributed/utils/metadata_cache.c +++ b/src/backend/distributed/utils/metadata_cache.c @@ -31,6 +31,7 @@ #include "distributed/metadata_cache.h" #include "distributed/multi_logical_optimizer.h" #include "distributed/pg_dist_local_group.h" +#include "distributed/pg_dist_node_metadata.h" #include "distributed/pg_dist_node.h" #include "distributed/pg_dist_partition.h" #include "distributed/pg_dist_shard.h" @@ -3167,3 +3168,51 @@ CitusInvalidateRelcacheByShardId(int64 shardId) /* bump command counter, to force invalidation to take effect */ CommandCounterIncrement(); } + + +/* + * DistNodeMetadata returns the single metadata jsonb object stored in + * pg_dist_node_metadata. + */ +Datum +DistNodeMetadata(void) +{ + Datum metadata = 0; + SysScanDesc scanDescriptor = NULL; + ScanKeyData scanKey[1]; + const int scanKeyCount = 0; + HeapTuple heapTuple = NULL; + Oid metadataTableOid = InvalidOid; + Relation pgDistNodeMetadata = NULL; + TupleDesc tupleDescriptor = NULL; + + metadataTableOid = get_relname_relid("pg_dist_node_metadata", PG_CATALOG_NAMESPACE); + if (metadataTableOid == InvalidOid) + { + ereport(ERROR, (errmsg("pg_dist_node_metadata was not found"))); + } + + pgDistNodeMetadata = heap_open(metadataTableOid, AccessShareLock); + scanDescriptor = systable_beginscan(pgDistNodeMetadata, + InvalidOid, false, + NULL, scanKeyCount, scanKey); + tupleDescriptor = RelationGetDescr(pgDistNodeMetadata); + + heapTuple = systable_getnext(scanDescriptor); + if (HeapTupleIsValid(heapTuple)) + { + bool isNull = false; + metadata = heap_getattr(heapTuple, Anum_pg_dist_node_metadata_metadata, + tupleDescriptor, &isNull); + Assert(!isNull); + } + else + { + ereport(ERROR, (errmsg("could not find any entries in pg_dist_metadata"))); + } + + systable_endscan(scanDescriptor); + heap_close(pgDistNodeMetadata, AccessShareLock); + + return metadata; +} diff --git a/src/backend/distributed/utils/statistics_collection.c b/src/backend/distributed/utils/statistics_collection.c index 901ee015d..e0855ca2e 100644 --- a/src/backend/distributed/utils/statistics_collection.c +++ b/src/backend/distributed/utils/statistics_collection.c @@ -11,6 +11,12 @@ #include "postgres.h" #include "citus_version.h" +#include "fmgr.h" +#include "utils/uuid.h" + +#if PG_VERSION_NUM >= 100000 +#include "utils/backend_random.h" +#endif bool EnableStatisticsCollection = true; /* send basic usage statistics to Citus */ @@ -25,6 +31,11 @@ bool EnableStatisticsCollection = true; /* send basic usage statistics to Citus #include "distributed/worker_manager.h" #include "lib/stringinfo.h" #include "utils/json.h" +#include "utils/jsonb.h" + +#if PG_VERSION_NUM >= 100000 +#include "utils/fmgrprotos.h" +#endif static uint64 NextPow2(uint64 n); static uint64 ClusterSize(List *distributedTableList); @@ -61,6 +72,8 @@ CollectBasicUsageStatistics(void) uint64 roundedClusterSize = 0; uint32 workerNodeCount = 0; StringInfo fields = makeStringInfo(); + Datum metadataJsonbDatum = 0; + char *metadataJsonbStr = NULL; struct utsname unameData; memset(&unameData, 0, sizeof(unameData)); @@ -80,8 +93,9 @@ CollectBasicUsageStatistics(void) roundedDistTableCount = NextPow2(list_length(distributedTables)); roundedClusterSize = NextPow2(ClusterSize(distributedTables)); workerNodeCount = ActivePrimaryNodeCount(); - CommitTransactionCommand(); - + metadataJsonbDatum = DistNodeMetadata(); + metadataJsonbStr = DatumGetCString(DirectFunctionCall1(jsonb_out, + metadataJsonbDatum)); uname(&unameData); appendStringInfoString(fields, "{\"citus_version\": "); @@ -95,8 +109,11 @@ CollectBasicUsageStatistics(void) escape_json(fields, unameData.release); appendStringInfoString(fields, ",\"hwid\": "); escape_json(fields, unameData.machine); + appendStringInfo(fields, ",\"node_metadata\": %s", metadataJsonbStr); appendStringInfoString(fields, "}"); + CommitTransactionCommand(); + return SendHttpPostJsonRequest(STATS_COLLECTION_HOST "/v1/usage_reports", fields->data, HTTP_TIMEOUT_SECONDS); } @@ -224,3 +241,39 @@ SendHttpPostJsonRequest(const char *url, const char *jsonObj, long timeoutSecond #endif /* HAVE_LIBCURL */ + +PG_FUNCTION_INFO_V1(citus_server_id); + +/* + * citus_server_id returns a random UUID value as server identifier. This is + * modeled after PostgreSQL's pg_random_uuid(). + */ +Datum +citus_server_id(PG_FUNCTION_ARGS) +{ + uint8 *buf = (uint8 *) palloc(UUID_LEN); + +#if PG_VERSION_NUM >= 100000 + if (!pg_backend_random((char *) buf, UUID_LEN)) + { + ereport(ERROR, (errmsg("failed to generate server identifier"))); + } +#else + { + int bufIdx = 0; + for (bufIdx = 0; bufIdx < UUID_LEN; bufIdx++) + { + buf[bufIdx] = (uint8) (random() & 0xFF); + } + } +#endif + + /* + * Set magic numbers for a "version 4" (pseudorandom) UUID, see + * http://tools.ietf.org/html/rfc4122#section-4.4 + */ + buf[6] = (buf[6] & 0x0f) | 0x40; /* "version" field */ + buf[8] = (buf[8] & 0x3f) | 0x80; /* "variant" field */ + + PG_RETURN_UUID_P((pg_uuid_t *) buf); +} diff --git a/src/include/distributed/metadata_cache.h b/src/include/distributed/metadata_cache.h index 3d78390a3..1d61d4c38 100644 --- a/src/include/distributed/metadata_cache.h +++ b/src/include/distributed/metadata_cache.h @@ -87,6 +87,7 @@ extern List * ShardPlacementList(uint64 shardId); extern void CitusInvalidateRelcacheByRelid(Oid relationId); extern void CitusInvalidateRelcacheByShardId(int64 shardId); extern void InvalidateMetadataSystemCache(void); +extern Datum DistNodeMetadata(void); extern bool CitusHasBeenLoaded(void); extern bool CheckCitusVersion(int elevel); diff --git a/src/include/distributed/pg_dist_node_metadata.h b/src/include/distributed/pg_dist_node_metadata.h new file mode 100644 index 000000000..54fa29a0e --- /dev/null +++ b/src/include/distributed/pg_dist_node_metadata.h @@ -0,0 +1,22 @@ +/*------------------------------------------------------------------------- + * + * pg_dist_node_metadata.h + * definition of the relation that holds the metadata table (pg_dist_node_metadata). + * + * Copyright (c) 2017, Citus Data, Inc. + * + *------------------------------------------------------------------------- + */ + +#ifndef PG_DIST_NODE_METADATA_H +#define PG_DIST_NODE_METADATA_H + + +/* ---------------- + * compiler constants for pg_dist_node_metadata + * ---------------- + */ +#define Natts_pg_dist_node_metadata 1 +#define Anum_pg_dist_node_metadata_metadata 1 + +#endif /* PG_DIST_NODE_METADATA_H */