### Home Classes Methods

### In Files

- lib/taskjuggler/daemon/ProjectServer.rb

### Parent

Object

### Methods

- ::new
- #getProjectName
- #getReportList
- #getReportServer
- #loadProject
- #ping

### Included Modules

- TaskJuggler::ProcessIntercom

### Files

- CHANGELOG
- COPYING
- README.rdoc

### Class/Module Index

Quicksearch

- TaskJuggler
- TaskJuggler::Account
- TaskJuggler::AccountAttribute
- TaskJuggler::AccountCredit
- TaskJuggler::AccountCreditListAttribute
- TaskJuggler::AccountListRE
- TaskJuggler::AccountScenario
- TaskJuggler::AlertLevelDefinition
- TaskJuggler::AlertLevelDefinitions
- TaskJuggler::Allocation
- TaskJuggler::AllocationAttribute
- TaskJuggler::AttributeBase
- TaskJuggler::AttributeDefinition
- TaskJuggler::AttributeOverwrite
- TaskJuggler::BatchProcessor
- TaskJuggler::Booking
- TaskJuggler::BookingListAttribute
- TaskJuggler::BooleanAttribute
- TaskJuggler::CSVFile
- TaskJuggler::CellSettingPattern
- TaskJuggler::CellSettingPatternList
- TaskJuggler::Charge
- TaskJuggler::ChargeListAttribute
- TaskJuggler::ChargeSet
- TaskJuggler::ChargeSetListAttribute
- TaskJuggler::ChartPlotter
- TaskJuggler::ChartPlotterError
- TaskJuggler::CollisionDetector
- TaskJuggler::ColumnListAttribute
- TaskJuggler::ColumnTable
- TaskJuggler::Daemon
- TaskJuggler::DaemonConnector
- TaskJuggler::DaemonConnectorMixin
- TaskJuggler::DataCache
- TaskJuggler::DataCacheEntry
- TaskJuggler::DateAttribute
- TaskJuggler::DefinitionListAttribute
- TaskJuggler::DependencyListAttribute
- TaskJuggler::DurationAttribute
- TaskJuggler::ExportRE
- TaskJuggler::FileList
- TaskJuggler::FileRecord
- TaskJuggler::FixnumAttribute
- TaskJuggler::FlagListAttribute
- TaskJuggler::FloatAttribute
- TaskJuggler::FormatListAttribute
- TaskJuggler::GanttChart
- TaskJuggler::GanttContainer
- TaskJuggler::GanttHeader
- TaskJuggler::GanttHeaderScaleItem
- TaskJuggler::GanttLine
- TaskJuggler::GanttLoadStack
- TaskJuggler::GanttMilestone
- TaskJuggler::GanttRouter
- TaskJuggler::GanttTaskBar
- TaskJuggler::HTMLDocument
- TaskJuggler::HTMLElements
- TaskJuggler::HTMLGraphics
- TaskJuggler::ICalReport
- TaskJuggler::ICalendar
- TaskJuggler::ICalendar::Component
- TaskJuggler::ICalendar::Event
- TaskJuggler::ICalendar::Journal
- TaskJuggler::ICalendar::Person
- TaskJuggler::ICalendar::Todo
- TaskJuggler::Interval
- TaskJuggler::IntervalList
- TaskJuggler::JobInfo
- TaskJuggler::Journal
- TaskJuggler::JournalEntry
- TaskJuggler::JournalEntryList
- TaskJuggler::JournalSortListAttribute
- TaskJuggler::KateSyntax
- TaskJuggler::KeywordArray
- TaskJuggler::KeywordDocumentation
- TaskJuggler::Leave
- TaskJuggler::LeaveAllowance
- TaskJuggler::LeaveAllowanceList
- TaskJuggler::LeaveAllowanceListAttribute
- TaskJuggler::LeaveList
- TaskJuggler::LeaveListAttribute
- TaskJuggler::Limits
- TaskJuggler::Limits::Limit
- TaskJuggler::LimitsAttribute
- TaskJuggler::ListAttributeBase
- TaskJuggler::Log
- TaskJuggler::LogicalAttribute
- TaskJuggler::LogicalExpression
- TaskJuggler::LogicalExpressionAttribute
- TaskJuggler::LogicalExpressionListAttribute
- TaskJuggler::LogicalFlag
- TaskJuggler::LogicalFunction
- TaskJuggler::LogicalOperation
- TaskJuggler::ManagerResponsibilities
- TaskJuggler::ManagerStatusRecord
- TaskJuggler::Message
- TaskJuggler::MessageHandler
- TaskJuggler::MessageHandlerInstance
- TaskJuggler::MspXmlRE
- TaskJuggler::Navigator
- TaskJuggler::NavigatorElement
- TaskJuggler::NikuProject
- TaskJuggler::NikuReport
- TaskJuggler::NikuResource
- TaskJuggler::NodeListAttribute
- TaskJuggler::PTNProxy
- TaskJuggler::Painter
- TaskJuggler::Painter::Circle
- TaskJuggler::Painter::Color
- TaskJuggler::Painter::Element
- TaskJuggler::Painter::Ellipse
- TaskJuggler::Painter::FontMetrics
- TaskJuggler::Painter::FontMetricsData
- TaskJuggler::Painter::Group
- TaskJuggler::Painter::Line
- TaskJuggler::Painter::Points
- TaskJuggler::Painter::PolyLine
- TaskJuggler::Painter::Primitives
- TaskJuggler::Painter::Rect
- TaskJuggler::Painter::SVGSupport
- TaskJuggler::Painter::Text
- TaskJuggler::PlaceHolderCell
- TaskJuggler::ProcessIntercom
- TaskJuggler::ProcessIntercomIface
- TaskJuggler::Project
- TaskJuggler::ProjectBroker
- TaskJuggler::ProjectBrokerIface
- TaskJuggler::ProjectFileParser
- TaskJuggler::ProjectFileScanner
- TaskJuggler::ProjectRecord
- TaskJuggler::ProjectServer
- TaskJuggler::ProjectServerIface
- TaskJuggler::PropertyAttribute
- TaskJuggler::PropertyList
- TaskJuggler::PropertySet
- TaskJuggler::PropertyTreeNode
- TaskJuggler::Query
- TaskJuggler::RTFHandlers
- TaskJuggler::RTFNavigator
- TaskJuggler::RTFQuery
- TaskJuggler::RTFReport
- TaskJuggler::RTFReportLink
- TaskJuggler::RTFWithQuerySupport
- TaskJuggler::RealFormat
- TaskJuggler::RealFormatAttribute
- TaskJuggler::ReferenceAttribute
- TaskJuggler::Report
- TaskJuggler::ReportBase
- TaskJuggler::ReportContext
- TaskJuggler::ReportScenario
- TaskJuggler::ReportServer
- TaskJuggler::ReportServerIface
- TaskJuggler::ReportServerRecord
- TaskJuggler::ReportServlet
- TaskJuggler::ReportTable
- TaskJuggler::ReportTableCell
- TaskJuggler::ReportTableColumn
- TaskJuggler::ReportTableLegend
- TaskJuggler::ReportTableLine
- TaskJuggler::Resource
- TaskJuggler::ResourceListAttribute
- TaskJuggler::ResourceListRE
- TaskJuggler::ResourceScenario
- TaskJuggler::RichText
- TaskJuggler::RichTextAttribute
- TaskJuggler::RichTextDocument
- TaskJuggler::RichTextElement
- TaskJuggler::RichTextFunctionExample
- TaskJuggler::RichTextFunctionHandler
- TaskJuggler::RichTextImage
- TaskJuggler::RichTextIntermediate
- TaskJuggler::RichTextParser
- TaskJuggler::RichTextScanner
- TaskJuggler::RichTextSnip
- TaskJuggler::RichTextSyntaxRules
- TaskJuggler::Scenario
- TaskJuggler::ScenarioData
- TaskJuggler::ScenarioListAttribute
- TaskJuggler::Scoreboard
- TaskJuggler::ScoreboardInterval
- TaskJuggler::SheetHandlerBase
- TaskJuggler::SheetReceiver
- TaskJuggler::SheetSender
- TaskJuggler::Shift
- TaskJuggler::ShiftAssignment
- TaskJuggler::ShiftAssignments
- TaskJuggler::ShiftAssignmentsAttribute
- TaskJuggler::ShiftScenario
- TaskJuggler::SimpleQueryExpander
- TaskJuggler::SortListAttribute
- TaskJuggler::StatusSheetReceiver
- TaskJuggler::StatusSheetReport
- TaskJuggler::StatusSheetSender
- TaskJuggler::StdIoWrapper
- TaskJuggler::StringAttribute
- TaskJuggler::SymbolAttribute
- TaskJuggler::SymbolListAttribute
- TaskJuggler::SyntaxReference
- TaskJuggler::TOCEntry
- TaskJuggler::TSResourceRecord
- TaskJuggler::TSTaskRecord
- TaskJuggler::TableColumnDefinition
- TaskJuggler::TableColumnSorter
- TaskJuggler::TableOfContents
- TaskJuggler::TableReport
- TaskJuggler::TableReportColumn
- TaskJuggler::TagFile
- TaskJuggler::TagFile::TagFileEntry
- TaskJuggler::Task
- TaskJuggler::TaskDepListAttribute
- TaskJuggler::TaskDependency
- TaskJuggler::TaskListAttribute
- TaskJuggler::TaskListRE
- TaskJuggler::TaskScenario
- TaskJuggler::TernarySearchTree
- TaskJuggler::TextFormatter
- TaskJuggler::TextParser
- TaskJuggler::TextParser::Macro
- TaskJuggler::TextParser::MacroTable
- TaskJuggler::TextParser::Pattern
- TaskJuggler::TextParser::Rule
- TaskJuggler::TextParser::Scanner
- TaskJuggler::TextParser::Scanner::BufferStreamHandle
- TaskJuggler::TextParser::Scanner::FileStreamHandle
- TaskJuggler::TextParser::Scanner::MacroStackEntry
- TaskJuggler::TextParser::Scanner::StreamHandle
- TaskJuggler::TextParser::SourceFileInfo
- TaskJuggler::TextParser::StackElement
- TaskJuggler::TextParser::State
- TaskJuggler::TextParser::StateTransition
- TaskJuggler::TextParser::TextParserResultArray
- TaskJuggler::TextParser::TokenDoc
- TaskJuggler::TextReport
- TaskJuggler::TimeInterval
- TaskJuggler::TimeIntervalListAttribute
- TaskJuggler::TimeSheet
- TaskJuggler::TimeSheetReceiver
- TaskJuggler::TimeSheetRecord
- TaskJuggler::TimeSheetReport
- TaskJuggler::TimeSheetSender
- TaskJuggler::TimeSheetSummary
- TaskJuggler::TimeSheets
- TaskJuggler::Tj3
- TaskJuggler::Tj3AppBase
- TaskJuggler::Tj3Client
- TaskJuggler::Tj3Daemon
- TaskJuggler::Tj3Man
- TaskJuggler::Tj3SheetAppBase
- TaskJuggler::Tj3SsReceiver
- TaskJuggler::Tj3SsSender
- TaskJuggler::Tj3TsReceiver
- TaskJuggler::Tj3TsSender
- TaskJuggler::Tj3TsSummary
- TaskJuggler::Tj3WebD
- TaskJuggler::TjException
- TaskJuggler::TjRuntimeError
- TaskJuggler::TjTime
- TaskJuggler::TjpExample
- TaskJuggler::TjpExportRE
- TaskJuggler::TjpSyntaxRules
- TaskJuggler::TraceReport
- TaskJuggler::URLParameter
- TaskJuggler::UserManual
- TaskJuggler::VimSyntax
- TaskJuggler::WebServer
- TaskJuggler::WelcomePage
- TaskJuggler::WorkingHours
- TaskJuggler::WorkingHoursAttribute
- TaskJuggler::XMLBlob
- TaskJuggler::XMLComment
- TaskJuggler::XMLDocument
- TaskJuggler::XMLElement
- TaskJuggler::XMLNamedText
- TaskJuggler::XMLText
- Diff
- Diff::Hunk
- AppConfig
- Diffable
- DiffableString
- Object
- RuntimeConfig
- String

