sub load { my $class = shift; return $class->set_error( "called as instance method") if ref $class; return $class->set_error( "Too many arguments provided to load()") if @_ > 5; my $self = bless { _DATA => { _SESSION_ID => undef, _SESSION_CTIME => undef, _SESSION_ATIME => undef, _SESSION_REMOTE_ADDR => $ENV{REMOTE_ADDR} || "", # # Following two attributes may not exist in every single session, and declaring # them now will force these to get serialized into database, wasting space. But they # are here to remind the coder of their purpose # # _SESSION_ETIME => undef, # _SESSION_EXPIRE_LIST => {} }, # session data _DSN => {}, # parsed DSN params _OBJECTS => {}, # keeps necessary objects _DRIVER_ARGS=> {}, # arguments to be passed to driver _CLAIMED_ID => undef, # id **claimed** by client _STATUS => STATUS_UNSET,# status of the session object _QUERY => undef # query object }, $class; #### # checking for expiration ticker if ( $self->{_DATA}->{_SESSION_ETIME} ) { if ( ($self->{_DATA}->{_SESSION_ATIME} + $self->{_DATA}->{_SESSION_ETIME}) <= time() ) { $self->_set_status( STATUS_EXPIRED | # <-- so client can detect expired sessions STATUS_DELETED ); # <-- session should be removed from database $self->flush(); # <-- flush() will do the actual removal! return $self; } } #### sub flush { my $self = shift; # Would it be better to die or err if something very basic is wrong here? # I'm trying to address the DESTROY related warning # from: http://rt.cpan.org/Ticket/Display.html?id=17541 # return unless defined $self; return unless $self->id; # <-- empty session # neither new, nor deleted nor modified return if !defined($self->{_STATUS}) or $self->{_STATUS} == STATUS_UNSET; if ( $self->_test_status(STATUS_NEW) && $self->_test_status(STATUS_DELETED) ) { $self->{_DATA} = {}; return $self->_unset_status(STATUS_NEW | STATUS_DELETED); } my $driver = $self->_driver(); my $serializer = $self->_serializer(); if ( $self->_test_status(STATUS_DELETED) ) { defined($driver->remove($self->id)) or return $self->set_error( "flush(): couldn't remove session data: " . $driver->errstr ); $self->{_DATA} = {}; # <-- removing all the data, making sure # it won't be accessible after flush() return $self->_unset_status(STATUS_DELETED); } if ( $self->_test_status(STATUS_NEW | STATUS_MODIFIED) ) { my $datastr = $serializer->freeze( $self->dataref ); unless ( defined $datastr ) { return $self->set_error( "flush(): couldn't freeze data: " . $serializer->errstr ); } defined( $driver->store($self->id, $datastr) ) or return $self->set_error( "flush(): couldn't store datastr: " . $driver->errstr); $self->_unset_status(STATUS_NEW | STATUS_MODIFIED); } return 1; }