http://code.google.com/p/openserverplatform/source/detail?r=121
Modified:
/trunk/bin/osp_ctl
/trunk/doc/manual/OSP-Manual.tex
/trunk/src/Makefile
/trunk/src/osp_admin.erl
/trunk/src/osp_manager.erl
/trunk/src/osp_proto.erl
/trunk/src/osp_web.erl
=======================================
--- /trunk/bin/osp_ctl Wed Nov 4 05:36:34 2009
+++ /trunk/bin/osp_ctl Sun Nov 8 15:53:31 2009
@@ -19,9 +19,29 @@
echo " stop - stop the OSP cluster"
echo " stats - print some information about the running cluster"
echo " webadmin - opens the web based administration system"
+ echo " app_start <appname> <port> <node> - Starts appname on node"
+ echo " app_stop <appname> <node> - Stops appname on node"
exit 0
fi
+if [ ${1} == "app_start" ]; then
+ if [ $# -eq 4 ]; then
+ RET=`echo "start ${2} ${3} ${4}" | nc localhost 9876`
+ exit 0
+ fi
+ echo "Invalid number of arguments, format is app_start <appname>
<port> <node>"
+ exit -1
+fi
+
+if [ ${1} == "app_stop" ]; then
+ if [ $# -eq 3 ]; then
+ RET=`echo "stop ${2} ${3}" | nc localhost 9876`
+ exit 0
+ fi
+ echo "Invalid number of arguments, format is app_stop <appname> <node>"
+ exit -1
+fi
+
if [ ${1} == "webadmin" ]; then
xdg-open http://localhost:9877
exit 0
=======================================
--- /trunk/doc/manual/OSP-Manual.tex Wed Nov 4 05:36:34 2009
+++ /trunk/doc/manual/OSP-Manual.tex Sun Nov 8 15:53:31 2009
@@ -0,0 +1,55 @@
+\documentclass{book}
+\author{Jacob Torrey}
+\title{Open Server Platform Manual}
+\begin{document}
+\maketitle{}
+\chapter{Introducing Open Server Platform}
+\section{Introduction}
+As the Internet scales beyond a simple system for serving static content
over
+limited bandwidth links, there is growing need to support complex
operations
+and for services to never go down. For a number of companies, their online
+services are their entire revenue stream, and if they were to go down, they
+would instantly lose money and customers. This desire for highly-available
+systems are driving software development to use multiple hardware machines
or
+move their web applications into the `cloud'. However, developing software
to
+perform under distributed conditions is a far greater challenge than
developing
+for the single machine counterpart.
+
+Open Server Platform (OSP) attempts to bridge this gap between developing a
+simple single-threaded, single-machine networked application and a
distributed,
+redundant system capable of handling thousands of concurrent users. Based
off
+of Erlang's Open Telecom Platform (OTP), OSP allows application developers
to
+focus on just the core logic of their system, and let OSP handle the rest
of
+the heavy lifting. Using OSP, the developer must only focus on handling a
+single request, from there OSP takes care of the rest.
+
+\section{Features}
+OSP provides a number of features to aide in the development and runtime
+management of an application cluster. Below the most promenient features
are
+outlined at a high level:
+
+\begin{enumerate}
+\item Automatic multi-threading and highly concurrent application brokerage
+system
+\item Socket handling and packet routing
+\item Per-application shared state redundantly shared across the cluster
+\item Atomicity of shared state transactions (commit all or commit none)
+\item Telnet console for application management and cluster monitoring
+\item Web-based at-a-glance cluster statistics, drag-and-drop application
+management and simple application deployment
+\item Command-line cluster operations
+\item Automatic application recovery
+\item Supports diskless nodes that dynamically load code from other nodes
+\end{enumerate}
+
+Throughout the rest of this manual there will be more information regarding
+each of these features and how to best leverage them in a distributed
server
+application.
+
+\section{Usage Scenario}
+This section will describe a hypothetical use case for OSP, and
demonstrate how
+it can be leveraged to simplify application development and deployment.
+
+\subsection{Scenario Background}
+
+\end{document}
=======================================
--- /trunk/src/Makefile Wed Nov 4 05:36:34 2009
+++ /trunk/src/Makefile Sun Nov 8 15:53:31 2009
@@ -9,4 +9,5 @@
clean:
-rm ../ebin/osp*.beam *~ ../erl_crash.dump ../osp_rel* ../mnesia/*
docs:
+ cd ../doc/manual && latex OSP-Manual.tex && dvips *.dvi
cd .. && erl -pa ./ebin -s osp gen_docs
=======================================
--- /trunk/src/osp_admin.erl Thu Nov 5 10:24:11 2009
+++ /trunk/src/osp_admin.erl Sun Nov 8 15:53:31 2009
@@ -42,7 +42,7 @@
String3 = string:strip(String2, right, $\r),
case String3 of
"help" -> % Print out the help message
- send(Sock, <<"OSP Admin Console\n\tquit - Quits the console\n\tstats
- Prints general stats about the OSP cluster\n\tstart <appname> <port>
<node> - Starts appname on node\n\tadd-diskless-ip <ip> - Adds IP to the
allowed diskless server pool\n\tshutdown - Shutdown OSP on all
nodes\n\tadd-backup-server <node> <type> - Makes node a backup server
keeping an up-to-date copy of all the shared state in the cluster; type may
be ram for faster, non-persistant storage, or disk for data
persistance\n\tstop <appname> <node> - Stops the given servlet on
node\n\tmigrate <appname> <fromnode> <tonode> <port> - Migrates a servlet
from fromnode to tonode, starting it on the given port\n">>);
+ send(Sock, <<"OSP Admin Console\n\tquit - Quits the console\n\tstats
- Prints general stats about the OSP cluster\n\tstart <appname> <port>
<node> - Starts appname on node\n\tadd-diskless-ip <ip> - Adds IP to the
allowed diskless server pool\n\tshutdown - Shutdown OSP on all
nodes\n\tadd-backup-server <node> <type> - Makes node a backup server
keeping an up-to-date copy of all the shared state in the cluster; type may
be ram for faster, non-persistant storage, or disk for data
persistance\n\tstop <appname> <node> - Stops the given servlet on
node\n\tmigrate <appname> <fromnode> <tonode> <port> - Migrates a servlet
from fromnode to tonode, starting it on the given port\n\trunning - Prints
a list of all the running applications on the cluster\n">>);
"stats" -> % Display some stats
send(Sock, osp_manager:stats());
"quit" ->
@@ -52,6 +52,9 @@
send(Sock, "Shutting down\r\n"),
close(Sock),
osp_manager:shutdown_osp();
+ "running" ->
+ NA = osp_manager:nodeapp(),
+ send(Sock, print_nodeapp(NA));
"" ->
ok;
Unknown -> % Handle multi-word command
@@ -63,11 +66,13 @@
Port = erlang:list_to_integer(PortList),
App = erlang:list_to_atom(AppList),
Node = erlang:list_to_atom(NodeList),
- case osp_mamager:start_servlet(App, Port, Node) of
+ case osp_manager:start_servlet(App, Port, Node) of
ok ->
sendf(Sock, "~p started on ~p port ~p~n", [App, Node, Port]);
- error ->
- send(Sock, "Sorry, the node you requested couldn't be found\r\n")
+ {error, nonode} ->
+ send(Sock, "Sorry, the node you requested couldn't be found\r\n");
+ {error, noapp} ->
+ send(Sock, "Sorry, the app you requested couldn't be found\r\n")
end;
"migrate" ->
[Comm, AppList, FromNodeList, NodeList, PortList ] = Split,
@@ -78,8 +83,10 @@
case osp_manager:start_servlet(App, Port, Node) of
ok ->
sendf(Sock, "~p started on ~p port ~p~n", [App, Node, Port]);
- error ->
- send(Sock, "Sorry, the node you requested couldn't be found\r\n")
+ {error, nonode} ->
+ send(Sock, "Sorry, the node you requested couldn't be found\r\n");
+ {error, noapp} ->
+ send(Sock, "Sorry, the app you requested couldn't be found\r\n")
end,
case osp_manager:stop_servlet(App, From) of
ok ->
@@ -123,6 +130,18 @@
end
end.
+%% @doc Returns a human readable string of the nodeapp data
+%% @spec print_nodeapp(list()) -> string()
+print_nodeapp(NA) ->
+ F1 = fun({App, Port}, Str) ->
+ Str ++ "\n " ++ erlang:atom_to_list(App) ++ ":" ++
erlang:integer_to_list(Port)
+ end,
+ F2 = fun({Node, Applist}, Str) ->
+ AppStr = lists:foldl(F1, "", Applist),
+ Str ++ erlang:atom_to_list(Node) ++ AppStr ++ "\n"
+ end,
+ lists:foldl(F2, "", NA).
+
%% @doc Callback for the OSP broker service
%% @spec init() -> ok
init() ->
=======================================
--- /trunk/src/osp_manager.erl Thu Nov 5 10:24:11 2009
+++ /trunk/src/osp_manager.erl Sun Nov 8 15:53:31 2009
@@ -169,17 +169,22 @@
start_servlet(App, Port, Node) ->
case lists:member(Node, [node() | nodes()]) of
true ->
- if
- Node =:= node() ->
- osp_broker:start(App, Port);
- true->
- start_db(Node, App),
- rpc:call(Node, osp_broker, start, [App, Port])
- end,
- add_app_to_list(Node, App, Port),
- ok;
+ case code:load_file(App) of
+ {module, App} ->
+ if
+ Node =:= node() ->
+ osp_broker:start(App, Port);
+ true->
+ start_db(Node, App),
+ rpc:call(Node, osp_broker, start, [App, Port])
+ end,
+ add_app_to_list(Node, App, Port),
+ ok;
+ {error, _} ->
+ {error, noapp}
+ end;
false ->
- error
+ {error, nonode}
end.
%% @doc Returns a human readable string of the cluster uptime
=======================================
--- /trunk/src/osp_proto.erl Wed Nov 4 05:36:34 2009
+++ /trunk/src/osp_proto.erl Sun Nov 8 15:53:31 2009
@@ -71,7 +71,7 @@
end;
accept(sctp) ->
fun(Sock, Timeout) ->
- gen_sctp:recv(Sock, 0, Timeout)
+ gen_sctp:recv(Sock, Timeout)
end;
accept(udp) ->
fun(Sock, Timeout) ->
=======================================
--- /trunk/src/osp_web.erl Thu Nov 5 10:24:11 2009
+++ /trunk/src/osp_web.erl Sun Nov 8 15:53:31 2009
@@ -57,8 +57,18 @@
"nodes" ->
mod_esi:deliver(Session, erlang:integer_to_list(length([node() |
nodes()])));
"appnode" ->
- mod_esi:deliver(Session, io_lib:format("~p",
[osp_manager:nodeapp()]));
+ mod_esi:deliver(Session, json_nodeapp(osp_manager:nodeapp()));
_ ->
mod_esi:deliver(Session, "")
end.
+%% @doc JSONizes the nodeapp information for the web application frontend
+%% @spec json_nodeapp(list()) -> string()
+json_nodeapp(NA) ->
+ F1 = fun({App, Port}, Str) ->
+ Str ++ "{\"name: \"" ++ erlang:atom_to_list(App) ++ "\", \"port\": \""
++ erlang:integer_to_list(Port) ++ "\"}"
+ end,
+ F2 = fun({Node, Applist}, Str) ->
+ Str ++ "{\"node\": \"" ++ erlang:atom_to_list(Node) ++ "\",
\"running_apps\": [" ++ lists:foldl(F1, "", Applist) ++ "]}"
+ end,
+ "[" ++ lists:foldl(F2, "", NA) ++ "]".