Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

merge origin changes

  • Loading branch information...
commit 783183dc66aabb3f15a5dd1fb4f602e189b3c032 2 parents e2cb521 + 54ba892
Andy Skelton authored
3  doc/edoc-info
View
@@ -0,0 +1,3 @@
+{application,php}.
+{packages,[]}.
+{modules,[php,php_app,php_eval,php_sup,php_util]}.
BIN  doc/erlang.png
View
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
17 doc/index.html
View
@@ -0,0 +1,17 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html>
+<head>
+<title>The php application</title>
+</head>
+<frameset cols="20%,80%">
+<frame src="modules-frame.html" name="modulesFrame" title="">
+
+<frame src="overview-summary.html" name="overviewFrame" title="">
+<noframes>
+<h2>This page uses frames</h2>
+<p>Your browser does not accept frames.
+<br>You should go to the <a href="overview-summary.html">non-frame version</a> instead.
+</p>
+</noframes>
+</frameset>
+</html>
16 doc/modules-frame.html
View
@@ -0,0 +1,16 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html>
+<head>
+<title>The php application</title>
+<link rel="stylesheet" type="text/css" href="stylesheet.css" title="EDoc">
+</head>
+<body bgcolor="white">
+<h2 class="indextitle">Modules</h2>
+<table width="100%" border="0" summary="list of modules">
+<tr><td><a href="php.html" target="overviewFrame" class="module">php</a></td></tr>
+<tr><td><a href="php_app.html" target="overviewFrame" class="module">php_app</a></td></tr>
+<tr><td><a href="php_eval.html" target="overviewFrame" class="module">php_eval</a></td></tr>
+<tr><td><a href="php_sup.html" target="overviewFrame" class="module">php_sup</a></td></tr>
+<tr><td><a href="php_util.html" target="overviewFrame" class="module">php_util</a></td></tr></table>
+</body>
+</html>
15 doc/overview-summary.html
View
@@ -0,0 +1,15 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html>
+<head>
+<title>The php application</title>
+<link rel="stylesheet" type="text/css" href="stylesheet.css" title="EDoc">
+</head>
+<body bgcolor="white">
+<div class="navbar"><a name="#navbar_top"></a><table width="100%" border="0" cellspacing="0" cellpadding="2" summary="navigation bar"><tr><td><a href="overview-summary.html" target="overviewFrame">Overview</a></td><td><a href="http://www.erlang.org/"><img src="erlang.png" align="right" border="0" alt="erlang logo"></a></td></tr></table></div>
+<h1>The php application</h1>
+
+<hr>
+<div class="navbar"><a name="#navbar_bottom"></a><table width="100%" border="0" cellspacing="0" cellpadding="2" summary="navigation bar"><tr><td><a href="overview-summary.html" target="overviewFrame">Overview</a></td><td><a href="http://www.erlang.org/"><img src="erlang.png" align="right" border="0" alt="erlang logo"></a></td></tr></table></div>
+<p><i>Generated by EDoc, Aug 19 2010, 16:13:09.</i></p>
+</body>
+</html>
11 doc/packages-frame.html
View
@@ -0,0 +1,11 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html>
+<head>
+<title>The php application</title>
+<link rel="stylesheet" type="text/css" href="stylesheet.css" title="EDoc">
+</head>
+<body bgcolor="white">
+<h2 class="indextitle">Packages</h2>
+<table width="100%" border="0" summary="list of packages"></table>
+</body>
+</html>
54 php.html → doc/php.html
View
@@ -40,7 +40,8 @@ <h3 class="typedecl"><a name="type-result">result()</a></h3>
<h2><a name="index">Function Index</a></h2>
-<table width="100%" border="1" cellspacing="0" cellpadding="2" summary="function index"><tr><td valign="top"><a href="#eval-1">eval/1</a></td><td>Equivalent to eval(Code, undefined, infinity).</td></tr>
+<table width="100%" border="1" cellspacing="0" cellpadding="2" summary="function index"><tr><td valign="top"><a href="#call-2">call/2</a></td><td>Evaluates a function and returns the return value.</td></tr>
+<tr><td valign="top"><a href="#eval-1">eval/1</a></td><td>Equivalent to eval(Code, undefined, infinity).</td></tr>
<tr><td valign="top"><a href="#eval-2">eval/2</a></td><td>Equivalent to eval(Code, Php, infinity) or eval(Code,
undefined, Timeout).</td></tr>
<tr><td valign="top"><a href="#eval-3">eval/3</a></td><td>Tests syntax and evaluates PHP code.</td></tr>
@@ -48,17 +49,33 @@ <h3 class="typedecl"><a name="type-result">result()</a></h3>
`ps -o rss`.</td></tr>
<tr><td valign="top"><a href="#release-1">release/1</a></td><td>Cancels the reservation of a PHP instance, returning it
to the pool of available instances.</td></tr>
+<tr><td valign="top"><a href="#reload-0">reload/0</a></td><td>Reloads the application completely, carrying over any requires.</td></tr>
+<tr><td valign="top"><a href="#reload_clean-0">reload_clean/0</a></td><td>Same as reload() except no requires are carried over.</td></tr>
+<tr><td valign="top"><a href="#require_code-1">require_code/1</a></td><td>Adds code to be executed when initializing a PHP worker and
+ restarts all.</td></tr>
<tr><td valign="top"><a href="#reserve-0">reserve/0</a></td><td>Equivalent to reserve(undefined).</td></tr>
<tr><td valign="top"><a href="#reserve-1">reserve/1</a></td><td>Reserves a PHP instance that will only be accessible to
callers possessing the key returned by this function.</td></tr>
<tr><td valign="top"><a href="#restart_all-0">restart_all/0</a></td><td>Restarts each PHP thread, waiting if any are reserved.</td></tr>
+<tr><td valign="top"><a href="#return-2">return/2</a></td><td>Same as call/2 except this returns the return, not the whole result.</td></tr>
<tr><td valign="top"><a href="#start-0">start/0</a></td><td>Starts the PHP application, supervisor, a number of workers,
and this API server module with the options set in php.app.</td></tr>
<tr><td valign="top"><a href="#stop-0">stop/0</a></td><td>Stops the PHP application and everything it started.</td></tr>
+<tr><td valign="top"><a href="#unrequire-1">unrequire/1</a></td><td>Removes code from PHP worker initialization and restarts all.</td></tr>
</table>
<h2><a name="functions">Function Details</a></h2>
+<h3 class="function"><a name="call-2">call/2</a></h3>
+<div class="spec">
+<p><tt>call(Func::Function, Args) -&gt; <a href="#type-result">result()</a></tt>
+<ul class="definitions"><li><tt>Function = string()</tt></li>
+<li><tt>Args = [Arg]</tt></li>
+<li><tt>Arg = string() | integer() | float()</tt></li>
+</ul></p>
+</div><p>Evaluates a function and returns the return value. Args are
+ automatically escaped.</p>
+
<h3 class="function"><a name="eval-1">eval/1</a></h3>
<div class="spec">
<p><tt>eval(Code) -&gt; <a href="#type-result">result()</a></tt>
@@ -104,6 +121,25 @@ <h3 class="function"><a name="release-1">release/1</a></h3>
</div><p>Cancels the reservation of a PHP instance, returning it
to the pool of available instances.</p>
+<h3 class="function"><a name="reload-0">reload/0</a></h3>
+<div class="spec">
+<p><tt>reload() -&gt; ok</tt></p>
+</div><p>Reloads the application completely, carrying over any requires.
+ Specifically, this stops the app, unloads the app, loads the
+ app, loads the modules, starts the app, adds each require.
+ Meanwhile calls will result in noproc.</p>
+
+<h3 class="function"><a name="reload_clean-0">reload_clean/0</a></h3>
+<div class="spec">
+<p><tt>reload_clean() -&gt; ok</tt></p>
+</div><p>Same as reload() except no requires are carried over.</p>
+
+<h3 class="function"><a name="require_code-1">require_code/1</a></h3>
+<div class="spec">
+<p><tt>require_code(Code::string()) -&gt; <a href="#type-ref">ref()</a></tt></p>
+</div><p>Adds code to be executed when initializing a PHP worker and
+ restarts all. The return value can be passed to unrequire/1.</p>
+
<h3 class="function"><a name="reserve-0">reserve/0</a></h3>
<div class="spec">
<p><tt>reserve() -&gt; reference()</tt></p>
@@ -128,6 +164,15 @@ <h3 class="function"><a name="restart_all-0">restart_all/0</a></h3>
</div><p>Restarts each PHP thread, waiting if any are reserved. This
is intended to force an updated PHPLOOP into use.</p>
+<h3 class="function"><a name="return-2">return/2</a></h3>
+<div class="spec">
+<p><tt>return(Func::Function, Args) -&gt; any()</tt>
+<ul class="definitions"><li><tt>Function = string()</tt></li>
+<li><tt>Args = [Arg]</tt></li>
+<li><tt>Arg = string() | integer() | float()</tt></li>
+</ul></p>
+</div><p>Same as call/2 except this returns the return, not the whole result.</p>
+
<h3 class="function"><a name="start-0">start/0</a></h3>
<div class="spec">
<p><tt>start() -&gt; ok</tt></p>
@@ -138,9 +183,14 @@ <h3 class="function"><a name="stop-0">stop/0</a></h3>
<div class="spec">
<p><tt>stop() -&gt; ok</tt></p>
</div><p>Stops the PHP application and everything it started.</p>
+
+<h3 class="function"><a name="unrequire-1">unrequire/1</a></h3>
+<div class="spec">
+<p><tt>unrequire(Ref::<a href="#type-ref">ref()</a>) -&gt; ok</tt></p>
+</div><p>Removes code from PHP worker initialization and restarts all.</p>
<hr>
<div class="navbar"><a name="#navbar_bottom"></a><table width="100%" border="0" cellspacing="0" cellpadding="2" summary="navigation bar"><tr><td><a href="overview-summary.html" target="overviewFrame">Overview</a></td><td><a href="http://www.erlang.org/"><img src="erlang.png" align="right" border="0" alt="erlang logo"></a></td></tr></table></div>
-<p><i>Generated by EDoc, Feb 6 2009, 09:29:57.</i></p>
+<p><i>Generated by EDoc, Aug 19 2010, 16:13:09.</i></p>
</body>
</html>
37 doc/php_app.html
View
@@ -0,0 +1,37 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html>
+<head>
+<title>Module php_app</title>
+<link rel="stylesheet" type="text/css" href="stylesheet.css" title="EDoc">
+</head>
+<body bgcolor="white">
+<div class="navbar"><a name="#navbar_top"></a><table width="100%" border="0" cellspacing="0" cellpadding="2" summary="navigation bar"><tr><td><a href="overview-summary.html" target="overviewFrame">Overview</a></td><td><a href="http://www.erlang.org/"><img src="erlang.png" align="right" border="0" alt="erlang logo"></a></td></tr></table></div>
+<hr>
+
+<h1>Module php_app</h1>
+<ul class="index"><li><a href="#index">Function Index</a></li><li><a href="#functions">Function Details</a></li></ul>
+
+<p><b>Behaviours:</b> <a href="application.html"><tt>application</tt></a>.</p>
+
+<h2><a name="index">Function Index</a></h2>
+<table width="100%" border="1" cellspacing="0" cellpadding="2" summary="function index"><tr><td valign="top"><a href="#start-2">start/2</a></td><td></td></tr>
+<tr><td valign="top"><a href="#stop-1">stop/1</a></td><td></td></tr>
+</table>
+
+<h2><a name="functions">Function Details</a></h2>
+
+<h3 class="function"><a name="start-2">start/2</a></h3>
+<div class="spec">
+<p><tt>start(Type, StartArgs) -&gt; any()</tt></p>
+</div>
+
+<h3 class="function"><a name="stop-1">stop/1</a></h3>
+<div class="spec">
+<p><tt>stop(State) -&gt; any()</tt></p>
+</div>
+<hr>
+
+<div class="navbar"><a name="#navbar_bottom"></a><table width="100%" border="0" cellspacing="0" cellpadding="2" summary="navigation bar"><tr><td><a href="overview-summary.html" target="overviewFrame">Overview</a></td><td><a href="http://www.erlang.org/"><img src="erlang.png" align="right" border="0" alt="erlang logo"></a></td></tr></table></div>
+<p><i>Generated by EDoc, Aug 19 2010, 16:13:09.</i></p>
+</body>
+</html>
67 doc/php_eval.html
View
@@ -0,0 +1,67 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html>
+<head>
+<title>Module php_eval</title>
+<link rel="stylesheet" type="text/css" href="stylesheet.css" title="EDoc">
+</head>
+<body bgcolor="white">
+<div class="navbar"><a name="#navbar_top"></a><table width="100%" border="0" cellspacing="0" cellpadding="2" summary="navigation bar"><tr><td><a href="overview-summary.html" target="overviewFrame">Overview</a></td><td><a href="http://www.erlang.org/"><img src="erlang.png" align="right" border="0" alt="erlang logo"></a></td></tr></table></div>
+<hr>
+
+<h1>Module php_eval</h1>
+<ul class="index"><li><a href="#index">Function Index</a></li><li><a href="#functions">Function Details</a></li></ul>
+
+<p><b>Behaviours:</b> <a href="gen_server.html"><tt>gen_server</tt></a>.</p>
+
+<h2><a name="index">Function Index</a></h2>
+<table width="100%" border="1" cellspacing="0" cellpadding="2" summary="function index"><tr><td valign="top"><a href="#code_change-3">code_change/3</a></td><td></td></tr>
+<tr><td valign="top"><a href="#handle_call-3">handle_call/3</a></td><td></td></tr>
+<tr><td valign="top"><a href="#handle_cast-2">handle_cast/2</a></td><td></td></tr>
+<tr><td valign="top"><a href="#handle_info-2">handle_info/2</a></td><td></td></tr>
+<tr><td valign="top"><a href="#init-1">init/1</a></td><td></td></tr>
+<tr><td valign="top"><a href="#start_link-2">start_link/2</a></td><td></td></tr>
+<tr><td valign="top"><a href="#terminate-2">terminate/2</a></td><td></td></tr>
+</table>
+
+<h2><a name="functions">Function Details</a></h2>
+
+<h3 class="function"><a name="code_change-3">code_change/3</a></h3>
+<div class="spec">
+<p><tt>code_change(OldVsn, State, Extra) -&gt; any()</tt></p>
+</div>
+
+<h3 class="function"><a name="handle_call-3">handle_call/3</a></h3>
+<div class="spec">
+<p><tt>handle_call(Request, From, State) -&gt; any()</tt></p>
+</div>
+
+<h3 class="function"><a name="handle_cast-2">handle_cast/2</a></h3>
+<div class="spec">
+<p><tt>handle_cast(Msg, State) -&gt; any()</tt></p>
+</div>
+
+<h3 class="function"><a name="handle_info-2">handle_info/2</a></h3>
+<div class="spec">
+<p><tt>handle_info(Info, State) -&gt; any()</tt></p>
+</div>
+
+<h3 class="function"><a name="init-1">init/1</a></h3>
+<div class="spec">
+<p><tt>init(Opts) -&gt; any()</tt></p>
+</div>
+
+<h3 class="function"><a name="start_link-2">start_link/2</a></h3>
+<div class="spec">
+<p><tt>start_link(Args, Proc) -&gt; any()</tt></p>
+</div>
+
+<h3 class="function"><a name="terminate-2">terminate/2</a></h3>
+<div class="spec">
+<p><tt>terminate(Reason, State) -&gt; any()</tt></p>
+</div>
+<hr>
+
+<div class="navbar"><a name="#navbar_bottom"></a><table width="100%" border="0" cellspacing="0" cellpadding="2" summary="navigation bar"><tr><td><a href="overview-summary.html" target="overviewFrame">Overview</a></td><td><a href="http://www.erlang.org/"><img src="erlang.png" align="right" border="0" alt="erlang logo"></a></td></tr></table></div>
+<p><i>Generated by EDoc, Aug 19 2010, 16:13:09.</i></p>
+</body>
+</html>
43 doc/php_sup.html
View
@@ -0,0 +1,43 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html>
+<head>
+<title>Module php_sup</title>
+<link rel="stylesheet" type="text/css" href="stylesheet.css" title="EDoc">
+</head>
+<body bgcolor="white">
+<div class="navbar"><a name="#navbar_top"></a><table width="100%" border="0" cellspacing="0" cellpadding="2" summary="navigation bar"><tr><td><a href="overview-summary.html" target="overviewFrame">Overview</a></td><td><a href="http://www.erlang.org/"><img src="erlang.png" align="right" border="0" alt="erlang logo"></a></td></tr></table></div>
+<hr>
+
+<h1>Module php_sup</h1>
+<ul class="index"><li><a href="#index">Function Index</a></li><li><a href="#functions">Function Details</a></li></ul>
+
+<p><b>Behaviours:</b> <a href="supervisor.html"><tt>supervisor</tt></a>.</p>
+
+<h2><a name="index">Function Index</a></h2>
+<table width="100%" border="1" cellspacing="0" cellpadding="2" summary="function index"><tr><td valign="top"><a href="#init-1">init/1</a></td><td></td></tr>
+<tr><td valign="top"><a href="#start_link-0">start_link/0</a></td><td></td></tr>
+<tr><td valign="top"><a href="#start_link-1">start_link/1</a></td><td></td></tr>
+</table>
+
+<h2><a name="functions">Function Details</a></h2>
+
+<h3 class="function"><a name="init-1">init/1</a></h3>
+<div class="spec">
+<p><tt>init(Args) -&gt; any()</tt></p>
+</div>
+
+<h3 class="function"><a name="start_link-0">start_link/0</a></h3>
+<div class="spec">
+<p><tt>start_link() -&gt; any()</tt></p>
+</div>
+
+<h3 class="function"><a name="start_link-1">start_link/1</a></h3>
+<div class="spec">
+<p><tt>start_link(Args) -&gt; any()</tt></p>
+</div>
+<hr>
+
+<div class="navbar"><a name="#navbar_bottom"></a><table width="100%" border="0" cellspacing="0" cellpadding="2" summary="navigation bar"><tr><td><a href="overview-summary.html" target="overviewFrame">Overview</a></td><td><a href="http://www.erlang.org/"><img src="erlang.png" align="right" border="0" alt="erlang logo"></a></td></tr></table></div>
+<p><i>Generated by EDoc, Aug 19 2010, 16:13:09.</i></p>
+</body>
+</html>
42 doc/php_util.html
View
@@ -0,0 +1,42 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html>
+<head>
+<title>Module php_util</title>
+<link rel="stylesheet" type="text/css" href="stylesheet.css" title="EDoc">
+</head>
+<body bgcolor="white">
+<div class="navbar"><a name="#navbar_top"></a><table width="100%" border="0" cellspacing="0" cellpadding="2" summary="navigation bar"><tr><td><a href="overview-summary.html" target="overviewFrame">Overview</a></td><td><a href="http://www.erlang.org/"><img src="erlang.png" align="right" border="0" alt="erlang logo"></a></td></tr></table></div>
+<hr>
+
+<h1>Module php_util</h1>
+<ul class="index"><li><a href="#index">Function Index</a></li><li><a href="#functions">Function Details</a></li></ul>
+
+
+<h2><a name="index">Function Index</a></h2>
+<table width="100%" border="1" cellspacing="0" cellpadding="2" summary="function index"><tr><td valign="top"><a href="#get_opt-3">get_opt/3</a></td><td></td></tr>
+<tr><td valign="top"><a href="#unserialize-1">unserialize/1</a></td><td></td></tr>
+<tr><td valign="top"><a href="#unserialize_session-1">unserialize_session/1</a></td><td></td></tr>
+</table>
+
+<h2><a name="functions">Function Details</a></h2>
+
+<h3 class="function"><a name="get_opt-3">get_opt/3</a></h3>
+<div class="spec">
+<p><tt>get_opt(Opt, Opts, Default) -&gt; any()</tt></p>
+</div>
+
+<h3 class="function"><a name="unserialize-1">unserialize/1</a></h3>
+<div class="spec">
+<p><tt>unserialize(S) -&gt; any()</tt></p>
+</div>
+
+<h3 class="function"><a name="unserialize_session-1">unserialize_session/1</a></h3>
+<div class="spec">
+<p><tt>unserialize_session(S) -&gt; any()</tt></p>
+</div>
+<hr>
+
+<div class="navbar"><a name="#navbar_bottom"></a><table width="100%" border="0" cellspacing="0" cellpadding="2" summary="navigation bar"><tr><td><a href="overview-summary.html" target="overviewFrame">Overview</a></td><td><a href="http://www.erlang.org/"><img src="erlang.png" align="right" border="0" alt="erlang logo"></a></td></tr></table></div>
+<p><i>Generated by EDoc, Aug 19 2010, 16:13:09.</i></p>
+</body>
+</html>
55 doc/stylesheet.css
View
@@ -0,0 +1,55 @@
+/* standard EDoc style sheet */
+body {
+ font-family: Verdana, Arial, Helvetica, sans-serif;
+ margin-left: .25in;
+ margin-right: .2in;
+ margin-top: 0.2in;
+ margin-bottom: 0.2in;
+ color: #000000;
+ background-color: #ffffff;
+}
+h1,h2 {
+ margin-left: -0.2in;
+}
+div.navbar {
+ background-color: #add8e6;
+ padding: 0.2em;
+}
+h2.indextitle {
+ padding: 0.4em;
+ background-color: #add8e6;
+}
+h3.function,h3.typedecl {
+ background-color: #add8e6;
+ padding-left: 1em;
+}
+div.spec {
+ margin-left: 2em;
+ background-color: #eeeeee;
+}
+a.module,a.package {
+ text-decoration:none
+}
+a.module:hover,a.package:hover {
+ background-color: #eeeeee;
+}
+ul.definitions {
+ list-style-type: none;
+}
+ul.index {
+ list-style-type: none;
+ background-color: #eeeeee;
+}
+
+/*
+ * Minor style tweaks
+ */
+ul {
+ list-style-type: square;
+}
+table {
+ border-collapse: collapse;
+}
+td {
+ padding: 3
+}
3  src/php.app
View
@@ -1,5 +1,8 @@
{application, php,
[
+ {modules,
+ [php, php_app, php_eval, php_sup, php_util]
+ },
{mod,
{php_app,
[
131 src/php.erl
View
@@ -52,7 +52,11 @@
call/2,
return/2,
get_mem/1,
- restart_all/0
+ restart_all/0,
+ require_code/1,
+ unrequire/1,
+ reload/0,
+ reload_clean/0
]).
%% gen_server callbacks
@@ -64,17 +68,18 @@
free = [],
reserved = [],
waiting = [],
- restart
+ restart,
+ require = []
}).
-record(php, {
ref,
- pid,
+ proc,
maxmem
}).
-record(restart, {
- pids = [],
+ procs = [],
froms = []
}).
@@ -207,6 +212,50 @@ get_mem(Ref) ->
restart_all() ->
gen_server:call(?MODULE, restart_all, infinity).
+%% @private
+require({code, Code}) ->
+ require_code(Code).
+
+%% @spec require_code(string()) -> ref()
+%% @doc Adds code to be executed when initializing a PHP worker and
+%% restarts all. The return value can be passed to unrequire/1.
+require_code(Code) ->
+ gen_server:call(?MODULE, {require_code, Code}, infinity).
+
+%% @spec unrequire(ref()) -> ok
+%% @doc Removes code from PHP worker initialization and restarts all.
+unrequire(Ref) ->
+ gen_server:call(?MODULE, {unrequire, Ref}, infinity),
+ restart_all().
+
+%% @spec reload() -> ok
+%% @doc Reloads the application completely, carrying over any requires.
+%% Specifically, this stops the app, unloads the app, loads the
+%% app, loads the modules, starts the app, adds each require.
+%% Meanwhile calls will result in noproc.
+reload() ->
+ State = gen_server:call(?MODULE, get_state, infinity),
+ Require = State#state.require,
+ ok = reload_clean(),
+ [ require(Req) || {_, Req} <- Require ],
+ ok.
+
+%% @spec reload_clean() -> ok
+%% @doc Same as reload() except no requires are carried over.
+reload_clean() ->
+ application:stop(php),
+ application:unload(php),
+ application:load(php),
+ {ok, Mods} = application:get_key(php, modules),
+ lists:foreach(
+ fun(Mod) ->
+ code:purge(Mod),
+ code:load_file(Mod)
+ end,
+ Mods),
+ php:start().
+
+
%%====================================================================
%% gen_server callbacks
%%====================================================================
@@ -239,20 +288,20 @@ handle_call({reserve, MaxMem, What}, From, State) ->
[] -> % no processes waiting for php reservation
case {State#state.free, State#state.reserved} of
{[],[]} -> % php_eval workers undiscovered (first call to reserve)
- [Pid|Free] = lists:foldl(
- fun ({_,Pid,_,[php_eval]}, Acc)->[Pid|Acc];
+ [Proc|Free] = lists:foldl(
+ fun ({Proc,_,_,[php_eval]}, Acc)->[Proc|Acc];
(_, Acc) -> Acc
end,
[],
supervisor:which_children(State#state.sup)
),
- Php = make_php(Pid,MaxMem),
+ Php = make_php(Proc,MaxMem),
{reply, make_reply(Php, What), State#state{free=Free, reserved=[Php]}};
{[],_} -> % all php_eval workers are reserved
Waiting = [{From,MaxMem,What}],
{noreply, State#state{waiting=Waiting}};
- {[Pid|Free],_} -> % at least one php_eval worker is free
- Php = make_php(Pid,MaxMem),
+ {[Proc|Free],_} -> % at least one php_eval worker is free
+ Php = make_php(Proc,MaxMem),
Reserved = [Php|State#state.reserved],
{reply, make_reply(Php, What), State#state{free=Free, reserved=Reserved}}
end;
@@ -269,9 +318,23 @@ handle_call({get_mem, Ref}, From, State) ->
end;
handle_call(restart_all, From, State) ->
Froms = (State#state.restart)#restart.froms,
- Pids = all_pids(State),
- [spawn(fun()->eval(";")end) || _ <- lists:seq(1,length(Pids))],
- {noreply, State#state{restart=#restart{froms=[From|Froms],pids=Pids}}};
+ Procs = all_procs(State),
+ %% Restart occurs on worker release. These evals cause idle workers
+ %% to reserve/release ASAP. Reserved workers will hold up the reply
+ %% to the processes that called restart_all() until they release.
+ [spawn(fun()->eval(";")end) || _ <- lists:seq(1,length(Procs))],
+ {noreply, State#state{restart=#restart{froms=[From|Froms],procs=Procs}}};
+handle_call({require_code, Code}, _From, #state{require=Require}=State) ->
+ Ref = make_ref(),
+ Procs = all_procs(State),
+ NewRequire = Require ++ [{Ref, {code, Code}}],
+ require_all(Procs, NewRequire),
+ {reply, Ref, State#state{require=NewRequire}};
+handle_call({unrequire, Ref}, _From, #state{require=Require}=State) ->
+ Procs = all_procs(State),
+ NewRequire = proplists:delete(Ref, Require),
+ require_all(Procs, NewRequire),
+ {reply, ok, State#state{require=NewRequire}};
handle_call(Request, _From, State) ->
{reply, {unknown_call, Request}, State}.
@@ -281,7 +344,7 @@ handle_cast({release, Ref}, State) ->
none ->
{noreply, State};
Php ->
- State2 = maybe_restart(Php#php.pid, State),
+ State2 = maybe_restart(Php#php.proc, State),
State3 = do_release(Php, State2),
{noreply, State3}
end;
@@ -307,62 +370,68 @@ code_change(_OldVsn, State, _Extra) ->
reserve_php() ->
gen_server:call(?MODULE, {reserve, undefined, php}, infinity).
-maybe_restart(Pid, #state{restart=#restart{froms=Froms,pids=Pids}}=State) ->
- case lists:member(Pid, Pids) of
+maybe_restart(Proc, #state{restart=#restart{froms=Froms,procs=Procs}}=State) ->
+ case lists:member(Proc, Procs) of
false ->
State;
true ->
- gen_server:call(Pid, {eval, "exit;", 1, infinity}, infinity),
- Pids2 = lists:delete(Pid, Pids),
+ gen_server:call(Proc, {eval, "exit;", 1, infinity}, infinity),
+ Procs2 = lists:delete(Proc, Procs),
if
- Pids2 =:= [] ->
+ Procs2 =:= [] ->
Restart = #restart{},
lists:foreach(
fun (From) -> gen_server:reply(From, ok) end,
Froms
);
true ->
- Restart = #restart{froms=Froms,pids=Pids2}
+ Restart = #restart{froms=Froms,procs=Procs2}
end,
State#state{restart=Restart}
end.
do_release(Php, State) ->
Reserved = lists:delete(Php, State#state.reserved),
- Free = State#state.free ++ [Php#php.pid],
+ Free = State#state.free ++ [Php#php.proc],
case State#state.waiting of
[] -> % no processes in the queue
State#state{reserved=Reserved, free=Free};
[{From,MaxMem,What}|Waiting] -> % there is a process waiting for a reservation
- [Pid|NewFree] = Free,
- NextPhp=make_php(Pid,MaxMem),
+ [Proc|NewFree] = Free,
+ NextPhp=make_php(Proc,MaxMem),
gen_server:reply(From, make_reply(NextPhp, What)),
State#state{waiting=Waiting, reserved=[NextPhp|Reserved], free=NewFree}
end.
-do_eval(Code, #php{pid=Pid,maxmem=MaxMem}, From, Timeout) ->
- Reply = gen_server:call(Pid, {eval, Code, Timeout, MaxMem}, infinity),
+do_eval(Code, #php{proc=Proc,maxmem=MaxMem}, From, Timeout) ->
+ Reply = gen_server:call(Proc, {eval, Code, Timeout, MaxMem}, infinity),
gen_server:reply(From, Reply);
do_eval(Code, _, From, Timeout) ->
Php = reserve_php(),
do_eval(Code, Php, From, Timeout),
release(Php#php.ref).
-do_get_mem(#php{pid=Pid}, From) ->
- Mem = gen_server:call(Pid, get_mem),
+do_get_mem(#php{proc=Proc}, From) ->
+ Mem = gen_server:call(Proc, get_mem),
gen_server:reply(From, Mem).
-all_pids(#state{free=[], reserved=[]}) ->
+require_all([], _Req) ->
+ ok;
+require_all([Proc | Procs], Require) ->
+ gen_server:call(Proc, {require, Require}, infinity),
+ require_all(Procs, Require).
+
+all_procs(#state{free=[], reserved=[]}) ->
[];
-all_pids(#state{free=Free,reserved=Reserved}) ->
+all_procs(#state{free=Free,reserved=Reserved}) ->
lists:foldl(
- fun (#php{pid=Pid}, Acc) -> [Pid|Acc] end,
+ fun (#php{proc=Proc}, Acc) -> [Proc|Acc] end,
Free,
Reserved
).
-make_php(Pid, MaxMem) ->
- #php{ref=make_ref(),pid=Pid,maxmem=MaxMem}.
+make_php(Proc, MaxMem) ->
+ #php{ref=make_ref(),proc=Proc,maxmem=MaxMem}.
find_php(_, []) ->
none;
4 src/php_app.erl
View
@@ -12,7 +12,9 @@
-export([start/2, stop/1]).
start(_Type, StartArgs) ->
- php_sup:start_link(StartArgs).
+ Start = php_sup:start_link(StartArgs),
+ php:eval(";"),
+ Start.
stop(_State) ->
ok.
32 src/php_eval.erl
View
@@ -10,7 +10,7 @@
-behaviour(gen_server).
%% API
--export([start_link/0, start_link/1]).
+-export([start_link/2]).
%% gen_server callbacks
-export([init/1, handle_call/3, handle_cast/2, handle_info/2,
@@ -19,21 +19,20 @@
-import(php_util,[get_opt/3]).
%% port handler in PHP
--define(PHPLOOP, "ini_set('track_errors',true);do{ob_start();@$_C_=fread(STDIN,array_pop(unpack('N',fread(STDIN,4))));@trigger_error('');if(eval('return true;'.$_C_)){$_R_=serialize(eval($_C_));}else{$_R_='E;';}$_R_.=serialize($php_errormsg);$_R_.=serialize(ob_get_clean());fwrite(STDOUT,pack('N',strlen($_R_)).$_R_);}while(!empty($_C_));exit;").
+-define(PHPLOOP, "ini_set('track_errors',true);do{ob_start();@$_C_=fread(STDIN,array_pop(unpack('N',fread(STDIN,4))));@trigger_error('');if(eval('return true;if(0){'.$_C_.'}')){$_R_=serialize(eval($_C_));}else{$_R_='E;';}$_R_.=serialize($php_errormsg);$_R_.=serialize(ob_get_clean());fwrite(STDOUT,pack('N',strlen($_R_)).$_R_);}while(!empty($_C_));exit;").
-record(state, {
port,
opts,
- pid
+ pid,
+ require = []
}).
%%====================================================================
%% API
%%====================================================================
-start_link() ->
- start_link([]).
-start_link(Args) ->
- gen_server:start_link(?MODULE, Args, []).
+start_link(Args, Proc) ->
+ gen_server:start_link({local, Proc}, ?MODULE, Args, []).
%%====================================================================
%% gen_server callbacks
@@ -88,6 +87,14 @@ handle_call(get_mem, _, OrigState) ->
{reply, Mem, State};
handle_call(restart_php, _, State) ->
{reply, ok, restart_php(State)};
+handle_call({require, Require}, _From, OrigState) ->
+ NewState = restart_php(OrigState#state{require=Require}),
+ case NewState#state.pid of
+ Pid when is_integer(Pid) ->
+ {reply, ok, NewState};
+ _ ->
+ {reply, error, restart_php(OrigState)}
+ end;
handle_call(_Request, _From, State) ->
{noreply, State}.
@@ -110,7 +117,7 @@ code_change(_OldVsn, State, _Extra) ->
%%% Internal functions
%%--------------------------------------------------------------------
-start_php(#state{opts=Opts}=State) ->
+start_php(#state{opts=Opts, require=Require}=State) ->
Php = get_opt(php, Opts, "php"),
Init = get_opt(init, Opts, []),
Dir = get_opt(dir, Opts, []),
@@ -126,9 +133,16 @@ start_php(#state{opts=Opts}=State) ->
_ -> [{env, Envs}]
end,
Port = open_port({spawn, Command}, PortOpts),
+ require(Port, Require),
Pid = get_pid(Port),
State#state{port=Port,pid=Pid}.
+require(_, []) ->
+ ok;
+require(Port, [{_, {code, Code}} | Require]) ->
+ exec_php(Port, Code, 5000),
+ require(Port, Require).
+
stop_php(Port) ->
case erlang:port_info(Port) of
undefined ->
@@ -184,7 +198,7 @@ escape([H|T], Acc) ->
end.
exec_php(Port, Code, Timeout) ->
- Port ! {self(), {command, list_to_binary(Code)}},
+ Port ! {self(), {command, unicode:characters_to_binary(Code)}},
receive
{Port, {exit_status, Status}} -> {exit, Status};
{Port, {data, Data}} -> {Return, Rest} = php_util:unserialize(Data),
6 src/php_sup.erl
View
@@ -40,10 +40,10 @@ init(Args) ->
Opts = get_opt(opts, Args, []),
Interface = { php, {php, start_link, [] },
permanent, 2000, worker, [php] },
- Servers = [ {get_proc_name(phpeval,P),{php_eval,start_link,[Opts]},
+ Servers = [ {Proc,{php_eval,start_link,[Opts, Proc]},
permanent,2000,worker,[php_eval]}
- || P <- lists:seq(1, Procs) ],
- {ok,{{one_for_all,1,1}, Servers ++ [Interface]}}.
+ || P <- lists:seq(1, Procs), Proc <- [get_proc_name(phpeval,P)] ],
+ {ok,{{one_for_one,1,1}, Servers ++ [Interface]}}.
%%====================================================================
%% Internal functions
Please sign in to comment.
Something went wrong with that request. Please try again.