Please disable Adblockers and enable JavaScript for domain CEWebS.cs.univie.ac.at! We have NO ADS, but they may interfere with some of our course material.

Name: server/engine/implementation.rb 
1:
require ::File.dirname(__FILE__) + '/controller'
2:
 
3:
class Callback #{{{
4:
  def initialize(info,handler,method,event,key,protocol,*context)
5:
    @info = info
6:
    @event = event
7:
    @key = key
8:
    @context = context
9:
    @handler = handler
10:
    @protocol = protocol
11:
    @method = method.class == Symbol ? method : :callback
12:
  end
13:
 
14:
  attr_reader :info, :protocol
15:
 
16:
  def delete_if!(event,key)
17:
    @handler.send @method, :DELETE, *@context if @key == key && @event == event
18:
    nil
19:
  end
20:
 
21:
  def callback(result)
22:
    @handler.send @method, result, *@context
23:
  end
24:
end #}}}
25:
 
26:
class ExCallback < Riddl::Implementation #{{{
27:
  def response
28:
    controller = @a[0]
29:
    id = @r[0].to_i
30:
    callback = @r[2]
31:
      controller[id].mutex.synchronize do
32:
      if controller[id].callbacks.has_key?(callback)
33:
        controller[id].callbacks[callback].callback(@p)
34:
      end
35:
    end
36:
  end
37:
end #}}}
38:
 
39:
class Callbacks < Riddl::Implementation #{{{
40:
  def response
41:
    controller = @a[0]
42:
    unless File.exists?("instances/#{@r[0]}")
43:
      @status = 400
44:
      return
45:
    end
46:
    Riddl::Parameter::Complex.new("info","text/xml") do
47:
      cb = XML::Smart::string("<?xml-stylesheet href='/xsls/callbacks.xsl' type='text/xsl'?><callbacks details='#{@a[0]}'/>")
48:
      id = @r[0].to_i
49:
      controller[id].callbacks.each do |k,v|
50:
        cb.root.add("callback",{"id" => k},"[#{v.protocol.to_s}] #{v.info}")
51:
      end
52:
      cb.to_s
53:
    end
54:
  end
55:
end #}}}
56:
 
57:
class Instances < Riddl::Implementation #{{{
58:
  def response
59:
    controller = @a[0]
60:
    Riddl::Parameter::Complex.new("wis","text/xml") do
61:
      ins = XML::Smart::string('<instances/>')
62:
      controller.each do |k,v|
63:
        name = v.properties.data.find("string(/p:properties/p:name)")
64:
        state = v.properties.data.find("string(/p:properties/p:state)")
65:
        ins.root.add('instance',name, 'id' => k, 'state' => state)
66:
      end
67:
      ins.to_s
68:
    end
69:
  end
70:
end #}}}
71:
 
72:
class NewInstance < Riddl::Implementation #{{{
73:
  def response
74:
    controller = @a[0]
75:
    opts = @a[1]
76:
    name = @p[0].value
77:
    id = controller.keys.sort.last.to_i
78:
 
79:
    while true
80:
      id += 1
81:
      Dir.mkdir(opts[:instances] + "/#{id}") rescue nil
82:
      break
83:
    end
84:
    controller[id] = Controller.new(id,opts)
85:
    controller[id].properties.data.find("/p:properties/p:name").first.text = name
86:
 
87:
    Riddl::Parameter::Simple.new("id", id)
88:
  end
89:
end #}}}
90:
 
91:
class Info < Riddl::Implementation #{{{
92:
  def response
93:
    controller = @a[0]
94:
    id = @r[0].to_i
95:
    unless controller[id]
96:
      @status = 400
97:
      return
98:
    end
99:
    Riddl::Parameter::Complex.new("info","text/xml") do
100:
      i = XML::Smart::string <<-END
101:
        <?xml-stylesheet href="../xsls/info.xsl" type="text/xsl"?>
102:
        <info instance='#{@r[0]}'>
103:
          <events/>
104:
          <notifications/>
105:
          <properties/>
106:
          <callbacks/>
107:
        </info>
108:
      END
109:
      i.to_s
110:
    end
111:
  end
112:
end #}}}
113:
 
114:
class DeleteInstance < Riddl::Implementation #{{{
115:
  def response
116:
    controller = @a[0]
117:
    unless File.exists?("instances/#{@r[0]}")
118:
      @status = 400
119:
      return
120:
    end
121:
    FileUtils.rm_r("instances/#{@r[0]}")
122:
    controller.delete(@r[0])
123:
  end
124:
end #}}}
125:
 
126:
class Event < Riddl::Implementation #{{{
127:
  def response
128:
    controller = @a[0]
129:
    id = @r[0].to_i
130:
    topic = @p.find{|e|e.name=='topic'}.value
131:
    event = @p.find{|e|e.name=='vote'}.value
132:
    parameters = JSON::parse(@p.find{|e|e.name=='notification'}.value)
133:
 
134:
    name = "#{topic}_#{event}"
135:
    para = {}
136:
    parameters.each do |k,v|
137:
      para[k.to_sym] = v
138:
    end
139:
    ret = []
140:
    if controller[id].test_push(name,para)
141:
      @headers << Riddl::Header.new("CPEE-CALLBACK",'true')
142:
      ret << Riddl::Parameter::Simple.new('continue','callback')
143:
    else
144:
      @headers << Riddl::Header.new("CPEE-CALLBACK",'false')
145:
      ret << Riddl::Parameter::Simple.new('continue','true')
146:
    end
147:
    Thread.new { controller[id].push(name,para) }
148:
    ret
149:
  end
150:
end #}}}
151:
 
152:
class PropertiesHandler < Riddl::Utils::Properties::HandlerBase #{{{
153:
  def sync
154:
    if @property == 'state'
155:
      state = @data.state
156:
      if state == 'stopped'
157:
        @data.stop
158:
        @data.notify("properties/#{@property}/change")
159:
      end
160:
      if state == 'running'
161:
        if @data.call_vote("properties/#{@property}/running")
162:
          @data.start
163:
          @data.notify("properties/#{@property}/change")
164:
        else
165:
          @data.serialize_state!('stopped')
166:
        end
167:
      end
168:
    else
169:
      @data.unserialize_context!(@property)
170:
      @data.notify("properties/#{@property}/change")
171:
    end
172:
  end
173:
 
174:
  def create; sync; end
175:
  def update; sync; end
176:
  def delete; sync; end
177:
end #}}}
178:
 
179:
class NotificationsHandler < Riddl::Utils::Notifications::Producer::HandlerBase #{{{
180:
  def ws_open(socket)
181:
     @data.add_ws(@key,socket)
182:
  end
183:
  def ws_close
184:
    @data.del_ws(@key)
185:
  end
186:
  def ws_message(socket,data)
187:
    begin
188:
      doc = XML::Smart::string(data)
189:
      callback = doc.find("string(/vote/@id)")
190:
      result = doc.find("string(/vote)")
191:
      @data.callbacks[callback].callback(result == 'true' ? true : false)
192:
      @data.callbacks.delete(callback)
193:
    rescue
194:
      puts "Invalid message over websocket"
195:
    end
196:
  end
197:
 
198:
  def create
199:
    @data.unserialize_event!(:cre,@key)
200:
    @data.notify('properties/handlers/change')
201:
  end
202:
  def delete
203:
    @data.unserialize_event!(:del,@key)
204:
    @data.notify('properties/handlers/change')
205:
  end
206:
  def update
207:
    @data.unserialize_event!(:upd,@key)
208:
    @data.notify('properties/handlers/change')
209:
  end
210:
end #}}}