No matching classes.

# TaskJuggler::ProjectServer

The ProjectServer objects are created from the ProjectBroker to handle the data of a particular project. Each ProjectServer runs in a separate process that is forked-off in the constructor. Any action such as adding more files or generating a report will cause the process to fork again, creating a ReportServer object. This way the initially loaded project can be modified but the original version is always preserved for subsequent calls. Each ProjectServer process has a unique secret authentication key that only the ProjectBroker knows. It will pass it with the URI of the ProjectServer to the client to permit direct access to the ProjectServer.

### Attributes

authKey[R]
uri[R]

### Public Class Methods

new(daemonAuthKey, projectData = nil, logConsole = false) click to toggle source

    # File lib/taskjuggler/daemon/ProjectServer.rb, line 38
    def initialize(daemonAuthKey, projectData = nil, logConsole = false)
      @daemonAuthKey = daemonAuthKey
      @projectData = projectData
      # Since we are still in the ProjectBroker process, the current DRb
      # server is still the ProjectBroker DRb server.
      @daemonURI = DRb.current_server.uri
      # Used later to store the DRbObject of the ProjectBroker.
      @daemon = nil
      initIntercom

      @logConsole = logConsole
      @pid = nil
      @uri = nil

      # A reference to the TaskJuggler object that holds the project data.
      @tj = nil
      # The current state of the project.
      @state = :new
      # A time stamp when the last @state update happened.
      @stateUpdated = TjTime.new
      # A lock to protect access to @state
      @stateLock = Monitor.new

      # A Queue to asynchronously generate new ReportServer objects.
      @reportServerRequests = Queue.new

      # A list of active ReportServer objects
      @reportServers = []
      @reportServers.extend(MonitorMixin)

      @lastPing = TjTime.new

      # We've started a DRb server before. This will continue to live somewhat
      # in the child. All attempts to create a DRb connection from the child
      # to the parent will end up in the child again. So we use a Pipe to
      # communicate the URI of the child DRb server to the parent. The
      # communication from the parent to the child is not affected by the
      # zombie DRb server in the child process.
      rd, wr = IO.pipe

      if (@pid = fork) == -1
        fatal('ps_fork_failed', 'ProjectServer fork failed')
      elsif @pid.nil?
        # This is the child
        if @logConsole
          # If the Broker wasn't daemonized, log stdout and stderr to PID
          # specific files.
          $stderr.reopen("tj3d.ps.#{$$}.stderr", 'w')
          $stdout.reopen("tj3d.ps.#{$$}.stdout", 'w')
        end
        begin
          $SAFE = 1
          DRb.install_acl(ACL.new(] deny all allow 127.0.0.1 ]))
          iFace = ProjectServerIface.new(self)
          begin
            @uri = DRb.start_service('druby://127.0.0.1:0', iFace).uri
            debug('', "Project server is listening on #{@uri}")
          rescue
            error('ps_cannot_start_drb', "ProjectServer can't start DRb: #{$!}")
          end

          # Send the URI of the newly started DRb server to the parent process.
          rd.close
          wr.write @uri
          wr.close

          # Start a Thread that waits for the @terminate flag to be set and does
          # other background tasks.
          startTerminator
          # Start another Thread that will be used to fork-off ReportServer
          # processes.
          startHousekeeping

          # Cleanup the DRb threads
          DRb.thread.join
          debug('', 'Project server terminated')
          exit 0
        rescue => exception
          # TjRuntimeError exceptions are simply passed through.
          if exception.is_a?(TjRuntimeError)
            raise TjRuntimeError, $!
          end

          error('ps_cannot_start_drb', "ProjectServer can't start DRb: #{$!}")
        end
      else
        # This is the parent
        Process.detach(@pid)
        wr.close
        @uri = rd.read
        rd.close
      end
    end

