$OpenBSD: patch-agent_lib_libstatsinfo_c,v 1.7 2020/02/06 19:26:34 jeremy Exp $

Work with PostgreSQL 12.

Index: agent/lib/libstatsinfo.c
--- agent/lib/libstatsinfo.c.orig
+++ agent/lib/libstatsinfo.c
@@ -7,6 +7,7 @@
 #include "libstatsinfo.h"
 
 #include <fcntl.h>
+#include <float.h>
 #include <unistd.h>
 #include <sys/stat.h>
 #include <sys/types.h>
@@ -34,9 +35,10 @@
 #include "storage/procarray.h"
 #include "utils/builtins.h"
 #include "utils/guc.h"
-#include "utils/tqual.h"
+#include "utils/snapmgr.h"
 #include "utils/lsyscache.h"
 #include "utils/ps_status.h"
+#include "utils/varlena.h"
 
 #if PG_VERSION_NUM >= 90100
 #include "catalog/pg_collation.h"
@@ -595,6 +597,7 @@ sample_activity(void)
 	int			waiting = 0;
 	int			running = 0;
 	int			i;
+	volatile PGPROC *proc = MyProc;
 
 	if (!long_xacts)
 	{
@@ -1887,9 +1890,11 @@ statsinfo_restart(PG_FUNCTION_ARGS)
 #define NUM_STAT_FIELDS_MIN		6
 
 /* not support a kernel that does not have the required fields at "/proc/stat" */
+#if defined(__linux__)
 #if !LINUX_VERSION_AT_LEAST(2,5,41)
 #error kernel version 2.5.41 or later is required
 #endif
+#endif
 
 /*
  * statsinfo_cpustats - get cpu information
@@ -1928,6 +1933,7 @@ statsinfo_cpustats_noarg(PG_FUNCTION_ARGS)
 	PG_RETURN_DATUM(get_cpustats(fcinfo, 0, 0, 0, 0));
 }
 
+#ifdef __OpenBSD__
 static Datum
 get_cpustats(FunctionCallInfo fcinfo,
 			 int64 prev_cpu_user,
@@ -1940,6 +1946,59 @@ get_cpustats(FunctionCallInfo fcinfo,
 	int64			 cpu_system;
 	int64			 cpu_idle;
 	int64			 cpu_iowait;
+	HeapTuple		 tuple;
+	Datum			 values[NUM_CPUSTATS_COLS];
+	bool			 nulls[NUM_CPUSTATS_COLS];
+	long			 cp_time[CPUSTATES];
+	char			 errbuf[_POSIX2_LINE_MAX];
+	int			 mib[] = {CTL_KERN, KERN_CPTIME};
+	size_t			 size = sizeof( cp_time );
+
+	must_be_superuser();
+
+	/* Build a tuple descriptor for our result type */
+	if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE)
+		elog(ERROR, "return type must be a row type");
+
+	Assert(tupdesc->natts == lengthof(values));
+
+	if (sysctl(mib, 2, &cp_time, &size, NULL, 0) < 0)
+		elog(ERROR,"failed to get kern.cptime");
+
+	memset(nulls, 0, sizeof(nulls));
+	memset(values, 0, sizeof(values));
+
+	cpu_user = cp_time[CP_USER] + cp_time[CP_IDLE];
+	cpu_system = cp_time[CP_SYS];
+	cpu_idle = cp_time[CP_IDLE];
+	cpu_iowait = cp_time[CP_INTR];
+
+	values[0] = CStringGetTextDatum((char *)"cpu");
+	values[1] = Int64GetDatum(cpu_user);
+	values[2] = Int64GetDatum(cpu_system);
+	values[3] = Int64GetDatum(cpu_idle);
+	values[4] = Int64GetDatum(cpu_iowait);
+	values[5] = Int16GetDatum(cpu_user < prev_cpu_user ? 1 : 0);
+	values[6] = Int16GetDatum(cpu_system < prev_cpu_system ? 1 : 0);
+	values[7] = Int16GetDatum(cpu_idle < prev_cpu_idle ? 1 : 0);
+	values[8] = Int16GetDatum(cpu_iowait < prev_cpu_iowait ? 1 : 0);
+
+	tuple = heap_form_tuple(tupdesc, values, nulls);
+	return HeapTupleGetDatum(tuple);
+}
+#else
+static Datum
+get_cpustats(FunctionCallInfo fcinfo,
+			 int64 prev_cpu_user,
+			 int64 prev_cpu_system,
+			 int64 prev_cpu_idle,
+			 int64 prev_cpu_iowait)
+{
+	TupleDesc		 tupdesc;
+	int64			 cpu_user;
+	int64			 cpu_system;
+	int64			 cpu_idle;
+	int64			 cpu_iowait;
 	List			*records = NIL;
 	List			*fields = NIL;
 	HeapTuple		 tuple;
@@ -2012,6 +2071,7 @@ get_cpustats(FunctionCallInfo fcinfo,
 
 	return HeapTupleGetDatum(tuple);
 }
+#endif
 
 #define NUM_DEVICESTATS_COLS			17
 #define TYPE_DEVICE_TABLESPACES			TEXTOID
@@ -2185,10 +2245,46 @@ statsinfo_devicestats(PG_FUNCTION_ARGS)
 /*
  * statsinfo_loadavg - get loadavg information
  */
+#if defined(__OpenBSD__)
 Datum
 statsinfo_loadavg(PG_FUNCTION_ARGS)
 {
 	TupleDesc	tupdesc;
+	HeapTuple	tuple;
+	Datum		values[NUM_LOADAVG_COLS];
+	bool		nulls[NUM_LOADAVG_COLS];
+	char		errbuf[_POSIX2_LINE_MAX];
+	struct loadavg	load;
+	int		 mib[] = {CTL_VM, VM_LOADAVG};
+	size_t		 size = sizeof( load );
+
+	must_be_superuser();
+
+	/* Build a tuple descriptor for our result type */
+	if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE)
+		elog(ERROR, "return type must be a row type");
+
+	Assert(tupdesc->natts == lengthof(values));
+
+	if (sysctl(mib, 2, &load, &size, NULL, 0) < 0)
+		elog(ERROR,"failed to get vm.loadavg");
+
+	memset(nulls, 0, sizeof(nulls));
+	memset(values, 0, sizeof(values));
+
+	values[0] = Float4GetDatum(load.ldavg[0]);
+	values[1] = Float4GetDatum(load.ldavg[1]);
+	values[2] = Float4GetDatum(load.ldavg[2]);
+
+	tuple = heap_form_tuple(tupdesc, values, nulls);
+
+	return HeapTupleGetDatum(tuple);
+}
+#else
+Datum
+statsinfo_loadavg(PG_FUNCTION_ARGS)
+{
+	TupleDesc	tupdesc;
 	int			fd;
 	char		buffer[256];
 	int			nbytes;
@@ -2247,6 +2343,7 @@ statsinfo_loadavg(PG_FUNCTION_ARGS)
 
 	return HeapTupleGetDatum(tuple);
 }
