-
Notifications
You must be signed in to change notification settings - Fork 2
/
store.rb
114 lines (100 loc) · 3.64 KB
/
store.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
require 'dm-core'
module DataMapper
module Session
module Abstract
class Store
def initialize(app, options, id_generator)
@mutex = Mutex.new
if options.delete(:cache)
@@cache = if RUBY_PLATFORM =~ /java/
begin
# to avoid memory leaks use a hashmap which clears
# itself on severe memory shortage
require 'softhashmap'
m = Java.SoftHashMap.new
def m.delete(key)
remove(key)
end
m
rescue
# fallback to non java Hash
{}
end
else
{}
end
@@semaphore = Mutex.new
else
@@cache = nil unless self.class.class_variable_defined? :@@cache
end
@@session_class = options.delete(:session_class) || Session unless (self.class.class_variable_defined?(:@@session_class) and @@session_class)
@id_generator = id_generator
end
def get_session(env, sid)
@mutex.lock if env['rack.multithread']
if sid
session =
if @@cache
@@cache[sid] || @@session_class.get(sid)
else
@@session_class.get(sid)
end
end
unless sid and session
env['rack.errors'].puts("Session '#{sid.inspect}' not found, initializing...") if $VERBOSE and not sid.nil?
sid = @id_generator.call
session = @@session_class.create(:session_id => sid)
@@cache[sid] = session if @@cache
end
#session.instance_variable_set('@old', {}.merge(session))
return [sid, session.data]
ensure
@mutex.unlock if env['rack.multithread']
end
def set_session(env, sid, session_data, options)
@mutex.lock if env['rack.multithread']
session =
if @@cache
@@cache[sid] || @@session_class.get(sid)
else
@@session_class.get(sid)
end
return false if session.nil?
if options[:renew] or options[:drop]
@@cache.delete(sid) if @@cache
session.destroy
return false if options[:drop]
sid = @id_generator.call
session = @@session_class.create(:session_id => sid)
@@cache[sid] = session if @@cache
end
# old_session = new_session.instance_variable_get('@old') || {}
# session = merge_sessions session_id, old_session, new_session, session
session.data = session_data
if session.save
session.session_id
else
false
end
ensure
@mutex.unlock if env['rack.multithread']
end
end
class Session
include ::DataMapper::Resource
def self.name
"session"
end
property :session_id, String, :key => true
property :data, Text, :nullable => false, :default => ::Base64.encode64(Marshal.dump({}))
property :updated_at, DateTime, :nullable => true, :index => true
def data=(data)
attribute_set(:data, ::Base64.encode64(Marshal.dump(data)))
end
def data
Marshal.load(::Base64.decode64(attribute_get(:data)))
end
end
end
end
end