### Public Instance Methods

getProjectName() click to toggle source

Return the name of the loaded project or nil.

    # File lib/taskjuggler/daemon/ProjectServer.rb, line 182
    def getProjectName
      return nil unless @tj
      restartTimer
      @tj.projectName
    end

getReportList() click to toggle source

Return a list of the HTML reports defined for the project.

    # File lib/taskjuggler/daemon/ProjectServer.rb, line 189
    def getReportList
      return [] unless @tj && (project = @tj.project)
      list = []
      project.reports.each do |report|
        unless report.get('formats').empty?
          list << [ report.fullId, report.name ]
        end
      end
      restartTimer
      list
    end

getReportServer() click to toggle source

This function triggers the creation of a new ReportServer process. It will return the URI and the authentication key of this new server.

    # File lib/taskjuggler/daemon/ProjectServer.rb, line 203
    def getReportServer
      # ReportServer objects only make sense for successfully scheduled
      # projects.
      return [ nil, nil ] unless @state == :ready

      # The ReportServer will be created asynchronously in another Thread. To
      # find it in the @reportServers list, we create a unique tag to identify
      # it.
      tag = rand(99999999999999)
      debug('', "Pushing #{tag} onto report server request queue")
      @reportServerRequests.push(tag)

      # Now wait until the new ReportServer shows up in the list.
      reportServer = nil
      while reportServer.nil?
        @reportServers.synchronize do
          @reportServers.each do |rs|
            reportServer = rs if rs.tag == tag
          end
        end
        # It should not take that long, so we use a short idle time here.
        sleep 0.1 if reportServer.nil?
      end

      debug('', "Got report server with URI #{reportServer.uri} for " +
            "tag #{tag}")
      restartTimer
      [ reportServer.uri, reportServer.authKey ]
    end

