Virun enger Zäit ware mir mam Problem konfrontéiert fir Tupelen a Raum ze botzen
E gutt Beispill fir eis war den Tarantool Modul genannt
Beschreiwung
D'Dokumentatioun fir Tarantool huet eng ganz gutt
Loosst eis vu wäitem ufänken a kucken wéi e capped expirationed Modul vu baussen ausgesäit:
fiber = require('fiber')
net_box = require('net.box')
box.cfg{listen = 3300}
box.schema.func.create('libcapped-expirationd.start', {language = 'C'})
box.schema.user.grant('guest', 'execute', 'function', 'libcapped-expirationd.start')
box.schema.func.create('libcapped-expirationd.kill', {language = 'C'})
box.schema.user.grant('guest', 'execute', 'function', 'libcapped-expirationd.kill')
box.schema.space.create('tester')
box.space.tester:create_index('primary', {unique = true, parts = {1, 'unsigned'}})
capped_connection = net_box:new(3300)
Fir Einfachheet lancéiere mir Tarantool am Verzeechnes wou eis libcapped-expirationd.so Bibliothéik läit. Zwou Funktiounen ginn aus der Bibliothéik exportéiert: Start an Kill. Den éischte Schrëtt ass dës Funktiounen vu Lua verfügbar ze maachen mat box.schema.func.create a box.schema.user.grant. Dann erstellt e Raum deem seng Tupel nëmmen dräi Felder enthält: déi éischt ass en eenzegaartegen Identifizéierer, déi zweet ass E-Mail, an déi drëtt ass d'Liewensdauer vum Tupel. Mir bauen e Bamindex uewen um éischte Feld a nennen et primär. Als nächst kréie mir de Verbindungsobjekt an eis gebierteg Bibliothéik.
No der Virbereedungsaarbecht, lafen d'Startfunktioun aus:
capped_connection:call('libcapped-expirationd.start', {'non-indexed', box.space.tester.id, box.space.tester.index.primary, box.space.tester.index.primary, 3, 1024, 3600})
Dëst Beispill funktionnéiert beim Scannen genau d'selwecht wéi den ofgelaafte Modul, deen am Lua geschriwwe gëtt. Dat éischt Argument fir d'Startfunktioun ass den eenzegaartegen Numm vun der Aufgab. Déi zweet ass de Raumidentifizéierer. Déi drëtt ass en eenzegaartegen Index, duerch deen d'Tupelen geläscht ginn. Déi véiert ass den Index, duerch deen d'Tupelen duerchgefouert ginn. De fënneften ass d'Zuel vum Tupelfeld mat Liewensdauer (Nummeréierung fänkt vun 1 un, net 0!). De sechsten a siwenten sinn Scannen Astellunge. 1024 ass déi maximal Unzuel vun Tuples déi an enger eenzeger Transaktioun gekuckt kënne ginn. 3600 - Voll Scan Zäit a Sekonnen.
Notéiert datt d'Beispill deeselwechten Index benotzt fir ze krauchen an ze läschen. Wann dëst e Bamindex ass, da gëtt d'Traversal vum méi klenge Schlëssel op dee méi groussen duerchgefouert. Wann et en aneren ass, zum Beispill, Hash Index, da gëtt d'Traversal als Regel an zoufälleg Uerdnung duerchgefouert. All Raum tuples sinn an engem Scan gescannt.
Loosst eis e puer Tupelen an de Raum mat enger Liewensdauer vu 60 Sekonnen setzen:
box.space.tester:insert{0, '[email protected]', math.floor(fiber.time()) + 60}
box.space.tester:insert{1, '[email protected]', math.floor(fiber.time()) + 60}
box.space.tester:insert{2, '[email protected]', math.floor(fiber.time()) + 60}
Loosst eis kucken ob d'Insertioun erfollegräich war:
tarantool> box.space.tester.index.primary:select()
---
- - [0, '[email protected]', 1576418976]
- [1, '[email protected]', 1576418976]
- [2, '[email protected]', 1576418976]
...
Loosst eis d'Auswiel widderhuelen no 60+ Sekonnen (zählen vum Ufank vun der Insertioun vum éischten Tupel) a kuckt datt de capped expirationed Modul scho veraarbecht ass:
tarantool> box.space.tester.index.primary:select()
---
- []
...
Loosst eis d'Aufgab ophalen:
capped_connection:call('libcapped-expirationd.kill', {'non-indexed'})
Loosst eis en zweet Beispill kucken wou e separaten Index fir de Crawl benotzt gëtt:
fiber = require('fiber')
net_box = require('net.box')
box.cfg{listen = 3300}
box.schema.func.create('libcapped-expirationd.start', {language = 'C'})
box.schema.user.grant('guest', 'execute', 'function', 'libcapped-expirationd.start')
box.schema.func.create('libcapped-expirationd.kill', {language = 'C'})
box.schema.user.grant('guest', 'execute', 'function', 'libcapped-expirationd.kill')
box.schema.space.create('tester')
box.space.tester:create_index('primary', {unique = true, parts = {1, 'unsigned'}})
box.space.tester:create_index('exp', {unique = false, parts = {3, 'unsigned'}})
capped_connection = net_box:new(3300)
Alles hei ass d'selwecht wéi am éischte Beispill, mat e puer Ausnahmen. Mir bauen e Bamindex uewen um drëtte Feld a nennen et exp. Dësen Index muss net eenzegaarteg sinn, am Géigesaz zum Index genannt Primär. Traversal gëtt duerch exp Index duerchgefouert, a Läschung duerch Primär. Mir erënneren datt fréier béid nëmme mam primären Index gemaach goufen.
No der Virbereedungsaarbecht lafen mir d'Startfunktioun mat neien Argumenter:
capped_connection:call('libcapped-expirationd.start', {'indexed', box.space.tester.id, box.space.tester.index.primary, box.space.tester.index.exp, 3, 1024, 3600})
Loosst eis mat enger Liewensdauer vu 60 Sekonnen erëm e puer Tupelen an de Raum setzen:
box.space.tester:insert{0, '[email protected]', math.floor(fiber.time()) + 60}
box.space.tester:insert{1, '[email protected]', math.floor(fiber.time()) + 60}
box.space.tester:insert{2, '[email protected]', math.floor(fiber.time()) + 60}
No 30 Sekonnen, no Analogie, addéiere mer e puer méi Tupels:
box.space.tester:insert{3, '[email protected]', math.floor(fiber.time()) + 60}
box.space.tester:insert{4, '[email protected]', math.floor(fiber.time()) + 60}
box.space.tester:insert{5, '[email protected]', math.floor(fiber.time()) + 60}
Loosst eis kucken ob d'Insertioun erfollegräich war:
tarantool> box.space.tester.index.primary:select()
---
- - [0, '[email protected]', 1576421257]
- [1, '[email protected]', 1576421257]
- [2, '[email protected]', 1576421257]
- [3, '[email protected]', 1576421287]
- [4, '[email protected]', 1576421287]
- [5, '[email protected]', 1576421287]
...
Loosst eis d'Auswiel widderhuelen no 60+ Sekonnen (zählen vum Ufank vun der Insertioun vum éischten Tupel) a kuckt datt de capped expirationed Modul scho veraarbecht ass:
tarantool> box.space.tester.index.primary:select()
---
- - [3, '[email protected]', 1576421287]
- [4, '[email protected]', 1576421287]
- [5, '[email protected]', 1576421287]
...
Et sinn nach e puer Tupelen am Raum, déi ongeféier 30 Sekonnen méi ze liewen hunn. Ausserdeem huet de Scan gestoppt wann Dir vun engem Tupel mat enger ID vun 2 an enger Liewensdauer vun 1576421257 op en Tupel mat enger ID vun 3 an enger Liewensdauer vun 1576421287 geplënnert ass. d'exp Index Schlësselen. Dëst sinn d'Erspuernisser, déi mir am Ufank wollten erreechen.
Loosst eis d'Aufgab ophalen:
capped_connection:call('libcapped-expirationd.kill', {'indexed'})
Ëmsetzung
De beschte Wee fir iwwer all d'Features vun engem Projet ze erzielen ass seng originell Quell.
D'Argumenter, déi mir un d'Startmethod passéieren, ginn an enger Struktur gespäichert genannt expirationd_task:
struct expirationd_task
{
char name[256];
uint32_t space_id;
uint32_t rm_index_id;
uint32_t it_index_id;
uint32_t it_index_type;
uint32_t field_no;
uint32_t scan_size;
uint32_t scan_time;
};
Den Numm Attribut ass den Numm vun der Aufgab. D'Space_id Attribut ass de Raumidentifizéierer. Den Attribut rm_index_id ass den Identifizéierer vum eenzegaartegen Index, duerch deen d'Tupelen geläscht ginn. D'it_index_id Attribut ass den Identifizéierer vum Index, duerch deen d'Tupelen duerchgefouert ginn. D'it_index_type Attribut ass den Typ vum Index, duerch deen d'Tupelen duerchgestrachenem ginn. De filed_no Attribut ass d'Zuel vum Tupelfeld mat Liewensdauer. D'Scan_size Attribut ass déi maximal Unzuel vun Tuples déi an enger Transaktioun gescannt ginn. De scan_time Attribut ass déi voll Scanzäit a Sekonnen.
Mir wäerten d'Argumenter net analyséieren. Dëst ass eng ustrengend awer einfach Aarbecht, mat där d'Bibliothéik Iech hëlleft
Mir lëschten d'Prototypen vun alle Funktiounen déi fir d'Parsing benotzt ginn:
bool expirationd_parse_name(struct expirationd_task *task, const char **pos);
bool expirationd_parse_space_id(struct expirationd_task *task, const char **pos);
bool expirationd_parse_rm_index_id(struct expirationd_task *task, const char **pos);
bool expirationd_parse_rm_index_unique(struct expirationd_task *task, const char **pos);
bool expirationd_parse_rm_index(struct expirationd_task *task, const char **pos);
bool expirationd_parse_it_index_id(struct expirationd_task *task, const char **pos);
bool expirationd_parse_it_index_type(struct expirationd_task *task, const char **pos);
bool expirationd_parse_it_index(struct expirationd_task *task, const char **pos);
bool expirationd_parse_field_no(struct expirationd_task *task, const char **pos);
bool expirationd_parse_scan_size(struct expirationd_task *task, const char **pos);
bool expirationd_parse_scan_time(struct expirationd_task *task, const char **pos);
Loosst eis elo op déi wichtegst Saach réckelen - d'Logik vum Raum ëmzegoen an Tuples ze läschen. All Block vun Tuples net méi grouss wéi scan_size gëtt gescannt a geännert ënner enger eenzeger Transaktioun. Wann et erfollegräich ass, ass dës Transaktioun engagéiert; wann de Feeler geschitt, gëtt se zréckgezunn. Dat lescht Argument fir d'Expirationd_iterate Funktioun ass e Pointer op den Iterator, aus deem d'Scannen ufänkt oder weider geet. Dësen Iterator gëtt intern eropgebaut bis e Feeler geschitt, de Raum leeft oder et ass net méiglech de Prozess am Viraus ze stoppen. D'Funktioun expirationd_expired kontrolléiert d'Liewensdauer vun engem Tupel, expirationd_delete läscht en Tupel, expirationd_breakable kontrolléiert ob mir weider musse goen.
Expirationd_iterate Funktiounscode:
static bool
expirationd_iterate(struct expirationd_task *task, box_iterator_t **iterp)
{
box_iterator_t *iter = *iterp;
box_txn_begin();
for (uint32_t i = 0; i < task->scan_size; ++i) {
box_tuple_t *tuple = NULL;
if (box_iterator_next(iter, &tuple) < 0) {
box_iterator_free(iter);
*iterp = NULL;
box_txn_rollback();
return false;
}
if (!tuple) {
box_iterator_free(iter);
*iterp = NULL;
box_txn_commit();
return true;
}
if (expirationd_expired(task, tuple))
expirationd_delete(task, tuple);
else if (expirationd_breakable(task))
break;
}
box_txn_commit();
return true;
}
Funktiounscode expirationd_expired:
static bool
expirationd_expired(struct expirationd_task *task, box_tuple_t *tuple)
{
const char *buf = box_tuple_field(tuple, task->field_no - 1);
if (!buf || mp_typeof(*buf) != MP_UINT)
return false;
uint64_t val = mp_decode_uint(&buf);
if (val > fiber_time64() / 1000000)
return false;
return true;
}
Expirationd_delete Funktiounscode:
static void
expirationd_delete(struct expirationd_task *task, box_tuple_t *tuple)
{
uint32_t len;
const char *str = box_tuple_extract_key(tuple, task->space_id, task->rm_index_id, &len);
box_delete(task->space_id, task->rm_index_id, str, str + len, NULL);
}
Funktiounscode expiration_breakable:
static bool
expirationd_breakable(struct expirationd_task *task)
{
return task->it_index_id != task->rm_index_id && task->it_index_type == ITER_GT;
}
Applikatioun
Dir kënnt de Quellcode kucken op
Source: will.com