-
Notifications
You must be signed in to change notification settings - Fork 1
/
spin-wait-blob.pgc
132 lines (116 loc) · 2.88 KB
/
spin-wait-blob.pgc
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
/*
* Synopsis:
* Spin wait on a blob in an SQL table, up to a timeout seconds.
* Description:
* Spin wait for a blob to appear in an SQL table, backing off
* exponentially until more seconds than timeout has expired.
* Execute the following SQL query for existence:
*
* SELECT EXISTS (
* SELECT
* <column_name>
* FROM
* <table_name>
* WHERE
* <column_name> = <blob>::udig
* )
*
* Usage:
* spin-wait-blob <table> <row> <trys> <blob udig>
* Exit Status:
* 0 blob appeared
* 1 blob never appeared
* 2 invocation error
* 3 sql warning
* 4 sql error
* Note:
* Find a clearer way to assemble the query than appending with
* _strcat().
*
* For fast syncing environments, adding a back-off algorithm might
* be reasonable.
*
* spin-wait-blob plus1 ...
* spin-wait-blob double
*
* spin-wait-blob is a desparate but effective hack. hopefully pg logical
* replication will alleviate the need for wating on sunk data to appear
* in the database.
*/
static char progname[] = "spin-wait-blob";
#define EXIT_OK 0
#define EXIT_NO_BLOB 1
#define EXIT_BAD_INVO 2
#define EXIT_SQLWARN 3
#define EXIT_SQLERROR 4
#define COMMON_NEED_DIE2
#include "common.c"
#define COMMON_ECPG_NEED_SQL_ERROR
#define COMMON_ECPG_NEED_SQL_WARNING
#include "common-ecpg.c"
#include <stdlib.h>
int
main(int argc, char **argv)
{
int try_count;
char *table_name, *column_name, *blob;
EXEC SQL BEGIN DECLARE SECTION;
bool blob_exists;
char query[4096];
EXEC SQL END DECLARE SECTION;
if (argc != 5)
die(EXIT_BAD_INVO, "wrong number of arguments");
table_name = argv[1];
column_name = argv[2];
blob = argv[4];
/*
* Parse the number of trys.
*/
{
char *trys = argv[3];
size_t len = strlen(trys);
if (len < 1 || len > 19)
die2(EXIT_BAD_INVO,"trys not > 0 and < 20 chars", trys);
try_count = atoi(trys);
if (try_count <= 0)
die2(EXIT_BAD_INVO, "negative number of trys", trys);
}
EXEC SQL WHENEVER SQLERROR CALL _ecpg_sql_error(
(struct _ecpg_sql_state_fault *)0
);
EXEC SQL WHENEVER SQLWARNING CALL _ecpg_sql_warning(
(struct _ecpg_sql_state_fault *)0
);
EXEC SQL CONNECT TO default;
/*
* Build the query:
*
* SELECT EXISTS (
* SELECT
* <column_name>
* FROM
* <table_name>
* WHERE
* <column_name> = <blob>::udig
* )
*/
query[0] = 0;
_strcat(query, sizeof query, "SELECT EXISTS (SELECT ");
_strcat(query, sizeof query, column_name);
_strcat(query, sizeof query, " FROM ");
_strcat(query, sizeof query, table_name);
_strcat(query, sizeof query, " WHERE ");
_strcat(query, sizeof query, column_name);
_strcat(query, sizeof query, " = '");
_strcat(query, sizeof query, blob);
_strcat(query, sizeof query, "'::udig)");
EXEC SQL PREPARE get_blob FROM :query;
AGAIN:
EXEC SQL EXECUTE get_blob INTO :blob_exists;
if (blob_exists)
_exit(EXIT_OK);
if (--try_count <= 0)
_exit(EXIT_NO_BLOB);
sleep(1);
goto AGAIN;
}