loadProject(args) click to toggle source

Wait until the project load has been finished. The result is true if the project scheduled without errors. Otherwise the result is false. args is an Array of Strings. The first element is the working directory. The second one is the master project file (.tjp file). Additionally a list of optional .tji files can be provided.

    # File lib/taskjuggler/daemon/ProjectServer.rb, line 137
    def loadProject(args)
      dirAndFiles = args.dup.untaint
      # The first argument is the working directory
      Dir.chdir(args.shift.untaint)

      # Save a time stamp of when the project file loading started.
      @modifiedCheck = TjTime.new

      updateState(:loading, dirAndFiles, false)
      begin
        @tj = TaskJuggler.new
        # Make sure that trace reports get CSV formats included so there
        # reports can be generated on request.
        @tj.generateTraces = true

        # Parse all project files
        unless @tj.parse(args, true)
          warning('parse_failed', "Parsing of #{args.join(' ')} failed")
          updateState(:failed, nil, false)
          @terminate = true
          return false
        end

        # Then schedule the project
        unless @tj.schedule
          warning('schedule_failed',
                  "Scheduling of project #{@tj.projectId} failed")
          updateState(:failed, @tj.projectId, false)
          @terminate = true
          return false
        end
      rescue TjRuntimeError
        updateState(:failed, nil, false)
        @terminate = true
        return false
      end

      # Great, everything went fine. We've got a project to work with.
      updateState(:ready, @tj.projectId, false)
      debug('', "Project #{@tj.projectId} loaded")
      restartTimer
      true
    end

ping() click to toggle source

This function is called regularly by the ProjectBroker process to check that the ProjectServer is still operating properly.

    # File lib/taskjuggler/daemon/ProjectServer.rb, line 235
    def ping
      # Store the time stamp. If we don't get the ping for some time, we
      # assume the ProjectBroker has died.
      @lastPing = TjTime.new

      # Now also check our ReportServers if they are still there. If not, we
      # can remove them from the @reportServers list.
      @reportServers.synchronize do
        deadServers = []
        @reportServers.each do |rs|
          unless rs.ping
            deadServers << rs
          end
        end
        @reportServers.delete_if { |rs| deadServers.include?(rs) }
      end
    end

[Validate]

Generated with the Darkfish Rdoc Generator 2.