our
$VERSION
=
'1.3.16'
;
our
@ISA
=
qw(Apache::Session)
;
our
$redis
=
$Apache::Session::Browseable::Store::Redis::redis
;
sub
populate {
my
$self
=
shift
;
$self
->{object_store} = new Apache::Session::Browseable::Store::Redis
$self
;
$self
->{lock_manager} = new Apache::Session::Lock::Null
$self
;
$self
->{generate} = \
&Apache::Session::Generate::SHA256::generate
;
$self
->{validate} = \
&Apache::Session::Generate::SHA256::validate
;
$self
->{serialize} = \
&Apache::Session::Serialize::JSON::serialize
;
$self
->{unserialize} = \
&Apache::Session::Serialize::JSON::unserialize
;
return
$self
;
}
sub
unserialize {
my
$session
=
shift
;
my
$tmp
= {
serialized
=>
$session
};
Apache::Session::Serialize::JSON::unserialize(
$tmp
);
return
$tmp
->{data};
}
sub
searchOn {
my
(
$class
,
$args
,
$selectField
,
$value
,
@fields
) =
@_
;
my
%res
= ();
if
(
$class
->isIndexed(
$args
,
$selectField
) ) {
my
$redisObj
=
$class
->_getRedis(
$args
);
my
@keys
=
$redisObj
->smembers(
"${selectField}_$value"
);
foreach
my
$k
(
@keys
) {
next
unless
(
$k
);
my
$tmp
=
$redisObj
->get(
$k
);
next
unless
(
$tmp
);
eval
{
$tmp
= unserialize(
$tmp
);
if
(
@fields
) {
$res
{
$k
}->{
$_
} =
$tmp
->{
$_
}
foreach
(
@fields
);
}
else
{
$res
{
$k
} =
$tmp
;
}
};
if
($@) {
print
STDERR
"Error in session $k: $@\n"
;
delete
$res
{
$k
};
}
}
}
else
{
$class
->get_key_from_all_sessions(
$args
,
sub
{
my
$entry
=
shift
;
my
$id
=
shift
;
return
undef
unless
(
defined
$entry
->{
$selectField
}
and
$entry
->{
$selectField
} eq
$value
);
if
(
@fields
) {
$res
{
$id
}->{
$_
} =
$entry
->{
$_
}
foreach
(
@fields
);
}
else
{
$res
{
$id
} =
$entry
;
}
undef
;
}
);
}
return
\
%res
;
}
sub
searchOnExpr {
my
(
$class
,
$args
,
$selectField
,
$value
,
@fields
) =
@_
;
my
%res
;
if
(
$class
->isIndexed(
$args
,
$selectField
) ) {
my
$redisObj
=
$class
->_getRedis(
$args
);
my
$cursor
= 0;
do
{
my
(
$new_cursor
,
$sets
) =
$redisObj
->scan(
$cursor
,
MATCH
=>
"${selectField}_$value"
);
foreach
my
$set
(
@$sets
) {
next
unless
$redisObj
->type(
$set
) eq
'set'
;
my
@keys
=
$redisObj
->smembers(
$set
);
foreach
my
$k
(
@keys
) {
my
$v
=
$redisObj
->get(
$k
);
next
unless
$v
;
my
$tmp
= unserialize(
$v
);
if
(
$tmp
) {
$res
{
$k
} =
$class
->extractFields(
$tmp
,
@fields
);
}
}
}
$cursor
=
$new_cursor
;
}
while
(
$cursor
!= 0 );
}
else
{
$value
=
quotemeta
(
$value
);
$value
=~ s/\\\*/\.\*/g;
$value
=
qr/^$value$/
;
$class
->get_key_from_all_sessions(
$args
,
sub
{
my
(
$entry
,
$id
) =
@_
;
return
undef
unless
(
$entry
->{
$selectField
} =~
$value
);
$res
{
$id
} =
$class
->extractFields(
$entry
,
@fields
);
undef
;
}
);
}
return
\
%res
;
}
sub
deleteIfLowerThan {
my
(
$class
,
$args
,
$rule
) =
@_
;
my
$deleted
= 0;
my
$redisObj
=
$class
->_getRedis(
$args
);
$class
->get_key_from_all_sessions(
$args
,
sub
{
my
(
$v
,
$k
) =
@_
;
if
(
$rule
->{not} ) {
foreach
(
keys
%{
$rule
->{not} } ) {
if
(
defined
(
$v
->{
$_
} ) and
$v
->{
$_
} eq
$rule
->{not}->{
$_
}) {
return
();
}
}
}
if
(
$rule
->{or} ) {
foreach
(
keys
%{
$rule
->{or} } ) {
if
(
defined
(
$v
->{
$_
} ) and
$v
->{
$_
} <
$rule
->{or}->{
$_
} )
{
$redisObj
->del(
$k
);
$deleted
++;
return
();
}
}
}
elsif
(
$rule
->{and} ) {
my
$res
= 1;
foreach
(
keys
%{
$rule
->{and} } ) {
$res
= 0
unless
defined
(
$v
->{
$_
} )
and
$v
->{
$_
} <
$rule
->{not}->{
$_
};
}
if
(
$res
) {
$redisObj
->del(
$k
);
$deleted
++;
}
}
return
();
},
);
return
( 1,
$deleted
);
}
sub
extractFields {
my
(
$class
,
$entry
,
@fields
) =
@_
;
my
$res
;
if
(
@fields
) {
$res
->{
$_
} =
$entry
->{
$_
}
foreach
(
@fields
);
}
else
{
$res
=
$entry
;
}
return
$res
;
}
sub
isIndexed {
my
(
$class
,
$args
,
$field
) =
@_
;
my
$indexes
=
ref
(
$args
->{Index} ) ?
$args
->{Index} : [
split
/\s+/,
$args
->{Index} ];
return
grep
{
$_
eq
$field
}
@$indexes
;
}
sub
isLlngKey {
my
(
$class
,
$args
,
$name
) =
@_
;
my
$expr
=
$args
->{keysRe} ||
'^[0-9a-f]{32,}$'
;
return
(
$name
=~ /
$expr
/o );
}
sub
get_key_from_all_sessions {
my
(
$class
,
$args
,
$data
) =
@_
;
my
%res
;
my
$redisObj
=
$class
->_getRedis(
$args
);
my
$cursor
= 0;
do
{
my
(
$new_cursor
,
$keys
) =
$redisObj
->scan(
$cursor
);
foreach
my
$k
(
@$keys
) {
next
unless
$class
->isLlngKey(
$args
,
$k
);
next
unless
$redisObj
->type(
$k
) eq
'string'
;
eval
{
my
$v
=
$redisObj
->get(
$k
);
next
unless
$v
;
my
$tmp
= unserialize(
$v
);
if
(
ref
(
$data
) eq
'CODE'
) {
$tmp
=
&$data
(
$tmp
,
$k
);
$res
{
$k
} =
$tmp
if
(
defined
(
$tmp
) );
}
elsif
(
$data
) {
$data
= [
$data
]
unless
(
ref
(
$data
) );
$res
{
$k
}->{
$_
} =
$tmp
->{
$_
}
foreach
(
@$data
);
}
else
{
$res
{
$k
} =
$tmp
;
}
};
if
($@) {
print
STDERR
"Error in session $k: $@\n"
;
}
}
$cursor
=
$new_cursor
;
}
while
(
$cursor
!= 0 );
return
\
%res
;
}
sub
_getRedis {
my
$class
=
shift
;
my
$args
=
shift
;
$args
->{encoding} =
undef
if
(
$args
->{encoding}
and
$args
->{encoding} eq
"undef"
);
if
(
$args
->{sentinels}
and
ref
$args
->{sentinels} ne
'ARRAY'
)
{
$args
->{sentinels} =
[
split
/[,\s]+/,
$args
->{sentinels} ];
}
my
$redisObj
=
$redis
->new( %{
$args
} );
$redisObj
->
select
(
$args
->{database} )
if
defined
$args
->{database};
return
$redisObj
;
}
1;