Browse code

Start rewriting single-thread app to multi-thread

Cinan Rakosnik authored on 02/01/2013 at 19:29:26
Showing 4 changed files
... ...
@@ -4,8 +4,7 @@ require_relative "rubysermon/mod_template"
4 4
 require_relative "rubysermon/configurator"
5 5
 require_relative "rubysermon/db"
6 6
 require_relative "rubysermon/output_driver_template"
7
-
8
-require "date"
7
+require_relative "rubysermon/result_grabber"
9 8
 
10 9
 module Rubysermon
11 10
 	LIB_PATH = File.expand_path(File.dirname(__FILE__))
... ...
@@ -30,8 +29,6 @@ module Rubysermon
30 30
 			require "#{LIB_PATH}/rubysermon/output_drivers/#{@config[:output].downcase}"
31 31
 			@output_driver	= (Rubysermon.const_get(@config[:output])).new
32 32
 
33
-			@results		= []
34
-
35 33
 			check_args()
36 34
 		end
37 35
 
... ...
@@ -44,9 +41,11 @@ module Rubysermon
44 44
 			end
45 45
 
46 46
 			#start_db()
47
-			start_fetch_process_sleep_cycle()
47
+			start_result_processor()
48 48
 		end
49 49
 
50
+		#TODO destructor na ukoncenie threadov
51
+
50 52
 		private
51 53
 
52 54
 		def check_args
... ...
@@ -95,29 +94,12 @@ module Rubysermon
95 95
 			@db = DB.new(@config[:db_path])
96 96
 		end
97 97
 
98
-		def start_fetch_process_sleep_cycle
99
-			while true
100
-				current_time = DateTime.now()
101
-				@running_mods.each do |mod|
102
-					save_results(mod, current_time, mod.results())
103
-					notify() if mod.notify?
104
-				end
105
-				make_output()
106
-				sleep @config[:repeat]
107
-			end
108
-		end
109
-
110
-		def save_results(mod, time, result)
111
-			#results should be specialized object
112
-			mod_results = @results[mod]
113
-
114
-			if mod_results.size >= @config[:history_size]
115
-				mod_results.slice!(@config[:history_size], @results[mod].size)
116
-			end
98
+		def start_result_processor
99
+			@result_grabber = ResultGrabber.new(@running_mods, @config[:repeat])
100
+			@result_grabber.run()
117 101
 
118
-			#shift() and push() operations have O(1) complexity.
119
-			mod_results.shift()
120
-			mod_results.push([time: time, value: result])
102
+			#TODO spravit event machine na pytanie sa, ci netreba poslat notify
103
+			#Kazdy cas interval sa dozadovat grabbera na vysledky.
121 104
 		end
122 105
 
123 106
 		def notify
124 107
new file mode 100644
... ...
@@ -0,0 +1,72 @@
0
+require "date"
1
+require "monitor"
2
+
3
+module Rubysermon
4
+
5
+	# Nastartuje nekonecny cyklus v treade, ktory si bude volat
6
+	# moduly (ich vysledky), tie bude ukladat do svojho hasha,
7
+	# pripadne vysle signal na notify.
8
+	#
9
+	class ResultGrabber
10
+
11
+		def initialize(mods, sleep)
12
+			@results = {}
13
+			@grabber_thread = nil
14
+
15
+			@running_mods = mods
16
+			@sleep = sleep
17
+
18
+			@monitor = Monitor.new
19
+		end
20
+
21
+		def run
22
+			@grabber_thread = Thread.new do
23
+				while true
24
+					current_time = DateTime.now()
25
+					@running_mods.each do |mod|
26
+						#$stdout.puts mod.results()
27
+						save_results(mod.class, current_time, mod.results())
28
+					end
29
+					sleep @sleep
30
+				end
31
+			end
32
+		end
33
+
34
+		def stop
35
+			@grabber_thread.exit()
36
+		end
37
+
38
+		def get_last_results
39
+			results = []
40
+			@monitor.synchronize do
41
+				results = get_results()
42
+				empty_results()
43
+			end
44
+
45
+			results
46
+		end
47
+
48
+		private
49
+
50
+		def save_results(mod_name, time, result)
51
+			mod_results = @results[mod_name].to_a
52
+
53
+			@monitor.synchronize do
54
+				#shift() and push() operations have O(1) complexity.
55
+				mod_results.shift()
56
+				mod_results.push({time: time, value: result})
57
+
58
+				@results[mod_name] = mod_results
59
+			end
60
+		end
61
+
62
+		def get_results
63
+			#TODO samostatny objekt vysledkov a nie pole
64
+			@results
65
+		end
66
+
67
+		def empty_results
68
+			@results = {}
69
+		end
70
+	end
71
+end
0 72
\ No newline at end of file
1 73
new file mode 100644
... ...
@@ -0,0 +1,31 @@
0
+require_relative '../../test_helper.rb'
1
+
2
+class ResultGrabber_test < MiniTest::Unit::TestCase
3
+
4
+	def test_run_cycle
5
+		loaded_mods = [Rubysermon::ModLoader.load('cpu')]
6
+		rp = Rubysermon::ResultGrabber.new(loaded_mods, 1)
7
+
8
+		rp.run()
9
+
10
+		try_count = 0
11
+		until ((results = rp.get_last_results()) != {}) do
12
+			try_count = try_count + 1
13
+
14
+			if try_count > 2
15
+				assert false
16
+			end
17
+
18
+			sleep(1) #neda sa to spravit nejak inak?
19
+		end
20
+
21
+		assert(results.length > 0)
22
+
23
+		first_result_pair = results.first[1][0]
24
+		assert_equal(first_result_pair[:time].class.to_s, "DateTime")
25
+
26
+		#todo a teraz nech sa zoberie dalsi vysledok a nech je iny nez ten prvy
27
+
28
+		rp.stop()
29
+	end
30
+end
0 31
\ No newline at end of file
... ...
@@ -62,22 +62,4 @@ class Rubysermon_test < MiniTest::Unit::TestCase
62 62
 
63 63
 		assert_equal("Wrong config file path. Exiting.", exception.message)
64 64
 	end
65
-
66
-	def test_results_cpu
67
-		skip("Use thread instead of sleep")
68
-		#depends on cpu module
69
-
70
-		ARGV[0] = "#{TEST_PATH}/fixtures/dummy_results.json"
71
-		@app = Rubysermon::App.new
72
-
73
-
74
-		thread = Thread.new do
75
-			@app.run()
76
-		end
77
-
78
-		sleep(2)
79
-		thread.kill()
80
-
81
-		#todo check stdout
82
-	end
83 65
 end
84 66
\ No newline at end of file