1
0
Fork 0
mirror of https://github.com/puma/puma.git synced 2022-11-09 13:48:40 -05:00

Finalizes the new look for the config tool and makes it functional for 0.3.10.

git-svn-id: svn+ssh://rubyforge.org/var/svn/mongrel/trunk@100 19e92222-5c0b-0410-8929-a290d50e31e9
This commit is contained in:
zedshaw 2006-03-12 07:30:25 +00:00
parent 375bf06a84
commit d4749060f4
20 changed files with 475 additions and 50 deletions

View file

@ -72,7 +72,7 @@ class Start < GemPlugin::Plugin "/commands"
def configure_rails def configure_rails
# need this later for safe reloading # need this later for safe reloading
@orig_dollar_quote = $".clone $orig_dollar_quote = $".clone
ENV['RAILS_ENV'] = @environment ENV['RAILS_ENV'] = @environment
require 'config/environment' require 'config/environment'
@ -97,6 +97,7 @@ class Start < GemPlugin::Plugin "/commands"
# graceful shutdown # graceful shutdown
trap("TERM") { trap("TERM") {
server.stop server.stop
File.unlink @pid_file if File.exist?(@pid_file)
} }
# rails reload # rails reload
@ -109,6 +110,7 @@ class Start < GemPlugin::Plugin "/commands"
# restart # restart
trap("USR2") { trap("USR2") {
server.stop server.stop
File.unlink @pid_file if File.exist?(@pid_file)
@restart = true @restart = true
} }
end end
@ -179,8 +181,6 @@ class Stop < GemPlugin::Plugin "/commands"
else else
send_signal("TERM", @pid_file) send_signal("TERM", @pid_file)
end end
File.unlink(@pid_file)
end end
end end
@ -214,8 +214,6 @@ class Restart < GemPlugin::Plugin "/commands"
else else
send_signal("USR2", @pid_file) send_signal("USR2", @pid_file)
end end
File.unlink(@pid_file)
end end
end end

View file

@ -46,6 +46,20 @@
<h4>NEWS</h4> <h4>NEWS</h4>
<dl> <dl>
<dt>Mar-12-2006</dt>
<dd>
<h5><a href="{relocatable: news.html}">Mongrel 0.3.10 -- Big Release Day</a></h5>
<p>I normally do lots of little releases rather than large big ones, but this
release involved lots of little touches all over the entire code base. It
now has a ton of features and should have the best Rails support yet. It's
even got <b>GemPlugins</b> to a leve that anyone can use it. Read the
news for the full scoop.
</p>
<a href="http://rubyforge.org/frs/?group_id=1306" title="Downloads">Download</a>
<a href="{relocatable: news.html}"><img src="{relocatable: images/li4.gif}" alt="more" /><br /></a></p>
</dd>
<dt>Mar-06-2006</dt> <dt>Mar-06-2006</dt>
<dd> <dd>
<h5><a href="{relocatable: news.html}">Mongrel 0.3.9 -- Gem Based Plugins</a></h5> <h5><a href="{relocatable: news.html}">Mongrel 0.3.9 -- Gem Based Plugins</a></h5>

View file

