Skip to content

Commit 71f4bbd

Browse files
committed
bugfixes
1 parent a5efb5a commit 71f4bbd

File tree

7 files changed

+339
-160
lines changed

7 files changed

+339
-160
lines changed

README.md

Lines changed: 21 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -66,17 +66,32 @@ create_range_partitions(
6666
start_value ANYELEMENT,
6767
interval ANYELEMENT,
6868
premake INTEGER)
69-
```
70-
Performs RANGE partitioning for `relation` by partitioning key `attribute`. `start_value` argument specifies initial value, `interval` sets the range of values in a single partition, `premake` is the number of premade partitions (the only one partition will be created if `premake` is 0).
71-
```
69+
7270
create_range_partitions(
7371
relation TEXT,
7472
attribute TEXT,
7573
start_value ANYELEMENT,
7674
interval INTERVAL,
7775
premake INTEGER)
7876
```
79-
Same as above but suitable for `DATE` and `TIMESTAMP` partitioning keys.
77+
Performs RANGE partitioning for `relation` by partitioning key `attribute`. `start_value` argument specifies initial value, `interval` sets the range of values in a single partition, `premake` is the number of premade partitions.
78+
79+
```
80+
create_partitions_from_range(
81+
relation TEXT,
82+
attribute TEXT,
83+
start_value ANYELEMENT,
84+
end_value ANYELEMENT,
85+
interval ANYELEMENT)
86+
87+
create_partitions_from_range(
88+
relation TEXT,
89+
attribute TEXT,
90+
start_value ANYELEMENT,
91+
end_value ANYELEMENT,
92+
interval INTERVAL)
93+
```
94+
Performs RANGE-partitioning from specified range for `relation` by partitioning key `attribute`.
8095

8196
### Utilities
8297
```
@@ -162,9 +177,9 @@ INSERT INTO range_rel (dt) SELECT g FROM generate_series('2010-01-01'::date, '20
162177
```
163178
Run create_range_partitions() function to create partitions so that each partition would contain data for one month:
164179
```
165-
SELECT create_range_partitions('range_rel', 'dt', '2010-01-01'::date, '1 month'::interval, 59);
180+
SELECT create_range_partitions('range_rel', 'dt', '2010-01-01'::date, '1 month'::interval, 60);
166181
```
167-
It will create 60 partitions (one partition is created regardless of `premake` parameter). Now move data from the parent to partitions.
182+
It will create 60 partitions. Now let's move data from the parent to partitions.
168183
```
169184
SELECT partition_data('range_rel');
170185
```

README.rus.md

Lines changed: 20 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -67,17 +67,32 @@ create_range_partitions(
6767
start_value ANYELEMENT,
6868
interval ANYELEMENT,
6969
premake INTEGER)
70-
```
71-
Выполняет RANGE-секционирование таблицы `relation` по полю `attribute`. Аргумент `start_value` задает начальное значение, `interval` -- диапазон значений внутри одной секции, `premake` -- количество заранее создаваемых секций (если 0, то будет создана единственная секция).
72-
```
70+
7371
create_range_partitions(
7472
relation TEXT,
7573
attribute TEXT,
7674
start_value ANYELEMENT,
7775
interval INTERVAL,
7876
premake INTEGER)
7977
```
80-
Аналогично предыдущей с тем лишь отличием, что данная функция предназначена для секционирования по полю типа `DATE` или `TIMESTAMP`.
78+
Выполняет RANGE-секционирование таблицы `relation` по полю `attribute`. Аргумент `start_value` задает начальное значение, `interval` -- диапазон значений внутри одной секции, `premake` -- количество заранее создаваемых секций.
79+
80+
```
81+
create_partitions_from_range(
82+
relation TEXT,
83+
attribute TEXT,
84+
start_value ANYELEMENT,
85+
end_value ANYELEMENT,
86+
interval ANYELEMENT)
87+
88+
create_partitions_from_range(
89+
relation TEXT,
90+
attribute TEXT,
91+
start_value ANYELEMENT,
92+
end_value ANYELEMENT,
93+
interval INTERVAL)
94+
```
95+
Выполняет RANGE-секционирование для заданного диапазона таблицы `relation` по полю `attribute`.
8196

8297
### Утилиты
8398
```
@@ -164,9 +179,8 @@ INSERT INTO range_rel (dt) SELECT g FROM generate_series('2010-01-01'::date, '20
164179
```
165180
Разобьем таблицу на 60 секций так, чтобы каждая секция содержала данные за один месяц:
166181
```
167-
SELECT create_range_partitions('range_rel', 'dt', '2010-01-01'::date, '1 month'::interval, 59);
182+
SELECT create_range_partitions('range_rel', 'dt', '2010-01-01'::date, '1 month'::interval, 60);
168183
```
169-
> Значение `premake` равно 59, а не 60, т.к. 1 секция создается независимо от значения `premake`
170184

171185
Перенесем данные из родительской таблицы в дочерние секции.
172186
```

dsm_array.c

Lines changed: 77 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,18 @@
44
#include "storage/lwlock.h"
55
#include <stdint.h>
66

7-
// static Table *table;
7+
88
static dsm_segment *segment = NULL;
9-
static dsm_handle *segment_handle = 0;
10-
static size_t _first_free = 0;
11-
static size_t _block_size = 0;
9+
10+
typedef struct DsmConfig
11+
{
12+
dsm_handle segment_handle;
13+
size_t block_size;
14+
size_t blocks_count;
15+
size_t first_free;
16+
} DsmConfig;
17+
18+
static DsmConfig *dsm_cfg = NULL;
1219

1320
typedef int BlockHeader;
1421
typedef BlockHeader* BlockHeaderPtr;
@@ -29,9 +36,14 @@ void
2936
alloc_dsm_table()
3037
{
3138
bool found;
32-
segment_handle = ShmemInitStruct("dsm table", sizeof(dsm_handle), &found);
39+
dsm_cfg = ShmemInitStruct("dsm config", sizeof(DsmConfig), &found);
3340
if (!found)
34-
*segment_handle = 0;
41+
{
42+
dsm_cfg->segment_handle = 0;
43+
dsm_cfg->block_size = 0;
44+
dsm_cfg->blocks_count = INITIAL_BLOCKS_COUNT;
45+
dsm_cfg->first_free = 0;
46+
}
3547
}
3648

3749

@@ -40,33 +52,35 @@ alloc_dsm_table()
4052
* false if attached to existing segment
4153
*/
4254
bool
43-
init_dsm_segment(size_t block_size)
55+
init_dsm_segment(size_t blocks_count, size_t block_size)
4456
{
4557
bool ret;
4658

4759
/* lock here */
4860
LWLockAcquire(dsm_init_lock, LW_EXCLUSIVE);
4961

5062
/* if there is already an existing segment then attach to it */
51-
if (*segment_handle != 0)
63+
if (dsm_cfg->segment_handle != 0)
5264
{
5365
ret = false;
54-
segment = dsm_attach(*segment_handle);
66+
segment = dsm_attach(dsm_cfg->segment_handle);
5567
}
5668

5769
/*
5870
* If segment hasn't been created yet or has already been destroyed
5971
* (it happens when last session detaches segment) then create new one
6072
*/
61-
if (*segment_handle == 0 || segment == NULL)
73+
if (dsm_cfg->segment_handle == 0 || segment == NULL)
6274
{
6375
/* create segment */
64-
segment = dsm_create(block_size * BLOCKS_COUNT, 0);
65-
*segment_handle = dsm_segment_handle(segment);
66-
init_dsm_table(block_size);
76+
segment = dsm_create(block_size * blocks_count, 0);
77+
dsm_cfg->segment_handle = dsm_segment_handle(segment);
78+
dsm_cfg->first_free = 0;
79+
dsm_cfg->block_size = block_size;
80+
dsm_cfg->blocks_count = blocks_count;
81+
init_dsm_table(block_size, 0, dsm_cfg->blocks_count);
6782
ret = true;
6883
}
69-
_block_size = block_size;
7084

7185
/*
7286
* Keep mapping till the end of the session. Otherwise it would be
@@ -84,20 +98,19 @@ init_dsm_segment(size_t block_size)
8498
* Initialize allocated segment with block structure
8599
*/
86100
void
87-
init_dsm_table(size_t block_size)
101+
init_dsm_table(size_t block_size, size_t start, size_t end)
88102
{
89103
int i;
90104
BlockHeaderPtr header;
91105
char *ptr = dsm_segment_address(segment);
92106

93107
/* create blocks */
94-
for (i=0; i<BLOCKS_COUNT; i++)
108+
for (i=start; i<end; i++)
95109
{
96110
header = (BlockHeaderPtr) &ptr[i * block_size];
97111
*header = set_free(header);
98112
*header = set_length(header, 1);
99113
}
100-
_first_free = 0;
101114

102115
return;
103116
}
@@ -112,30 +125,34 @@ alloc_dsm_array(DsmArray *arr, size_t entry_size, size_t length)
112125
int size_requested = entry_size * length;
113126
int min_pos = 0;
114127
int max_pos = 0;
115-
size_t offset = 0;
128+
bool found = false;
129+
bool collecting_blocks = false;
130+
size_t offset = -1;
116131
size_t total_length = 0;
117-
char *ptr = dsm_segment_address(segment);
118132
BlockHeaderPtr header;
133+
char *ptr = dsm_segment_address(segment);
119134

120-
for (i = _first_free; i<BLOCKS_COUNT; )
135+
for (i = dsm_cfg->first_free; i<dsm_cfg->blocks_count; )
121136
{
122-
header = (BlockHeaderPtr) &ptr[i * _block_size];
137+
header = (BlockHeaderPtr) &ptr[i * dsm_cfg->block_size];
123138
if (is_free(header))
124139
{
125-
if (!offset)
140+
if (!collecting_blocks)
126141
{
127-
offset = i * _block_size;
128-
total_length = _block_size - sizeof(BlockHeader);
142+
offset = i * dsm_cfg->block_size;
143+
total_length = dsm_cfg->block_size - sizeof(BlockHeader);
129144
min_pos = i;
145+
collecting_blocks = true;
130146
}
131147
else
132148
{
133-
total_length += _block_size;
149+
total_length += dsm_cfg->block_size;
134150
}
135151
i++;
136152
}
137153
else
138154
{
155+
collecting_blocks = false;
139156
offset = 0;
140157
total_length = 0;
141158
i += get_length(header);
@@ -144,29 +161,49 @@ alloc_dsm_array(DsmArray *arr, size_t entry_size, size_t length)
144161
if (total_length >= size_requested)
145162
{
146163
max_pos = i-1;
164+
found = true;
147165
break;
148166
}
149167
}
150168

169+
/*
170+
* If dsm segment size is not enough then resize it (or allocate bigger
171+
* for segment SysV and Windows, not implemented yet)
172+
*/
173+
if (!found)
174+
{
175+
size_t new_blocks_count = dsm_cfg->blocks_count * 2;
176+
177+
dsm_resize(segment, new_blocks_count * dsm_cfg->block_size);
178+
init_dsm_table(dsm_cfg->block_size, dsm_cfg->blocks_count, new_blocks_count);
179+
dsm_cfg->blocks_count = new_blocks_count;
180+
181+
/* try again */
182+
return alloc_dsm_array(arr, entry_size, length);
183+
}
184+
151185
/* look up for first free block */
152-
for (; i<BLOCKS_COUNT; )
186+
if (dsm_cfg->first_free == min_pos)
153187
{
154-
header = (BlockHeaderPtr) &ptr[i * _block_size];
155-
if (is_free(header))
156-
{
157-
_first_free = i;
158-
break;
159-
}
160-
else
188+
for (; i<dsm_cfg->blocks_count; )
161189
{
162-
i += get_length(header);
190+
header = (BlockHeaderPtr) &ptr[i * dsm_cfg->block_size];
191+
if (is_free(header))
192+
{
193+
dsm_cfg->first_free = i;
194+
break;
195+
}
196+
else
197+
{
198+
i += get_length(header);
199+
}
163200
}
164201
}
165202

166203
/* if we found enough of space */
167204
if (total_length >= size_requested)
168205
{
169-
header = (BlockHeaderPtr) &ptr[min_pos * _block_size];
206+
header = (BlockHeaderPtr) &ptr[min_pos * dsm_cfg->block_size];
170207
*header = set_used(header);
171208
*header = set_length(header, max_pos - min_pos + 1);
172209

@@ -178,22 +215,22 @@ alloc_dsm_array(DsmArray *arr, size_t entry_size, size_t length)
178215
void
179216
free_dsm_array(DsmArray *arr)
180217
{
181-
int start = arr->offset / _block_size;
218+
int start = arr->offset / dsm_cfg->block_size;
182219
int i = 0;
183220
char *ptr = dsm_segment_address(segment);
184-
BlockHeaderPtr header = (BlockHeaderPtr) &ptr[start * _block_size];
221+
BlockHeaderPtr header = (BlockHeaderPtr) &ptr[start * dsm_cfg->block_size];
185222
size_t blocks_count = get_length(header);
186223

187224
/* set blocks free */
188225
for(; i < blocks_count; i++)
189226
{
190-
header = (BlockHeaderPtr) &ptr[(start + i) * _block_size];
227+
header = (BlockHeaderPtr) &ptr[(start + i) * dsm_cfg->block_size];
191228
*header = set_free(header);
192229
*header = set_length(header, 1);
193230
}
194231

195-
if (start < _first_free)
196-
_first_free = start;
232+
if (start < dsm_cfg->first_free)
233+
dsm_cfg->first_free = start;
197234

198235
arr->offset = 0;
199236
arr->length = 0;

0 commit comments

Comments
 (0)