Skip to content

Commit 3157940

Browse files
committed
Add pg_gtm extension
1 parent 56c8ce8 commit 3157940

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

52 files changed

+7684
-6
lines changed

contrib/pg_gtm/Makefile

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
MODULE_big = pg_dtm
2+
OBJS = pg_dtm.o libdtm.o
3+
4+
EXTENSION = pg_dtm
5+
DATA = pg_dtm--1.0.sql
6+
7+
ifdef USE_PGXS
8+
PG_CONFIG = pg_config
9+
PGXS := $(shell $(PG_CONFIG) --pgxs)
10+
include $(PGXS)
11+
else
12+
subdir = contrib/pg_dtm
13+
top_builddir = ../..
14+
include $(top_builddir)/src/Makefile.global
15+
include $(top_srcdir)/contrib/contrib-global.mk
16+
endif

contrib/pg_gtm/README

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
===
2+
dtm
3+
===
4+
5+
Distributed transaction management tools for PostgreSQL.
6+
7+
--------------------
8+
Communication scheme
9+
--------------------
10+
11+
.- Backend -.
12+
/ \
13+
/ \
14+
DTM ---- Backend ---- Coordinator
15+
\ /
16+
\ /
17+
`- Backend -´
18+
19+
-----------------------
20+
Coordinator-Backend API
21+
-----------------------
22+
23+
This API includes a set of postgres procedures that
24+
the coordinator can call with "select" statement.
25+
26+
extend_transaction (n integer) -> (higcid gcid)
27+
join_transaction (higcid gcid) -> ()
28+
FIXME: add procedures that would start and finish 2pc
29+
30+
----------
31+
libdtm api
32+
----------
33+
34+
typedef unsigned long long cid_t;
35+
36+
// Connects to the specified DTM.
37+
DTMConn DtmConnect(char *host, int port);
38+
39+
// Disconnects from the DTM. Do not use the 'dtm' pointer after this call, or
40+
// bad things will happen.
41+
void DtmDisconnect(DTMConn dtm);
42+
43+
// Asks DTM for the first 'gcid' with unknown status. This 'gcid' is used as a
44+
// kind of snapshot. Returns the 'gcid' on success, or INVALID_GCID otherwise.
45+
cid_t DtmGlobalGetNextCid(DTMConn dtm);
46+
47+
// Prepares a commit. Returns the 'gcid' on success, or INVALID_GCID otherwise.
48+
cid_t DtmGlobalPrepare(DTMConn dtm);
49+
50+
// Finishes a given commit with 'committed' status. Returns 'true' on success,
51+
// 'false' otherwise.
52+
bool DtmGlobalCommit(DTMConn dtm, cid_t gcid);
53+
54+
// Finishes a given commit with 'aborted' status.
55+
void DtmGlobalRollback(DTMConn dtm, cid_t gcid);
56+
57+
// Gets the status of the commit identified by 'gcid'. Returns the status on
58+
// success, or -1 otherwise.
59+
int DtmGlobalGetTransStatus(DTMConn dtm, cid_t gcid);
60+
61+
--------------------
62+
Backend-DTM Protocol
63+
--------------------
64+
65+
DTM <--> Backend:
66+
67+
<- 'p'<hex16 self> - "prepare"
68+
-> '+'<hex16 gcid> - "commit prepared"
69+
-> '-' - "something went wrong"
70+
71+
<- 'c'<hex16 gcid> - "commit"
72+
-> '+' - "commit saved"
73+
-> '-' - "something went wrong"
74+
75+
<- 'a'<hex16 gcid> - "abort"
76+
-> '+' - "abort saved"
77+
-> '-' - "something went wrong"
78+
79+
<- 'h' - "horizon"
80+
-> '+'<hex16 gcid> - "here is a gcid you can use as a snapshot"
81+
-> '-' - "something went wrong"
82+
83+
<- 's'<hex16 gcid> - "status"
84+
-> '+''c|a|?' - "here is the transaction status"
85+
(c)ommitted, (a)borted or (?)unknown
86+
-> '-' - "something went wrong"
87+
88+
Backend disconnection is considered as an abort of all incomplete commits
89+
prepared by that backend.

contrib/pg_gtm/dtmd/Makefile

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
CC=gcc
2+
CFLAGS=-g -pedantic -Wall -Iinclude -D_LARGEFILE64_SOURCE
3+
LIBUV_PREFIX=$(HOME)/libuv-build
4+
LIBUV_CFLAGS=-I"$(LIBUV_PREFIX)/include" -L"$(LIBUV_PREFIX)/lib"
5+
LIBUV_LDFLAGS=-luv -pthread
6+
7+
SYSTEM=$(shell uname -s)
8+
ifeq ($(SYSTEM),Darwin)
9+
CFLAGS += -D_DARWIN_C_SOURCE
10+
endif
11+
12+
.PHONY: all clean check bindir objdir
13+
14+
all: bin/dtmd
15+
@echo Done.
16+
@echo Feel free to run the tests with \'make check\'.
17+
18+
bin/dtmd: obj/eventwrap.o obj/main.o obj/parser.o obj/clog.o obj/clogfile.o obj/util.o | bindir objdir
19+
$(CC) -o bin/dtmd $(CFLAGS) $(LIBUV_CFLAGS) \
20+
obj/eventwrap.o obj/main.o obj/parser.o \
21+
obj/clog.o obj/clogfile.o obj/util.o \
22+
$(LIBUV_LDFLAGS)
23+
24+
obj/eventwrap.o: src/eventwrap.c | objdir
25+
$(CC) -c -o obj/eventwrap.o $(CFLAGS) $(LIBUV_CFLAGS) src/eventwrap.c
26+
27+
check: bin/util-test bin/clog-test bin/parser-test
28+
./check.sh util parser clog
29+
30+
obj/%.o: src/%.c | objdir
31+
$(CC) $(CFLAGS) -c -o $@ $<
32+
33+
bin/util-test: obj/util-test.o obj/util.o | bindir
34+
$(CC) -o bin/util-test $(CFLAGS) obj/util-test.o obj/util.o
35+
36+
bin/clog-test: obj/clog-test.o obj/clog.o obj/clogfile.o obj/util.o | bindir
37+
$(CC) -o bin/clog-test $(CFLAGS) obj/clog-test.o obj/clog.o obj/clogfile.o obj/util.o
38+
39+
bin/parser-test: obj/parser-test.o obj/parser.o | bindir
40+
$(CC) -o bin/parser-test $(CFLAGS) obj/parser-test.o obj/parser.o
41+
42+
bindir:
43+
mkdir -p bin
44+
45+
objdir:
46+
mkdir -p obj
47+
48+
clean:
49+
rm -rfv bin obj test.log

contrib/pg_gtm/dtmd/bin/dtmd

51.2 KB
Binary file not shown.

contrib/pg_gtm/dtmd/check.sh

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
#!/bin/sh
2+
rm -rf test.log
3+
failed=0
4+
passed=0
5+
for testname in $@; do
6+
if bin/${testname}-test >> test.log 2>&1; then
7+
echo "${testname} ok"
8+
passed=$((passed + 1))
9+
else
10+
echo "${testname} FAILED"
11+
failed=$((failed + 1))
12+
fi
13+
done
14+
15+
echo "tests passed: $passed"
16+
echo "tests failed: $failed"
17+
if [ $failed -eq 0 ]; then
18+
rm -rf test.log
19+
else
20+
echo "see test.log for details"
21+
exit 1
22+
fi

contrib/pg_gtm/dtmd/include/clog.h

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
/*
2+
* This module provides a high-level API to access clog files.
3+
*/
4+
5+
#ifndef CLOG_H
6+
#define CLOG_H
7+
8+
#include <stdbool.h>
9+
#include "int.h"
10+
11+
#define INVALID_GCID 0
12+
#define MIN_GCID 42
13+
#define MAX_GCID 0xdeadbeefcafebabe
14+
15+
#define COMMIT_UNKNOWN 0
16+
#define COMMIT_YES 1
17+
#define COMMIT_NO 2
18+
19+
typedef struct clog_data_t *clog_t;
20+
21+
// Open the clog at the specified path. Try not to open the same datadir twice
22+
// or in two different processes. Return a clog object on success, NULL
23+
// otherwise.
24+
clog_t clog_open(char *datadir);
25+
26+
// Get the status of the specified global commit.
27+
int clog_read(clog_t clog, cid_t gcid);
28+
29+
// Set the status of the specified global commit. Return 'true' on success,
30+
// 'false' otherwise.
31+
bool clog_write(clog_t clog, cid_t gcid, int status);
32+
33+
// Allocate a fresh unused gcid. Return INVALID_GCID on error.
34+
cid_t clog_advance(clog_t clog);
35+
36+
// Get the first unknown commit id (used as a snapshot). Return INVALID_GCID on
37+
// error.
38+
cid_t clog_horizon(clog_t clog);
39+
40+
// Forget about the commits before the given one ('until'), and free the
41+
// occupied space if possible. Return 'true' on success, 'false' otherwise.
42+
bool clog_forget(clog_t clog, cid_t until);
43+
44+
// Close the specified clog. Do not use the clog object after closing. Return
45+
// 'true' on success, 'false' otherwise.
46+
bool clog_close(clog_t clog);
47+
48+
#endif
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
/*
2+
* This module provides a low-level API to access clog files.
3+
*/
4+
5+
#include <stdbool.h>
6+
#include "int.h"
7+
8+
#ifndef CLOGFILE_H
9+
#define CLOGFILE_H
10+
11+
#define BITS_PER_COMMIT 2
12+
#define COMMIT_MASK ((1 << BITS_PER_COMMIT) - 1)
13+
#define COMMITS_PER_BYTE 4
14+
#define COMMITS_PER_FILE 1024 // 0x100000000
15+
#define BYTES_PER_FILE ((COMMITS_PER_FILE) / (COMMITS_PER_BYTE))
16+
#define GCID_TO_FILEID(GCID) ((GCID) / (COMMITS_PER_FILE))
17+
#define GCID_TO_OFFSET(GCID) (((GCID) % (COMMITS_PER_FILE)) / (COMMITS_PER_BYTE))
18+
#define GCID_TO_SUBOFFSET(GCID) (((GCID) % (COMMITS_PER_FILE)) % (COMMITS_PER_BYTE))
19+
20+
typedef struct clogfile_t {
21+
char *path;
22+
cid_t min;
23+
cid_t max;
24+
void *data; // ptr for mmap
25+
} clogfile_t;
26+
27+
// Open a clog file with the gived id. Create before opening if 'create' is
28+
// true. Return 'true' on success, 'false' otherwise.
29+
bool clogfile_open_by_id(clogfile_t *clogfile, char *datadir, int fileid, bool create);
30+
31+
// Close and remove the given clog file. Return 'true' on success, 'false'
32+
// otherwise.
33+
bool clogfile_remove(clogfile_t *clogfile);
34+
35+
// Close the specified clogfile. Return 'true' on success, 'false' otherwise.
36+
bool clogfile_close(clogfile_t *clogfile);
37+
38+
// Get the status of the specified global commit from the clog file.
39+
int clogfile_get_status(clogfile_t *clogfile, cid_t gcid);
40+
41+
// Set the status of the specified global commit in the clog file. Return
42+
// 'true' on success, 'false' otherwise.
43+
bool clogfile_set_status(clogfile_t *clogfile, cid_t gcid, int status);
44+
45+
#endif
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
/*
2+
* This module is used as a layer of abstraction between the main logic and the
3+
* event library. This should, theoretically, allow us to switch to another
4+
* library with less effort.
5+
*/
6+
7+
#ifndef EVENTWRAP_H
8+
#define EVENTWRAP_H
9+
10+
int eventwrap(
11+
const char *host,
12+
int port,
13+
char *(*ondata)(void *client, size_t len, char *data),
14+
void (*onconnect)(void **client),
15+
void (*ondisconnect)(void *client)
16+
);
17+
18+
#endif

contrib/pg_gtm/dtmd/include/int.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
#ifndef INT_H
2+
#define INT_H
3+
4+
typedef unsigned long long cid_t;
5+
6+
#endif

contrib/pg_gtm/dtmd/include/parser.h

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
#ifndef PARSER_H
2+
#define PARSER_H
3+
4+
#include <stdbool.h>
5+
6+
#include "int.h"
7+
8+
#define CMD_PREPARE 'p'
9+
#define CMD_COMMIT 'c'
10+
#define CMD_ABORT 'a'
11+
#define CMD_HORIZON 'h'
12+
#define CMD_STATUS 's'
13+
14+
typedef struct cmd_t {
15+
char cmd;
16+
cid_t arg;
17+
} cmd_t;
18+
19+
// Do not rely on the inner structure, it may change tomorrow.
20+
typedef struct parser_data_t *parser_t;
21+
22+
// Allocate and initialize a parser.
23+
parser_t parser_create();
24+
25+
// Destroy the parser. The 'p' handle becomes invalid, so do not refer to it
26+
// after destroying the parser.
27+
void parser_destroy(parser_t p);
28+
29+
// Initialize the parser.
30+
void parser_init(parser_t p);
31+
32+
// Check if parser has failed.
33+
bool parser_failed(parser_t p);
34+
35+
// Get the error message for the parser.
36+
char *parser_errormsg(parser_t p);
37+
38+
// Feeds a character to the parser, and returns a parsed command if it is
39+
// complete. Returns NULL if command is not complete. The caller should check
40+
// for errors, please use parser_failed() method for that. Also the caller
41+
// should free the cmd after use.
42+
cmd_t *parser_feed(parser_t p, char c);
43+
44+
#endif

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy