Added bytecodecache
[project/luci.git] / libs / core / luasrc / ccache.lua
1 --[[
2 LuCI - Lua Configuration Interface
3
4 Copyright 2008 Steven Barth <steven@midlink.org>
5 Copyright 2008 Jo-Philipp Wich <xm@leipzig.freifunk.net>
6
7 Licensed under the Apache License, Version 2.0 (the "License");
8 you may not use this file except in compliance with the License.
9 You may obtain a copy of the License at
10
11 http://www.apache.org/licenses/LICENSE-2.0
12
13 $Id$
14 ]]--
15
16 local io = require "io"
17 local util = require "luci.util"
18 local posix = require "posix"
19 local debug = require "debug"
20 local string = require "string"
21 local package = require "package"
22
23 local type, loadfile = type, loadfile
24
25
26 module "luci.ccache"
27
28 function cache_ondemand(...)
29         if debug.getinfo(1, 'S').source ~= "=?" then
30                 cache_enable(...)
31         end
32 end
33
34 function cache_enable(cachepath, mode)
35         cachepath = cachepath or "/tmp/.luciccache"
36         mode = mode or "r--r--r--"
37
38         local loader = package.loaders[2]
39         local uid    = posix.getpid("uid")
40
41         if not posix.stat(cachepath) then
42                 posix.mkdir(cachepath)
43         end
44
45         local function _encode_filename(name)
46                 local encoded = ""
47                 for i=1, #name do
48                         encoded = encoded .. ("%2X" % string.byte(name, i))
49                 end
50                 return encoded
51         end
52
53         local function _load_sane(file)
54                 local stat = posix.stat(file)
55                 if stat and stat.uid == uid and stat.mode == mode then
56                         return loadfile(file)
57                 end
58         end
59
60         local function _write_sane(file, func)
61                 if posix.getpid("uid") == uid then
62                         local fp = io.open(file, "w")
63                         if fp then
64                                 fp:write(util.get_bytecode(func))
65                                 fp:close()
66                                 posix.chmod(file, mode)
67                         end
68                 end
69         end
70
71         package.loaders[2] = function(mod)
72                 local encoded = cachepath .. "/" .. _encode_filename(mod)
73                 local modcons = _load_sane(encoded)
74                 
75                 if modcons then
76                         return modcons
77                 end
78
79                 -- No cachefile
80                 modcons = loader(mod)
81                 if type(modcons) == "function" then
82                         _write_sane(encoded, modcons)
83                 end
84                 return modcons
85         end
86 end