
рдХрд╛рд╣реА рдХрд╛рд│рд╛рдкреВрд░реНрд╡реА рдЖрдореНрд╣рд╛рд▓рд╛ рдЬрд╛рдЧрд╛рдВрдордзреАрд▓ рдЯрдкрд▓реНрд╕ рд╕рд╛рдл рдХрд░рдгреНрдпрд╛рдЪреА рд╕рдорд╕реНрдпрд╛ рдЖрд▓реА. рдЯреЕрд░рдВрдЯреВрд▓рдЪреА рдореЗрдорд░реА рдХрдореА рдЕрд╕рддрд╛рдирд╛ рд╕рд╛рдлрд╕рдлрд╛рдИ рд╕реБрд░реВ рдХрд░рдгреЗ рдЖрд╡рд╢реНрдпрдХ рдирд╡реНрд╣рддреЗ, рддрд░ рдЖрдЧрд╛рдК рдЖрдгрд┐ рдПрдХрд╛ рд╡рд┐рд╢рд┐рд╖реНрдЯ рд╡рд╛рд░рдВрд╡рд╛рд░рддреЗрдиреЗ рд╕реБрд░реВ рдХрд░рдгреЗ рдЖрд╡рд╢реНрдпрдХ рд╣реЛрддреЗ. рдпрд╛ рдХрд╛рдорд╛рд╕рд╛рдареА рдЯреЕрд░рдВрдЯреВрд▓рдордзреНрдпреЗ рд▓реБрдЖ рднрд╛рд╖реЗрдд рд▓рд┐рд╣рд┐рд▓реЗрд▓реЗ рдПрдХ рдореЙрдбреНрдпреВрд▓ рдЖрд╣реЗ, рдЬреНрдпрд╛рд▓рд╛ рдореНрд╣рдгрддрд╛рдд рдереЛрдбреНрдпрд╛ рдХрд╛рд│рд╛рд╕рд╛рдареА рд╣реЗ рдореЙрдбреНрдпреВрд▓ рд╡рд╛рдкрд░рд▓реНрдпрд╛рдирдВрддрд░, рдЖрдореНрд╣рд╛рд▓рд╛ рдЬрд╛рдгрд╡рд▓реЗ рдХреА рддреЗ рдЖрдордЪреНрдпрд╛ рдЧрд░рдЬрд╛рдВрд╕рд╛рдареА рдпреЛрдЧреНрдп рдирд╛рд╣реА: рдореЛрдареНрдпрд╛ рдкреНрд░рдорд╛рдгрд╛рдд рдбреЗрдЯрд╛рдЪреНрдпрд╛ рд╕рддрдд рд╕рд╛рдлрд╕рдлрд╛рдИ рджрд░рдореНрдпрд╛рди рд▓реБрдЖ рдХреНрд░реЕрд╢ рд╣реЛрдд рд╣реЛрддрд╛. рдореНрд╣рдгреВрди рдЖрдореНрд╣реА рдЖрдордЪреЗ рд╕реНрд╡рддрдГрдЪреЗ рдХреЕрдкреНрдб рдПрдХреНрд╕рдкрд╛рдпрд░реЗрд╢рди рдореЙрдбреНрдпреВрд▓ рд╡рд┐рдХрд╕рд┐рдд рдХрд░рдгреНрдпрд╛рдЪрд╛ рд╡рд┐рдЪрд╛рд░ рдХреЗрд▓рд╛, рдЕрд╢реА рдЖрд╢рд╛ рд╣реЛрддреА рдХреА рдореВрд│ рдкреНрд░реЛрдЧреНрд░рд╛рдорд┐рдВрдЧ рднрд╛рд╖реЗрдд рд▓рд┐рд╣рд┐рд▓реЗрд▓рд╛ рдХреЛрдб рдЖрдордЪреНрдпрд╛ рдЧрд░рдЬрд╛ рд╕рд░реНрд╡реЛрддреНрддрдо рдкреНрд░рдХрд╛рд░реЗ рдкреВрд░реНрдг рдХрд░реЗрд▓.
рдЖрдордЪреНрдпрд╛рд╕рд╛рдареА рдПрдХ рдЪрд╛рдВрдЧрд▓реЗ рдЙрджрд╛рд╣рд░рдг рдореНрд╣рдгрдЬреЗ рдЯреЕрд░рдВрдЯреВрд▓ рдореЙрдбреНрдпреВрд▓ рдЬреНрдпрд╛рд▓рд╛ рдореНрд╣рдгрддрд╛рдд рддреЛ рд╡рд╛рдкрд░рдд рдЕрд╕рд▓реЗрд▓рд╛ рджреГрд╖реНрдЯрд┐рдХреЛрди рдЯреНрдпреБрдкрд▓рдЪрд╛ рдЯрд╛рдЗрдо-рдЯреВ-рд▓рд╛рдЗрд╡реНрд╣ (TTL) рдирд┐рд░реНрджрд┐рд╖реНрдЯ рдХрд░рдгрд╛рд▒реНрдпрд╛ рдЬрд╛рдЧреЗрдд рдПрдХ рд╡реЗрдЧрд│реЗ рдлреАрд▓реНрдб рддрдпрд╛рд░ рдХрд░рдгреНрдпрд╛рд╡рд░ рдЖрдзрд╛рд░рд┐рдд рдЖрд╣реЗ. рдореЙрдбреНрдпреВрд▓ рдкрд╛рд░реНрд╢реНрд╡рднреВрдореАрддреАрд▓ рдЬрд╛рдЧрд╛ рд╕реНрдХреЕрди рдХрд░рддреЛ, TTL рдЪреА рд╕рдзреНрдпрд╛рдЪреНрдпрд╛ рд╡реЗрд│реЗрд╢реА рддреБрд▓рдирд╛ рдХрд░рддреЛ рдЖрдгрд┐ рдЯреНрдпреБрдкрд▓ рд╣рдЯрд╡рд╛рдпрдЪрд╛ рдХреА рдирд╛рд╣реА рд╣реЗ рдард░рд╡рддреЛ. рдореЗрдордХреЕрдЪ рдХреЗрд▓реЗрд▓реНрдпрд╛ рдореЙрдбреНрдпреВрд▓рдЪрд╛ рдХреЛрдб рд╕реЛрдкрд╛ рдЖрдгрд┐ рд╕реБрдВрджрд░ рдЖрд╣реЗ, рдкрд░рдВрддреБ рдЦреВрдк рд╕рд╛рдорд╛рдиреНрдп рдЖрд╣реЗ. рдкреНрд░рдердо, рддреЛ рдХреЛрдгрддреНрдпрд╛ рдкреНрд░рдХрд╛рд░рдЪрд╛ рдЗрдВрдбреЗрдХреНрд╕ рдЯреНрд░реЕрд╡реНрд╣рд░реНрд╕ рдХреЗрд▓рд╛ рдЬрд╛рдд рдЖрд╣реЗ рдЖрдгрд┐ рд╣рдЯрд╡рд▓рд╛ рдЬрд╛рдд рдЖрд╣реЗ рд╣реЗ рд╡рд┐рдЪрд╛рд░рд╛рдд рдШреЗрдд рдирд╛рд╣реА. рджреБрд╕рд░реЗ, рдкреНрд░рддреНрдпреЗрдХ рдкрд╛рд╕ рд╕рд░реНрд╡ рдЯреНрдпреБрдкрд▓ рд╕реНрдХреЕрди рдХрд░рддреЛ, рдЬреЗ рдмрд░реЗрдЪ рдореЛрдареЗ рдЕрд╕реВ рд╢рдХрддрд╛рдд. рдХрд╛рд▓рдмрд╛рд╣реНрдп рдЭрд╛рд▓реЗрд▓реНрдпрд╛ рдореЙрдбреНрдпреВрд▓рдиреЗ рдкрд╣рд┐рд▓реА рд╕рдорд╕реНрдпрд╛ рд╕реЛрдбрд╡рд▓реА (рдЯреНрд░реА рдЗрдВрдбреЗрдХреНрд╕ рд╡реЗрдЧрд│реНрдпрд╛ рд╡рд░реНрдЧрд╛рдд рд╡реЗрдЧрд│реЗ рдХрд░рдгреЗ), рддрд░ рджреБрд╕рд░реА рд╕рдорд╕реНрдпрд╛ рдЕрджреНрдпрд╛рдкрд╣реА рд╕реБрдЯрд▓реЗрд▓реА рдирд╛рд╣реА. рдпрд╛ рддреАрди рдореБрджреНрджреНрдпрд╛рдВрдиреА рдорд╛рдЭрд╛ рд╕реНрд╡рддрдГрдЪрд╛ рдХреЛрдб рд▓рд┐рд╣рд┐рдгреНрдпрд╛рдЪрд╛ рдкрд░реНрдпрд╛рдп рдирд┐рд╢реНрдЪрд┐рдд рдХреЗрд▓рд╛.
рд╡рд░реНрдгрди
рдЯреЕрд░рдВрдЯреВрд▓рд╕рд╛рдареА рдЦреВрдк рдЪрд╛рдВрдЧрд▓реЗ рджрд╕реНрддрдРрд╡рдЬреАрдХрд░рдг рдЖрд╣реЗ. C рдордзреНрдпреЗ рддреБрдордЪреНрдпрд╛ рд╕реНрд╡рддрдГрдЪреНрдпрд╛ рд╕рдВрдЧреНрд░рд╣рд┐рдд рдкреНрд░рдХреНрд░рд┐рдпрд╛ рдХрд╢рд╛ рд▓рд┐рд╣рд╛рдпрдЪреНрдпрд╛ рдпрд╛рдмрджреНрджрд▓ рдореА рддреБрдореНрд╣рд╛рд▓рд╛ рд╕рд▓реНрд▓рд╛ рджреЗрддреЛ рдХреА рддреБрдореНрд╣реА рдкреНрд░рдердо рддреНрдпрд╛рд╢реА рдкрд░рд┐рдЪрд┐рдд рд╡реНрд╣рд╛, рдЬреЗрдгреЗрдХрд░реВрди рддреБрдореНрд╣рд╛рд▓рд╛ рдЦрд╛рд▓реА рджрд┐рд╕рдгрд╛рд░реЗ рдЖрджреЗрд╢ рдЖрдгрд┐ рдХреЛрдб рд╕рдордЬрддреАрд▓. рдпрд╛рдХрдбреЗ рджреЗрдЦреАрд▓ рд▓рдХреНрд╖ рджреЗрдгреЗ рдпреЛрдЧреНрдп рдЖрд╣реЗ. рддреБрдордЪреЗ рд╕реНрд╡рддрдГрдЪреЗ рдХреЕрдкреНрдб рдореЙрдбреНрдпреВрд▓ рд▓рд┐рд╣рд┐рддрд╛рдирд╛ рдЙрдкрд▓рдмреНрдз рдЕрд╕рд▓реЗрд▓реНрдпрд╛ рдСрдмреНрдЬреЗрдХреНрдЯреНрд╕рдирд╛, рдореНрд╣рдгрдЬреЗ , , ╨╕ .
рдЪрд▓рд╛ рдмрд╛рд╣реЗрд░реВрди рд╕реБрд░реБрд╡рд╛рдд рдХрд░реВрдпрд╛ рдЖрдгрд┐ рдХреЕрдкреНрдб рдПрдХреНрд╕рдкрд╛рдпрд░реНрдб рдореЙрдбреНрдпреВрд▓ рдХрд╕рд╛ рджрд┐рд╕рддреЛ рддреЗ рдкрд╛рд╣реВрдпрд╛:
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)рд╕реЛрдкреНрдпрд╛ рднрд╛рд╖реЗрдд, рдЖрдкрдг рдЖрдкрд▓реНрдпрд╛ libcapped-expirationd.so рд▓рд╛рдпрдмреНрд░рд░реА рдЕрд╕рд▓реЗрд▓реНрдпрд╛ рдбрд╛рдпрд░реЗрдХреНрдЯрд░реАрдордзреНрдпреЗ tarantool рдЪрд╛рд▓рд╡рддреЛ. рд▓рд╛рдпрдмреНрд░рд░реА рджреЛрди рдлрдВрдХреНрд╢рдиреНрд╕ рдПрдХреНрд╕рдкреЛрд░реНрдЯ рдХрд░рддреЗ: start рдЖрдгрд┐ kill. рдкреНрд░рдердо, рдЖрдкрд▓реНрдпрд╛рд▓рд╛ box.schema.func.create рдЖрдгрд┐ box.schema.user.grant рд╡рд╛рдкрд░реВрди Lua рдордзреВрди рд╣реА рдлрдВрдХреНрд╢рдиреНрд╕ рдЕреЕрдХреНрд╕реЗрд╕ рдХрд░рдгреНрдпрд╛рдпреЛрдЧреНрдп рдмрдирд╡рд╛рд╡реА рд▓рд╛рдЧрддреАрд▓. рдирдВрддрд░, рдЖрдкрдг рдПрдХ рд╕реНрдкреЗрд╕ рддрдпрд╛рд░ рдХрд░рддреЛ рдЬреНрдпрд╛рдЪреНрдпрд╛ рдЯреНрдпреБрдкрд▓реНрд╕рдордзреНрдпреЗ рдлрдХреНрдд рддреАрди рдлреАрд▓реНрдб рдЕрд╕рддреАрд▓: рдкрд╣рд┐рд▓реЗ рдпреБрдирд┐рдХ рдЖрдпрдбреЗрдВрдЯрд┐рдлрд╛рдпрд░, рджреБрд╕рд░реЗ рдИрдореЗрд▓ рдЕреЕрдбреНрд░реЗрд╕ рдЖрдгрд┐ рддрд┐рд╕рд░реЗ рдЯреНрдпреБрдкрд▓реНрд╕рдЪреЗ рд▓рд╛рдИрдлрдЯрд╛рдЗрдо. рдЖрдкрдг рдкрд╣рд┐рд▓реНрдпрд╛ рдлреАрд▓реНрдбрдЪреНрдпрд╛ рд╡рд░ рдПрдХ рдЯреНрд░реА рдЗрдВрдбреЗрдХреНрд╕ рддрдпрд╛рд░ рдХрд░рддреЛ рдЖрдгрд┐ рддреНрдпрд╛рд▓рд╛ рдкреНрд░рд╛рдпрдорд░реА рдореНрд╣рдгрддреЛ. рдкреБрдвреЗ, рдЖрдкрд▓реНрдпрд╛рд▓рд╛ рдЖрдкрд▓реНрдпрд╛ рдореВрд│ рд▓рд╛рдпрдмреНрд░рд░реАрд╕рд╛рдареА рдХрдиреЗрдХреНрд╢рди рдСрдмреНрдЬреЗрдХреНрдЯ рдорд┐рд│рддреЛ.
рддрдпрд╛рд░реАрдЪреНрдпрд╛ рдХрд╛рдорд╛рдирдВрддрд░, рдЖрдореНрд╣реА рд╕реНрдЯрд╛рд░реНрдЯ рдлрдВрдХреНрд╢рди рд▓рд╛рдБрдЪ рдХрд░рддреЛ:
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})рд╣реЗ рдЙрджрд╛рд╣рд░рдг рд╕реНрдХреЕрдирд┐рдВрдЧ рджрд░рдореНрдпрд╛рди рдЕрдЧрджреА рддреНрдпрд╛рдЪ рдкреНрд░рдХрд╛рд░реЗ рдХрд╛рдо рдХрд░реЗрд▓ рдЬрд╕реЗ рдПрдХреНрд╕рдкрд╛рдпрд░реНрдб рдореЙрдбреНрдпреВрд▓, рдЬреЗ рд▓реБрдЖ рдордзреНрдпреЗ рд▓рд┐рд╣рд┐рд▓реЗрд▓реЗ рдЖрд╣реЗ. рд╕реНрдЯрд╛рд░реНрдЯ рдлрдВрдХреНрд╢рдирд▓рд╛ рджрд┐рд▓реЗрд▓рд╛ рдкрд╣рд┐рд▓рд╛ рдпреБрдХреНрддрд┐рд╡рд╛рдж рдореНрд╣рдгрдЬреЗ рдпреБрдирд┐рдХ рдЯрд╛рд╕реНрдХ рдиреЗрдо. рджреБрд╕рд░рд╛ рд╕реНрдкреЗрд╕ рдЖрдпрдбреЗрдВрдЯрд┐рдлрд╛рдпрд░. рддрд┐рд╕рд░рд╛ рдпреБрдирд┐рдХ рдЗрдВрдбреЗрдХреНрд╕ рдЖрд╣реЗ рдЬреНрдпрд╛рджреНрд╡рд╛рд░реЗ рдЯреНрдпреБрдкрд▓реНрд╕ рдбрд┐рд▓реАрдЯ рдХреЗрд▓реЗ рдЬрд╛рддреАрд▓. рдЪреМрдерд╛ рдЗрдВрдбреЗрдХреНрд╕ рдЖрд╣реЗ рдЬреНрдпрд╛рджреНрд╡рд╛рд░реЗ рдЯреНрдпреБрдкрд▓реНрд╕ рдЯреНрд░реЕрд╡реНрд╣рд░реНрд╕ рдХреЗрд▓реЗ рдЬрд╛рддреАрд▓. рдкрд╛рдЪрд╡рд╛ рдЯреНрдпреБрдкрд▓реНрд╕ рдлреАрд▓реНрдб рдирдВрдмрд░ рдЖрд╣реЗ рдЬреНрдпрд╛рдордзреНрдпреЗ рд▓рд╛рдЗрд╡реНрд╣ рд╡реЗрд│ рдЖрд╣реЗ (рдХреНрд░рдорд╛рдВрдХрди 1 рдкрд╛рд╕реВрди рд╕реБрд░реВ рд╣реЛрддреЗ, 0 рдкрд╛рд╕реВрди рдирд╛рд╣реА!). рд╕рд╣рд╛рд╡рд╛ рдЖрдгрд┐ рд╕рд╛рддрд╡рд╛ рд╕реНрдХреЕрдирд┐рдВрдЧ рд╕реЗрдЯрд┐рдВрдЧреНрдЬ рдЖрд╣реЗрдд. 1024 рд╣реА рдПрдХрд╛ рд╡реНрдпрд╡рд╣рд╛рд░рд╛рдд рд╕реНрдХреЕрди рдХреЗрд▓реЗрд▓реНрдпрд╛ рдЯреНрдпреБрдкрд▓реНрд╕рдЪреА рдХрдорд╛рд▓ рд╕рдВрдЦреНрдпрд╛ рдЖрд╣реЗ. 3600 рд╣рд╛ рд╕реЗрдХрдВрджрд╛рдд рдкреВрд░реНрдг рд╕реНрдХреЕрди рд╡реЗрд│ рдЖрд╣реЗ.
рд▓рдХреНрд╖рд╛рдд рдареЗрд╡рд╛ рдХреА рдЙрджрд╛рд╣рд░рдгрд╛рдд рдЯреНрд░реЕрд╡реНрд╣рд░реНрд╕рд▓ рдЖрдгрд┐ рдбрд┐рд▓реАрд╢рдирд╕рд╛рдареА рд╕рдорд╛рди рдЗрдВрдбреЗрдХреНрд╕ рд╡рд╛рдкрд░рд▓рд╛ рдЖрд╣реЗ. рдЬрд░ рддреЛ рдЯреНрд░реА рдЗрдВрдбреЗрдХреНрд╕ рдЕрд╕реЗрд▓, рддрд░ рдЯреНрд░реЕрд╡реНрд╣рд░реНрд╕рд▓ рд▓рд╣рд╛рди рдХреА рд╡рд░реВрди рдореЛрдареНрдпрд╛ рдХреА рдХрдбреЗ рдЬрд╛рддреЗ. рдЬрд░ рддреЛ рд╣реЕрд╢ рдЗрдВрдбреЗрдХреНрд╕ рд╕рд╛рд░рдЦрд╛ рджреБрд╕рд░рд╛ рдЗрдВрдбреЗрдХреНрд╕ рдЕрд╕реЗрд▓, рддрд░ рдЯреНрд░реЕрд╡реНрд╣рд░реНрд╕рд▓ рд╕рд╛рдорд╛рдиреНрдпрддрдГ рдпрд╛рджреГрдЪреНрдЫрд┐рдХ рдХреНрд░рдорд╛рдиреЗ рдХреЗрд▓реЗ рдЬрд╛рддреЗ. рдЬрд╛рдЧреЗрддреАрд▓ рд╕рд░реНрд╡ рдЯрдкрд▓реНрд╕ рдПрдХрд╛рдЪ рд╕реНрдХреЕрдирдордзреНрдпреЗ рд╕реНрдХреЕрди рдХреЗрд▓реЗ рдЬрд╛рддрд╛рдд.
рдЪрд▓рд╛ ремреж рд╕реЗрдХрдВрджрд╛рдВрдЪреНрдпрд╛ рдЖрдпреБрд╖реНрдпрд╛рд╕рд╣ рдЬрд╛рдЧреЗрдд рдЕрдиреЗрдХ рдЯрдкрд▓реНрд╕ рдШрд╛рд▓реВрдпрд╛:
box.space.tester:insert{0, 'user0@tarantool.io', math.floor(fiber.time()) + 60}
box.space.tester:insert{1, 'user1@tarantool.io', math.floor(fiber.time()) + 60}
box.space.tester:insert{2, 'user2@tarantool.io', math.floor(fiber.time()) + 60}рдЪрд▓рд╛ рдЗрдиреНрд╕рд░реНрд╢рди рдпрд╢рд╕реНрд╡реА рдЭрд╛рд▓реЗ рдЖрд╣реЗ рдХрд╛ рддреЗ рддрдкрд╛рд╕реВрдпрд╛:
tarantool> box.space.tester.index.primary:select()
---
- - [0, 'user0@tarantool.io', 1576418976]
- [1, 'user1@tarantool.io', 1576418976]
- [2, 'user2@tarantool.io', 1576418976]
...рдЪрд▓рд╛ ремреж+ рд╕реЗрдХрдВрджрд╛рдВрдирдВрддрд░ (рдкрд╣рд┐рд▓реНрдпрд╛ рдЯрдкрд▓ рдЗрдиреНрд╕рд░реНрд╢рдирдЪреНрдпрд╛ рд╕реБрд░реБрд╡рд╛рддреАрдкрд╛рд╕реВрди рдореЛрдЬрдгреА рдХрд░реВрди) рд╕рд┐рд▓реЗрдХреНрдЯрдЪреА рдкреБрдирд░рд╛рд╡реГрддреНрддреА рдХрд░реВрдпрд╛ рдЖрдгрд┐ рдХреЕрдкреНрдб рдПрдХреНрд╕рдкрд╛рдпрд░реНрдб рдореЙрдбреНрдпреВрд▓ рдЖрдзреАрдЪ рдХрд╛рдо рдХрд░рдд рдЖрд╣реЗ рдХрд╛ рддреЗ рдкрд╛рд╣реВрдпрд╛:
tarantool> box.space.tester.index.primary:select()
---
- []
...рдЪрд▓рд╛ рдХрд╛рдо рдерд╛рдВрдмрд╡реВрдпрд╛:
capped_connection:call('libcapped-expirationd.kill', {'non-indexed'})рдЪрд▓рд╛ рджреБрд╕рд░реЗ рдЙрджрд╛рд╣рд░рдг рдкрд╛рд╣реВ рдЬрд┐рдереЗ рдЯреНрд░реЕрд╡реНрд╣рд░реНрд╕рд▓рд╕рд╛рдареА рд╡реЗрдЧрд│рд╛ рдЗрдВрдбреЗрдХреНрд╕ рд╡рд╛рдкрд░рд▓рд╛ рдЬрд╛рддреЛ:
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)рдпреЗрдереЗ, рдХрд╛рд╣реА рдЕрдкрд╡рд╛рдж рд╡рдЧрд│рддрд╛, рд╕рд░реНрд╡рдХрд╛рд╣реА рдкрд╣рд┐рд▓реНрдпрд╛ рдЙрджрд╛рд╣рд░рдгрд╛рдкреНрд░рдорд╛рдгреЗрдЪ рдЖрд╣реЗ. рдЖрдкрдг рддрд┐рд╕рд▒реНрдпрд╛ рдлреАрд▓реНрдбрдЪреНрдпрд╛ рд╡рд░ рдПрдХ рдЯреНрд░реА рдЗрдВрдбреЗрдХреНрд╕ рддрдпрд╛рд░ рдХрд░рддреЛ рдЖрдгрд┐ рддреНрдпрд╛рд▓рд╛ рдПрдХреНрд╕рдк рдореНрд╣рдгрддреЛ. рд╣рд╛ рдЗрдВрдбреЗрдХреНрд╕ рдкреНрд░рд╛рдпрдорд░реА рдирд╛рд╡рд╛рдЪреНрдпрд╛ рдЗрдВрдбреЗрдХреНрд╕рдкреНрд░рдорд╛рдгреЗ рдЕрджреНрд╡рд┐рддреАрдп рдЕрд╕рдгреНрдпрд╛рдЪреА рдЧрд░рдЬ рдирд╛рд╣реА. рдЯреНрд░реЕрд╡реНрд╣рд░реНрд╕рд▓ рдПрдХреНрд╕рдк рдЗрдВрдбреЗрдХреНрд╕ рд╡рд╛рдкрд░реВрди рдХреЗрд▓реЗ рдЬрд╛рдИрд▓ рдЖрдгрд┐ рдбрд┐рд▓реАрд╢рди рдкреНрд░рд╛рдпрдорд░реА рдЗрдВрдбреЗрдХреНрд╕ рд╡рд╛рдкрд░реВрди рдХреЗрд▓реЗ рдЬрд╛рдИрд▓. рдЖрдкрд▓реНрдпрд╛рд▓рд╛ рдЖрдард╡рддреЗ рдХреА рдкреВрд░реНрд╡реА рджреЛрдиреНрд╣реА рдХреЗрд╡рд│ рдкреНрд░рд╛рдпрдорд░реА рдЗрдВрдбреЗрдХреНрд╕ рд╡рд╛рдкрд░реВрди рдХреЗрд▓реЗ рдЬрд╛рдд рд╣реЛрддреЗ.
рддрдпрд╛рд░реАрдЪреНрдпрд╛ рдХрд╛рдорд╛рдирдВрддрд░, рдЖрдореНрд╣реА рдирд╡реАрди рд╡рд┐рддрд░реНрдХрд╛рдВрд╕рд╣ рдкреНрд░рд╛рд░рдВрдн рдлрдВрдХреНрд╢рди рдЪрд╛рд▓рд╡рддреЛ:
capped_connection:call('libcapped-expirationd.start', {'indexed', box.space.tester.id, box.space.tester.index.primary, box.space.tester.index.exp, 3, 1024, 3600})рдЪрд▓рд╛ рдкреБрдиреНрд╣рд╛ рдЬрд╛рдЧреЗрдд рдЕрдиреЗрдХ рдЯрдкрд▓реНрд╕ рдШрд╛рд▓реВрдпрд╛, рдЬреНрдпрд╛рдВрдЪреЗ рдЖрдпреБрд╖реНрдп 60 рд╕реЗрдХрдВрдж рдЖрд╣реЗ:
box.space.tester:insert{0, 'user0@tarantool.io', math.floor(fiber.time()) + 60}
box.space.tester:insert{1, 'user1@tarantool.io', math.floor(fiber.time()) + 60}
box.space.tester:insert{2, 'user2@tarantool.io', math.floor(fiber.time()) + 60}рейреж рд╕реЗрдХрдВрджрд╛рдВрдирдВрддрд░, рдЖрдкрдг рддреНрдпрд╛рдЪ рдкреНрд░рдХрд╛рд░реЗ рдЖрдгрдЦреА рдХрд╛рд╣реА рдЯрдкрд▓реНрд╕ рдЬреЛрдбреВ:
box.space.tester:insert{3, 'user3@tarantool.io', math.floor(fiber.time()) + 60}
box.space.tester:insert{4, 'user4@tarantool.io', math.floor(fiber.time()) + 60}
box.space.tester:insert{5, 'user5@tarantool.io', math.floor(fiber.time()) + 60}рдЪрд▓рд╛ рдЗрдиреНрд╕рд░реНрд╢рди рдпрд╢рд╕реНрд╡реА рдЭрд╛рд▓реЗ рдЖрд╣реЗ рдХрд╛ рддреЗ рддрдкрд╛рд╕реВрдпрд╛:
tarantool> box.space.tester.index.primary:select()
---
- - [0, 'user0@tarantool.io', 1576421257]
- [1, 'user1@tarantool.io', 1576421257]
- [2, 'user2@tarantool.io', 1576421257]
- [3, 'user3@tarantool.io', 1576421287]
- [4, 'user4@tarantool.io', 1576421287]
- [5, 'user5@tarantool.io', 1576421287]
...рдЪрд▓рд╛ ремреж+ рд╕реЗрдХрдВрджрд╛рдВрдирдВрддрд░ (рдкрд╣рд┐рд▓реНрдпрд╛ рдЯрдкрд▓ рдЗрдиреНрд╕рд░реНрд╢рдирдЪреНрдпрд╛ рд╕реБрд░реБрд╡рд╛рддреАрдкрд╛рд╕реВрди рдореЛрдЬрдгреА рдХрд░реВрди) рд╕рд┐рд▓реЗрдХреНрдЯрдЪреА рдкреБрдирд░рд╛рд╡реГрддреНрддреА рдХрд░реВрдпрд╛ рдЖрдгрд┐ рдХреЕрдкреНрдб рдПрдХреНрд╕рдкрд╛рдпрд░реНрдб рдореЙрдбреНрдпреВрд▓ рдЖрдзреАрдЪ рдХрд╛рдо рдХрд░рдд рдЖрд╣реЗ рдХрд╛ рддреЗ рдкрд╛рд╣реВрдпрд╛:
tarantool> box.space.tester.index.primary:select()
---
- - [3, 'user3@tarantool.io', 1576421287]
- [4, 'user4@tarantool.io', 1576421287]
- [5, 'user5@tarantool.io', 1576421287]
...рддреНрдпрд╛ рдЬрд╛рдЧреЗрдд рдЕрд╕реЗ рдЯреНрдпреБрдкрд▓реНрд╕ рд╢рд┐рд▓реНрд▓рдХ рд╣реЛрддреЗ рдЬреНрдпрд╛рдВрдЪреЗ рдЖрдпреБрд╖реНрдп рдЕрдВрджрд╛рдЬреЗ рейреж рд╕реЗрдХрдВрдж рд╣реЛрддреЗ. рд╢рд┐рд╡рд╛рдп, рдЖрдпрдбреА реи рдЖрдгрд┐ резрелренремрекреирезреирелрен рдЪреНрдпрд╛ рдЖрдпреБрд╖реНрдпрдорд╛рди рдЕрд╕рд▓реЗрд▓реНрдпрд╛ рдЯреНрдпреБрдкрд▓рд╡рд░реВрди рдЖрдпрдбреА рей рдЖрдгрд┐ резрелренремрекреирезреиреорен рдЪреНрдпрд╛ рдЖрдпреБрд╖реНрдпрдорд╛рди рдЕрд╕рд▓реЗрд▓реНрдпрд╛ рдЯреНрдпреБрдкрд▓рдХрдбреЗ рдЬрд╛рддрд╛рдирд╛ рд╕реНрдХреЕрди рдерд╛рдВрдмрд▓рд╛. рдПрдХреНрд╕рдк рдЗрдВрдбреЗрдХреНрд╕ рдХреАрдЬрдЪреНрдпрд╛ рдХреНрд░рдорд╛рдореБрд│реЗ резрелренремрекреирезреиреорен рдХрд┐рдВрд╡рд╛ рддреНрдпрд╛рд╣реВрди рдЕрдзрд┐рдХ рдЖрдпреБрд╖реНрдпрдорд╛рди рдЕрд╕рд▓реЗрд▓реНрдпрд╛ рдЯреНрдпреБрдкрд▓реНрд╕ рд╕реНрдХреЕрди рдХреЗрд▓реЗ рдЧреЗрд▓реЗ рдирд╛рд╣реАрдд. рд╕реБрд░реБрд╡рд╛рддреАрдкрд╛рд╕реВрдирдЪ рдЖрдореНрд╣реА рд╣реА рдмрдЪрдд рдХрд░рдгреНрдпрд╛рдЪреЗ рд▓рдХреНрд╖реНрдп рдареЗрд╡рдд рд╣реЛрддреЛ.
рдЪрд▓рд╛ рдХрд╛рдо рдерд╛рдВрдмрд╡реВрдпрд╛:
capped_connection:call('libcapped-expirationd.kill', {'indexed'})рдЕрдВрдорд▓рдмрдЬрд╛рд╡рдгреА
рдкреНрд░рдХрд▓реНрдкрд╛рдЪреНрдпрд╛ рд╕рд░реНрд╡ рд╡реИрд╢рд┐рд╖реНрдЯреНрдпрд╛рдВрдмрджреНрджрд▓ рд╕рд╛рдВрдЧрдгреНрдпрд╛рдЪрд╛ рд╕рд░реНрд╡реЛрддреНрддрдо рдорд╛рд░реНрдЧ рдореНрд╣рдгрдЬреЗ рддреНрдпрд╛рдЪреНрдпрд╛ рд╕реНрд░реЛрддрд╛рдХрдбреВрди рдорд╛рд╣рд┐рддреА рдорд┐рд│рд╡рдгреЗ. рдпрд╛ рдкреНрд░рдХрд╛рд╢рдирд╛рдд, рдЖрдкрдг рдлрдХреНрдд рд╕рд░реНрд╡рд╛рдд рдорд╣рддреНрддреНрд╡рд╛рдЪреНрдпрд╛ рдореБрджреНрджреНрдпрд╛рдВрд╡рд░ рд▓рдХреНрд╖ рдХреЗрдВрджреНрд░рд┐рдд рдХрд░реВ, рдореНрд╣рдгрдЬреЗ, рд╕реНрдкреЗрд╕ рдмрд╛рдпрдкрд╛рд╕ рдЕрд▓реНрдЧреЛрд░рд┐рджрдо.
рдЖрдкрдг start рдореЗрдердбрд▓рд╛ рдкрд╛рд╕ рдХреЗрд▓реЗрд▓реЗ рдЖрд░реНрдЧреНрдпреБрдореЗрдВрдЯреНрд╕ 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;
};рдирд╛рд╡ рдЧреБрдгрдзрд░реНрдо рд╣реЗ рдХрд╛рд░реНрдпрд╛рдЪреЗ рдирд╛рд╡ рдЖрд╣реЗ. space_id рдЧреБрдгрдзрд░реНрдо рд╣рд╛ рд╕реНрдкреЗрд╕ рдЖрдпрдбреЗрдВрдЯрд┐рдлрд╛рдпрд░ рдЖрд╣реЗ. rm_index_id рдЧреБрдгрдзрд░реНрдо рд╣рд╛ рдЯрдкрд▓ рдбрд┐рд▓реАрдЯ рдХрд░рдгреНрдпрд╛рд╕рд╛рдареА рд╡рд╛рдкрд░рд▓реНрдпрд╛ рдЬрд╛рдгрд╛рд▒реНрдпрд╛ рдЕрджреНрд╡рд┐рддреАрдп рдирд┐рд░реНрджреЗрд╢рд╛рдВрдХрд╛рдЪрд╛ рдЖрдпрдбреЗрдВрдЯрд┐рдлрд╛рдпрд░ рдЖрд╣реЗ. it_index_id рдЧреБрдгрдзрд░реНрдо рд╣рд╛ рдЯрдкрд▓ рдЯреНрд░реЕрд╡реНрд╣рд░реНрд╕рд▓рд╕рд╛рдареА рд╡рд╛рдкрд░рд▓реНрдпрд╛ рдЬрд╛рдгрд╛рд▒реНрдпрд╛ рдирд┐рд░реНрджреЗрд╢рд╛рдВрдХрд╛рдЪрд╛ рдЖрдпрдбреЗрдВрдЯрд┐рдлрд╛рдпрд░ рдЖрд╣реЗ. it_index_type рдЧреБрдгрдзрд░реНрдо рд╣рд╛ рдЯрдкрд▓ рдЯреНрд░реЕрд╡реНрд╣рд░реНрд╕рд▓рд╕рд╛рдареА рд╡рд╛рдкрд░рд▓рд╛ рдЬрд╛рдгрд╛рд░рд╛ рдЗрдВрдбреЗрдХреНрд╕ рдкреНрд░рдХрд╛рд░ рдЖрд╣реЗ. filed_no рдЧреБрдгрдзрд░реНрдо рд╣рд╛ рдЯрдкрд▓ рдлреАрд▓реНрдб рдХреНрд░рдорд╛рдВрдХ рдЖрд╣реЗ рдЬреНрдпрд╛рдордзреНрдпреЗ рдЯрд╛рдЗрдо-рдЯреВ-рд▓рд╛рдЗрд╡реНрд╣ рдореВрд▓реНрдп рдЖрд╣реЗ. рд╕реНрдХреЕрди_рд╕рд╛рдИрдЬ рдЧреБрдгрдзрд░реНрдо рдореНрд╣рдгрдЬреЗ рдПрдХрд╛ рд╡реНрдпрд╡рд╣рд╛рд░рд╛рдд рд╕реНрдХреЕрди рдХреЗрд▓реЗрд▓реНрдпрд╛ рдЯрдкрд▓рдЪреА рдХрдорд╛рд▓ рд╕рдВрдЦреНрдпрд╛. рд╕реНрдХреЕрди_рдЯрд╛рдЗрдо рдЧреБрдгрдзрд░реНрдо рдореНрд╣рдгрдЬреЗ рд╕реЗрдХрдВрджрд╛рдВрдордзреНрдпреЗ рдкреВрд░реНрдг рд╕реНрдХреЕрди рд╡реЗрд│.
рдЖрдореНрд╣реА рдпреБрдХреНрддрд┐рд╡рд╛рдж рд╡рд┐рд╢реНрд▓реЗрд╖рдгрд╛рдЪрд╛ рд╕рдорд╛рд╡реЗрд╢ рдХрд░рдгрд╛рд░ рдирд╛рд╣реА. рд╣реЗ рдХрд╖реНрдЯрд╛рдЪреЗ рдкрдг рд╕реЛрдкреЗ рдХрд╛рдо рдЖрд╣реЗ рдЖрдгрд┐ рд▓рд╛рдпрдмреНрд░рд░реА рддреБрдореНрд╣рд╛рд▓рд╛ рддреНрдпрд╛рдд рдорджрдд рдХрд░реЗрд▓. рд╕рд╛рдзреНрдпрд╛ mp_bool, mp_double, mp_int, mp_uint рдЖрдгрд┐ mp_array рдкреНрд░рдХрд╛рд░рд╛рдВрдЪрд╛ рд╡рд╛рдкрд░ рдХрд░рдгреНрдпрд╛рдРрд╡рдЬреА, рдХреЗрд╡рд│ рд▓реБрдЖрдордзреВрди mp_map рдкреНрд░рдХрд╛рд░рд╛рд╕рд╣ рдЬрдЯрд┐рд▓ рдбреЗрдЯрд╛ рд╕реНрдЯреНрд░рдХреНрдЪрд░ рдореНрд╣рдгреВрди рдкрд╛рд╕ рдХреЗрд▓реЗрд▓реНрдпрд╛ рдирд┐рд░реНрджреЗрд╢рд╛рдВрдХрд╛рдВрдордзреНрдпреЗ рдЕрдбрдЪрдгреА рдпреЗрдК рд╢рдХрддрд╛рдд. рддрдерд╛рдкрд┐, рд╕рдВрдкреВрд░реНрдг рдирд┐рд░реНрджреЗрд╢рд╛рдВрдХрд╛рдЪреЗ рд╡рд┐рд╢реНрд▓реЗрд╖рдг рдХрд░рдгреЗ рдЖрд╡рд╢реНрдпрдХ рдирд╛рд╣реА. рдлрдХреНрдд рддреНрдпрд╛рдЪреА рд╡рд┐рд╢рд┐рд╖реНрдЯрддрд╛ рддрдкрд╛рд╕рдгреЗ, рдкреНрд░рдХрд╛рд░ рдореЛрдЬрдгреЗ рдЖрдгрд┐ рдУрд│рдЦрдХрд░реНрддрд╛ рдХрд╛рдврдгреЗ рдкреБрд░реЗрд╕реЗ рдЖрд╣реЗ.
рдкрд╛рд░реНрд╕рд┐рдВрдЧрд╕рд╛рдареА рд╡рд╛рдкрд░рд▓реНрдпрд╛ рдЬрд╛рдгрд╛рд▒реНрдпрд╛ рд╕рд░реНрд╡ рдлрдВрдХреНрд╢рдиреНрд╕рдЪреНрдпрд╛ рдкреНрд░реЛрдЯреЛрдЯрд╛рдЗрдкрдЪреА рдпрд╛рджреА рдХрд░реВрдпрд╛:
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);рдЖрддрд╛ рдЖрдкрдг рд╕рд░реНрд╡рд╛рдд рдорд╣рддреНрд╡рд╛рдЪреНрдпрд╛ рднрд╛рдЧрд╛рдХрдбреЗ рд╡рд│реВрдпрд╛ - рд╕реНрдкреЗрд╕ рдЯреНрд░реЕрд╡реНрд╣рд░реНрд╕рд▓ рдЖрдгрд┐ рдЯреНрдпреБрдкрд▓ рдбрд┐рд▓реАрд╢рдирдорд╛рдЧреАрд▓ рд▓реЙрдЬрд┐рдХ. рд╕реНрдХреЕрди_рд╕рд╛рдИрдЬрдкреЗрдХреНрд╖рд╛ рдореЛрдареЗ рдирд╕рд▓реЗрд▓реЗ рдЯреНрдпреБрдкрд▓рдЪреЗ рдкреНрд░рддреНрдпреЗрдХ рдмреНрд▓реЙрдХ рдПрдХрд╛рдЪ рд╡реНрдпрд╡рд╣рд╛рд░рд╛рджреНрд╡рд╛рд░реЗ рд╕реНрдХреЕрди рдЖрдгрд┐ рдореЙрдбрд┐рдлрд╛рдп рдХреЗрд▓реЗ рдЬрд╛рддреЗ. рдпрд╢рд╕реНрд╡реА рдЭрд╛рд▓реНрдпрд╛рд╕, рд╣рд╛ рд╡реНрдпрд╡рд╣рд╛рд░ рдХреЗрд▓рд╛ рдЬрд╛рддреЛ; рдЬрд░ рдПрдЦрд╛рджреА рддреНрд░реБрдЯреА рдЖрд▓реА рддрд░ рддреА рдкрд░рдд рдЖрдгрд▓реА рдЬрд╛рддреЗ. expirationd_iterate рдлрдВрдХреНрд╢рдирд▓рд╛ рджрд┐рд▓реЗрд▓рд╛ рд╢реЗрд╡рдЯрдЪрд╛ рдпреБрдХреНрддрд┐рд╡рд╛рдж рдЗрдЯрд░реЗрдЯрд░рдХрдбреЗ рдирд┐рд░реНрджреЗрд╢рдХ рдЕрд╕рддреЛ рдЬрд┐рдереВрди рд╕реНрдХреЕрди рд╕реБрд░реВ рд╣реЛрддреЛ рдХрд┐рдВрд╡рд╛ рд╕реБрд░реВ рд░рд╛рд╣рддреЛ. рдПрд░рд░ рдпреЗрдИрдкрд░реНрдпрдВрдд, рд╕реНрдкреЗрд╕ рд╕рдВрдкреЗрдкрд░реНрдпрдВрдд рдХрд┐рдВрд╡рд╛ рдкреНрд░рдХреНрд░рд┐рдпрд╛ рд▓рд╡рдХрд░ рдерд╛рдВрдмрд╡рдгреНрдпрд╛рдЪрд╛ рдХреЛрдгрддрд╛рд╣реА рдорд╛рд░реНрдЧ рдирд╕реЗрдкрд░реНрдпрдВрдд рд╣реЗ рдЗрдЯрд░реЗрдЯрд░ рдЕрдВрддрд░реНрдЧрддрд░рд┐рддреНрдпрд╛ рд╡рд╛рдврд╡рд▓реЗ тАЛтАЛрдЬрд╛рддреЗ. expirationd_expired рдлрдВрдХреНрд╢рди рдЯреНрдпреБрдкрд▓рдЪреЗ рдЖрдпреБрд╖реНрдпрдорд╛рди рддрдкрд╛рд╕рддреЗ, expirationd_delete рдЯреНрдпреБрдкрд▓ рдбрд┐рд▓реАрдЯ рдХрд░рддреЗ рдЖрдгрд┐ expirationd_breakable рдЖрдкрд▓реНрдпрд╛рд▓рд╛ рдкреБрдвреЗ рдЬрд╛рдпрдЪреЗ рдЖрд╣реЗ рдХреА рдирд╛рд╣реА рддреЗ рддрдкрд╛рд╕рддреЗ.
Expirationd_iterate рдлрдВрдХреНрд╢рди рдХреЛрдб:
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;
}рдлрдВрдХреНрд╢рди рдХреЛрдб expired_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;
}рдПрдХреНрд╕рдкрд╛рдпрд░реЗрд╢рдирдбреА_рдбрд┐рд▓реАрдЯ рдлрдВрдХреНрд╢рди рдХреЛрдб:
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);
}Expirationd_breakable рдлрдВрдХреНрд╢рди рдХреЛрдб:
static bool
expirationd_breakable(struct expirationd_task *task)
{
return task->it_index_id != task->rm_index_id && task->it_index_type == ITER_GT;
}рдЕрдиреБрдкреНрд░рдпреЛрдЧ
рддреБрдореНрд╣реА рд╕реЛрд░реНрд╕ рдХреЛрдб рдпреЗрдереЗ рдкрд╛рд╣реВ рд╢рдХрддрд╛ !
рд╕реНрддреНрд░реЛрдд: www.habr.com
