Add-on:Common plugin cache: Difference between revisions
>TobiasTheCommie |
m (Addon-Bot repo category update) |
||
(141 intermediate revisions by 6 users not shown) | |||
Line 1: | Line 1: | ||
{{Addon | {{Addon | ||
|Name=Common plugin cache | |Name=Common plugin cache | ||
|provider-name=TheCollective | |provider-name=anxdpanic, TheCollective | ||
|ID=script.common.plugin.cache | |ID=script.common.plugin.cache | ||
|latest-version=0 | |latest-version=3.0.0 | ||
|extension point=xbmc.service | |extension point=xbmc.service | ||
|provides= | |provides= | ||
|Summary= | |Summary=A common caching API for Kodi add-ons. | ||
|Description= | |Description=A common caching API for Kodi add-ons. | ||
|Platform=all | |Platform=all | ||
|icon url=}} | |Language= | ||
|License=GPL-3.0-only | |||
|Forum= | |||
|Website= | |||
|Source=https://github.com/anxdpanic/script.common.plugin.cache | |||
|Email= | |||
|broken= | |||
|icon url=http://mirrors.kodi.tv/addons/omega/script.common.plugin.cache/icon.png}} | |||
= Testing/Status = | = Testing/Status = | ||
Integration and unittests are run continously by Jenkins | Integration and unittests are run continously by Jenkins | ||
Line 18: | Line 25: | ||
This service works as an independant storage server to XBMC's implementation. | This service works as an independant storage server to XBMC's implementation. | ||
It provides proper thread safe locking and | It provides proper thread safe locking and get set functions to store data. | ||
Do note that important data should NOT be stored using this service as the sqlite database will be deleted on any corruption. | |||
Development and support thread: http://forum.kodi.tv/showthread.php?t=116496 | |||
== Setup == | == Setup == | ||
To use the cacheing service add the following to your py file. | To use the cacheing service edit your addon.xml file like this. | ||
<requires> | |||
<import addon="xbmc.python" version="2.1.0"/> | |||
<import addon="script.common.plugin.cache" version="2.5.5"/> # Add this | |||
</requires> | |||
And add the following to your py file. | |||
try: | try: | ||
Line 27: | Line 45: | ||
except: | except: | ||
import storageserverdummy as StorageServer | import storageserverdummy as StorageServer | ||
cache = StorageServer.StorageServer( | cache = StorageServer.StorageServer("tablename", 24) # (Your plugin name, Cache time in hours) | ||
You can now access the caching service through the "cache" variable. | You can now access the caching service through the "cache" variable. | ||
Remember to include a fallback | Remember to include a fallback storageserverdummy.py file(Copy it from the script.common.plugin.cache/lib/ directory) | ||
== Debugging == | == Debugging == | ||
To enable debugging set the following values in default.py | To enable debugging set the following values in default.py | ||
dbg = True | dbg = True | ||
Or you can change it after import with. | Or you can change it after import with. | ||
common.dbg = True | common.dbg = True | ||
Note: Only the client communication will be debugged when setting this flag. | |||
== cacheFunction(self, funct = False, *args) == | == cacheFunction(self, funct = False, *args) == | ||
Caching function results for one day | Caching function results for one day. | ||
The function being cached must return a list or a dictionary. | |||
A cache is only stored if the result returned is longer than 0 in length. | |||
Returns what the provided function returns. | |||
def pi_count(self): | def pi_count(self): | ||
Line 70: | Line 89: | ||
unity = 10**(digits + 10) | unity = 10**(digits + 10) | ||
pi = 4 * (4*arccot(5, unity) - arccot(239, unity)) | pi = 4 * (4*arccot(5, unity) - arccot(239, unity)) | ||
return | return pi // 10**10 | ||
result = cache.cacheFunction(pi_count) # This will call the pi_count function, save the result in the cache, and return the result. | result = cache.cacheFunction(pi_count) # This will call the pi_count function, save the result in the cache, and return the result. | ||
time.sleep(300) | time.sleep(300) | ||
Line 78: | Line 96: | ||
time.sleep(3600) | time.sleep(3600) | ||
result = cache.cacheFunction(pi_count) # This will again call pi_count since the result is now considered stale. | result = cache.cacheFunction(pi_count) # This will again call pi_count since the result is now considered stale. | ||
To pass arguments to the function, you just add them as additional arguments to cacheFunction. | |||
result = cache.cacheFunction(calc_add, 4, 4) | |||
second_result = cache.cacheFunction(another_function, 5, ret = "True", { "complicated": "true" } ) | |||
If you need to pass on another function as an argument, this must be done in in a dictionary like this: { "new_results_function": pi_count }. | |||
Because functions are instances they have specific identifiers that will change on every run. When cacheFunction generates the hash for a call and its result it will not take into account params["new_results_function"]. This means: | |||
* One should NOT use params["new_results_function"] for anything OTHER than a function, since cacheFunction will then return false matches. | |||
* One should NOT pass on a function in any way other than params["new_results_function"], as cacheFunction will never find a match. | |||
def some_function(first, second, params = {} ): | |||
if params.has_key("new_results_function"): | |||
return params["new_results_function"](first, second) | |||
else: | |||
return 0 | |||
result = cache.cacheFunction(some_function, 1, 3, params = { "new_results_function": calc_add } ) | |||
== lock(self, str) == | == lock(self, str) == | ||
Line 94: | Line 131: | ||
== unlock(self, str) == | == unlock(self, str) == | ||
Try to unlock | |||
Returns bool | Returns bool | ||
Line 108: | Line 145: | ||
if not new_unlocked: | if not new_unlocked: | ||
print "Couldn't discard lock." | print "Couldn't discard lock." | ||
== delete(self, str) == | |||
Delete entities matching the str. | |||
This functions accepts [http://www.w3schools.com/SQL/sql_wildcards.asp SQL wildcards]. | |||
Returns nothing | |||
cache.table_name = "PluginName" | |||
cache.set("mystring", "string") | |||
cache.set("myint", 1234) | |||
cache.set("mydict", repr({ "our": { "dictionary": [] } }) ) | |||
cache.delete("my%") | |||
some_int = cache.get("myint") | |||
print some_int # prints "" | |||
some_string = cache.get("mystring") | |||
print some_string # prints "" | |||
some_dict = cache.get("mydict") | |||
print some_dict # prints "" | |||
== set(self, str, object ) == | == set(self, str, object ) == | ||
Line 117: | Line 176: | ||
cache.set("some_string", "string") | cache.set("some_string", "string") | ||
cache.set("some_int", 1234) | cache.set("some_int", 1234) | ||
cache.set("some_dict", { "our": { "dictionary": [] } } ) | cache.set("some_dict", repr({ "our": { "dictionary": [] } }) ) | ||
== setMulti(self, str, dict) == | == setMulti(self, str, dict) == | ||
Line 126: | Line 185: | ||
cache.table_name = "PluginName" | cache.table_name = "PluginName" | ||
save_data = { "some_string": "string", "some_int": 1234, "some_dict": { "our": { "dictionary": [] } } } | save_data = { "some_string": "string", "some_int": 1234, "some_dict": repr({ "our": { "dictionary": [] } }) } | ||
cache.setMulti("pre-", save_data) | cache.setMulti("pre-", save_data) | ||
Line 137: | Line 196: | ||
cache.set("some_string", "string") | cache.set("some_string", "string") | ||
cache.set("some_int", 1234) | cache.set("some_int", 1234) | ||
cache.set("some_dict", { "our": { "dictionary": [] } } ) | cache.set("some_dict", repr({ "our": { "dictionary": [] } }) ) | ||
some_string = cache.get("some_string") | some_string = cache.get("some_string") | ||
Line 146: | Line 205: | ||
some_dict = cache.get("some_dict") | some_dict = cache.get("some_dict") | ||
print | print eval(some_dict) # prints '{ "our": { "dictionary": [] } }' | ||
== getMulti(self, str, list) == | == getMulti(self, str, list) == | ||
Line 155: | Line 214: | ||
cache.table_name = "PluginName" | cache.table_name = "PluginName" | ||
save_data = { "some_string": "string", "some_int": 1234, "some_dict": { "our": { "dictionary": [] } } } | save_data = { "some_string": "string", "some_int": 1234, "some_dict": repr({ "our": { "dictionary": [] } }) } | ||
cache.setMulti("pre-", save_data) | cache.setMulti("pre-", save_data) | ||
Line 162: | Line 221: | ||
print result[0] # Prints "string" | print result[0] # Prints "string" | ||
print result[1] # Prints 1234 | print result[1] # Prints 1234 | ||
print | print eval(result[2]) # Prints '{ "our": { "dictionary": [] } }' | ||
[[Category: | [[Category:Add-ons with license tag]] | ||
[[Category:Add-ons with source tag]] | |||
[[Category:All add-ons]] | |||
[[Category:Service add-ons]] | |||
[[Category:Gotham add-on repository]] | |||
[[Category:Helix add-on repository]] | |||
[[Category:Isengard add-on repository]] | |||
[[Category:Jarvis add-on repository]] | |||
[[Category:Krypton add-on repository]] | |||
[[Category:Leia add-on repository]] | |||
[[Category:Matrix add-on repository]] | |||
[[Category:Nexus add-on repository]] | |||
[[Category:Omega add-on repository]] |
Latest revision as of 19:26, 11 April 2024
Common plugin cache | ||||||||||||||
|
Add-ons | Common plugin cache |
A common caching API for Kodi add-ons.
Installing
This add-on is installed from the Add-on browser located in Kodi as follows:
Testing/Status
Integration and unittests are run continously by Jenkins
http://tc.tobiasussing.dk/jenkins/view/Cache%20Service/
Developers
This service works as an independant storage server to XBMC's implementation.
It provides proper thread safe locking and get set functions to store data.
Do note that important data should NOT be stored using this service as the sqlite database will be deleted on any corruption.
Development and support thread: http://forum.kodi.tv/showthread.php?t=116496
Setup
To use the cacheing service edit your addon.xml file like this.
<requires> <import addon="xbmc.python" version="2.1.0"/> <import addon="script.common.plugin.cache" version="2.5.5"/> # Add this </requires>
And add the following to your py file.
try: import StorageServer except: import storageserverdummy as StorageServer cache = StorageServer.StorageServer("tablename", 24) # (Your plugin name, Cache time in hours)
You can now access the caching service through the "cache" variable.
Remember to include a fallback storageserverdummy.py file(Copy it from the script.common.plugin.cache/lib/ directory)
Debugging
To enable debugging set the following values in default.py
dbg = True
Or you can change it after import with.
common.dbg = True
Note: Only the client communication will be debugged when setting this flag.
cacheFunction(self, funct = False, *args)
Caching function results for one day.
The function being cached must return a list or a dictionary.
A cache is only stored if the result returned is longer than 0 in length.
Returns what the provided function returns.
def pi_count(self): def arccot(x, unity): sum = xpower = unity // x n = 3 sign = -1 while 1: xpower = xpower // (x*x) term = xpower // n if not term: break sum += sign * term sign = -sign n += 2 return sum digits = 40 unity = 10**(digits + 10) pi = 4 * (4*arccot(5, unity) - arccot(239, unity)) return pi // 10**10 result = cache.cacheFunction(pi_count) # This will call the pi_count function, save the result in the cache, and return the result. time.sleep(300) result = cache.cacheFunction(pi_count) # This will return the cached result time.sleep(3600) result = cache.cacheFunction(pi_count) # This will again call pi_count since the result is now considered stale.
To pass arguments to the function, you just add them as additional arguments to cacheFunction.
result = cache.cacheFunction(calc_add, 4, 4) second_result = cache.cacheFunction(another_function, 5, ret = "True", { "complicated": "true" } )
If you need to pass on another function as an argument, this must be done in in a dictionary like this: { "new_results_function": pi_count }.
Because functions are instances they have specific identifiers that will change on every run. When cacheFunction generates the hash for a call and its result it will not take into account params["new_results_function"]. This means:
- One should NOT use params["new_results_function"] for anything OTHER than a function, since cacheFunction will then return false matches.
- One should NOT pass on a function in any way other than params["new_results_function"], as cacheFunction will never find a match.
def some_function(first, second, params = {} ): if params.has_key("new_results_function"): return params["new_results_function"](first, second) else: return 0 result = cache.cacheFunction(some_function, 1, 3, params = { "new_results_function": calc_add } )
lock(self, str)
Try to aquire a lock
Returns bool
cache.table_name = "PluginName" locked = cache.lock("lock_me") # Returns True if locked: print "Got lock" new_lock = cache.lock("lock_me") # Returns False if not new_lock: print "Couldn't aquire second lock.
unlock(self, str)
Try to unlock
Returns bool
cache.table_name = "PluginName" lock = cache.lock("lock_me") # Returns True unlocked = cache.unlock("lock_me") # Returns True if unlocked: print "Discarded lock" new_unlocked = cache.unlock("lock_me") # Returns False if not new_unlocked: print "Couldn't discard lock."
delete(self, str)
Delete entities matching the str.
This functions accepts SQL wildcards.
Returns nothing
cache.table_name = "PluginName" cache.set("mystring", "string") cache.set("myint", 1234) cache.set("mydict", repr({ "our": { "dictionary": [] } }) ) cache.delete("my%") some_int = cache.get("myint") print some_int # prints "" some_string = cache.get("mystring") print some_string # prints "" some_dict = cache.get("mydict") print some_dict # prints ""
set(self, str, object )
Store a value
Returns nothing
cache.table_name = "PluginName" cache.set("some_string", "string") cache.set("some_int", 1234) cache.set("some_dict", repr({ "our": { "dictionary": [] } }) )
setMulti(self, str, dict)
Store multiple values
Returns nothing
cache.table_name = "PluginName" save_data = { "some_string": "string", "some_int": 1234, "some_dict": repr({ "our": { "dictionary": [] } }) } cache.setMulti("pre-", save_data)
get(self, str)
Get a value
Returns stored data.
cache.table_name = "PluginName" cache.set("some_string", "string") cache.set("some_int", 1234) cache.set("some_dict", repr({ "our": { "dictionary": [] } }) ) some_string = cache.get("some_string") print some_string # Prints "string" some_int = cache.get("some_int") print some_int # prints 1234 some_dict = cache.get("some_dict") print eval(some_dict) # prints '{ "our": { "dictionary": [] } }'
getMulti(self, str, list)
Get multiple values
Retuns list of stored data elements.
cache.table_name = "PluginName" save_data = { "some_string": "string", "some_int": 1234, "some_dict": repr({ "our": { "dictionary": [] } }) } cache.setMulti("pre-", save_data) get_list = [ "some_string", "some_int", "some_dict" ] result = cache.getMulti("pre-", get_list) print result[0] # Prints "string" print result[1] # Prints 1234 print eval(result[2]) # Prints '{ "our": { "dictionary": [] } }'