require 'drb/drb' require 'public_api.rb' # # application.rb contains the definition of Application # Application is the basic class for all applications and services within appswarm. class Application include DRbUndumped publicAPI attr_reader :cluster attr_accessor :running def initialize(cluster,options) @running=false @threads=[] @cluster=cluster @options=options @provides={} @appName=shortName.downcase @appId=@options[:appId] @appId||=createAppId if @options[:appName] @appName=@options[:appName] elsif @options[@appName] @appName=@options[@appName] end @quit=false @quitMutex=Mutex.new end def quit? @quit end def quit @quitMutex.synchronize { @quit=true } end def provides?(xy) return true if self.class.providing.member?(xy) @provides[xy] end def getService(name) @cluster.getApp(name) end def startup end def run end def config end def quit end def stop @threads.each{|thread|thread.kill} @threads.each{|thread| log "KILL THREAD #{thread}" thread.kill! } @threads=[] end # get a shorter name for the current application. # def shortName self.class.to_s.gsub(/App$/,"") end # instanceName def getAppName @appName end def getAppId @appId end def info {} end def appswarmBaseDir cluster.appswarmBaseDir end def getAppDataWritePath path=File.join(appswarmBaseDir,getAppName) Dir.mkdir_save(path) path end def getAppDataPaths [getAppDataWritePath,getAppDataPath].flatten end def getAppDataPath dir=File.expand_path("../../data/#{self.class.to_s}",__FILE__) unless File.exist?(dir) return [] end dir end def withApp(name,&block) app=@cluster.getApp(name) if app app.instance_eval{block.call} end end def withAppFork(name,&block) @threads << Thread.new(name){|name| loop do a=@cluster.getApp(name) if a puts name,a #exit a.instance_eval(&block) break end sleep 5 end } end def getAppDir Application.getAppDir(self.class.to_s) end # gets the (absolute) application-directory for the given class(-name) def self.getAppDir(name) File.expand_path("../../../apps/#{name.to_s.gsub(/App$/,'').dirName}",__FILE__) end def warning(*x) log "WARNING",*x end # logs any objects to the logger-app or if such does not exist to the console def log(*s) logger=getApp(:logger) if logger # puts "[#{Time.new}][#{self}][#{place}] "+s.map{|v|v.to_s}.join(" ") logger.log(self.class,getAppName,*s) if logger else place=caller[0] if cluster cluster.log_direct(place,nil,s.to_s) else pp s end end end def getApp(*s) return cluster.getApp(*s) if cluster nil end def monitor(&b) log "start monitor" begin b.call rescue Object=>e log "Monitor error #{e}" log e.to_s+"\n"+e.backtrace.join("\n") #rescue Error=>e # log e.toString+"\n"+e.backtrace.join("\n") end end def retrieveConfig app=nil trials=0 loop do app=getApp(:localFileStore) if app.nil? cluster.run("LocalFileStore") else break end trials+=1 log "First trial failed to get LocalFileStore" if trials>2 puts "ERROR: NO LocalFileStore found!" log "ERROR: NO LocalFileStore found!" return nil end end app.config(self) end def providingAPIs @provides.keys end def self.requires(*x) @@requires||={} @@requires[self]||=[] @@requires[self]<