@ -17,6 +17,57 @@ new commands.
such as "mongrel_rails dostuff". Handlers and such as "mongrel_rails dostuff". Handlers and
Filters are on their way. Filters are on their way.
h2. Why Plugins for Mongrel?
If you've ever used other systems that have plugins you'll find there are
several painful parts to writing your own plugin:
* You don't have their developer tools so it takes forever to get started.
* You don't know how to structure the project or even where to start.
* Once you get it built you have to figure out how to register and install it.
* When you want to update it you have to somehow get the update out to users.
* You have to manage dependencies between your plugin and other plugins.
* Including and using your own resources (images, html files, etc.) or config files
is really painful. Not sure why this is but it's really annoying.
Most people solve many of the problems by the "sourdough method". They
take a plugin that currently works, copy it, and base their plugin
on the prototype. This works great until you want to do something
original or until you find out the original author did something wrong.
GemPlugin solves this problem by relying on the regular RubyGems
package management system to give you:
* A simple way to package, distribute, manage, and update your Mongrel plugins.
* Dynamic loading based on the gem dependencies and not on specific configurations.
* Segregated extensions for Mongrel in case you want a different license than LGPL.
* All the capabilities of RubyGems. GemPlugin doesn't mess with them at all.
* A little generator that starts your project off right similar to how Rails generators work.
* The ability to package resources (images, configs, etc.) with your gem and then load them
dynamically no matter where the gem eventually gets installed.
In the end GemPlugins are just RubyGems that get loaded a special way
so they are activated right away. The only extra thing is a bit of
"magic" that puts plugins into a nice little namespace outside of
the usual Ruby module and class hierarchy.
The advantage for Mongrel is that people can write their own
plugins and distribute them easily without anything more complex
than what all Ruby developers already have: RubyGems.
h2. How They Work
Mongrel plugins (a.k.a. GemPlugins) are really very simple. Basically
when you use the GemPlugin API you tell it what kind of dependencies
will trigger a gem to be loaded. GemPlugin then goes through all of
the installed gems and loads any that meet the dependency description.
Then your plugin just registers itself in the right "plugin category"
and everything starts working. The user of your plugin won't have to
do too much unless you want to give them additional configuration.
The best way to understand this is to actually build a plugin
and watch it work.
h2. Your First Plugin h2. Your First Plugin

View file

@ -83,7 +83,7 @@ h3. Q: How did you make this site?
The site was actually incredibly easy to create. I simply went to "OSWD":http://openwebdesign.org/ The site was actually incredibly easy to create. I simply went to "OSWD":http://openwebdesign.org/
and found a design that fit what I wanted for the site. I then went to "Flickr":http://flickr.com/ and found a design that fit what I wanted for the site. I then went to "Flickr":http://flickr.com/
and found pictures of various animals that were licensed under the and found pictures of various animals that were licensed under the
"Creative Commons":http://openwebdesign.org/ license. Once I chopped the images up, worked them "Creative Commons":http://creativecommons.org/ license. Once I chopped the images up, worked them
into the design structure, and wrote an initial set of content I was done. into the design structure, and wrote an initial set of content I was done.
The tool I use to generate the site is called "webgen":http://webgen.rubyforge.org/ which The tool I use to generate the site is called "webgen":http://webgen.rubyforge.org/ which

Binary file not shown.

After

Width:  |  Height:  |  Size: 37 KiB

View file

@ -7,6 +7,57 @@ ordering: 2
h1. Latest News h1. Latest News
h2. Mar-12: Mongrel 0.3.10 -- Big Release Day
This release is a bigger release than those in the
past but it was necessary as it touched many little
parts of the code base and includes a more complete
GemPlugin functionality. This release features the
following changes:
* GemPlugin now supports including and easily finding resources and config files
you package with your gems.
* GemPlugin loading doesn't use any deprecated RubyGems APIs.
* GemPlugin comes with a generator called *gpgen* that will make it easy to start off
a plugin project.
* A complete document on "Writing A Mongrel Plugin":/docs/gem_plugin.html that
also explains how they work.
* The "Mongrel Config Tool":/images/config_tool_snap.png that demonstrates
building a useful command for controlling a Mongrel server.
** It uses a "Camping":http://camping.rubyforge.org/ to present an interface.
** Demonstrates combining Camping handlers with Mongrel handlers.
** Shows how to use the new GemPlugin resources API to include ERB templates, images,
and CSS stylesheets which are loaded out of the gem (no external install needed).
* Restructuring of the project source a bit to support testing all the
default plugins and to make building much easier.
* Properly loads any gems that depend on Rails (including GemPlugins) until the
very last minute after Rails is loaded and configured.
* A slight hack courtesy of Sean Treadway which jacks up the default server
listen queue from 5 to 1024. This should work on all platforms where
available and should improve concurrency for everyone.
* A more complete and useful Camping postamble that makes it the same size
as the WEBrick one. Also makes sure that Camping handlers and Mongrel
handlers can live in peace together.
There's also a bunch of bug fixes:
* Should work well with edge rails now and tries to be very nice.
* It holds of Rails configuration until the absolute latest time to
avoid having the daemonize call from closing log files Rails opens.
* Tweaks to the API docs in various places and cleaned out dead code.
* Lots of fixes to the build. If you get the source and are on Unix
you can just do "rake install" to install the whole thing via gems.
This release has been tested on Linux, OSX, and FreeBSD with only
light testing on Win32. I'll be making the 0.3.11 release Win32
specific so that the config tool can be useful for those folks too.
Otherwise this is a large release so please grab it and test like
mad.
"Download 0.3.10":http://rubyforge.org/frs/?group_id=1306
h2. Mar-06: Mongrel 0.3.9 -- Gem Based Plugins h2. Mar-06: Mongrel 0.3.9 -- Gem Based Plugins
This release features the beginning of a plugin system based This release features the beginning of a plugin system based

View file

@ -76,7 +76,7 @@ class RailsHandler < Mongrel::HttpHandler
def reload! def reload!
@guard.synchronize do @guard.synchronize do
$".replace @orig_dollar_quote $".replace $orig_dollar_quote
GC.start GC.start
Dispatcher.reset_application! Dispatcher.reset_application!
ActionController::Routing::Routes.reload ActionController::Routing::Routes.reload

View file

@ -189,7 +189,6 @@ module GemPlugin
file = File.join(@gems[gem_name], "resources", path) file = File.join(@gems[gem_name], "resources", path)
puts "Looking for: #{file}"
if File.exist? file if File.exist? file
return file return file
else else

View file

@ -15,7 +15,7 @@ setup_rdoc ['README', 'LICENSE', 'COPYING', 'lib/**/*.rb', 'doc/**/*.rdoc']
desc "Does a full compile, test run" desc "Does a full compile, test run"
task :default => [:test, :package] task :default => [:test, :package]
version="0.1" version="0.2"
name="mongrel_config" name="mongrel_config"
setup_gem(name, version) do |spec| setup_gem(name, version) do |spec|

View file

@ -1,7 +1,7 @@
require 'mongrel' require 'mongrel'
require 'gem_plugin' require 'gem_plugin'
require 'camping' require 'camping'
require 'erb'
Camping.goes :Configure Camping.goes :Configure
@ -17,74 +17,148 @@ module Configure::Controllers
class Start < R '/start' class Start < R '/start'
def get def get
`mongrel_rails start -d -p 4000` render :start
redirect Index end
def post
@results = `mongrel_rails start -d -p #{input.port} -e #{input.env} -n #{input.num_procs} -a #{input.address}`
render :start_done
end end
end end
class Kill < R '/kill/(\w+)'
def get(signal)
if _running?
@signal = signal.upcase
pid = open($PID_FILE) {|f| f.read }
begin
Process.kill(@signal, pid.to_i)
@results = "Mongrel sent PID #{pid} signal #{@signal}."
rescue
puts "ERROR: #$!"
@results = "Failed to signal the Mongrel process. Maybe it is not running?<p>#$!</p>"
end
else
@results = "Mongrel does not seem to be running. Maybe delete the pid file #{$PID_FILE} or start again."
end
render :kill
end
end
class Stop < R '/stop' class Stop < R '/stop'
def get def get
`mongrel_rails stop` render :stop
redirect Index
end end
end end
class Shutdown < R '/shutdown' class Logs < R '/logs'
def get def get
Thread.new do @log_files = Dir.glob("log/**/*")
STDERR.puts "Shutdown requested..." render :logs
sleep 2
$server.stop
STDERR.puts "Bye."
end
render :shutdown
end end
end end
end end
module Configure::Views module Configure::Views
def layout def layout
html do body_content = yield
head do currently_running = _running?
title 'Mongrel Configure Tool' pid = _pid
end open(GemPlugin::Manager.instance.resource("mongrel_config", "/index.html")) do |f|
body do template = ERB.new(f.read)
h1 "Mongrel Configure Tool" self << template.result(binding)
p do
a 'start', :href => R(Start)
a 'stop', :href => R(Stop)
a 'shutdown', :href => R(Shutdown)
a 'logs', :href => "../logs"
end
div.content do
self << yield
end
end
end end
end end
def show def show
body do div do
h2 { "Status" }
if _running? if _running?
p { "Running..." } p { "Currently running with PID #{_pid}." }
else else
p { "Not running..." } p { "Mongrel is not running." }
end end
end end
end end
def shutdown def start
body do div do
p { "Shutdown shortly..." } form :action => "/start", :method => "POST" do
p { span { "Port:" }; input :name => "port", :value => "4000" }
p { span { "Environment:" }; input :name => "env", :value => "development" }
p { span { "Address:" }; input :name => "address", :value => "0.0.0.0" }
p { span { "Number Processors:" }; input :name => "num_procs", :value => "20" }
input :type => "submit", :value => "START"
end
end
end
def start_done
div do
p { @results }
end
end
def kill
div do
p { @results }
case @signal
when "HUP":
p { "A reload (HUP) does not stop the process, but may not be complete." }
when "TERM":
p { "Stopped with TERM signal. The process should exit shortly, but only after processing pending requests." }
when "USR2":
p { "Complete restart (USR2) may take a little while. Check status in a few seconds or read logs." }
when "KILL":
p { "Process was violently stopped (KILL) so pending requests will be lost." }
end
end
end
def stop
if _running?
ul do
li { a "Stop (TERM)", :href => "/kill/term" }
li { a "Reload (HUP)", :href => "/kill/hup" }
li { a "Restart (USR2)", :href => "/kill/usr2" }
li { a "Kill (KILL)", :href => "/kill/kill" }
end
else
p { "Mongrel does not appear to be running (no PID file at #$PID_FILE)." }
end
end
def logs
div do
h2 { "Logs" }
table do
tr do
th { "File"}; th { "Bytes" }; th { "Last Modified" }
end
@log_files.each do |file|
tr do
td { a file, :href => "../#{file}" }
td { File.size file }
td { File.mtime file }
end
end
end
end end
end end
def _running? def _running?
File.exist? $PID_FILE File.exist? $PID_FILE
end end
def _pid
open($PID_FILE) {|f| f.read } if _running?
end
end end
def Configure.create def Configure.create
@ -139,7 +213,9 @@ class ConfigTool < GemPlugin::Plugin "/commands"
end end
# add our log directory # add our log directory
$server.register("/logs", Mongrel::DirHandler.new("log")) $server.register("/log", Mongrel::DirHandler.new("log"))
resources = GemPlugin::Manager.instance.resource "mongrel_config", "/"
$server.register("/config/resources", Mongrel::DirHandler.new(resources))
$server.acceptor.join $server.acceptor.join
end end

