Major update

This commit is contained in:
Coder12a 2019-01-08 00:32:34 -06:00
parent 60bc174189
commit 02796f2998
3 changed files with 866 additions and 884 deletions

140
README.md
View File

@ -11,28 +11,28 @@ Copy both *colddb.lua* and *async* files to your minetest mod or game. Copy the
Write this code in your lua file. Write this code in your lua file.
1. create a directory and link it as a database. 1. create a directory and link it as a database.
```lua ```lua
coldbase = colddb.get_db("mydb") coldbase = colddb.Colddb("mydb")
``` ```
2. add an extra folder to the directory. every new file will be added to the global tag(folder). 2. add an extra folder to the directory. every new file will be added to the global tag(folder).
```lua ```lua
colddb.add_global_tag(coldbase,"ips") coldbase.add_global_tag("ips")
``` ```
3. store key item(this key has no value) 3. store key item(this key has no value)
```lua ```lua
colddb.set_key(coldbase,"MyKey") coldbase.set_key("MyKey")
``` ```
4. store key-value item 4. store key-value item
```lua ```lua
colddb.set(coldbase,"MyKeyAndValue","Hello world") coldbase.set("MyKeyAndValue", "Hello world")
``` ```
5. retrieve items (get_key's callback(arg) will return true, false, or nil) 5. retrieve items (get_key's callback(arg) will return true, false, or nil)
```lua ```lua
colddb.get(coldbase,"MyKeyAndValue",nil,function(arg) coldbase.get("MyKeyAndValue", nil, function(arg)
if arg then if arg then
minetest.log(string.format("value:%s",arg)) minetest.log(string.format("value:%s", arg))
end end
end) end)
colddb.get_key(coldbase,"MyKey",nil,function(arg) coldbase.get_key("MyKey", nil, function(arg)
if arg then if arg then
minetest.log("Found key") minetest.log("Found key")
else else
@ -42,7 +42,7 @@ end)
``` ```
6. delete key(file) this function works on both keys and key-value keys. 6. delete key(file) this function works on both keys and key-value keys.
```lua ```lua
colddb.remove(coldbase,"MyKeyAndValue") coldbase.remove("MyKeyAndValue")
``` ```
7. if add_to_mem_pool is true(true by default). keys are stored in a weak lua table(memory) it will be removed by the gc if its not in-use. Storing data in memory is to prevent the database from constantly loading up data from files. 7. if add_to_mem_pool is true(true by default). keys are stored in a weak lua table(memory) it will be removed by the gc if its not in-use. Storing data in memory is to prevent the database from constantly loading up data from files.
```lua ```lua
@ -54,23 +54,23 @@ coldbase.indexes = true
``` ```
9. only if coldbase.indexes is true. returns the amount of keys that are in the indexing file. 9. only if coldbase.indexes is true. returns the amount of keys that are in the indexing file.
```lua ```lua
colddb.get_count(coldbase) coldbase.get_count()
``` ```
10. only if coldbase.indexes is true. iterates through the indexing file(breaks and ends if it reaches the end of the file). 10. only if coldbase.indexes is true. iterates through the indexing file(breaks and ends if it reaches the end of the file).
```lua ```lua
colddb.iterate_index_table(coldbase,nil,func_list_keys,nil) coldbase.iterate_index_table(nil, func_list_keys, nil)
``` ```
11. adds a folder which can be used in other functions that have tag_name arg. 11. adds a folder which can be used in other functions that have tag_name arg.
```lua ```lua
colddb.add_tag(coldbase,"Extra_Folder",{"Extra","Folder"}) coldbase.add_tag("Extra_Folder", {"Extra", "Folder"})
``` ```
12. returns the tag name if the tag does not exists it creates one. 12. returns the tag name if the tag does not exists it creates one.
```lua ```lua
colddb.get_or_add_tag(coldbase,"Extra_Folder",{"Extra","Folder"}) coldbase.get_or_add_tag("Extra_Folder", {"Extra", "Folder"})
``` ```
13. remove tag by name. 13. remove tag by name.
```lua ```lua
colddb.remove_tag(coldbase,"Extra_Folder") coldbase.remove_tag("Extra_Folder")
``` ```
Quick Look Quick Look
@ -78,28 +78,11 @@ Quick Look
```lua ```lua
-- create an directory(watchlist) and link it as a database. -- create an directory(watchlist) and link it as a database.
ip_db = colddb.get_db("watchlist") ip_db = colddb.Colddb("watchlist")
-- add an extra folder to the directory.
colddb.add_global_tag(ip_db,"ips")
-- return a recorded ip address from the data base.
function ip_db.find(player,callback)
colddb.get(ip_db,player,nil,callback)
end
-- Key is the file and file name. Value is the content's within the file.
-- global tag(ips)--->key(Player name)--->value(ip address)
function ip_db.record_ip(player,ip)
colddb.set(ip_db,player,ip)
end
function ip_db.delete(player)
colddb.remove(db,player)
end
-- When ever a player join's his/her ip address is recorded to the database by player name. -- When ever a player join's his/her ip address is recorded to the database by player name.
minetest.register_on_prejoinplayer(function(name, ip) minetest.register_on_prejoinplayer(function(name, ip)
ip_db.record_ip(name,ip) ip_db.set(name, ip, ip_db.get_or_add_tag("ips", "ips"))
end) end)
minetest.register_chatcommand("ip", { minetest.register_chatcommand("ip", {
@ -107,17 +90,27 @@ minetest.register_chatcommand("ip", {
description = "Get an player's ip address.", description = "Get an player's ip address.",
func = function(name, param) func = function(name, param)
-- Get the ip record asynchronously. -- Get the ip record asynchronously.
colddb.get(ip_db,param,nil,function(record) ip_db.get(param, ip_db.get_or_add_tag("ips", "ips"), function(record)
-- If database contains the record data then send it to the player. -- If record is contains data send it to the player.
if record then if record then
minetest.chat_send_player(name,string.format("%s:%s",param,record)) minetest.chat_send_player(name, string.format("%s:%s", param, record))
else else
-- No record was found. -- No record was found.
minetest.chat_send_player(name,"Can not find ip record.") minetest.chat_send_player(name, "Can not find ip record.")
end end
end) end)
end end
}) })
minetest.register_chatcommand("clear", {
params = "<player>",
description = "Clear out the ip database.",
func = function(name, param)
ip_db.remove_tag(ip_db.get_or_add_tag("ips", "ips"))
minetest.chat_send_player(name, "Ip Database Cleared!")
end
})
``` ```
Quick Look Notes Quick Look Notes
@ -126,81 +119,6 @@ Quick Look Notes
In the example above we could also create a more complex ip database using tags. Creating tags named after the player then assigning the ip files to them.<br> In the example above we could also create a more complex ip database using tags. Creating tags named after the player then assigning the ip files to them.<br>
This way we could store many ips associated with the player instead of just one ip. This way we could store many ips associated with the player instead of just one ip.
API
===========
- **Functions**
- **colddb.get_db(directory) --> db**
Creates an directory and links it as a database. Returns a 'db' obeject.
- **colddb.add_global_tag(db,tag)**
Adds an extra folder to the directory and advance the database to the added folder.
- **colddb.add_tag(db,name,tag)**
- Creates a folder from the given table in tag.
- **colddb.get_or_add_tag(db,name,tag) --> tag_name**
Returns a tag or creates a new one if does not exist.
- **colddb.remove_tag(db,name)**
Removes a tag.
- **colddb.get_count(db,tag_name) --> count**
Returns the count from the index table file.
- **colddb.iterate_index_table(db,begin_func,func_on_iterate,end_func,args,tag_name)**
- function iterates through the index table file.
- **begin_func(args) --> args**
- function that is ran before the loop begins.
- **func_on_iterate(key,index,args)**
- function that is ran in the for loop.
- **end_func(args)**
- end function that is ran after the for loop ends.
- **colddb.set(db,name,_table,tag_name)**
- Writes data to the database. Key-Value.
- **colddb.set_key(db,name,tag_name)**
- Writes data to the database. Key-nil.
- **colddb.get(db,name,tag_name,callback(arg))**
- Returns specified data from the database in a callback function.
- **colddb.get_key(db,name,tag_name,callback(arg))**
- Returns if the key exist in the database.
- **colddb.remove(db,name,tag_name)**
- Deletes the specified data from the database.
- **Database object fields**
- **indexes**
- If truth the database makes a indexing file for keys.
- **add_to_mem_pool**
- If truth when you get keys or values it gets cached in the memory for faster access next time.
License License
=========== ===========

398
async.lua
View File

@ -5,202 +5,232 @@ if not extended_api.Async then
extended_api.Async = {} extended_api.Async = {}
end end
function extended_api.Async.create_async_pool() function extended_api.Async()
local pool = {threads = {},globalstep_threads = {},task_queue = {},resting = 200,maxtime = 200,queue_threads = 8,state = "suspended"} local self = {}
return pool
end self.pool = {threads = {}, globalstep_threads = {}, task_queue = {}, resting = 200, maxtime = 200, queue_threads = 8, state = "suspended"}
self.create_worker = function(func)
local thread = coroutine.create(func)
if not thread or coroutine.status(thread) == "dead" then
minetest.after(0.3, self.create_worker, func)
minetest.after(0.5, self.schedule_worker)
minetest.chat_send_all("Fall")
return
end
table.insert(self.pool.threads, thread)
end
self.create_globalstep_worker = function(func)
local thread = coroutine.create(func)
if not thread or coroutine.status(thread) == "dead" then
minetest.after(0.3, self.create_globalstep_worker, func)
minetest.after(0.5, self.schedule_globalstep_worker)
return
end
table.insert(self.pool.globalstep_threads, thread)
end
self.run_worker = function(index)
local thread = self.pool.threads[index]
if not thread or coroutine.status(thread) == "dead" then
table.remove(self.pool.threads, index)
minetest.after(0, self.schedule_worker)
return false
else
coroutine.resume(thread)
minetest.after(0, self.schedule_worker)
return true
end
end
function extended_api.Async.create_worker(pool,func) self.run_globalstep_worker = function(index)
local thread = coroutine.create(func) local thread = self.pool.globalstep_threads[index]
table.insert(pool.threads, thread) if not thread or coroutine.status(thread) == "dead" then
end table.remove(self.pool.globalstep_threads, index)
minetest.after(0, self.schedule_globalstep_worker)
return false
else
coroutine.resume(thread)
minetest.after(0, self.schedule_globalstep_worker)
return true
end
end
function extended_api.Async.create_globalstep_worker(pool,func) self.schedule_worker = function()
local thread = coroutine.create(func) self.pool.state = "running"
table.insert(pool.globalstep_threads, thread) for index, value in ipairs(self.pool.threads) do
end minetest.after(self.pool.resting / 1000, self.run_worker, index)
return true
function extended_api.Async.run_worker(pool,index) end
local thread = pool.threads[index] self.pool.state = "suspended"
if thread == nil or coroutine.status(thread) == "dead" then
table.remove(pool.threads, index)
minetest.after(0,extended_api.Async.schedule_worker,pool)
return false return false
else
coroutine.resume(thread)
minetest.after(0,extended_api.Async.schedule_worker,pool)
return true
end end
end
function extended_api.Async.run_globalstep_worker(pool,index) self.schedule_globalstep_worker = function()
local thread = pool.globalstep_threads[index] for index, value in ipairs(self.pool.globalstep_threads) do
if thread == nil or coroutine.status(thread) == "dead" then minetest.after(0, self.run_globalstep_worker, index)
table.remove(pool.globalstep_threads, index) return true
minetest.after(0,extended_api.Async.schedule_globalstep_worker,pool) end
return false return false
else
coroutine.resume(thread)
minetest.after(0,extended_api.Async.schedule_globalstep_worker,pool)
return true
end end
end
function extended_api.Async.schedule_worker(pool) self.priority = function(resting, maxtime)
pool.state = "running" self.pool.resting = resting
for index,value in ipairs(pool.threads) do self.pool.maxtime = maxtime
minetest.after(pool.resting / 1000,extended_api.Async.run_worker,pool,index)
return true
end end
pool.state = "suspended"
return false
end
function extended_api.Async.schedule_globalstep_worker(pool) self.iterate = function(from, to, func, callback)
for index,value in ipairs(pool.globalstep_threads) do self.create_worker(function()
minetest.after(0,extended_api.Async.run_globalstep_worker,pool,index) local last_time = minetest.get_us_time() / 1000
return true local maxtime = self.pool.maxtime
end for i = from, to do
return false local b = func(i)
end if b ~= nil and b == false then
function extended_api.Async.priority(pool,resting,maxtime)
pool.resting = resting
pool.maxtime = maxtime
end
function extended_api.Async.iterate(pool,from,to,func,callback)
extended_api.Async.create_worker(pool,function()
local last_time = minetest.get_us_time() * 1000
local maxtime = pool.maxtime
for i = from, to do
local b = func(i)
if b ~= nil and b == false then
break
end
if minetest.get_us_time() * 1000 > last_time + maxtime then
coroutine.yield()
last_time = minetest.get_us_time() * 1000
end
end
if callback then
callback()
end
end)
extended_api.Async.schedule_worker(pool)
end
function extended_api.Async.foreach(pool,array, func, callback)
extended_api.Async.create_worker(pool,function()
local last_time = minetest.get_us_time() * 1000
local maxtime = pool.maxtime
for k,v in ipairs(array) do
local b = func(k,v)
if b ~= nil and b == false then
break
end
if minetest.get_us_time() * 1000 > last_time + maxtime then
coroutine.yield()
last_time = minetest.get_us_time() * 1000
end
end
if callback then
callback()
end
end)
extended_api.Async.schedule_worker(pool)
end
function extended_api.Async.do_while(pool,condition_func, func, callback)
extended_api.Async.create_worker(pool,function()
local last_time = minetest.get_us_time() * 1000
local maxtime = pool.maxtime
while(condition_func()) do
local c = func()
if c ~= nil and c ~= condition_func() then
break
end
if minetest.get_us_time() * 1000 > last_time + maxtime then
coroutine.yield()
last_time = minetest.get_us_time() * 1000
end
end
if callback then
callback()
end
end)
extended_api.Async.schedule_worker(pool)
end
function extended_api.Async.register_globalstep(pool,func)
extended_api.Async.create_globalstep_worker(pool,function()
local last_time = minetest.get_us_time() * 1000
local dtime = last_time
while(true) do
func(dtime)
dtime = minetest.get_us_time() * 1000
-- 0.05 seconds
if minetest.get_us_time() * 1000 > last_time + 50 then
coroutine.yield()
local last_time = minetest.get_us_time() * 1000
end
end
end)
extended_api.Async.schedule_globalstep_worker(pool)
end
function extended_api.Async.chain_task(pool,tasks,callback)
extended_api.Async.create_worker(pool,function()
local pass_arg = nil
local last_time = minetest.get_us_time() * 1000
local maxtime = pool.maxtime
for index, task_func in pairs(tasks) do
local p = task_func(pass_arg)
if p ~= nil then
pass_arg = p
end
if minetest.get_us_time() * 1000 > last_time + maxtime then
coroutine.yield()
last_time = minetest.get_us_time() * 1000
end
end
if callback then
callback(pass_arg)
end
end)
extended_api.Async.schedule_worker(pool)
end
function extended_api.Async.queue_task(pool,func,callback)
table.insert(pool.task_queue,{func = func,callback = callback})
if pool.queue_threads > 0 then
pool.queue_threads = pool.queue_threads - 1
extended_api.Async.create_worker(pool,function()
local pass_arg = nil
local last_time = minetest.get_us_time() * 1000
local maxtime = pool.maxtime
while(true) do
local task_func = pool.task_queue[1]
table.remove(pool.task_queue,1)
if task_func and task_func.func then
pass_arg = nil
local p = task_func.func(pass_arg)
if p ~= nil then
pass_arg = p
end
if task_func.callback then
task_func.callback(pass_arg)
end
if minetest.get_us_time() * 1000 > last_time + maxtime then
coroutine.yield()
last_time = minetest.get_us_time() * 1000
end
else
pool.queue_threads = pool.queue_threads + 1
break break
end end
if minetest.get_us_time() / 1000 > last_time + maxtime then
coroutine.yield()
last_time = minetest.get_us_time() / 1000
end
end
if callback then
callback()
end
return
end)
self.schedule_worker()
end
self.foreach = function(array, func, callback)
self.create_worker(function()
local last_time = minetest.get_us_time() / 1000
local maxtime = self.pool.maxtime
for k,v in ipairs(array) do
local b = func(k,v)
if b ~= nil and b == false then
break
end
if minetest.get_us_time() / 1000 > last_time + maxtime then
coroutine.yield()
last_time = minetest.get_us_time() / 1000
end
end
if callback then
callback()
end
return
end)
self.schedule_worker()
end
self.do_while = function(condition_func, func, callback)
self.create_worker(function()
local last_time = minetest.get_us_time() / 1000
local maxtime = self.pool.maxtime
while(condition_func()) do
local c = func()
if c ~= nil and c ~= condition_func() then
break
end
if minetest.get_us_time() / 1000 > last_time + maxtime then
coroutine.yield()
last_time = minetest.get_us_time() / 1000
end
end
if callback then
callback()
end
return
end)
self.schedule_worker()
end
self.register_globalstep = function(func)
self.create_globalstep_worker(function()
local last_time = minetest.get_us_time() / 1000000
local dtime = last_time
while(true) do
dtime = (minetest.get_us_time() / 1000000) - last_time
func(dtime)
-- 0.05 seconds
if minetest.get_us_time() / 1000000 > last_time + 0.05 then
coroutine.yield()
last_time = minetest.get_us_time() / 1000000
end
end end
end) end)
extended_api.Async.schedule_worker(pool) self.schedule_globalstep_worker()
end end
end
self.chain_task = function(tasks, callback)
self.create_worker(function()
local pass_arg = nil
local last_time = minetest.get_us_time() / 1000
local maxtime = self.pool.maxtime
for index, task_func in pairs(tasks) do
local p = task_func(pass_arg)
if p ~= nil then
pass_arg = p
end
if minetest.get_us_time() / 1000 > last_time + maxtime then
coroutine.yield()
last_time = minetest.get_us_time() / 1000
end
end
if callback then
callback(pass_arg)
end
return
end)
self.schedule_worker()
end
self.queue_task = function(func, callback)
table.insert(self.pool.task_queue, {func = func,callback = callback})
if self.pool.queue_threads > 0 then
self.pool.queue_threads = self.pool.queue_threads - 1
self.create_worker(function()
local pass_arg = nil
local last_time = minetest.get_us_time() / 1000
local maxtime = self.pool.maxtime
while(true) do
local task_func = self.pool.task_queue[1]
table.remove(self.pool.task_queue, 1)
if task_func and task_func.func then
pass_arg = nil
local p = task_func.func()
if p ~= nil then
pass_arg = p
end
if task_func.callback then
task_func.callback(pass_arg)
end
if minetest.get_us_time() / 1000 > last_time + maxtime then
coroutine.yield()
last_time = minetest.get_us_time() / 1000
end
else
self.pool.queue_threads = self.pool.queue_threads + 1
return
end
end
end)
self.schedule_worker()
end
end
self.single_task = function(func, callback)
self.create_worker(function()
local pass_arg = func()
if p ~= nil then
pass_arg = p
end
if task_func.callback then
task_func.callback(pass_arg)
end
return
end)
self.schedule_worker()
end
return self
end

1212
colddb.lua

File diff suppressed because it is too large Load Diff