+#endif
 
 #define FILE_MEMINFO		"/proc/meminfo"
 #define NUM_MEMORY_COLS		5
@@ -2266,6 +2363,7 @@ compare_meminfo_table(const void *a, const void *b)
 /*
  * statsinfo_memory - get memory information
  */
+#if defined(__OpenBSD__)
 Datum
 statsinfo_memory(PG_FUNCTION_ARGS)
 {
@@ -2273,6 +2371,36 @@ statsinfo_memory(PG_FUNCTION_ARGS)
 	HeapTuple		 tuple;
 	Datum			 values[NUM_MEMORY_COLS];
 	bool			 nulls[NUM_MEMORY_COLS];
+
+	must_be_superuser();
+
+	/* Build a tuple descriptor for our result type */
+	if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE)
+		elog(ERROR, "return type must be a row type");
+
+	Assert(tupdesc->natts == lengthof(values));
+
+	memset(nulls, 0, sizeof(nulls));
+	memset(values, 0, sizeof(values));
+
+	values[0] = Int64GetDatum(0);
+	values[1] = Int64GetDatum(0);
+	values[2] = Int64GetDatum(0);
+	values[3] = Int64GetDatum(0);
+	values[4] = Int64GetDatum(0);
+
+	tuple = heap_form_tuple(tupdesc, values, nulls);
+
+	return HeapTupleGetDatum(tuple);
+}
+#else
+Datum
+statsinfo_memory(PG_FUNCTION_ARGS)
+{
+	TupleDesc		 tupdesc;
+	HeapTuple		 tuple;
+	Datum			 values[NUM_MEMORY_COLS];
+	bool			 nulls[NUM_MEMORY_COLS];
 	int				 fd;
 	char			 buffer[2048];
 	int				 nbytes;
@@ -2371,6 +2499,7 @@ nextline:
 
 	return HeapTupleGetDatum(tuple);
 }
+#endif
 
 #define FILE_PROFILE		"/proc/systemtap/statsinfo_prof/profile"
 #define NUM_PROFILE_COLS	3
@@ -2379,9 +2508,16 @@ nextline:
 /*
  * statsinfo_profile - get profile information
  */
+#if defined(__OpenBSD__)
 Datum
 statsinfo_profile(PG_FUNCTION_ARGS)
 {
+	PG_RETURN_VOID();
+}
+#else
+Datum
+statsinfo_profile(PG_FUNCTION_ARGS)
+{
 	ReturnSetInfo	*rsinfo = (ReturnSetInfo *) fcinfo->resultinfo;
 	TupleDesc		 tupdesc;
 	Tuplestorestate	*tupstore;
@@ -2488,6 +2624,7 @@ statsinfo_profile(PG_FUNCTION_ARGS)
 
 	PG_RETURN_VOID();
 }
+#endif
 
 static bool
 checked_write(int fd, const void *buf, int size)
@@ -3014,7 +3151,7 @@ statsinfo_tablespaces(PG_FUNCTION_ARGS)
 	Tuplestorestate	   *tupstore;
 	MemoryContext		per_query_ctx;
 	MemoryContext		oldcontext;
-	HeapScanDesc		scan;
+	TableScanDesc		scan;
 	HeapTuple			tuple;
 	Relation			relation;
 	Datum				values[TABLESPACES_COLS];
@@ -3053,9 +3190,9 @@ statsinfo_tablespaces(PG_FUNCTION_ARGS)
 
 	relation = heap_open(TableSpaceRelationId, AccessShareLock);
 #if PG_VERSION_NUM >= 90400
-	scan = heap_beginscan_catalog(relation, 0, NULL);
+	scan = table_beginscan_catalog(relation, 0, NULL);
 #else
-	scan = heap_beginscan(relation, SnapshotNow, 0, NULL);
+	scan = table_beginscan(relation, SnapshotNow, 0, NULL);
 #endif
 	while ((tuple = heap_getnext(scan, ForwardScanDirection)) != NULL)
 	{
@@ -3067,20 +3204,20 @@ statsinfo_tablespaces(PG_FUNCTION_ARGS)
 		i = 0;
 
 		/* oid */
-		values[i++] = ObjectIdGetDatum(HeapTupleGetOid(tuple));
+		values[i++] = ObjectIdGetDatum(form->oid);
 
 		/* name */
 		values[i++] = CStringGetTextDatum(NameStr(form->spcname));
 
 		/* location */
-		if (HeapTupleGetOid(tuple) == DEFAULTTABLESPACE_OID ||
-			HeapTupleGetOid(tuple) == GLOBALTABLESPACE_OID)
+		if (form->oid == DEFAULTTABLESPACE_OID ||
+			form->oid == GLOBALTABLESPACE_OID)
 			datum = CStringGetTextDatum(DataDir);
 		else
 		{
 #if PG_VERSION_NUM >= 90200
 			datum = DirectFunctionCall1(pg_tablespace_location,
-										ObjectIdGetDatum(HeapTupleGetOid(tuple)));
+										ObjectIdGetDatum(form->oid));
 #else
 			bool isnull;
 			datum = fastgetattr(tuple, Anum_pg_tablespace_spclocation,
