package LATMOS::Accounts::SyncManager; use strict; use warnings; use LATMOS::Accounts::Log; use LATMOS::Accounts; use Config::IniFiles; =head1 NAME LATMOS::Accounts::SyncManager - Routine task manager =head1 DESCRIPTION Handle Task process run by L =head1 FUNCTIONS =cut =head2 new($config) Instaciate object. C<$config> is a path to an alternative configuration file to default one. =cut sub new { my ($class, $config) = @_; my $ini = Config::IniFiles->new( -file => join('/', ($config || '/etc/latmos-accounts'), 'la-sync-manager.ini'), ) or do { la_log LA_ERR, "Cannot load config"; return; }; foreach my $section (qw(basessynchro refreshexpired updatedyndata)) { if ( !grep { lc($ini->val($_, 'type', '')) eq $section } $ini->Sections ) { $ini->newval("_$section", 'type', $section); } } bless { ini => $ini, config => $config, lastrev => 0, }, $class; } =head2 ini Return a reference to the L object handling configuration. =cut sub ini { $_[0]->{ini} } =head2 dbrev Return the current base revision =cut sub dbrev { my ($self) = @_; my $LA = LATMOS::Accounts->new($self->{config}, noacl => 1); my $base = $LA->base; return $base->current_rev; } sub _load_state_ini { my ($self) = @_; my $la = LATMOS::Accounts->new($self->{config}, noacl => 1); my $state_file = $la->val('_default_', 'state_dir', '/'); $state_file .= '/la-sync-manager.ini'; la_log(LA_DEBUG, "Status file is %s", $state_file); if ($state_file && ! -w $state_file) { # don't exists, we have to create it open(my $handle, '>', $state_file) or do { la_log(LA_ERR, "Cannot open build net status file %s", $state_file); return; }; print $handle "[_default_]\n"; close($handle); } return Config::IniFiles->new( -file => $state_file ); } =head2 get_last_rev($module) Return the last revision the module succeed =cut sub get_last_rev { my ($self, $module) = @_; my $ini = $self->_load_state_ini or return(0, 0); return ($ini->val($module, 'rev', 0), $ini->val($module, 'time', 0)); } =head2 list_modules List configured task module =cut sub list_modules { my ($self) = @_; $self->ini->Sections; } =head2 listSortedModules List configured module ordered for running =cut sub listSortedModules { my ($self) = @_; my %modules = (); foreach my $module ($self->list_modules) { $modules{$module} = 1; my $modtype = $self->ini->val($module, 'type', $module); my $task = LATMOS::Accounts::Task->new( $modtype, config => $self->{config}, name => $module, syncm => $self, ) or do { la_log(LA_ERR, 'Cannot load module %s', $modtype); next; }; $modules{$module} = $task->order; } return sort { $modules{$a} <=> $modules{$b} } keys %modules; } =head2 process_module($module) Process C<$module>. =cut # TODO what is $dbrev, why is it need here ?? sub process_module { my ($self, $module) = @_; eval { if (!$self->ini->SectionExists($module)) { la_log LA_ERR, "Cannot run inexistant module %s", $module; return; } my $modtype = $self->ini->val($module, 'type', $module); my $task = LATMOS::Accounts::Task->new( $modtype, config => $self->{config}, name => $module, syncm => $self, ) or do { la_log(LA_ERR, 'Cannot load module %s', $modtype); return; }; if (!$task->init) { la_log(LA_ERR, 'init() failed for module %s', $module); return; } my $currentrev = $self->dbrev; $task->needToBeRun($self, $module) or return 1; la_log LA_NOTICE, "Processing sync module %s (%s)", $module, $modtype; my $res = $task->run; if (!$res) { my $ini = $self->_load_state_ini or return; $ini->newval($module, 'error', LATMOS::Accounts::Log::lastmessage()); la_log LA_ERR, "Task %s did not end successfully", $module; $ini->RewriteConfig; } else { $task->post if ($res); my $ini = $self->_load_state_ini or return; $ini->delval($module, 'error'); $ini->newval($module, 'rev', $currentrev); my $time = time; $ini->newval($module, 'time', $time); $ini->SetParameterComment( $module, 'time', scalar(localtime(time)), ); $ini->RewriteConfig; la_log LA_DEBUG, "end process $module"; } return $res; }; if ($@) { la_log(LA_CRIT, 'Fatal Perl Error: %s', $@); return; } else { return 1; } } =head2 reset_module_savepoint($module) Reset the savepoint for module C<$module> to force it to run at next synchronisation. =cut sub reset_module_savepoint { my ($self, $module) = @_; if (!$self->ini->SectionExists($module)) { la_log LA_ERR, "Cannot run inexistant module %s", $module; return; } my $modtype = $self->ini->val($module, 'type', $module); my $task = LATMOS::Accounts::Task->new( $modtype, config => $self->{config}, name => $module, syncm => $self, ) or do { la_log(LA_ERR, 'Cannot load module %s', $modtype); return; }; $task->init or do { la_log LA_ERR, "Cannot init module %s", $_; return; }; my $ini = $self->_load_state_ini or return; $ini->delval($module, 'rev'); $ini->newval($module, 'time', 0); $ini->SetParameterComment( $module, 'time', 'Reset to 0 the ' . scalar(localtime(time)), ); $task->reset_savepoint; # Specific reset $ini->RewriteConfig; } 1; __END__ =head1 SEE ALSO L =head1 AUTHOR Olivier Thauvin, Eolivier.thauvin@latmos.ipsl.frE =head1 COPYRIGHT AND LICENSE Copyright (C) 2012 CNRS SA/CETP/LATMOS This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself, either Perl version 5.10.0 or, at your option, any later version of Perl 5 you may have available. =cut