Nostrae scripturae capped exspirationd moduli ad tarantool

Nostrae scripturae capped exspirationd moduli ad tarantool

Dudum ante eramus ad problema purgationis tuples in spatiis tarantool. Purgatio inchoanda non erat cum tarantool iam memoria excurreret, sed in antecessum et frequentia quadam. Ad hoc opus, tarantool habet modulum scriptum in Lua vocato exspiratio. Hoc modulo paulisper adhibito, intelleximus non aptum esse nobis: ob assiduam purgationem magnarum copiarum notitiarum, Luam in GC pendentem. Ideo cogitavimus de explicandis propriis moduli cappedalibus expiratione, sperantes codicem in lingua programmandi indigena scriptum problemata nostra quam optimo modo solvere.

Exemplum bonum nobis fuit moduli tarantool vocati memcached. Accessus in eo nititur eo quod separatus creatur in spatio, quod indicat vita tuple, id est, ttl. Modulus in curriculo spatium lustrat, TTL cum tempore praesenti comparat et iudicat utrum tuplam delere necne. Codex moduli memcached simplex et elegans est, sed nimis genericus. Primum, non considerat genus indicis quod reptatur et deletum est. Secundo in singulis trans- lustrantur omnes tuples, quorum numerus satis magnus esse potest. Et si in modulo resoluto primum problema solvetur (index arboris in genus separatum separatum est), secundus adhuc nullam attentionem accepit. Haec tria praestituerunt electionem scribendi in codice meo.

Description

Documenta pro tarantool valde bona est doceo de modo scribendi rationes tuas conditas in C. Inprimis admoneo te ipsum eo adsuescere ad intelligendum ea quae cum mandatis et codice inseruntur quae infra patebunt. Valet etiam attendentes reference ad ea quae in promptu sunt, cum modulus tuus pinifer scribens, scilicet Box, fibra, Index ΠΈ txn.

Ex longinquo incipiamus et vide quid moduli capped exspirationis ab exterioribus similes sint:

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)

Pro simplicitate tarantool in indicem deducimus ubi bibliotheca nostra libcapped-expirationd.so sita est. Duae functiones e bibliotheca exportantur: incipite et occidunt. Primus gradus est haec munera praesto facere ex Luae box.schema.func.create et box.schema.user.grant. Tum spatium crea cuius tuples tantum tres agros continebit: prima est unica identificatio, secunda inscriptio est, tertia vita tupla est. Lignum indicem super primi campi construimus et primarium vocamus. Deinde nexum obiecto bibliothecae nostrae patriae consequimur.

Post opus praeparatorium, munus initium currite;

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})

Hoc exemplum in intuendo prorsus idem faciet ac moduli respirandi, qui in Lua scriptus est. Prima ratio ad initium functionis est singulare nomen muneris. Secundum est spatium identis. Tertius index singularis est quo tuples delebitur. Quartus index qua tuples percurretur. Quintus est numerus campi tupli cum vita sua (numbering incipit ab 1, not 0!). Sextus et septimus occasus scandunt. 1024 numerus maximus est tuples qui in una transactione spectari potest. MMMDC - plena scan tempus in secundis.

Nota quod exemplum eodem indice utitur ad reptando et delendo. Si index arboris hoc est, tunc traversalis exercetur a minore clave ad maiorem. Si est alius, exempli gratia, index Nullam, tunc peragitur traversalis fere in ordine temere. Totum spatium tuples in uno scan lustratur.

Plures tuples inseramus in spatium cum vita 60 secundis:

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}

Sit scriptor reprehendo insertionem valuitque;

tarantool> box.space.tester.index.primary:select()
---
- - [0, '[email protected]', 1576418976]
  - [1, '[email protected]', 1576418976]
  - [2, '[email protected]', 1576418976]
...

Repeamus electa post 60+ secundis (ab initio insertionis primae tuplae computatis) et videamus moduli cappedum expiratione iam discursum esse:

tarantool> box.space.tester.index.primary:select()
---
  - []
...

