webmcp
view framework/bin/mcp.lua @ 274:d22b58cafebf
Removed Lua 5.1 compatibility code in webmcp_accelerator.c
| author | jbe | 
|---|---|
| date | Sat Mar 21 14:37:32 2015 +0100 (2015-03-21) | 
| parents | 98537ccd0800 | 
| children | b5d0c0ab3ce2 | 
 line source
     1 #!/usr/bin/env moonbridge
     3 WEBMCP_VERSION = "2.0.0_devel"
     5 -- allow control of global environment
     6 local _G = _G
     7 local allowed_globals = {}
     8 local global_metatable = {
     9   __index = _G,
    10   __newindex = function(self, key, value)
    11     _G[key] = value
    12   end
    13 }
    14 _ENV = setmetatable({}, global_metatable)
    16 -- check if interactive mode
    17 if listen then  -- defined by moonbridge
    18   WEBMCP_MODE = "listen"
    19 else
    20   WEBMCP_MODE = "interactive"
    21 end
    23 -- configuration names are provided as 4th, 5th, etc. argument
    24 WEBMCP_CONFIG_NAMES = {select(4, ...)}
    26 -- determine framework and bath path from command line arguments
    27 -- or print usage synopsis (if applicable)
    28 do
    29   local arg1, arg2, arg3 = ...
    30   local helpout
    31   if
    32     arg1 == "-h" or arg1 == "--help" or
    33     arg2 == "-h" or arg2 == "--help"  -- if first arg is provided by wrapper
    34   then
    35     helpout = io.stdout
    36   elseif
    37     #WEBMCP_CONFIG_NAMES < 1 or
    38     (WEBMCP_MODE == "interactive") ~= (arg3 == "INTERACTIVE")
    39   then
    40     helpout = io.stderr
    41   end
    42   if helpout then
    43     helpout:write("Usage: moonbridge -- <framework path>/bin/mcp.lua <framework path> <app base path> <app name> <config name> [<config name> ...]\n")
    44     helpout:write("   or: lua -i <framework path>/bin/mcp.lua <framework path> <app base path> INTERACTIVE <config name> [<config name> ...]\n")
    45     if helpout == io.stderr then
    46       return 1
    47     else
    48       return 0
    49     end
    50   end
    51   local function append_trailing_slash(str)
    52     return string.gsub(str, "([^/])$", function(last) return last .. "/" end)
    53   end
    54   WEBMCP_FRAMEWORK_PATH = append_trailing_slash(arg1)
    55   WEBMCP_BASE_PATH      = append_trailing_slash(arg2)
    56   if WEBMCP_MODE == "listen" then
    57     WEBMCP_APP_NAME = arg3
    58   end
    59 end
    61 -- setup search paths for libraries
    62 do
    63   if string.match(package.path, "^[^;]") then
    64     package.path = ";" .. package.path
    65   end
    66   package.path = WEBMCP_FRAMEWORK_PATH .. "lib/?.lua" .. package.path
    67   -- find out which file name extension shared libraries have
    68   local slib_exts = {}
    69   for ext in string.gmatch(package.cpath, "%?%.([A-Za-z0-9_-]+)") do
    70     if not slib_exts[ext] then
    71       slib_exts[#slib_exts+1] = ext
    72       slib_exts[ext] = true
    73     end
    74   end
    75   local paths = {}
    76   for i, ext in ipairs(slib_exts) do
    77     paths[#paths+1] = WEBMCP_FRAMEWORK_PATH .. "accelerator/?." .. ext
    78   end
    79   for i, ext in ipairs(slib_exts) do
    80     paths[#paths+1] = WEBMCP_FRAMEWORK_PATH .. "lib/?." .. ext
    81   end
    82   paths[#paths+1] = package.cpath
    83   package.cpath = table.concat(paths, ";")
    84 end
    86 -- autoloader system for WebMCP environment "$WEBMCP_FRAMEWORK_PATH/env/",
    87 -- application environment extensions "$WEBMCP_BASE_PATH/env/"
    88 -- and models "$WEBMCP_BASE_PATH/model/"
    89 do
    90   local weakkey_mt = { __mode = "k" }
    91   local autoloader_category = setmetatable({}, weakkey_mt)
    92   local autoloader_path     = setmetatable({}, weakkey_mt)
    93   local autoloader_mt       = {}
    94   local function install_autoloader(self, category, path_fragment)
    95     autoloader_category[self] = category
    96     autoloader_path[self]     = path_fragment
    97     setmetatable(self, autoloader_mt)
    98   end
    99   local function try_exec(filename)
   100     local file = io.open(filename, "r")
   101     if file then
   102       local filedata = file:read("*a")
   103       io.close(file)
   104       local func, errmsg = load(filedata, "=" .. filename, nil, _ENV)
   105       if func then
   106         func()
   107         return true
   108       else
   109         error(errmsg, 0)
   110       end
   111     else
   112       return false
   113     end
   114   end
   115   function autoloader_mt.__index(self, key)
   116     local category, base_path, merge_base_path, file_key
   117     local merge = false
   118     if
   119       string.find(key, "^[a-z_][A-Za-z0-9_]*$") and
   120       not string.find(key, "^__")
   121     then
   122       category        = "env"
   123       base_path       = WEBMCP_FRAMEWORK_PATH .. "env/"
   124       merge           = true
   125       merge_base_path = WEBMCP_BASE_PATH .. "env/"
   126       file_key        = key
   127     elseif string.find(key, "^[A-Z][A-Za-z0-9]*$") then
   128       category        = "model"
   129       base_path       = WEBMCP_BASE_PATH .. "model/"
   130       local first = true
   131       file_key = string.gsub(key, "[A-Z]",
   132         function(c)
   133           if first then
   134             first = false
   135             return string.lower(c)
   136           else
   137             return "_" .. string.lower(c)
   138           end
   139         end
   140       )
   141     else
   142       return
   143     end
   144     local required_category = autoloader_category[self]
   145     if required_category and required_category ~= category then return end
   146     local path_fragment = autoloader_path[self]
   147     local path = base_path .. path_fragment .. file_key
   148     local merge_path
   149     if merge then
   150       merge_path = merge_base_path .. path_fragment .. file_key
   151     end
   152     local function try_dir(dirname)
   153       local dir = io.open(dirname)
   154       if dir then
   155         io.close(dir)
   156         local obj = {}
   157         install_autoloader(obj, category, path_fragment .. file_key .. "/")
   158         rawset(self, key, obj)
   159         try_exec(path .. "/__init.lua")
   160         if merge then try_exec(merge_path .. "/__init.lua") end
   161         return true
   162       else
   163         return false
   164       end
   165     end
   166     if self == _G then
   167       allowed_globals[key] = true
   168     end
   169     if merge and try_exec(merge_path .. ".lua") then
   170     elseif merge and try_dir(merge_path .. "/") then
   171     elseif try_exec(path .. ".lua") then
   172     elseif try_dir(path .. "/") then
   173     else end
   174     if self == _G then
   175       allowed_globals[key] = nil
   176     end
   177     return rawget(self, key)
   178   end
   179   install_autoloader(_G, nil, "")
   180   try_exec(WEBMCP_FRAMEWORK_PATH .. "env/__init.lua")
   181   try_exec(WEBMCP_BASE_PATH .. "env/__init.lua")
   182 end
   184 -- replace Moonbridge listen function
   185 local moonbridge_listen = listen
   186 local listeners = {}
   187 function listen(args)
   188   listeners[#listeners+1] = args
   189 end
   191 -- prohibit (unintended) definition of new global variables
   192 function global_metatable.__newindex(self, key, value)
   193   if not allowed_globals[key] then
   194     error("Setting of global variable prohibited", 2)
   195   end
   196   _G[key] = value
   197 end
   199 -- execute configurations and pre-fork initializers
   200 for i, config_name in ipairs(WEBMCP_CONFIG_NAMES) do
   201   execute.config(config_name)
   202 end
   203 execute.prefork_initializers()
   205 -- interactive console mode
   206 if WEBMCP_MODE == "interactive" then
   207   _G.multirand = require "multirand"  -- TODO: cleaner solution
   208   execute.postfork_initializers()
   209   trace.disable()  -- avoids memory leakage (TODO: needs general solution for moonbridge?)
   210 end
   212 -- invoke moonbridge
   213 if WEBMCP_MODE == "listen" then
   214   local http_options = request.get_http_options()
   215   local min_requests_per_connect = http_options.min_requests_per_connect or 90
   216   local max_requests_per_connect = http_options.max_requests_per_connect or 100
   217   local http = require("moonbridge_http")
   218   for i, listener in ipairs(listeners) do
   219     local request_count = 0
   220     local function inner_handler(http_request)
   221       request_count = request_count + 1
   222       request.handler(http_request, request_count >= max_requests_per_connect)
   223     end
   224     local outer_handler = http.generate_handler(inner_handler, http_options)
   225     --listener.prepare = execute.postfork_initializers
   226     listener.prepare = function()
   227       _G.multirand = require "multirand"
   228       execute.postfork_initializers()
   229     end
   230     listener.connect = function(socket)
   231       outer_handler(socket)
   232       return request_count < min_requests_per_connect
   233     end
   234     listener.finish = execute.finalizers
   235     moonbridge_listen(listener)
   236   end
   237 end
