module CPEE
This file is part of CPEE
.
CPEE
is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
CPEE
is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with CPEE
(file COPYING in the main directory). If not, see <www.gnu.org/licenses/>.
This file is part of CPEE
.
CPEE
is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
CPEE
is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with CPEE
(file COPYING in the main directory). If not, see <www.gnu.org/licenses/>.
This file is part of CPEE
.
CPEE
is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
CPEE
is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with CPEE
(file COPYING in the main directory). If not, see <www.gnu.org/licenses/>.
Constants
- PROPERTIES_PATHS_FULL
- PROPERTIES_PATHS_INDEX_ORDERED
- PROPERTIES_PATHS_INDEX_UNORDERED
- SERVER
Public Class Methods
Source
# File lib/cpee/implementation.rb, line 257 def self::cleanup_services(watchdog_start_off) return if watchdog_start_off Dir[File.join(__dir__,'..','..','server','routing','*.pid')].each do |s| pid = (File.read(s).to_i rescue nil) if !pid.nil? || (Process.kill(0, pid) rescue false) f = s.sub(/(-(\d+))?\.pid$/,'.rb') if $2.nil? system "#{f} stop 1>/dev/null 2>&1" else system "#{f} -w #{$2} stop 1>/dev/null 2>&1" end puts "➡ Service #{File.basename(s,'.pid')} stopped ..." end end end
Source
# File lib/cpee/implementation.rb, line 56 def self::implementation(opts) opts[:see_instances] ||= opts[:see_instances].nil? ? false : opts[:see_instances] opts[:instances] ||= File.expand_path(File.join(__dir__,'..','..','server','instances')) opts[:global_executionhandlers] ||= File.expand_path(File.join(__dir__,'..','..','server','executionhandlers')) opts[:executionhandlers] ||= '' opts[:topics] ||= File.expand_path(File.join(__dir__,'..','..','server','resources','topics.xml')) opts[:properties_init] ||= File.expand_path(File.join(__dir__,'..','..','server','resources','properties.init')) opts[:properties_empty] ||= File.expand_path(File.join(__dir__,'..','..','server','resources','properties.empty')) opts[:empty_dslx] ||= File.expand_path(File.join(__dir__,'..','..','server','resources','empty_dslx.xml')) opts[:notifications_init] ||= File.expand_path(File.join(__dir__,'..','..','server','resources','notifications')) opts[:states] ||= File.expand_path(File.join(__dir__,'..','..','server','resources','states.xml')) opts[:watchdog_frequency] ||= 7 opts[:watchdog_start_off] ||= false opts[:infinite_loop_stop] ||= 10000 opts[:workers] ||= 1 opts[:workers_single] ||= ['end','persist','forward-votes'] opts[:workers_multi] ||= ['forward-events'] opts[:dashing_frequency] ||= 3 opts[:dashing_target] ||= nil ### set redis_cmd to nil if you want to do global ### at least redis_path or redis_url and redis_db have to be set if you do global opts[:redis_path] ||= 'redis.sock' # use e.g. /tmp/redis.sock for global stuff. Look it up in your redis config opts[:redis_db] ||= 0 ### optional redis stuff opts[:redis_url] ||= nil opts[:redis_cmd] ||= 'redis-server --port 0 --unixsocket #redis_path# --unixsocketperm 600 --pidfile #redis_pid# --dir #redis_db_dir# --dbfilename #redis_db_name# --databases 1 --save 900 1 --save 300 10 --save 60 10000 --rdbcompression yes --daemonize yes' opts[:redis_pid] ||= 'redis.pid' # use e.g. /var/run/redis.pid if you do global. Look it up in your redis config opts[:redis_db_name] ||= 'redis.rdb' # use e.g. /var/lib/redis.rdb for global stuff. Look it up in your redis config opts[:libs_preload] ||= ['weel', 'json', 'redis', 'securerandom', 'riddl/client', 'cpee/value_helper', 'cpee/attributes_helper', 'cpee/message', 'cpee/redis', 'cpee/persistence', 'yaml', 'charlock_holmes', 'psych', 'xml/smart', 'ostruct', 'bigdecimal', 'mimemagic', 'cpee-eval-ruby/translation', 'get_process_mem'] opts[:libs_preloader] ||= '~/bin/by-server' opts[:libs_preloaderrun] ||= '~/bin/by' CPEE::redis_connect opts, 'Server Main' ### start by server if opts[:libs_preload]&.is_a?(Array) && opts[:libs_preload].length > 0 && opts[:libs_preloader]&.is_a?(String) && opts[:libs_preloader]&.strip != '' puts '(re)starting by-server ...' `pkill -f #{File.basename(opts[:libs_preloader])}` `#{opts[:libs_preloader]} '#{opts[:libs_preload].join("' '")}'` end opts[:sse_keepalive_frequency] ||= 10 opts[:sse_connections] = {} opts[:statemachine] = CPEE::StateMachine.new opts[:states] do |id| CPEE::Persistence::extract_item(id,opts,"state") end opts[:runtime_cmds] << [ "startclean", "Delete instances before starting.", Proc.new { |status| Dir.glob(File.expand_path(File.join(opts[:instances],'*'))).each do |d| FileUtils.rm_r(d) if File.basename(d) =~ /^\d+$/ end } ] Proc.new do Dir[File.join(opts[:global_executionhandlers],'*','execution.rb')].each do |h| require h end unless opts[:global_executionhandlers].nil? || opts[:global_executionhandlers].strip == '' Dir[File.join(opts[:executionhandlers],'*','execution.rb')].each do |h| require h end unless opts[:executionhandlers].nil? || opts[:executionhandlers].strip == '' CPEE::Message::set_workers(opts[:workers]) parallel do CPEE::watch_services(opts[:watchdog_start_off],opts[:redis_url],File.join(opts[:basepath],opts[:redis_path]),opts[:redis_db],opts[:workers],opts[:workers_single],opts[:workers_multi]) EM.add_periodic_timer(opts[:watchdog_frequency]) do ### start services CPEE::watch_services(opts[:watchdog_start_off],opts[:redis_url],File.join(opts[:basepath],opts[:redis_path]),opts[:redis_db],opts[:workers],opts[:workers_single],opts[:workers_multi]) end EM.defer do ### catch all sse connections CPEE::Notifications::sse_distributor(opts) end EM.add_periodic_timer(opts[:sse_keepalive_frequency]) do CPEE::Notifications::sse_heartbeat(opts) end if opts[:dashing_target] cpu_last = 0 idl_last = 0 EM.add_periodic_timer(opts[:dashing_frequency]) do src = `cat /proc/stat | head -n 1`.split("\n") srm = `cat /proc/meminfo`.split("\n") sc = {} sm = {} src.each do |e| x = e.split(' ') sc[x[0]] = x[1..-1].map{|r| r.to_i} end srm.each do |e| x = e.split(/\s+/) sm[x[0].chop] = x[1].to_i end scc = 0 sci = 0 sc.each do |_,e| scc = e[0..4].sum sci = e[3] end cpu_delta = scc - cpu_last cpu_idle = sci - idl_last cpu_used = cpu_delta - cpu_idle cpu_usage = '%.2f' % (100 * cpu_used / cpu_delta.to_f) mem_tot = '%.1f' % (sm['MemTotal']/1024.0) mem_fre = '%.1f' % (sm['MemFree']/1024.0) mem_ava = '%.1f' % (sm['MemAvailable']/1024.0) mem_buc = '%.1f' % ((sm['Buffers'] + sm['Cached'] + sm['SReclaimable'])/1024.0) mem_usd = '%.1f' % ((sm['MemTotal'] - sm['MemFree'] - sm['Buffers'] - sm['Cached'] - sm['SReclaimable'])/1024.0) # puts "CPU usage at #{cpu_usage}%" # puts "Mem usage at #{mem_tot}/#{mem_fre}/#{mem_usd}/#{mem_buc}/#{mem_ava}" content = {} content['cpu_usage'] = cpu_usage content['mem_total'] = mem_tot content['mem_free'] = mem_fre content['mem_available'] = mem_ava content['mem_bufferedandcached'] = mem_buc content['mem_used'] = mem_usd CPEE::Message::send_url(:event,'node/resource_utilization',File.join(opts[:url],'/'),content,File.join(opts[:dashing_target],'/dash/events')) # Keep this as last for our next read idl_last = sci cpu_last = scc end end end cleanup do CPEE::cleanup_services(opts[:watchdog_start_off]) end interface 'main' do run CPEE::Instances, opts if get '*' run CPEE::NewInstance, opts if post 'instance-new' run CPEE::NewInstanceFull, opts if post 'instance-full-new' on resource 'executionhandlers' do run CPEE::ExecutionHandlers, opts if get end on resource '\d+' do |r| run CPEE::Info, opts if get run CPEE::DeleteInstance, opts if delete end end interface 'properties' do |r| id = r[:h]['RIDDL_DECLARATION_PATH'].split('/')[1].to_i use CPEE::Properties::implementation(id.to_i, opts) end interface 'notifications' do |r| id = r[:h]['RIDDL_DECLARATION_PATH'].split('/')[1].to_i use CPEE::Notifications::implementation(id.to_i, opts) end interface 'callbacks' do |r| id = r[:h]['RIDDL_DECLARATION_PATH'].split('/')[1].to_i use CPEE::Callbacks::implementation(id.to_i, opts) end end end
Source
# File lib/cpee/redis.rb, line 18 def self::redis_connect(opts,name=nil) if opts[:redis_cmd].nil? begin if opts[:redis_path] opts[:redis_dyn] = Proc.new { |name| Redis.new(path: opts[:redis_path], db: opts[:redis_db], id: name.gsub(/[^a-zA-Z0-9]/,'-') ) } elsif opts[:redis_url] opts[:redis_dyn] = Proc.new { |name| Redis.new(url: opts[:redis_url], db: opts[:redis_db], id: name.gsub(/[^a-zA-Z0-9]/,'-') ) } else raise end opts[:redis] = opts[:redis_dyn].call name.gsub(/[^a-zA-Z0-9]/,'-') opts[:redis].dbsize rescue puts 'can not connect to redis. check if it is running and cpee is configured correctly ...' exit end else # we always assume file socket if redis is startet locally opts[:redis_dyn] = Proc.new { |name| Redis.new(path: File.join(opts[:basepath],opts[:redis_path]), db: opts[:redis_db].to_i, id: name.gsub(/[^a-zA-Z0-9]/,'-') ) } tried = false begin opts[:redis] = opts[:redis_dyn].call name.gsub(/[^a-zA-Z0-9]/,'-') opts[:redis].dbsize rescue => e puts e res = unless tried rcmd = opts[:redis_cmd] rcmd.gsub! /#redis_path#/, File.join(opts[:basepath],opts[:redis_path]) rcmd.gsub! /#redis_db_dir#/, opts[:basepath] rcmd.gsub! /#redis_db_name#/, opts[:redis_db_name] rcmd.gsub! /#redis_pid#/, File.join(opts[:basepath],opts[:redis_pid]) puts 'starting redis ... it will keep running, just to let you know ...' system rcmd else true end if res tried = true puts 'waiting for successful start ...' sleep 1 retry else puts 'can not start redis. check if cpee is configured correctly ...' exit end end end end
Source
# File lib/cpee/implementation.rb, line 221 def self::watch_services(watchdog_start_off,url,path,db,workers,workers_single,workers_multi) return if watchdog_start_off EM.defer do workers_single.each do |s| s = File.join(__dir__,'..','..','server','routing',s) next if File.exist?(s + '.lock') pid = (File.read(s + '.pid').to_i rescue nil) if (pid.nil? || !(Process.kill(0, pid) rescue false)) cmd = if url.nil? "-p \"#{path}\" -d #{db} -w #{workers} restart 1>/dev/null 2>&1" else "-u \"#{url}\" -d #{db} -w #{workers} restart 1>/dev/null 2>&1" end system "#{s}.rb " + cmd + " 1>/dev/null 2>&1" puts "➡ Service #{File.basename(s)} (#{cmd}) started ..." end end workers_multi.each do |s| s = File.join(__dir__,'..','..','server','routing',s.to_s) next if File.exist?(s + '.lock') (0...workers).each do |w| w = '%02i' % w pid = (File.read(s + '-' + w + '.pid').to_i rescue nil) if (pid.nil? || !(Process.kill(0, pid) rescue false)) cmd = if url.nil? "-p \"#{path}\" -d #{db} -w #{w} restart" else "-u \"#{url}\" -d #{db} -w #{w} restart" end system "#{s}.rb " + cmd + " 1>/dev/null 2>&1" puts "➡ Service #{File.basename(s)}-#{w} (#{cmd}) started ..." end end end end end