Skip to content

Commit 0de7bbb

Browse files
committed
pathman: rewrite dsm arrays
1 parent 8fc719d commit 0de7bbb

File tree

3 files changed

+87
-49
lines changed

3 files changed

+87
-49
lines changed

contrib/pg_pathman/dsm_array.c

Lines changed: 84 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -4,17 +4,34 @@
44
#include "storage/lwlock.h"
55

66

7-
static Table *table;
7+
// static Table *table;
88
static dsm_segment *segment = NULL;
9-
9+
static dsm_handle *segment_handle = 0;
10+
static size_t _first_free = 0;
11+
static size_t _block_size = 0;
12+
13+
typedef int BlockHeader;
14+
typedef BlockHeader* BlockHeaderPtr;
15+
16+
#define FREE_BIT 0x80000000
17+
#define is_free(header) \
18+
((*header) & FREE_BIT)
19+
#define set_free(header) \
20+
((*header) | FREE_BIT)
21+
#define set_used(header) \
22+
((*header) & ~FREE_BIT)
23+
#define get_length(header) \
24+
((*header) & ~FREE_BIT)
25+
#define set_length(header, length) \
26+
((length) | ((*header) & FREE_BIT))
1027

1128
void
1229
alloc_dsm_table()
1330
{
1431
bool found;
15-
table = (Table *) ShmemInitStruct("dsm table", sizeof(Table), &found);
32+
segment_handle = ShmemInitStruct("dsm table", sizeof(dsm_handle), &found);
1633
if (!found)
17-
table->segment_handle = 0;
34+
*segment_handle = 0;
1835
}
1936

2037

