Skip to content

Commit

Permalink
tj3d can now launch and kill tj3webd if -w option is provided.
Browse files Browse the repository at this point in the history
  • Loading branch information
scrapper committed Feb 25, 2012
1 parent cd8efe7 commit 1cdfe81
Show file tree
Hide file tree
Showing 7 changed files with 158 additions and 14 deletions.
12 changes: 8 additions & 4 deletions lib/taskjuggler/TjpSyntaxRules.rb
Expand Up @@ -6671,10 +6671,14 @@ def rule_traceReport
preserved and the corresponding columns will be the last ones in the CSV file.
When other formats are requested, the CSV file is read in and a report that
shows the tracked values over time will be generated. The HTML version
generates SVG graphs that are embedded in the HTML page. These graphs are only
visble if the web browser supports HTML5. This is true for the latest
generation of browsers, but older browsers may not support this format.
shows the tracked values over time will be generated. The CSV file may contain
all kinds of values that are being tracked. Report formats that don't support
a mix of different values will just show the values of the second column.
The HTML version generates SVG graphs that are embedded in the HTML page.
These graphs are only visble if the web browser supports HTML5. This is true
for the latest generation of browsers, but older browsers may not support this
format.
EOT
)
example('TraceReport')
Expand Down
50 changes: 50 additions & 0 deletions lib/taskjuggler/apps/Tj3Daemon.rb
Expand Up @@ -35,6 +35,9 @@ def initialize
@daemonize = true
@uriFile = File.join(Dir.getwd, '.tj3d.uri')
@port = nil
@webServer = false
@webServerPort = 8080
@webdPidFile = File.join(Dir.getwd, ".tj3webd-#{$$}.pid").untaint
end

def processArguments(argv)
Expand All @@ -59,6 +62,17 @@ def processArguments(argv)
'of the server.')) do |arg|
@uriFile = arg
end
@opts.on('-w', '--webserver',
format('Start a web server that serves the reports of ' +
'the loaded projects.')) do
@webServer = true
end
@opts.on('--webserver-port <NUMBER>', Integer,
format('Use the specified TCP/IP port to serve web browser ' +
'requests (Default: 8080).')) do |arg|
@webServerPort = arg
end

end
end

Expand All @@ -79,7 +93,43 @@ def appMain(files)
# is not disconnected from the terminal.
broker.logStdIO = !@daemonize

if @webServer
webdCommand = "tj3webd --webserver-port #{@webServerPort} " +
"--pidfile #{@webdPidFile}"
# Also start the web server as a separate process. We keep the PID, so
# we can terminate that process again when we exit the daemon.
begin
`#{webdCommand}`
rescue
error('tj3webd_start_failed', "Could not start tj3webd: #{$!}")
end
info('web_server_started', "Web server started as '#{webdCommand}'")
end

broker.start

if @webServer
pid = nil
begin
# Read the PID of the web server from the PID file.
File.open(@webdPidFile, 'r') do |f|
pid = f.read.to_i
end
rescue
warning('cannot_read_webd_pidfile',
"Cannot read tj3webd PID file (#{@webdPidFile}): #{$!}")
end
# If we have started the web server, we are also trying to terminate
# that process again.
begin
Process.kill("TERM", pid)
rescue
warning('tj3webd_term_failed',
"Could not terminate web server: #{$!}")
end
info('web_server_terminated', "Web server with PID #{pid} terminated")
end

0
end

Expand Down
9 changes: 8 additions & 1 deletion lib/taskjuggler/apps/Tj3WebD.rb
Expand Up @@ -35,6 +35,7 @@ def initialize
@uriFile = File.join(Dir.getwd, '.tj3d.uri')
@port = nil
@webServerPort = nil
@pidFile = nil
end

def processArguments(argv)
Expand All @@ -54,6 +55,11 @@ def processArguments(argv)
'TaskJuggler daemon (Default: 8474).')) do |arg|
@port = arg
end
@opts.on('--pidfile <FILE NAME>', String,
format('Write the process ID of the daemon to the ' +
'specified file.')) do |arg|
@pidFile = arg
end
@opts.on('--urifile', String,
format('If the port is 0, use this file to read the URI ' +
'of the TaskJuggler daemon.')) do |arg|
Expand All @@ -79,8 +85,9 @@ def appMain(files)
webServer.port = @port if @port
webServer.uriFile = @uriFile.untaint
webServer.webServerPort = @webServerPort if @webServerPort
webServer.projectFiles = sortInputFiles(files) unless files.empty?
webServer.daemonize = @daemonize
webServer.pidFile = @pidFile
debug('', "pidFile 1: #{@pidFile}")

webServer.start
0
Expand Down
41 changes: 40 additions & 1 deletion lib/taskjuggler/daemon/Daemon.rb
Expand Up @@ -22,13 +22,15 @@ class Daemon

include MessageHandler

attr_accessor :daemonize
attr_accessor :pidFile, :daemonize

def initialize
# You can set this flag to false to prevent the program from
# disconnecting from the current terminal. This is useful for debugging
# purposes.
@daemonize = true
# Save the PID of the running daemon as number into this file.
@pidFile = nil
end

# Call this method to turn the process into a background process.
Expand Down Expand Up @@ -57,6 +59,8 @@ def start

