CGI::Session::FileStore question

Hello,

I was wondering why FileStore converts the values of the session’s hash into
String objects before saving them? (Refer to the methods ‘update’ and
’restore’.) It is frustrating having to convert everything back from
strings all of the time.

Couldn’t we use marshaling and get the actual objects back? This would also
make FileStore work in the same way that MemoryStore does, which seems like
a Good Thing.

Is there a reason it wasn’t done this way in the first place?

Thanks,

Chris

Hi,

···

In message “CGI::Session::FileStore question” on 02/11/07, “Chris” nemo@hellotree.com writes:

I was wondering why FileStore converts the values of the session’s hash into
String objects before saving them? (Refer to the methods ‘update’ and
‘restore’.) It is frustrating having to convert everything back from
strings all of the time.

Couldn’t we use marshaling and get the actual objects back? This would also
make FileStore work in the same way that MemoryStore does, which seems like
a Good Thing.

Is there a reason it wasn’t done this way in the first place?

Marshal may not be what you want before saving data. So do it by
yourself, or wrap CGI::Session::FileStore to do marshaling. It is not
too hard to define something like CGI::Session::PStore. Sufficient
for your homework.

						matz.

Couldn’t we use marshaling and get the actual objects back? This would
also
make FileStore work in the same way that MemoryStore does, which seems like
a Good Thing.

Is there a reason it wasn’t done this way in the first place?

Marshal may not be what you want before saving data. So do it by
yourself, or wrap CGI::Session::FileStore to do marshaling. It is not
too hard to define something like CGI::Session::PStore. Sufficient
for your homework.

matz.

···

----- Original Message -----

My homework? You lost me there…

Anyway, I don’t really understand why Marshal might not be a good idea.
Performance?

Plus, it still seems like FileStore and MemoryStore should be
interchangable, and they definitely aren’t right now.

In any case, I threw something together which seems to work pretty well. It
was saving and loading Fixnums, booleans, Arrays of strings… much better
than saving all of your session data in strings, IMHO.

I also added a function to Session to get the hash object, because there are
other Hash functions I would like to be able to use (‘clear’ and ‘replace’
in particular) on the session data, and because I wanted the program logic
to be as separate as possible from the web interface. Passing a Hash
reference seemed more orthogonal than passing a Session reference. (I might
want to run this from other interfaces in the future.)

So this is what I add to my web scripts:

require ‘cgi.rb’
require ‘cgi/session.rb’
require ‘html/xhtml1.rb’

class CGI
class Session
def getHash
if (!@data)
@data = @dbman.restore
end
@data
end

class FileStore
  def restore
    unless @hash
      @hash = {}
      @f.flock File::LOCK_EX
      @f.rewind
      k = nil
      for line in @f
        line.chomp!
        if (!k)
          k = line
        else
          v = Marshal::load(CGI::unescape(line))
          @hash[CGI::unescape(k)] = v
          k = nil
        end
      end
    end
    @hash
  end

  def update
    return unless @hash
    @f.rewind
    for k,v in @hash
      v = Marshal::dump(v)
      @f.printf "%s\n", CGI::escape(k)
      @f.printf "%s\n", CGI::escape(v)
    end
    @f.truncate @f.tell
  end
end

end
end

Thoughts?

Chris

[snip]

It is not too hard to define something like CGI::Session::PStore.
Sufficient for your homework.

i think this is not directly possible because of = in CGI::Session we have

def =(key, val)
unless @write_lock
@write_lock = true
end
unless @data
@data = @dbman.restore
end
@data[key] = String(val) # <— problem here?
end

seems like this should only be

@data[key] = val

and left to the individual dbman to stringify, or not. i did create a working
PStoreStore by making this change (baby unit test included) but i thought one
should not have to change CGI::Session

require ‘cgi/session’
require ‘pstore’

class CGI
class Session
def =(key, val)
unless @write_lock
@write_lock = true
end
unless @data
@data = @dbman.restore
end
#@data[key] = String(val)
@data[key] = val
end

  class PStoreStore
def check_id(id)
  /[^0-9a-zA-Z]/ =~ id.to_s ? false : true
end

def initialize session, option={}
  dir = option['tmpdir'] || ENV['TMP'] || '/tmp'
  prefix = option['prefix'] || ''
  id = session.session_id
  unless check_id(id)
    raise ArgumentError, "session_id `%s' is invalid" % id
  end
  path = dir+"/"+prefix+id
  path.untaint
  unless File::exist? path
    @hash = {}
  end
  @p = PStore.new path
end

def restore
  unless @hash
    @p.transaction do
      begin
	@hash = @p['hash']
      rescue
	@hash = {}
      end
    end
  end
  @hash
end

def update
  @p.transaction do
      @p['hash'] = @hash
  end
end

def close
  update
end

def delete
  path = @p.path
  File::unlink path
end

  end
end

end

if $0 == FILE
require ‘cgi’
$stdin = open ‘|echo’
cgi = CGI.new
$stdin = STDIN
session = CGI::Session.new cgi, ‘database_manager’ => CGI::Session::PStoreStore
session[‘key’] = {‘k’ => ‘v’}
puts session[‘key’].type
fail unless Hash === session[‘key’]
puts session[‘key’].inspect
fail unless session[‘key’].inspect == ‘{“k”=>“v”}’
end

-ara

···

On Thu, 7 Nov 2002, Yukihiro Matsumoto wrote:

====================================

Ara Howard
NOAA Forecast Systems Laboratory
Information and Technology Services
Data Systems Group
R/FST 325 Broadway
Boulder, CO 80305-3328
Email: ahoward@fsl.noaa.gov
Phone: 303-497-7238
Fax: 303-497-7259
====================================

Hi,

Anyway, I don’t really understand why Marshal might not be a good idea.
Performance?

Patially, yes. You may not want unnecessary data conversion into
marshaled string, if you’re sure about data type to store.

Thoughts?

Great.

						matz.
···

In message “Re: CGI::Session::FileStore question” on 02/11/08, “Chris” nemo@hellotree.com writes:

[snip]

So this is what I add to my web scripts:
[snip]
Thoughts?
[snip]

why modify FileStore? does it make sense to escape/unescape arbitrary objects?
it does for FileStore since all it takes are Strings, but why bother for normal
object key/value?

i was thinking something like :

require ‘cgi/session’
require ‘pstore’

class CGI
class Session
class PStoreStore < FileStore
def initialize cgi, options={}
super
@p = PStore.new @f.path
end
def restore
@p.transaction do
begin
@hash = @p[‘hash’]
rescue
@hash = {}
end
end
@hash
end
def update
@p.transaction do
@p[‘hash’] = @hash
end
end
end
end
end

the other FileStore methods do not need to be overidden.

-a

···

On Fri, 8 Nov 2002, Chris wrote:

====================================

Ara Howard
NOAA Forecast Systems Laboratory
Information and Technology Services
Data Systems Group
R/FST 325 Broadway
Boulder, CO 80305-3328
Email: ahoward@fsl.noaa.gov
Phone: 303-497-7238
Fax: 303-497-7259
====================================

Hi,

···

In message “Re: CGI::Session::FileStore question” on 02/11/09, ahoward ahoward@fsl.noaa.gov writes:

@data[key] = String(val) # <— problem here?

seems like this should only be

@data[key] = val

and left to the individual dbman to stringify, or not. i did create a working
PStoreStore by making this change (baby unit test included) but i thought one
should not have to change CGI::Session

Yeah, maybe. Let me think about it.

						matz.