Binary file not shown.

After

Width:  |  Height:  |  Size: 130 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 135 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 624 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 490 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

View file

@ -0,0 +1,71 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html>
<head>
<title>Mongrel Config Tool</title>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
<link href="/config/resources/style.css" rel="stylesheet" type="text/css" />
</head>
<body>
<div id="container">
<div id="top">
<div id="title">Mongrel Config Tool</div>
</div>
<div id="middle">
<div id="nav">
<ul>
<li><a href="/config">Status</a></li>
<li><a href="/config/start">Start</a></li>
<li><a href="/config/stop">Stop</a></li>
<li><a href="/config/logs">Logs</a></li>
</ul>
</div>
<div id="content">
<div id="side">
<% if currently_running %>
<strong>Status</strong> <br />
<br />
Mongrel is running with PID <%= pid %>.
<% else %>
<strong>Status</strong> <br />
<br />
Mongrel is not running.
<% end %>
<br /><br />
<br />
<strong>Documentation</strong><br />
<br />
<a href="http://mongrel.rubyforge.org">Mongrel Home</a> <br />
<br />
<a href="http://mongrel.rubyforge.org/news.html">News</a><br />
<br />
<a href="http://mongrel.rubyforge.org/docs/started.html">Getting Started</a> <br />
<br />
<a href="http://mongrel.rubyforge.org/docs/win32.html">Win32 Guide</a><br />
<br />
<a href="http://mongrel.rubyforge.org/docs/lighttpd.html">Lighttpd Guide</a><br />
<br />
<a href="http://mongrel.rubyforge.org/rdoc/index.html">Mongrel API</a><br />
<br />
<a href="http://api.rubyonrails.org/">Ruby On Rails API</a><br />
<br />
<br /><br />
</div>
<%= body_content %>
</div>
</div>
</div>
<div id="bottom">&nbsp;</div>
<div id="footertext">Copyright 2006 &copy; Zed A. Shaw &nbsp; | &nbsp; Design by Kenneth Barbour.</div>
</body>
</html>