@@ -26,30 +43,30 @@ bool
2643
init_dsm_segment(size_t block_size)
2744
{
2845
bool ret;
29-
dsm_handle handle;
3046

3147
/* lock here */
3248
LWLockAcquire(dsm_init_lock, LW_EXCLUSIVE);
3349

3450
/* if there is already an existing segment then attach to it */
35-
if (table->segment_handle != 0)
51+
if (*segment_handle != 0)
3652
{
3753
ret = false;
38-
segment = dsm_attach(table->segment_handle);
54+
segment = dsm_attach(*segment_handle);
3955
}
4056

4157
/*
4258
* If segment hasn't been created yet or has already been destroyed
4359
* (it happens when last session detaches segment) then create new one
4460
*/
45-
if (table->segment_handle == 0 || segment == NULL)
61+
if (*segment_handle == 0 || segment == NULL)
4662
{
4763
/* create segment */
4864
segment = dsm_create(block_size * BLOCKS_COUNT, 0);
49-
handle = dsm_segment_handle(segment);
50-
init_dsm_table(table, handle, block_size);
65+
*segment_handle = dsm_segment_handle(segment);
66+
init_dsm_table(block_size);
5167
ret = true;
5268
}
69+
_block_size = block_size;
5370

5471
/*
5572
* Keep mapping till the end of the session. Otherwise it would be
@@ -63,25 +80,24 @@ init_dsm_segment(size_t block_size)
6380
return ret;
6481
}
6582

83+
/*
84+
* Initialize allocated segment with block structure
85+
*/
6686
void
67-
init_dsm_table(Table *tbl, dsm_handle h, size_t block_size)
87+
init_dsm_table(size_t block_size)
6888
{
6989
int i;
70-
Block *block;
71-
72-
memset(table, 0, sizeof(Table));
73-
table->segment_handle = h;
74-
table->block_size = block_size;
75-
table->first_free = 0;
90+
BlockHeaderPtr header;
91+
char *ptr = dsm_segment_address(segment);
7692

7793
/* create blocks */
7894
for (i=0; i<BLOCKS_COUNT; i++)
7995
{
80-
block = &table->blocks[i];
81-
block->segment = h;
82-
block->offset = i * block_size;
83-
block->is_free = true;
96+
header = (BlockHeaderPtr) &ptr[i * block_size];
97+
*header = set_free(header);
98+
*header = set_length(header, 1);
8499
}
100+
_first_free = 0;
85101

86102
return;
87103
}
@@ -93,71 +109,91 @@ void
93109
alloc_dsm_array(DsmArray *arr, size_t entry_size, size_t length)
94110
{
95111
int i = 0;
96-
Block *block = NULL;
97-
int free_count = 0;
98112
int size_requested = entry_size * length;
99113
int min_pos = 0;
100114
int max_pos = 0;
115+
size_t offset = 0;
116+
size_t total_length = 0;
117+
char *ptr = dsm_segment_address(segment);
118+
BlockHeaderPtr header;
101119

102-
for (i = table->first_free; i<BLOCKS_COUNT; i++)
120+
for (i = _first_free; i<BLOCKS_COUNT; )
103121
{
104-
if (table->blocks[i].is_free)
122+
header = (BlockHeaderPtr) &ptr[i * _block_size];
123+
if (is_free(header))
105124
{
106-
if (!block)
125+
if (!offset)
107126
{
108-
block = &table->blocks[i];
127+
offset = i * _block_size;
128+
total_length = _block_size - sizeof(BlockHeader);
109129
min_pos = i;
110130
}
111-
free_count++;
131+
else
132+
{
133+
total_length += _block_size;
134+
}
135+
i++;
112136
}
113137
else
114138
{
115-
free_count = 0;
116-
block = NULL;
139+
offset = 0;
140+
total_length = 0;
141+
i += get_length(header);
117142
}
118143

119-
if (free_count * table->block_size >= size_requested)
144+
if (total_length >= size_requested)
120145
{
121-
// return block->offset;
122-
max_pos = i;
146+
max_pos = i-1;
123147
break;
124148
}
125149
}
126150

127151
/* look up for first free block */
128-
for (i = i+1; i<BLOCKS_COUNT; i++)
129-
if (table->blocks[i].is_free == true)
152+
for (; i<BLOCKS_COUNT; )
153+
{
154+
header = (BlockHeaderPtr) &ptr[i * _block_size];
155+
if (is_free(header))
130156
{
131-
table->first_free = i;
157+
_first_free = i;
132158
break;
133159
}
160+
else
161+
{
162+
i += get_length(header);
163+
}
164+
}
134165

135166
/* if we found enough of space */
136-
if (free_count * table->block_size >= size_requested)
167+
if (total_length >= size_requested)
137168
{
138-
for(i=min_pos; i<=max_pos; i++)
139-
table->blocks[i].is_free = false;
140-
arr->offset = block->offset;
169+
header = (BlockHeaderPtr) &ptr[min_pos * _block_size];
170+
*header = set_used(header);
171+
*header = set_length(header, max_pos - min_pos + 1);
172+
173+
arr->offset = offset;
141174
arr->length = length;
142175
}
143176
}
144177

145178
void
146179
free_dsm_array(DsmArray *arr)
147180
{
148-
int start = arr->offset / table->block_size;
181+
int start = arr->offset / _block_size;
149182
int i = 0;
183+
char *ptr = dsm_segment_address(segment);
184+
BlockHeaderPtr header = (BlockHeaderPtr) &ptr[start * _block_size];
185+
size_t blocks_count = get_length(header);
150186

151187
/* set blocks free */
152-
for(;; i++)
188+
for(; i < blocks_count; i++)
153189
{
154-
table->blocks[start + i].is_free = true;
155-
if (i * table->block_size >= arr->length)
156-
break;
190+
header = (BlockHeaderPtr) &ptr[(start + i) * _block_size];
191+
*header = set_free(header);
192+
*header = set_length(header, 1);
157193
}
158194

159-
if (arr->offset < table->first_free)
160-
table->first_free = arr->offset;
195+
if (start < _first_free)
196+
_first_free = start;
161197

162198
arr->offset = 0;
163199
arr->length = 0;
@@ -166,5 +202,5 @@ free_dsm_array(DsmArray *arr)
166202
void *
167203
dsm_array_get_pointer(const DsmArray* arr)
168204
{
169-
return (uint8_t *) dsm_segment_address(segment) + arr->offset;
205+
return (char *) dsm_segment_address(segment) + arr->offset + sizeof(BlockHeader);
170206
}

contrib/pg_pathman/pathman.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -139,7 +139,7 @@ LWLock *dsm_init_lock;
139139
/* Dynamic shared memory functions */
140140
void alloc_dsm_table(void);
141141
bool init_dsm_segment(size_t block_size);
142-
void init_dsm_table(Table *tbl, dsm_handle h, size_t block_size);
142+
void init_dsm_table(size_t block_size);
143143
void alloc_dsm_array(DsmArray *arr, size_t entry_size, size_t length);
144144
void free_dsm_array(DsmArray *arr);
145145
void *dsm_array_get_pointer(const DsmArray* arr);

contrib/pg_pathman/pg_pathman.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -136,7 +136,9 @@ pathman_planner_hook(Query *parse, int cursorOptions, ParamListInfo boundParams)
136136
PlannedStmt *result;
137137

138138
if (initialization_needed)
139+
{
139140
load_config();
141+
}
140142

141143
inheritance_disabled = false;
142144
disable_inheritance(parse);

0 commit comments

Comments
 (0)