@pid = Process.pid

writePidFile

# Change current working directory to the file system root
Dir.chdir '/'
# Make sure we can create files with any permission
Expand All @@ -69,12 +73,47 @@ def start

info('daemon_pid',
"The process is running as daemon now with PID #{@pid}")

0
end

# This method may provide some cleanup functionality in the future. You
# better call it before you exit.
def stop
if @pidFile
begin
File.delete(@pidFile)
rescue
warning('cannot_delete_pidfile',
"Cannote delete the PID file (#{@pidFile}): #{$!}")
end
info('daemon_deleted_pidfile', "PID file #{@pidFile} deleted")
end
end

private

def writePidFile
if @pidFile
# Prepend the current working dir to @pidFile unless it's already an
# absolute path. The working dir is changed to '/' later. We need the
# absolute name to be able to delete it on exit again.
if @pidFile[0] != '/'
@pidFile = File.join(Dir.getwd, @pidFile)
end

# If requested, write the PID of the daemon to the specified file.
begin
File.open(@pidFile, 'w') do |f|
f.puts @pid
end
rescue
warning('cannot_save_pidfile', "Cannot write PID to #{@pidFile}")
end
info('daemon_wrote_pidfile',
"PID file #{@pidFile} written with PID #{@pid}")
end

end

end
Expand Down
5 changes: 5 additions & 0 deletions lib/taskjuggler/daemon/DaemonConnector.rb
Expand Up @@ -108,6 +108,11 @@ def initialize(authKey, host, port, uri)
@broker = connectDaemon
end

def disconnect
disconnectDaemon
@broker = nil
end

def getProject(projectId)
@broker.getProject(@authKey, projectId)
end
Expand Down
48 changes: 40 additions & 8 deletions lib/taskjuggler/daemon/ReportServlet.rb
Expand Up @@ -27,8 +27,6 @@ def initialize(config, options)
@host = options[1]
@port = options[2]
@uri = options[3]

@broker = DaemonConnector.new(*options)
end

def self.get_instance(config, options)
Expand Down Expand Up @@ -61,10 +59,25 @@ def do_GET(req, res)

private

def connectToBroker
begin
broker = DaemonConnector.new(@authKey, @host, @port, @uri)
rescue
error('cannot_connect_broker',
"Cannot connect to the TaskJuggler daemon: #{$!}\n" +
"Please make sure you have tj3d running and listening " +
"on port #{@port} or URI '#{@uri}'.")
end

broker
end

def generateReport(projectId, reportId, attributes)
broker = connectToBroker

# Request the Project credentials from the ProbjectBroker.
begin
@ps_uri, @ps_authKey = @broker.getProject(projectId)
@ps_uri, @ps_authKey = broker.getProject(projectId)
rescue
error('cannot_get_project_server',
"Cannot get project server for ID #{projectId}: #{$!}")
Expand Down Expand Up @@ -126,6 +139,7 @@ def generateReport(projectId, reportId, attributes)
"Report server termination failed: #{$!}")
end
@reportServer = nil
broker.disconnect

@res['content-type'] = 'text/html'
stdErr.rewind
Expand All @@ -137,8 +151,10 @@ def generateReport(projectId, reportId, attributes)
end

def generateWelcomePage(projectId)
broker = connectToBroker

begin
projects = @broker.getProjectList
projects = broker.getProjectList
rescue
error('cannot_get_project_list',
"Cannot get project list from daemon: #{$!}")
Expand All @@ -163,6 +179,10 @@ def generateWelcomePage(projectId)
text << "* [/taskjuggler?project=#{id} #{getProjectName(id)}]\n"
end
end

# We no longer need the broker.
broker.disconnect

rt = RichText.new(text)
rti = rt.generateIntermediateFormat
rti.sectionNumbers = false
Expand All @@ -174,19 +194,31 @@ def generateWelcomePage(projectId)
end

def getProjectName(id)
uri, authKey = @broker.getProject(id)
broker = connectToBroker

uri, authKey = broker.getProject(id)
return nil unless uri
projectServer = DRbObject.new(nil, uri)
return nil unless projectServer
projectServer.getProjectName(authKey)
res = projectServer.getProjectName(authKey)

broker.disconnect

res
end

def getReportList(id)
uri, authKey = @broker.getProject(id)
broker = connectToBroker

uri, authKey = broker.getProject(id)
return [] unless uri
projectServer = DRbObject.new(nil, uri)
return [] unless projectServer
projectServer.getReportList(authKey)
res = projectServer.getReportList(authKey)

broker.disconnect

res
end

def error(id, message)
Expand Down
7 changes: 7 additions & 0 deletions lib/taskjuggler/daemon/WebServer.rb
Expand Up @@ -48,6 +48,12 @@ def initialize

# Port used by the web server
@webServerPort = 8080

Kernel.trap('TERM') do
debug('webserver_term_signal', 'TERM signal received. Exiting...')
# When the OS sends us a TERM signal, we try to exit gracefully.
stop
end
end

def start
Expand Down Expand Up @@ -118,6 +124,7 @@ def stop
@server.shutdown
@server = nil
end
super
end

end
Expand Down

0 comments on commit 1cdfe81

Please sign in to comment.