/*-------------------------------------------------------------------------
 *
 * pg_stash_advice.h
 *	  main header for pg_stash_advice contrib module
 *
 * This module allows plan advice strings (as used and generated by
 * pg_plan_advice) to be "stashed" in dynamic shared memory and, from
 * there, automatically be applied to queries as they are planned.
 * You can create any number of advice stashes, each of which is
 * identified by a human-readable, ASCII identifier, and each of them is
 * essentially a query ID -> advice_string mapping.
 *
 * Copyright (c) 2016-2026, PostgreSQL Global Development Group
 *
 *	  contrib/pg_stash_advice/pg_stash_advice.h
 *
 *-------------------------------------------------------------------------
 */
#ifndef PG_STASH_ADVICE_H
#define PG_STASH_ADVICE_H

#include "lib/dshash.h"
#include "storage/lwlock.h"

#define PGSA_DUMP_FILE		"pg_stash_advice.tsv"

/*
 * The key that we use to find a particular stash entry.
 */
typedef struct pgsa_entry_key
{
	uint64		pgsa_stash_id;
	int64		queryId;
} pgsa_entry_key;

/*
 * A single stash entry.
 */
typedef struct pgsa_entry
{
	pgsa_entry_key key;
	dsa_pointer advice_string;
} pgsa_entry;

/*
 * The stash itself is just a mapping from a name to a stash ID.
 */
typedef struct pgsa_stash
{
	char		name[NAMEDATALEN];
	uint64		pgsa_stash_id;
} pgsa_stash;

/*
 * Top-level shared state object for pg_stash_advice.
 */
typedef struct pgsa_shared_state
{
	LWLock		lock;
	int			dsa_tranche;
	int			stash_tranche;
	int			entry_tranche;
	uint64		next_stash_id;
	dsa_handle	area;
	dshash_table_handle stash_hash;
	dshash_table_handle entry_hash;
	pid_t		bgworker_pid;
	pg_atomic_flag stashes_ready;
	pg_atomic_uint64 change_count;
} pgsa_shared_state;

/* For stash ID -> stash name hash table */
typedef struct pgsa_stash_name
{
	uint32		status;
	uint64		pgsa_stash_id;
	char	   *name;
} pgsa_stash_name;

/* Declare stash ID -> stash name hash table */
#define SH_PREFIX pgsa_stash_name_table
#define SH_ELEMENT_TYPE pgsa_stash_name
#define SH_KEY_TYPE uint64
#define SH_SCOPE extern
#define SH_DECLARE
#include "lib/simplehash.h"

/* Shared memory pointers */
extern pgsa_shared_state *pgsa_state;
extern dsa_area *pgsa_dsa_area;
extern dshash_table *pgsa_stash_dshash;
extern dshash_table *pgsa_entry_dshash;

/* GUC variables */
extern bool pg_stash_advice_persist;
extern int	pg_stash_advice_persist_interval;

/* Function prototypes */
extern void pgsa_attach(void);
extern void pgsa_check_lockout(void);
extern void pgsa_check_stash_name(char *stash_name);
extern void pgsa_clear_advice_string(char *stash_name, int64 queryId);
extern void pgsa_create_stash(char *stash_name);
extern void pgsa_drop_stash(char *stash_name);
extern uint64 pgsa_lookup_stash_id(char *stash_name);
extern void pgsa_reset_all_stashes(void);
extern void pgsa_set_advice_string(char *stash_name, int64 queryId,
								   char *advice_string);
extern void pgsa_start_worker(void);

#endif