Sit scriptor inhibere negotium:

capped_connection:call('libcapped-expirationd.kill', {'non-indexed'})

Intueamur alterum exemplum ubi index separatus ponitur pro repere:

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)

Omnia hic eadem, quae in primo exemplo, paucis exceptis. Arborem indicem super tertii campi construimus et eam appellamus exp. Hic index non habet esse unicum, dissimilis index qui vocatur primarius. Traversal peragetur index exp, et deletio primaria. Antea utrumque factum meminimus tantum indice primo utente.

Post opus praeparatorium, munus committitur novis argumentis;

capped_connection:call('libcapped-expirationd.start', {'indexed', box.space.tester.id, box.space.tester.index.primary, box.space.tester.index.exp, 3, 1024, 3600})

Plures tuples inseramus in spatium iterum cum vita 60 secundis:

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}

Post 30 seconds, per analogiam, plura tuples addemus;

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}

Sit scriptor reprehendo insertionem valuitque;

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]
...

Repeamus electa post 60+ secundis (ab initio insertionis primae tuplae computatis) et videamus moduli cappedum expiratione iam discursum esse:

tarantool> box.space.tester.index.primary:select()
---
- - [3, '[email protected]', 1576421287]
  - [4, '[email protected]', 1576421287]
  - [5, '[email protected]', 1576421287]
...

Sunt adhuc quidam tuples relicti in spatio quod circiter 30 plus secundis ad vivendum habebit. Praeterea, scan cessatum est a tupla cum ID of 2 et vita 1576421257 ad tuplum cum ID 3 et vita 1576421287 cessatum est. Tuples cum vita 1576421287 vel plura non lustrata sunt propter ordinationem. in indice clavium exp. Haec est compendia quam in ipso initio consequi voluimus.

Sit scriptor inhibere negotium:

capped_connection:call('libcapped-expirationd.kill', {'indexed'})

РСализация

Optime narrandum est de omnibus formis consilii fontem suum esse. Code! Ut pars editionis, solum in punctis maximis versarimus, scilicet spatium algorithmorum praeterire.

Argumenta ad methodum satus transeamus in structura quae vocatur 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;
};

Nomen attributum est nomen negotii. The space_id attributum est spatium identifier. Proprium rm_index_id est identifier index singularis quo tuples delebitur. Id attributum est identifier index quo tuples percurretur. Proprium illud_index_type est genus indices quo tuples percurretur. Filed_no attributum est numerus campi tuple cum vita. The scan_size attributum est numerus maximus tuples qui in una re lustrantur. Scan_time attributum est plenum scan tempus in secundis.

Nolumus parsing rationes. Hoc est officium accuratum sed simplex, quo bibliotheca te adiuvabit msppuck. Difficultates tantum possunt oriri cum indicibus, qui de Lua procedunt ut structurae notitiae implicatae cum typo mp_map, et non utens speciebus simplicibus mp_bool, mp_double, mp_int, mp_uint et mp_array. Sed totum indicem non opus est ad parse. Vos iustus postulo ut singularitatem eius inspicias, rationem calculate et identificantem extrahe.

Prototypa omnium functionum quae ad parsing adhibentur enumeramus:

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);

Nunc ad rem maximi momenti transeamus β€” logicam spatium praetermittens et tuples delendo. Uterque truncus tuples non maior quam scan_size lustratur ac modificatur sub una transactione. Si bene, hoc negotium committitur: si erratum est, revolvitur. Postrema ratio ad functionem expirationem_iterate monstrator est ad iteratorem a quo intuens incipit vel pergit. Hic iterator interius augetur donec error incidat, spatium decurrit vel processum in antecessum sistere non potest. Munus expirationd_exspirationis vitam tuplae supprimit, expirationd_deletum tuple delet, expirationd_breakable compescit an progrediendum opus est.

Expirationd_iterate munus codice:

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;
}

Munus codice 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 munus codice:

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);
}

Munus codicem 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;
}

application

Potes videre source code at hic!

Source: www.habr.com