Fixed race condition in Sessions.create().

This commit is contained in:
Martin Edenhofer 2015-05-03 11:22:48 +02:00
parent d8d506ea44
commit 6d5a02fd80

View file

@ -10,8 +10,7 @@ module Sessions
end
# get working directories
@path = @root + '/tmp/websocket'
@pid = @root + '/tmp/pids/sessionworker.pid'
@path = "#{@root}/tmp/websocket"
# create global vars for threads
@@client_threads = {}
@ -29,18 +28,27 @@ returns
=end
def self.create( client_id, session, meta )
path = @path + '/' + client_id.to_s
FileUtils.mkpath path
path = "#{@path}/#{client_id}"
path_tmp = "#{@path}/tmp/#{client_id}"
session_file = "#{path_tmp}/session"
# collect session data
meta[:last_ping] = Time.new.to_i.to_s
data = {
user: session,
meta: meta,
}
content = data.to_s
File.open( path + '/session', 'wb' ) { |file|
content = data.to_json
# store session data in session file
FileUtils.mkpath path_tmp
File.open( session_file, 'wb' ) { |file|
file.write content
}
# move to destination directory
FileUtils.mv( path_tmp, path )
# send update to browser
if session && session['id']
self.send(
@ -66,7 +74,7 @@ returns
=end
def self.sessions
path = @path + '/'
path = "#{@path}/"
# just make sure that spool path exists
if !File::exist?( path )
@ -75,7 +83,10 @@ returns
data = []
Dir.foreach( path ) do |entry|
next if entry == '.' || entry == '..' || entry == 'spool'
next if entry == '.'
next if entry == '..'
next if entry == 'tmp'
next if entry == 'spool'
data.push entry.to_s
end
data
@ -153,7 +164,7 @@ returns
=end
def self.destory( client_id )
path = @path + '/' + client_id.to_s
path = "#{@path}/#{client_id}"
FileUtils.rm_rf path
end
@ -171,7 +182,7 @@ returns
def self.destory_idle_sessions(idle_time_in_sec = 240)
list_of_closed_sessions = []
clients = Sessions.list
clients = Sessions.list
clients.each { |client_id, client|
if !client[:meta] || !client[:meta][:last_ping] || ( client[:meta][:last_ping].to_i + idle_time_in_sec ) < Time.now.to_i
list_of_closed_sessions.push client_id
@ -196,10 +207,11 @@ returns
def self.touch( client_id )
data = self.get(client_id)
return false if !data
path = @path + '/' + client_id.to_s
path = "#{@path}/#{client_id}"
data[:meta][:last_ping] = Time.new.to_i.to_s
content = data.to_json
File.open( path + '/session', 'wb' ) { |file|
file.write data.to_json
file.write content
}
true
end
@ -225,12 +237,12 @@ returns
=end
def self.get( client_id )
session_dir = @path + '/' + client_id.to_s
session_file = session_dir + '/session'
data = nil
session_dir = "#{@path}/#{client_id}"
session_file = "#{session_dir}/session"
data = nil
if !File.exist? session_file
self.destory(client_id)
puts "ERROR: missing session file for '#{client_id.to_s}', remove session."
puts "ERROR: missing session file for '#{client_id}', remove session."
return
end
begin
@ -266,14 +278,14 @@ returns
=end
def self.send( client_id, data )
path = @path + '/' + client_id.to_s + '/'
filename = 'send-' + Time.new().to_f.to_s# + '-' + rand(99999999).to_s
check = true
count = 0
path = "#{@path}/#{client_id}/"
filename = "send-#{ Time.new().to_f }"
check = true
count = 0
while check
if File::exist?( path + filename )
count += 1
filename = filename + '-' + count
filename = "#{filename}-#{count}"
else
check = false
end
@ -361,15 +373,16 @@ returns
=end
def self.queue( client_id )
path = @path + '/' + client_id.to_s + '/'
data = []
path = "#{@path}/#{client_id}/"
data = []
files = []
Dir.foreach( path ) {|entry|
next if entry == '.' || entry == '..'
next if entry == '.'
next if entry == '..'
files.push entry
}
files.sort.each {|entry|
filename = path + '/' + entry
filename = "#{path}/#{entry}"
if /^send/.match( entry )
data.push Sessions.queue_file_read( path, entry )
end
@ -378,10 +391,9 @@ returns
end
def self.queue_file_read( path, filename )
file_old = path + filename
file_new = path + 'a-' + filename
file_old = "#{path}#{filename}"
file_new = "#{path}a-#{filename}"
FileUtils.mv( file_old, file_new )
data = nil
all = ''
File.open( file_new, 'rb' ) { |file|
all = file.read
@ -390,15 +402,17 @@ returns
JSON.parse( all )
end
def self.spool_cleanup
path = @path + '/spool/'
def self.cleanup
path = "#{@path}/spool/"
FileUtils.rm_rf path
path = "#{@path}/tmp/"
FileUtils.rm_rf path
end
def self.spool_create( msg )
path = @path + '/spool/'
path = "#{@path}/spool/"
FileUtils.mkpath path
file = Time.new.to_f.to_s + '-' + rand(99_999).to_s
file = "#{Time.new.to_f}-#{rand(99_999)}"
File.open( path + '/' + file, 'wb' ) { |file|
data = {
msg: msg,
@ -409,20 +423,21 @@ returns
end
def self.spool_list( timestamp, current_user_id )
path = @path + '/spool/'
path = "#{@path}/spool/"
FileUtils.mkpath path
data = []
data = []
to_delete = []
files = []
files = []
Dir.foreach( path ) {|entry|
next if entry == '.' || entry == '..'
next if entry == '.'
next if entry == '..'
files.push entry
}
files.sort.each {|entry|
filename = path + '/' + entry
filename = "#{path}/#{entry}"
next if !File::exist?( filename )
File.open( filename, 'rb' ) { |file|
all = file.read
all = file.read
spool = JSON.parse( all )
begin
message_parsed = JSON.parse( spool['msg'] )
@ -433,7 +448,7 @@ returns
# ignore message older then 48h
if spool['timestamp'] + (2 * 86_400) < Time.now.to_i
to_delete.push path + '/' + entry
to_delete.push "#{path}/#{entry}"
next
end