class RSence::SessionStorage

SessionStorage doesn’t do anything by itself, it’s simply the superclass for SessionManager that handles the persistent storage.

Attributes

accept_requests[R]
db[RW]
db_avail[R]

Public Class Methods

new() click to toggle source
# File lib/rsence/sessionstorage.rb, line 20
def initialize
  ## Session data storage (by ses_id)
  @sessions     = {}

  ## Session id by key
  @session_keys = {}

  ## Session id by cookie key
  @session_cookie_keys = {}

  @clone_origins = {
    # id => [ id, id, id ... ]
  }
  @clone_sources = {
    # id => id
  }
  @clone_targets = {
    # id => [ id, id, id ... ]
  }

  ## Disposable keys (new ses_key each request)
  @config = RSence.config[:session_conf]

  @db_uri = RSence.config[:database][:ses_db]

  if db_test
    @db_avail = true
    db_init
  else
    @db_avail = false
    puts "Warning: Session database is not available. Can't use persistent sessions."
    @id_counter = 0
  end
  @accept_requests = true
  # workaround for the mutexes, would fail in ruby 2.0.0
  @shutdown_save = false
  @shutdown_saved = false
  Thread.new do
    Thread.pass
    until @shutdown_saved
      if @shutdown_save
        store_sessions
        @shutdown_saved = true
      end
      sleep 1
    end
  end
end

Public Instance Methods

expire_session( ses_id ) click to toggle source

Expires a session by its identifier

# File lib/rsence/sessionstorage.rb, line 143
def expire_session( ses_id )

  return unless @sessions.has_key? ses_id

  ses_data = @sessions[ ses_id ]

  # Makes the session invalid for xhr's by deleting its key
  @session_keys.delete( ses_data[:ses_key] )

  # Makes the session invalid for all requests by deleting its cookie key
  @session_cookie_keys.delete( ses_data[:cookie_key] )

  # Deletes the session data itself
  @sessions.delete( ses_id )

  # Removes all ticket-based storage bound to the session
  if @plugins
    @plugins.delegate( :expire_ses, ses_data )
    @plugins.delegate( :expire_ses_id, ses_id )
  end

  # target -> source cleanup
  if @clone_sources.has_key?( ses_id )
    source_id = @clone_sources[ ses_id ]
    @clone_sources.delete( ses_id ) if @clone_sources.has_key?( ses_id )
    @clone_targets[ source_id ].delete( ses_id ) if @clone_targets.has_key?( source_id )
  end

  # source -> targets cleanup
  if @clone_targets.has_key?( ses_id )
    @clone_targets[ ses_id ].each do |target_id|
      @clone_sources.delete( target_id ) if @clone_sources.has_key?( target_id )
    end
    @clone_targets.delete( ses_id ) if @clone_targets.has_key?( ses_id )
  end

  if @db_avail
    remove_session_data( ses_id )
    sleep @config[:db_sleep]
  end
end
expire_sessions() click to toggle source

Expires all sessions that meet the timeout criteria

# File lib/rsence/sessionstorage.rb, line 186
def expire_sessions

  # Loop through all sessions in memory:
  ses_ids = @sessions.keys.clone
  ses_ids.each do |ses_id|
    if @sessions[ses_id] and @sessions[ses_id].has_key?(:timeout)
      timed_out = @sessions[ ses_id ][:timeout] < Time.now.to_i
    else
      timed_out = true
    end
    ## Deletes the session, if the session is too old
    expire_session( ses_id ) if timed_out
  end
end
new_ses_id( cookie_key, ses_key, timeout_secs, user_id=0 ) click to toggle source

Returns a new, unique session identifier by storing the params to the database

# File lib/rsence/sessionstorage.rb, line 72
def new_ses_id( cookie_key, ses_key, timeout_secs, user_id=0 )
  if @db_avail
    return insert_session_data( {
      :cookie_key  => cookie_key,
      :ses_key     => ses_key,
      :ses_timeout => timeout_secs,
      :user_id     => user_id
    } )
  else
    @id_counter += 1
    return @id_counter
  end
end
reset_sessions() click to toggle source

Deletes all rows from rsence_session as well as rsence_uploads

# File lib/rsence/sessionstorage.rb, line 124
def reset_sessions
  unless @db_avail
    puts "Warning: Can't reset sessions: No database!" if RSence.args[:verbose]
    return
  end
  remove_all_session_data
end
restore_session( ses_id, ses_data ) click to toggle source

Restores a single session, called from the database backend

# File lib/rsence/sessionstorage.rb, line 112
def restore_session( ses_id, ses_data )
  ses_key = ses_data[:ses_key]
  @sessions[ses_id] = ses_data
  @session_keys[ ses_key ] = ses_id
  @session_cookie_keys[ ses_data[:cookie_key] ] = ses_id
  if @plugins
    @plugins.delegate( :load_ses_id, ses_id )
    @plugins.delegate( :load_ses, ses_data )
  end
end
restore_sessions() click to toggle source

Restores all saved sessions from db to ram

# File lib/rsence/sessionstorage.rb, line 133
def restore_sessions
  unless @db_avail
    puts "Warning: Can't restore sessions: No database!" if RSence.args[:verbose]
    return
  end
  puts "Restoring sessions..." if RSence.args[:verbose]
  load_session_data
end
shutdown() click to toggle source

Shut-down signal, triggers store_sessions for now

# File lib/rsence/sessionstorage.rb, line 202
def shutdown
  @accept_requests = false
  puts "Session shutdown in progress..." if RSence.args[:verbose]
  @shutdown_save = true
  sleep 1 until @shutdown_saved
  puts "Session shutdown complete." if RSence.args[:verbose]
end
store_sessions() click to toggle source

Stores all sessions to db from ram

# File lib/rsence/sessionstorage.rb, line 87
def store_sessions
  unless @db_avail
    puts "Warning: Can't store sessions: No database!" if RSence.args[:verbose]
    return
  end
  puts "Storing sessions..." if RSence.args[:verbose]
  ses_ids = @sessions.keys.clone
  ses_ids.each do |ses_id|
    ses_data = @sessions[ses_id]
    next if ses_data.nil?
    ses_data = @sessions[ses_id].clone
    if @plugins
      @plugins.delegate( :dump_ses, ses_data )
      @plugins.delegate( :dump_ses_id, ses_id )
    end
    begin
      store_session_data( ses_data )
      sleep @config[:db_sleep]
    rescue => e
      warn "Unable to dump session: #{ses_id}, because: #{e.message}"
    end
  end
end