View file

@ -0,0 +1,165 @@
/* CSS Document */
body {
margin: 25px auto 0px auto;
background-image: url(/config/resources/images/top.jpg);
background-repeat: repeat-x;
background-position: top;
font-family: "Lucida Grande", Verdana, Halvetica, sans-serif;
text-align: center;
}
a:hover {
color: #990000;
text-decoration: underline;
}
a {
color: #990000;
text-decoration: none;
}
#container {
font-weight: normal;
margin: 0px auto 0px auto;
width: 686px;
text-align: center;
}
#main {
padding-top: 50px;
padding-bottom: 50px;
border: 1px solid #CC0000;
height: auto;
}
#title {
font-family: Georgia, "Times New Roman", Times, serif;
font-size: 36px;
color: #FFF;
font-weight: normal;
font-size:36px;
text-align: center;
color: #FFFFFF;
padding-top: 28px;
}
#top {
margin: 0px auto;
width: 686px;
height: 96px;
background: url(/config/resources/images/topbar.jpg) no-repeat
}
#middle {
background: url(/config/resources/images/middle.jpg) no-repeat;
background-repeat: repeat-y;
margin: -2px auto 0px auto;
}
#bottom {
margin: -100px auto 0px;
width: 686px;
height: 106px;
background: url(/config/resources/images/bottom.gif) no-repeat;
clear: center;
}
#nav {
width: 455px;
padding: 20px 30px 10px;
margin: 0px auto;
color: #999;
font-weight: normal;
font-size: 11px;
text-align: center;
}
#nav li {
list-style: none;
display: inline;
margin-right: 20px;
}
#nav a {
font-size: 10px;
font-weight: bold;
color: #999;
text-decoration: none;
}
#nav a:hover {
color: #990000;
text-decoration: underline;
}
#content {
padding: 0px 68px 1px 68px;
margin: 0px auto 0px auto;
text-align: left;
height: 370px;
}
#side {
margin: 30px auto 0px auto;
width: 110px;
border-left: 1px dotted #C4D0D7;
padding: 0px 10px 0px 20px;
color: #999;
float: right;
font-size: 70%;
}
#content h2 {
color: #990000;
font-weight: bolder;
font-size: 14px;
padding: 0px 135px 0px 10px;
}
#content h2 a:hover{
color: #990000;
text-decoration: underline;
}
#content h2 a{
text-decoration: none;
}
#content h3 {
color: #000000;
font-size: 10px;
letter-spacing: .3em;
padding: 0px 135px 0px 10px;
text-decoration: underline;
}
#content p {
padding: 0px 170px 0px 10px;
font-size: 70%;
line-height: 1.7em;
margin: 0px 0px 1.7em 0px;
vertical-align: top;
color: #666666;
}
#footertext {
font-size: 10px;
font-weight: bold;
margin: 20px auto 0px;
height: 20px;
width: 686px;
height: 31px;
text-align: center;
color: #888;
}
#footertext a {
font-size: 10px;
font-weight: bold;
color: #999;
text-decoration: none;
}
#footertext a:hover {
text-decoration: underline;
}
table {
border-collapse: collapsed;
}
td {
font-size: 11px;
padding: 5px;
}
th {
border: 1px #990000 solid;
font-size: 12px;
background-color: #955;
color: #eeeeee;
}

View file

@ -15,7 +15,7 @@ setup_rdoc ['README', 'LICENSE', 'COPYING', 'lib/**/*.rb', 'doc/**/*.rdoc']
desc "Does a full compile, test run" desc "Does a full compile, test run"
task :default => [:test, :package] task :default => [:test, :package]
version="0.1" version="0.2"
name="mongrel_status" name="mongrel_status"
setup_gem(name, version) do |spec| setup_gem(name, version) do |spec|