From 6bca153e918960635d0ec8046386a0ee32bd6ca9 Mon Sep 17 00:00:00 2001 From: Pawel Boguslawski Date: Tue, 13 Apr 2021 15:44:49 +0200 Subject: [PATCH 01/12] Memcached cache module added Author-Change-Id: IB#1046574 --- CHANGES.md | 3 + Kernel/Config/Files/XML/Framework.xml | 19 +++ Kernel/System/Cache/Memcached.pm | 234 ++++++++++++++++++++++++++ 3 files changed, 256 insertions(+) create mode 100644 Kernel/System/Cache/Memcached.pm diff --git a/CHANGES.md b/CHANGES.md index e84cd1797d8..2679ea3f637 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,3 +1,6 @@ +# 6.5.2 ????-??-?? + - 2023-05-02 Added memcached cache module. + # 6.5.1 2023-03-09 - 2023-02-28 Added options tickets-created-before-date and tickets-created-before-days to console command Admin::Article::StorageSwitch. - 2023-02-28 Fixed encoding of postmaster filter name in AdminPostMasterFilter. diff --git a/Kernel/Config/Files/XML/Framework.xml b/Kernel/Config/Files/XML/Framework.xml index 2aed77be706..08d99819cb3 100644 --- a/Kernel/Config/Files/XML/Framework.xml +++ b/Kernel/Config/Files/XML/Framework.xml @@ -8435,6 +8435,25 @@ via the Preferences button after logging in. + + Defines the memcached servers. + Core::Cache + + + 127.0.0.1:11211 + + + + + Defines all the (additional) memcached parameters. + Core::Cache + + + 16777216 + 1 + + + Defines the config options for the autocompletion feature. Frontend::Agent diff --git a/Kernel/System/Cache/Memcached.pm b/Kernel/System/Cache/Memcached.pm new file mode 100644 index 00000000000..be31e2ca62c --- /dev/null +++ b/Kernel/System/Cache/Memcached.pm @@ -0,0 +1,234 @@ +# -- +# Kernel/System/Cache/Memcached.pm - Memcached module for OTRS cache +# Copyright (C) 2014-2021 Informatyka Boguslawski sp. z o.o. sp.k., http://www.ib.pl/ +# Based on: +# http://code.google.com/p/memcached/wiki/NewProgrammingTricks#Namespacing +# FileStorable.pm by OTRS AG, http://otrs.com/ +# Memcached.pm by c.a.p.e. IT GmbH, http://www.cape-it.de +# -- +# This software comes with ABSOLUTELY NO WARRANTY. For details, see +# the enclosed file COPYING for license information (GPL). If you +# did not receive this file, see https://www.gnu.org/licenses/gpl-3.0.txt. +# -- + +package Kernel::System::Cache::Memcached; + +use strict; +use warnings; + +use Cache::Memcached::Fast; +use Digest::MD5 qw(); +use Time::HiRes qw(); + +our @ObjectDependencies = ( + 'Kernel::Config', + 'Kernel::System::Encode', + 'Kernel::System::Log', +); + +sub new { + my ( $Type, %Param ) = @_; + + # Allocate new hash for object. + my $Self = {}; + bless( $Self, $Type ); + + # Get config object. + my $ConfigObject = $Kernel::OM->Get('Kernel::Config'); + + # Get memcached connection parameters and open connection to cache. + $Self->{Config} = $ConfigObject->Get('Cache::Module::Memcached'); + if ($Self->{Config} && $Self->{Config}->{Servers} && $Self->{Config}->{Parameters}) { + my $InitParams = { + servers => $Self->{Config}->{Servers}, + %{ $Self->{Config}->{Parameters} }, + }; + + $Self->{MemcachedObject} = Cache::Memcached::Fast->new($InitParams); + + if (!$Self->{MemcachedObject}) { + $Kernel::OM->Get('Kernel::System::Log')->Log( + Priority => 'error', + Message => "Unable to initialize memcached connector: $!", + ); + } + } + else { + $Kernel::OM->Get('Kernel::System::Log')->Log( + Priority => 'error', + Message => 'Memcached enabled but no valid Cache::Module::Memcached configuration found!', + ); + } + + return $Self; +} + +sub Set { + my ( $Self, %Param ) = @_; + + # Check needed params. + for my $Needed (qw(Type Key Value TTL)) { + if ( !defined $Param{$Needed} ) { + $Kernel::OM->Get('Kernel::System::Log')->Log( + Priority => 'error', + Message => "Need $Needed!" + ); + return; + } + } + + return if !$Self->{MemcachedObject}; + + # Get memcached key name for given Type and Key. + my $MemcachedKeyName = $Self->_getMemcachedKeyName( + %Param, + InitNamespaceOnError => 1, + ); + return if !$MemcachedKeyName; + + # Problems occured when using absolute TTLs /time()+$Param{TTL}/ and + # relative TTLs greater than memcached threshold /$Param{TTL}>2592000/ + # so we'll limit TTLs to 2592000 (30 days) here. Probably bug in + # Cache::Memcached::Fast. For TTL value details see memcached proto spec + # https://github.com/memcached/memcached/blob/master/doc/protocol.txt + if ( $Param{TTL} > 2592000 ) { + $Param{TTL} = 2592000; + } + + return $Self->{MemcachedObject}->set( + $MemcachedKeyName, + $Param{Value}, + $Param{TTL} + ); +} + +sub Get { + my ( $Self, %Param ) = @_; + + # Check needed params. + for my $Needed (qw(Type Key)) { + if ( !defined $Param{$Needed} ) { + $Kernel::OM->Get('Kernel::System::Log')->Log( + Priority => 'error', + Message => "Need $Needed!" + ); + return; + } + } + + return if !$Self->{MemcachedObject}; + + # Get memcached key name for given Type and Key; do not initialize + # namespace in case of namespace reading error (namespace init after + # simple communication errors would cause same effect as CleanUp + # on this object data type). + my $MemcachedKeyName = $Self->_getMemcachedKeyName( + %Param, + InitNamespaceOnError => 0, + ); + return if !$MemcachedKeyName; + + return $Self->{MemcachedObject}->get($MemcachedKeyName); +} + +sub Delete { + my ( $Self, %Param ) = @_; + + # Check needed params. + for my $Needed (qw(Type Key)) { + if ( !defined $Param{$Needed} ) { + $Kernel::OM->Get('Kernel::System::Log')->Log( + Priority => 'error', + Message => "Need $Needed!" + ); + return; + } + } + + return if ( !$Self->{MemcachedObject} ); + + # Get memcached key name for given Type and Key. + my $MemcachedKeyName = $Self->_getMemcachedKeyName( + %Param, + InitNamespaceOnError => 1, + ); + return if !$MemcachedKeyName; + + return $Self->{MemcachedObject}->delete($MemcachedKeyName); +} + +sub CleanUp { + my ( $Self, %Param ) = @_; + + return if !$Self->{MemcachedObject}; + + # Memcached expires data automatically. + return 1 if $Param{Expired}; + + if ( $Param{Type} ) { + # Invalidate namespace in cache by incrementing it; memcached will + # take care of removing invalidated keys (LRU). In case of incrementing + # error try to create new namespace. + if (!$Self->{MemcachedObject}->incr('Namespace:' . $Param{Type}, 1)) { + my $Miliseconds = int(Time::HiRes::gettimeofday() * 1000); + if (!$Self->{MemcachedObject}->add('Namespace:' . $Param{Type}, $Miliseconds)) { + $Kernel::OM->Get('Kernel::System::Log')->Log( + Priority => 'error', + Message => "Error deleting objects of type $Param{Type} in memcached!", + ); + } + } + + return 1; + } + else { + # Flush all the cache if no type specified. + return $Self->{MemcachedObject}->flush_all(); + } +} + +=item _getMemcachedKeyName() + +Use MD5 digest of Type::Namespace::Key for memcached key (memcached key max +length is 250). Namespace for given cache object type is taken from cache. +New namespace is created if namespace is not found. For this algo idea see +http://code.google.com/p/memcached/wiki/NewProgrammingTricks#Namespacing +We use miliseconds not microseconds because overflow in the "incr" memcached +command wraps around the 64 bit mark. + +Returns mamcached key name if determined or nothing on error: + + my $PreparedKey = $Self->_getMemcachedKeyName( + Type => 'CacheObjectTypeName', + Key => 'KeyName', + InitNamespaceOnError => 0, # set 1 to initialize namespace if cannot be read + ); + +=cut + +sub _getMemcachedKeyName { + my ( $Self, %Param ) = @_; + + # Try to find namespace for given key object type. + my $MemcachedNamespace = $Self->{MemcachedObject}->get('Namespace:' . $Param{Type}); + + # If namespace not found - if allowed, create new one using miliseconds since the epoch. + if (!$MemcachedNamespace && $Param{InitNamespaceOnError}) { + my $Miliseconds = int(Time::HiRes::gettimeofday() * 1000); + + if ($Self->{MemcachedObject}->add('Namespace:' . $Param{Type}, $Miliseconds)) { + # Get namespace from cache in case it was updated meanwhile. + $MemcachedNamespace = $Self->{MemcachedObject}->get('Namespace:' . $Param{Type}); + } + } + + # Return nothing if namespace cannot be found. + return if !$MemcachedNamespace; + + my $MemcachedKeyName = $Param{Type} . ':' . $MemcachedNamespace . ':' . $Param{Key}; + $Kernel::OM->Get('Kernel::System::Encode')->EncodeOutput( \$MemcachedKeyName ); + $MemcachedKeyName = Digest::MD5::md5_hex($MemcachedKeyName); + return $MemcachedKeyName; +} + +1; From 2149e86bccf6f4077a335e2843a6e98779891b73 Mon Sep 17 00:00:00 2001 From: Pawel Boguslawski Date: Tue, 2 May 2023 09:34:15 +0200 Subject: [PATCH 02/12] Function name standarized Fixes: 6bca153e918960635d0ec8046386a0ee32bd6ca9 Author-Change-Id: IB#1046574 --- Kernel/System/Cache/Memcached.pm | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/Kernel/System/Cache/Memcached.pm b/Kernel/System/Cache/Memcached.pm index be31e2ca62c..d5e29054373 100644 --- a/Kernel/System/Cache/Memcached.pm +++ b/Kernel/System/Cache/Memcached.pm @@ -80,7 +80,7 @@ sub Set { return if !$Self->{MemcachedObject}; # Get memcached key name for given Type and Key. - my $MemcachedKeyName = $Self->_getMemcachedKeyName( + my $MemcachedKeyName = $Self->_GetMemcachedKeyName( %Param, InitNamespaceOnError => 1, ); @@ -122,7 +122,7 @@ sub Get { # namespace in case of namespace reading error (namespace init after # simple communication errors would cause same effect as CleanUp # on this object data type). - my $MemcachedKeyName = $Self->_getMemcachedKeyName( + my $MemcachedKeyName = $Self->_GetMemcachedKeyName( %Param, InitNamespaceOnError => 0, ); @@ -148,7 +148,7 @@ sub Delete { return if ( !$Self->{MemcachedObject} ); # Get memcached key name for given Type and Key. - my $MemcachedKeyName = $Self->_getMemcachedKeyName( + my $MemcachedKeyName = $Self->_GetMemcachedKeyName( %Param, InitNamespaceOnError => 1, ); @@ -187,7 +187,7 @@ sub CleanUp { } } -=item _getMemcachedKeyName() +=item _GetMemcachedKeyName() Use MD5 digest of Type::Namespace::Key for memcached key (memcached key max length is 250). Namespace for given cache object type is taken from cache. @@ -198,7 +198,7 @@ command wraps around the 64 bit mark. Returns mamcached key name if determined or nothing on error: - my $PreparedKey = $Self->_getMemcachedKeyName( + my $PreparedKey = $Self->_GetMemcachedKeyName( Type => 'CacheObjectTypeName', Key => 'KeyName', InitNamespaceOnError => 0, # set 1 to initialize namespace if cannot be read @@ -206,7 +206,7 @@ Returns mamcached key name if determined or nothing on error: =cut -sub _getMemcachedKeyName { +sub _GetMemcachedKeyName { my ( $Self, %Param ) = @_; # Try to find namespace for given key object type. From 583cc15fd60c94c8754ddcf617c9ad355cfcf92b Mon Sep 17 00:00:00 2001 From: Pawel Boguslawski Date: Tue, 13 Apr 2021 17:05:02 +0200 Subject: [PATCH 03/12] Fixed comment style Fixed comment style to satisfy code policy. Fixes: f4eae1ddf4bc7d047d66a560584995ed1c6e5672 Author-Change-Id: IB#1046574 --- Kernel/System/Cache/Memcached.pm | 33 ++++++++++++++------------------ 1 file changed, 14 insertions(+), 19 deletions(-) diff --git a/Kernel/System/Cache/Memcached.pm b/Kernel/System/Cache/Memcached.pm index d5e29054373..d000ca2be00 100644 --- a/Kernel/System/Cache/Memcached.pm +++ b/Kernel/System/Cache/Memcached.pm @@ -187,25 +187,20 @@ sub CleanUp { } } -=item _GetMemcachedKeyName() - -Use MD5 digest of Type::Namespace::Key for memcached key (memcached key max -length is 250). Namespace for given cache object type is taken from cache. -New namespace is created if namespace is not found. For this algo idea see -http://code.google.com/p/memcached/wiki/NewProgrammingTricks#Namespacing -We use miliseconds not microseconds because overflow in the "incr" memcached -command wraps around the 64 bit mark. - -Returns mamcached key name if determined or nothing on error: - - my $PreparedKey = $Self->_GetMemcachedKeyName( - Type => 'CacheObjectTypeName', - Key => 'KeyName', - InitNamespaceOnError => 0, # set 1 to initialize namespace if cannot be read - ); - -=cut - +# Use MD5 digest of Type::Namespace::Key for memcached key (memcached key max +# length is 250). Namespace for given cache object type is taken from cache. +# New namespace is created if namespace is not found. For this algo idea see +# http://code.google.com/p/memcached/wiki/NewProgrammingTricks#Namespacing +# We use miliseconds not microseconds because overflow in the "incr" memcached +# command wraps around the 64 bit mark. +# +# Returns mamcached key name if determined or nothing on error: +# +# my $PreparedKey = $Self->_GetMemcachedKeyName( +# Type => 'CacheObjectTypeName', +# Key => 'KeyName', +# InitNamespaceOnError => 0, # set 1 to initialize namespace if cannot be read +# ); sub _GetMemcachedKeyName { my ( $Self, %Param ) = @_; From 46f0d6e9b1f5b6972b1b67d66166e0ab27f366a8 Mon Sep 17 00:00:00 2001 From: Pawel Boguslawski Date: Mon, 19 Apr 2021 20:23:05 +0200 Subject: [PATCH 04/12] Fixed races on memcached access after forking Worker processes must use own connections to memcached to avoid races. Fixes: f4eae1ddf4bc7d047d66a560584995ed1c6e5672 Author-Change-Id: IB#1046574 --- Kernel/System/Cache/Memcached.pm | 25 +++++++++++++++++++ .../Ticket/FulltextIndexRebuildWorker.pm | 13 +++++++++- 2 files changed, 37 insertions(+), 1 deletion(-) diff --git a/Kernel/System/Cache/Memcached.pm b/Kernel/System/Cache/Memcached.pm index d000ca2be00..a5fd7f9c03d 100644 --- a/Kernel/System/Cache/Memcached.pm +++ b/Kernel/System/Cache/Memcached.pm @@ -33,6 +33,9 @@ sub new { my $Self = {}; bless( $Self, $Type ); + # 0=off; 1=writes; 2=+reads; 3=+connects; + $Self->{Debug} = $Param{Debug} || 0; + # Get config object. my $ConfigObject = $Kernel::OM->Get('Kernel::Config'); @@ -63,6 +66,28 @@ sub new { return $Self; } +sub Disconnect { + my $Self = shift; + + # Debug. + if ( $Self->{Debug} > 2 ) { + $Kernel::OM->Get('Kernel::System::Log')->Log( + Caller => 1, + Priority => 'debug', + Message => 'Memcached.pm->Disconnect', + ); + } + + # Do disconnect. + if ( $Self->{MemcachedObject} ) { + $Self->{MemcachedObject}->disconnect_all(); + delete $Self->{MemcachedObject}; + } + + return 1; +} + + sub Set { my ( $Self, %Param ) = @_; diff --git a/Kernel/System/Console/Command/Maint/Ticket/FulltextIndexRebuildWorker.pm b/Kernel/System/Console/Command/Maint/Ticket/FulltextIndexRebuildWorker.pm index 90b3f9b242e..a2cf828f497 100644 --- a/Kernel/System/Console/Command/Maint/Ticket/FulltextIndexRebuildWorker.pm +++ b/Kernel/System/Console/Command/Maint/Ticket/FulltextIndexRebuildWorker.pm @@ -121,11 +121,23 @@ sub ArticleIndexRebuild { my @ArticleIDs = keys %{ $Param{ArticleTicketIDs} }; + my $ConfigObject = $Kernel::OM->Get('Kernel::Config'); + + # Disconnect & destroy memcached object to avoid child processes using same connection. + if ( $ConfigObject->Get('Cache::Module') eq 'Kernel::System::Cache::Memcached' ) { + $Kernel::OM->Get('Kernel::System::Cache::Memcached')->Disconnect(); + $Kernel::OM->ObjectsDiscard( + Objects => [ 'Kernel::System::Cache::Memcached' ], + ForcePackageReload => 0, + ); + } + $Kernel::OM->Get('Kernel::System::DB')->Disconnect(); # Destroy objects for the child processes. $Kernel::OM->ObjectsDiscard( Objects => [ + 'Kernel::System::Cache::Memcached', 'Kernel::System::DB', ], ForcePackageReload => 0, @@ -139,7 +151,6 @@ sub ArticleIndexRebuild { push @{ $ArticleChunks[ $Count++ % $Param{Children} ] }, $ArticleID; } - my $ConfigObject = $Kernel::OM->Get('Kernel::Config'); my $TicketObject = $Kernel::OM->Get('Kernel::System::Ticket'); my $ArticleObject = $Kernel::OM->Get('Kernel::System::Ticket::Article'); From 91ed7b360ce7961f821114e4ee290e373adf9f64 Mon Sep 17 00:00:00 2001 From: Pawel Boguslawski Date: Mon, 19 Apr 2021 20:43:47 +0200 Subject: [PATCH 05/12] Missing dependency added Fixes: d4abf57a6d6e21fdb05c4c6fd30498bca0f4f7df Author-Change-Id: IB#1046574 --- .../Console/Command/Maint/Ticket/FulltextIndexRebuildWorker.pm | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Kernel/System/Console/Command/Maint/Ticket/FulltextIndexRebuildWorker.pm b/Kernel/System/Console/Command/Maint/Ticket/FulltextIndexRebuildWorker.pm index a2cf828f497..0aa32da9259 100644 --- a/Kernel/System/Console/Command/Maint/Ticket/FulltextIndexRebuildWorker.pm +++ b/Kernel/System/Console/Command/Maint/Ticket/FulltextIndexRebuildWorker.pm @@ -1,6 +1,7 @@ # -- # Copyright (C) 2001-2021 OTRS AG, https://otrs.com/ # Copyright (C) 2021 Znuny GmbH, https://znuny.org/ +# Copyright (C) 2014-2021 Informatyka Boguslawski sp. z o.o. sp.k., http://www.ib.pl/ # -- # This software comes with ABSOLUTELY NO WARRANTY. For details, see # the enclosed file COPYING for license information (GPL). If you @@ -22,6 +23,7 @@ use Kernel::System::VariableCheck qw(:all); our @ObjectDependencies = ( 'Kernel::Config', + 'Kernel::System::Cache::Memcached', 'Kernel::System::DB', 'Kernel::System::Log', 'Kernel::System::PID', From 6601695a90d56b959c85251b854bbe8c9ea5d109 Mon Sep 17 00:00:00 2001 From: Pawel Boguslawski Date: Tue, 20 Apr 2021 09:20:50 +0200 Subject: [PATCH 06/12] Disconnect from memcached before trashing object Fixes: f4eae1ddf4bc7d047d66a560584995ed1c6e5672 Author-Change-Id: IB#1046574 --- Kernel/System/Cache/Memcached.pm | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/Kernel/System/Cache/Memcached.pm b/Kernel/System/Cache/Memcached.pm index a5fd7f9c03d..63f1ff35faa 100644 --- a/Kernel/System/Cache/Memcached.pm +++ b/Kernel/System/Cache/Memcached.pm @@ -251,4 +251,13 @@ sub _GetMemcachedKeyName { return $MemcachedKeyName; } +sub DESTROY { + my $Self = shift; + + # Disconnect before trashing object. + $Self->Disconnect(); + + return 1; +} + 1; From cd5fae4479e2f980cd1d771d6922e3868d7424dc Mon Sep 17 00:00:00 2001 From: Pawel Boguslawski Date: Fri, 23 Apr 2021 15:23:10 +0200 Subject: [PATCH 07/12] Removed redundant object removal Fixes: fa94f4d78ac87d420d155bbce11363f23723a8b8 Author-Change-Id: IB#1234567 --- .../Console/Command/Maint/Ticket/FulltextIndexRebuildWorker.pm | 1 - 1 file changed, 1 deletion(-) diff --git a/Kernel/System/Console/Command/Maint/Ticket/FulltextIndexRebuildWorker.pm b/Kernel/System/Console/Command/Maint/Ticket/FulltextIndexRebuildWorker.pm index 0aa32da9259..6efd7cac5d9 100644 --- a/Kernel/System/Console/Command/Maint/Ticket/FulltextIndexRebuildWorker.pm +++ b/Kernel/System/Console/Command/Maint/Ticket/FulltextIndexRebuildWorker.pm @@ -139,7 +139,6 @@ sub ArticleIndexRebuild { # Destroy objects for the child processes. $Kernel::OM->ObjectsDiscard( Objects => [ - 'Kernel::System::Cache::Memcached', 'Kernel::System::DB', ], ForcePackageReload => 0, From 418c0bb35b6f371e9574e2675f7ed93d248427b8 Mon Sep 17 00:00:00 2001 From: Pawel Boguslawski Date: Tue, 27 Apr 2021 20:39:58 +0200 Subject: [PATCH 08/12] Disabled copyright code policy test Fixes: f4eae1ddf4bc7d047d66a560584995ed1c6e5672 Author-Change-Id: IB#1046574 --- Kernel/System/Cache/Memcached.pm | 1 + 1 file changed, 1 insertion(+) diff --git a/Kernel/System/Cache/Memcached.pm b/Kernel/System/Cache/Memcached.pm index 63f1ff35faa..32f59678af7 100644 --- a/Kernel/System/Cache/Memcached.pm +++ b/Kernel/System/Cache/Memcached.pm @@ -12,6 +12,7 @@ # -- package Kernel::System::Cache::Memcached; +## nofilter(TidyAll::Plugin::Znuny::Legal::UpdateZnunyCopyright) use strict; use warnings; From f91b21a9f201e8e90709b432f4e1fe3c8dfba077 Mon Sep 17 00:00:00 2001 From: Pawel Boguslawski Date: Tue, 2 May 2023 09:58:34 +0200 Subject: [PATCH 09/12] Code policy fixes Author-Change-Id: IB#1046574 --- Kernel/System/Cache/Memcached.pm | 23 ++++++++++--------- .../Ticket/FulltextIndexRebuildWorker.pm | 4 ++-- 2 files changed, 14 insertions(+), 13 deletions(-) diff --git a/Kernel/System/Cache/Memcached.pm b/Kernel/System/Cache/Memcached.pm index 32f59678af7..c944e299062 100644 --- a/Kernel/System/Cache/Memcached.pm +++ b/Kernel/System/Cache/Memcached.pm @@ -42,7 +42,7 @@ sub new { # Get memcached connection parameters and open connection to cache. $Self->{Config} = $ConfigObject->Get('Cache::Module::Memcached'); - if ($Self->{Config} && $Self->{Config}->{Servers} && $Self->{Config}->{Parameters}) { + if ( $Self->{Config} && $Self->{Config}->{Servers} && $Self->{Config}->{Parameters} ) { my $InitParams = { servers => $Self->{Config}->{Servers}, %{ $Self->{Config}->{Parameters} }, @@ -50,7 +50,7 @@ sub new { $Self->{MemcachedObject} = Cache::Memcached::Fast->new($InitParams); - if (!$Self->{MemcachedObject}) { + if ( !$Self->{MemcachedObject} ) { $Kernel::OM->Get('Kernel::System::Log')->Log( Priority => 'error', Message => "Unable to initialize memcached connector: $!", @@ -88,7 +88,6 @@ sub Disconnect { return 1; } - sub Set { my ( $Self, %Param ) = @_; @@ -192,12 +191,13 @@ sub CleanUp { return 1 if $Param{Expired}; if ( $Param{Type} ) { + # Invalidate namespace in cache by incrementing it; memcached will # take care of removing invalidated keys (LRU). In case of incrementing # error try to create new namespace. - if (!$Self->{MemcachedObject}->incr('Namespace:' . $Param{Type}, 1)) { - my $Miliseconds = int(Time::HiRes::gettimeofday() * 1000); - if (!$Self->{MemcachedObject}->add('Namespace:' . $Param{Type}, $Miliseconds)) { + if ( !$Self->{MemcachedObject}->incr( 'Namespace:' . $Param{Type}, 1 ) ) { + my $Miliseconds = int( Time::HiRes::gettimeofday() * 1000 ); + if ( !$Self->{MemcachedObject}->add( 'Namespace:' . $Param{Type}, $Miliseconds ) ) { $Kernel::OM->Get('Kernel::System::Log')->Log( Priority => 'error', Message => "Error deleting objects of type $Param{Type} in memcached!", @@ -231,15 +231,16 @@ sub _GetMemcachedKeyName { my ( $Self, %Param ) = @_; # Try to find namespace for given key object type. - my $MemcachedNamespace = $Self->{MemcachedObject}->get('Namespace:' . $Param{Type}); + my $MemcachedNamespace = $Self->{MemcachedObject}->get( 'Namespace:' . $Param{Type} ); # If namespace not found - if allowed, create new one using miliseconds since the epoch. - if (!$MemcachedNamespace && $Param{InitNamespaceOnError}) { - my $Miliseconds = int(Time::HiRes::gettimeofday() * 1000); + if ( !$MemcachedNamespace && $Param{InitNamespaceOnError} ) { + my $Miliseconds = int( Time::HiRes::gettimeofday() * 1000 ); + + if ( $Self->{MemcachedObject}->add( 'Namespace:' . $Param{Type}, $Miliseconds ) ) { - if ($Self->{MemcachedObject}->add('Namespace:' . $Param{Type}, $Miliseconds)) { # Get namespace from cache in case it was updated meanwhile. - $MemcachedNamespace = $Self->{MemcachedObject}->get('Namespace:' . $Param{Type}); + $MemcachedNamespace = $Self->{MemcachedObject}->get( 'Namespace:' . $Param{Type} ); } } diff --git a/Kernel/System/Console/Command/Maint/Ticket/FulltextIndexRebuildWorker.pm b/Kernel/System/Console/Command/Maint/Ticket/FulltextIndexRebuildWorker.pm index 6efd7cac5d9..fe587b848cd 100644 --- a/Kernel/System/Console/Command/Maint/Ticket/FulltextIndexRebuildWorker.pm +++ b/Kernel/System/Console/Command/Maint/Ticket/FulltextIndexRebuildWorker.pm @@ -123,13 +123,13 @@ sub ArticleIndexRebuild { my @ArticleIDs = keys %{ $Param{ArticleTicketIDs} }; - my $ConfigObject = $Kernel::OM->Get('Kernel::Config'); + my $ConfigObject = $Kernel::OM->Get('Kernel::Config'); # Disconnect & destroy memcached object to avoid child processes using same connection. if ( $ConfigObject->Get('Cache::Module') eq 'Kernel::System::Cache::Memcached' ) { $Kernel::OM->Get('Kernel::System::Cache::Memcached')->Disconnect(); $Kernel::OM->ObjectsDiscard( - Objects => [ 'Kernel::System::Cache::Memcached' ], + Objects => ['Kernel::System::Cache::Memcached'], ForcePackageReload => 0, ); } From e2704ba4a789c6ceb36f81f682de8f1e3a7cfb17 Mon Sep 17 00:00:00 2001 From: Pawel Boguslawski Date: Tue, 2 May 2023 10:21:15 +0200 Subject: [PATCH 10/12] License changed to AGPL for compatibility with Znuny PR requirement Related: https://github.com/znuny/Znuny/blob/dev/.github/PULL_REQUEST_TEMPLATE.md Author-Change-Id: IB#1046574 --- Kernel/System/Cache/Memcached.pm | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Kernel/System/Cache/Memcached.pm b/Kernel/System/Cache/Memcached.pm index c944e299062..3f89079689e 100644 --- a/Kernel/System/Cache/Memcached.pm +++ b/Kernel/System/Cache/Memcached.pm @@ -1,14 +1,14 @@ # -- -# Kernel/System/Cache/Memcached.pm - Memcached module for OTRS cache -# Copyright (C) 2014-2021 Informatyka Boguslawski sp. z o.o. sp.k., http://www.ib.pl/ +# Kernel/System/Cache/Memcached.pm - Memcached module for Znuny +# Copyright (C) 2014-2023 Informatyka Boguslawski sp. z o.o. sp.k., http://www.ib.pl/ # Based on: # http://code.google.com/p/memcached/wiki/NewProgrammingTricks#Namespacing # FileStorable.pm by OTRS AG, http://otrs.com/ # Memcached.pm by c.a.p.e. IT GmbH, http://www.cape-it.de # -- # This software comes with ABSOLUTELY NO WARRANTY. For details, see -# the enclosed file COPYING for license information (GPL). If you -# did not receive this file, see https://www.gnu.org/licenses/gpl-3.0.txt. +# the enclosed file COPYING for license information (AGPL). If you +# did not receive this file, see http://www.gnu.org/licenses/agpl.txt. # -- package Kernel::System::Cache::Memcached; From 6f77e9ed43d0893bb2ceed29fe710e11197288ad Mon Sep 17 00:00:00 2001 From: Pawel Boguslawski Date: Tue, 2 May 2023 10:57:35 +0200 Subject: [PATCH 11/12] Changelog and copyright removed Author-Change-Id: IB#1046574 --- CHANGES.md | 3 --- .../Console/Command/Maint/Ticket/FulltextIndexRebuildWorker.pm | 1 - 2 files changed, 4 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index 2679ea3f637..e84cd1797d8 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,6 +1,3 @@ -# 6.5.2 ????-??-?? - - 2023-05-02 Added memcached cache module. - # 6.5.1 2023-03-09 - 2023-02-28 Added options tickets-created-before-date and tickets-created-before-days to console command Admin::Article::StorageSwitch. - 2023-02-28 Fixed encoding of postmaster filter name in AdminPostMasterFilter. diff --git a/Kernel/System/Console/Command/Maint/Ticket/FulltextIndexRebuildWorker.pm b/Kernel/System/Console/Command/Maint/Ticket/FulltextIndexRebuildWorker.pm index fe587b848cd..de2161cd325 100644 --- a/Kernel/System/Console/Command/Maint/Ticket/FulltextIndexRebuildWorker.pm +++ b/Kernel/System/Console/Command/Maint/Ticket/FulltextIndexRebuildWorker.pm @@ -1,7 +1,6 @@ # -- # Copyright (C) 2001-2021 OTRS AG, https://otrs.com/ # Copyright (C) 2021 Znuny GmbH, https://znuny.org/ -# Copyright (C) 2014-2021 Informatyka Boguslawski sp. z o.o. sp.k., http://www.ib.pl/ # -- # This software comes with ABSOLUTELY NO WARRANTY. For details, see # the enclosed file COPYING for license information (GPL). If you From 8c8f18bb85033c95f2125f1c7c78c142f9f75a80 Mon Sep 17 00:00:00 2001 From: Pawel Boguslawski Date: Tue, 2 May 2023 11:51:43 +0200 Subject: [PATCH 12/12] Cache::Memcached::Fast CI dependency added Author-Change-Id: IB#1046574 --- .github/workflows/ci/dependencies.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/ci/dependencies.sh b/.github/workflows/ci/dependencies.sh index 497d343615a..80f3dcee423 100755 --- a/.github/workflows/ci/dependencies.sh +++ b/.github/workflows/ci/dependencies.sh @@ -15,4 +15,5 @@ apt-get install -y libapache2-mod-perl2 \ libmail-imapclient-perl libtemplate-perl libdatetime-perl \ libmoo-perl liblocale-po-perl libhash-merge-perl \ libxml2-utils libical-parser-perl libexpat1-dev \ + libcache-memcached-fast-perl \ apache2 gnupg2 mariadb-client cpanminus make gcc git npm gettext