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;
}