summaryrefslogblamecommitdiffstats
path: root/config-db/ODLX/ConfigDB.pm
blob: 6bf8ab86d6021e105ea1c1749f20bde3e0981f14 (plain) (tree)





















                                                                                





                                                                       


                                           

                                                                           
                                           




                                                                           















































































































































                                                                                                                               
                             



                             








                                                                          




















                                                                          
                             



                             








                                                                          





























                                                                                
                        






                                                                

                                                                                                                             







                                        
                                                                                   
                                        
                                                                     











                                                   






































                                                                                                                           


























                                                                        
                        






                                                                
                                                                    








                                                                                                                              
                                                                                   
                                        
                                                                     











                                                   









































































































































                                                                                                                             


  
package ODLX::ConfigDB;

use strict;
use vars qw(@ISA @EXPORT @EXPORT_OK %EXPORT_TAGS $VERSION);
$VERSION = 1.01;		# API-version . implementation-version

################################################################################
### This module defines the data abstraction layer for the ODLX configuration
### database.
### Aim of this abstraction is to hide the details of the data layout and
### the peculiarities of individual database types behind a simple interface
### that offers straightforward access to and manipulation of the ODLX-systems
### and -clients (without the need to use SQL).
### The interface is divided into two parts:
### 	- data access methods (getting data)
### 	- data manipulation methods (adding, removing and changing data)
################################################################################
use Exporter;
@ISA = qw(Exporter);

my @accessExports = qw(
	connectConfigDB disconnectConfigDB
	fetchSystemsByFilter fetchSystemsById fetchAllSystemIDsOfClient
	fetchAllSystemIDsOfGroup
	fetchClientsByFilter fetchClientsById fetchAllClientIDsOfSystem
	fetchAllClientIDsOfGroup
	fetchGroupsByFilter fetchGroupsById fetchAllGroupIDsOfClient
	fetchAllGroupIDsOfSystem
);
my @manipulationExports = qw(
	addSystem removeSystem changeSystem
	setClientIDsOfSystem addClientIDsToSystem removeClientIDsFromSystem
	setGroupIDsOfSystem addGroupIDsToSystem removeGroupIDsFromSystem
	addClient removeClient changeClient
	setSystemIDsOfClient addSystemIDsToClient removeSystemIDsFromClient
	setGroupIDsOfClient addGroupIDsToClient removeGroupIDsFromClient
	addGroup removeGroup changeGroup
	setClientIDsOfGroup addClientIDsToGroup removeClientIDsFromGroup
	setSystemIDsOfGroup addSystemIDsToGroup removeSystemIDsFromGroup
);

@EXPORT = @accessExports;
@EXPORT_OK = @manipulationExports;
%EXPORT_TAGS = (
	'access' => [ @accessExports ],
	'manipulation' => [ @manipulationExports ],
);

################################################################################
### private stuff
################################################################################
use Carp;
use ODLX::Basics;
use ODLX::DBSchema;

sub _checkAndUpgradeDBSchemaIfNecessary
{
	my $metaDB = shift;

	vlog 2, "trying to determine schema version...";
	my $currVersion = $metaDB->schemaFetchDBVersion();
	if (!defined $currVersion) {
		# that's bad, someone has messed with our DB, as there is a
		# database, but the 'meta'-table is empty. There might still
		# be data in the other tables, but we have no way to find out
		# which schema version they're in. So it's safer to give up:
		croak _tr('Could not determine schema version of database');
	}

	if ($currVersion < $DbSchema->{version}) {
		vlog 1, _tr('Our schema-version is %s, DB is %s, upgrading DB...',
					$DbSchema->{version}, $currVersion);
		foreach my $v (sort { $a <=> $b } keys %DbSchemaHistory) {
			next if $v <= $currVersion;
			my $changeSet = $DbSchemaHistory{$v};
			foreach my $c (0..scalar(@$changeSet)-1) {
				my $changeDescr = @{$changeSet}[$c];
				my $cmd = $changeDescr->{cmd};
				if ($cmd eq 'add-table') {
					$metaDB->schemaAddTable($changeDescr->{'table'},
											$changeDescr->{'cols'},
											$changeDescr->{'vals'});
				} elsif ($cmd eq 'drop-table') {
					$metaDB->schemaDropTable($changeDescr->{'table'});
				} elsif ($cmd eq 'rename-table') {
					$metaDB->schemaRenameTable($changeDescr->{'old-table'},
											   $changeDescr->{'new-table'},
											   $changeDescr->{'cols'});
				} elsif ($cmd eq 'add-columns') {
					$metaDB->schemaAddColumns($changeDescr->{'table'},
											  $changeDescr->{'new-cols'},
											  $changeDescr->{'cols'});
				} elsif ($cmd eq 'drop-columns') {
					$metaDB->schemaDropColumns($changeDescr->{'table'},
											   $changeDescr->{'drop-cols'},
											   $changeDescr->{'cols'});
				} elsif ($cmd eq 'rename-columns') {
					$metaDB->schemaRenameColumns($changeDescr->{'table'},
												 $changeDescr->{'col-renames'},
												 $changeDescr->{'cols'});
				} else {
					confess _tr('UnknownDbSchemaCommand', $cmd);
				}
			}
		}
		vlog 1, _tr('upgrade done');
	} else {
		vlog 1, _tr('DB matches current schema version %s', $currVersion);
	}
}

sub _aref
{	# transparently converts the given reference to an array-ref
	my $ref = shift;
	$ref = [ $ref ] unless ref($ref) eq 'ARRAY';
	return $ref;
}

################################################################################
### data access interface
################################################################################
sub connectConfigDB
{
	my $dbParams = shift;
		# hash-ref with any additional info that might be required by
		# specific metadb-module (not used yet)

	my $dbType = $odlxConfig{'db-type'};
		# name of underlying database module
	my $dbModule = "ODLX::MetaDB::$dbType";
	unless (eval "require $dbModule") {
		confess _tr('Unable to load DB-module <%s> (%s)', $dbModule, $@);
	}
	my $modVersion = $dbModule->VERSION;
	if ($modVersion < $VERSION) {
		confess _tr('Could not load module <%s> (Version <%s> required, but <%s> found)',
					$dbModule, $VERSION, $modVersion);
	}
	$dbModule->import;

	my $metaDB = $dbModule->new();
	$metaDB->connectConfigDB($dbParams);
	my $confDB = {
		'db-type' => $dbType,
		'meta-db' => $metaDB,
	};
	foreach my $tk (keys %{$DbSchema->{tables}}) {
		$metaDB->schemaDeclareTable($tk, $DbSchema->{tables}->{$tk});
	}

	_checkAndUpgradeDBSchemaIfNecessary($metaDB);

	return $confDB;
}

sub disconnectConfigDB
{
	my $confDB = shift;

	$confDB->{'meta-db'}->disconnectConfigDB();
}

sub fetchSystemsByFilter
{
	my $confDB = shift;
	my $filter = shift;
	my $resultCols = shift;

	my @systems
		= $confDB->{'meta-db'}->fetchSystemsByFilter($filter, $resultCols);
	return wantarray() ? @systems : shift @systems;
}

sub fetchSystemsById
{
	my $confDB = shift;
	my $id = shift;

	my $filter = { 'id' => $id };
	my @systems = $confDB->{'meta-db'}->fetchSystemsByFilter($filter);
	return wantarray() ? @systems : shift @systems;
}

sub fetchAllSystemIDsOfClient
{
	my $confDB = shift;
	my $clientID = shift;

	return $confDB->{'meta-db'}->fetchAllSystemIDsOfClient($clientID);
}

sub fetchAllSystemIDsOfGroup
{
	my $confDB = shift;
	my $groupID = shift;

	return $confDB->{'meta-db'}->fetchAllSystemIDsOfClient($groupID);
}

sub fetchClientsByFilter
{
	my $confDB = shift;
	my $filter = shift;

	my @clients = $confDB->{'meta-db'}->fetchClientsByFilter($filter);
	return wantarray() ? @clients : shift @clients;
}

sub fetchClientsById
{
	my $confDB = shift;
	my $id = shift;

	my $filter = { 'id' => $id };
	my @clients = $confDB->{'meta-db'}->fetchClientsByFilter($filter);
	return wantarray() ? @clients : shift @clients;
}

sub fetchAllClientIDsOfSystem
{
	my $confDB = shift;
	my $systemID = shift;

	return $confDB->{'meta-db'}->fetchAllClientIDsOfSystem($systemID);
}

sub fetchAllClientIDsOfGroup
{
	my $confDB = shift;
	my $groupID = shift;

	return $confDB->{'meta-db'}->fetchAllClientIDsOfGroup($groupID);
}

################################################################################
### data manipulation interface
################################################################################
sub addSystem
{
	my $confDB = shift;
	my $valRows = _aref(shift);

	return $confDB->{'meta-db'}->addSystem($valRows);
}

sub removeSystem
{
	my $confDB = shift;
	my $systemIDs = _aref(shift);

	return $confDB->{'meta-db'}->removeSystem($systemIDs);
}

sub changeSystem
{
	my $confDB = shift;
	my $systemIDs = _aref(shift);
	my $valRows = _aref(shift);

	return $confDB->{'meta-db'}->changeSystem($systemIDs, $valRows);
}

sub setClientIDsOfSystem
{
	my $confDB = shift;
	my $systemID = shift;
	my $clientIDs = _aref(shift);

	my %seen;
	my @uniqueClientIDs = grep { !$seen{$_}++ } @$clientIDs;
	return $confDB->{'meta-db'}->setClientIDsOfSystem($systemID,
													  \@uniqueClientIDs);
}

sub addClientIDsToSystem
{
	my $confDB = shift;
	my $systemID = shift;
	my $newClientIDs = _aref(shift);

	my @clientIDs = $confDB->{'meta-db'}->fetchAllClientIDsOfSystem($systemID);
	push @clientIDs, @$newClientIDs;
	return setClientIDsOfSystem($confDB, $systemID, \@clientIDs);
}

sub removeClientIDsFromSystem
{
	my $confDB = shift;
	my $systemID = shift;
	my $removedClientIDs = _aref(shift);

	my %toBeRemoved;
	@toBeRemoved{@$removedClientIDs} = ();
	my @clientIDs
		= grep { !exists $toBeRemoved{$_} }
			   $confDB->{'meta-db'}->fetchAllClientIDsOfSystem($systemID);
	return setClientIDsOfSystem($confDB, $systemID, \@clientIDs);
}

sub setGroupIDsOfSystem
{
	my $confDB = shift;
	my $systemID = shift;
	my $groupIDs = _aref(shift);

	my %seen;
	my @uniqueGroupIDs = grep { !$seen{$_}++ } @$groupIDs;
	return $confDB->{'meta-db'}->setGroupIDsOfSystem($systemID,
													 \@uniqueGroupIDs);
}

sub addGroupIDsToSystem
{
	my $confDB = shift;
	my $systemID = shift;
	my $newGroupIDs = _aref(shift);

	my @groupIDs = $confDB->{'meta-db'}->fetchAllGroupIDsOfSystem($systemID);
	push @groupIDs, @$newGroupIDs;
	return setGroupIDsOfSystem($confDB, $systemID, \@groupIDs);
}

sub removeGroupIDsFromSystem
{
	my $confDB = shift;
	my $systemID = shift;
	my $toBeRemovedGroupIDs = _aref(shift);

	my %toBeRemoved;
	@toBeRemoved{@$toBeRemovedGroupIDs} = ();
	my @groupIDs
		= grep { !exists $toBeRemoved{$_} }
			   $confDB->{'meta-db'}->fetchAllGroupIDsOfSystem($systemID);
	return setGroupIDsOfSystem($confDB, $systemID, \@groupIDs);
}

sub addClient
{
	my $confDB = shift;
	my $valRows = _aref(shift);

	return $confDB->{'meta-db'}->addClient($valRows);
}

sub removeClient
{
	my $confDB = shift;
	my $clientIDs = _aref(shift);

	return $confDB->{'meta-db'}->removeClient($clientIDs);
}

sub changeClient
{
	my $confDB = shift;
	my $clientIDs = _aref(shift);
	my $valRows = _aref(shift);

	return $confDB->{'meta-db'}->changeClient($clientIDs, $valRows);
}

sub setSystemIDsOfClient
{
	my $confDB = shift;
	my $clientID = shift;
	my $systemIDs = _aref(shift);

	my %seen;
	my @uniqueSystemIDs = grep { !$seen{$_}++ } @$systemIDs;
	return $confDB->{'meta-db'}->setSystemIDsOfClient($clientID,
													   \@uniqueSystemIDs);
}

sub addSystemIDsToClient
{
	my $confDB = shift;
	my $clientID = shift;
	my $newSystemIDs = _aref(shift);

	my @systemIDs = $confDB->{'meta-db'}->fetchAllSystemIDsOfClient($clientID);
	push @systemIDs, @$newSystemIDs;
	return setSystemIDsOfClient($confDB, $clientID, \@systemIDs);
}

sub removeSystemIDsFromClient
{
	my $confDB = shift;
	my $clientID = shift;
	my $removedSystemIDs = _aref(shift);

	my %toBeRemoved;
	@toBeRemoved{@$removedSystemIDs} = ();
	my @systemIDs
		= grep { !exists $toBeRemoved{$_} }
			   $confDB->{'meta-db'}->fetchAllSystemIDsOfClient($clientID);
	return setSystemIDsOfClient($confDB, $clientID, \@systemIDs);
}

sub setGroupIDsOfClient
{
	my $confDB = shift;
	my $clientID = shift;
	my $groupIDs = _aref(shift);

	my %seen;
	my @uniqueGroupIDs = grep { !$seen{$_}++ } @$groupIDs;
	return $confDB->{'meta-db'}->setGroupIDsOfClient($clientID,
													 \@uniqueGroupIDs);
}

sub addGroupIDsToClient
{
	my $confDB = shift;
	my $clientID = shift;
	my $newGroupIDs = _aref(shift);

	my @groupIDs = $confDB->{'meta-db'}->fetchAllGroupIDsOfClient($clientID);
	push @groupIDs, @$newGroupIDs;
	return setGroupIDsOfClient($confDB, $clientID, \@groupIDs);
}

sub removeGroupIDsFromClient
{
	my $confDB = shift;
	my $clientID = shift;
	my $toBeRemovedGroupIDs = _aref(shift);

	my %toBeRemoved;
	@toBeRemoved{@$toBeRemovedGroupIDs} = ();
	my @groupIDs
		= grep { !exists $toBeRemoved{$_} }
			   $confDB->{'meta-db'}->fetchAllGroupIDsOfClient($clientID);
	return setGroupIDsOfClient($confDB, $clientID, \@groupIDs);
}

sub addGroup
{
	my $confDB = shift;
	my $valRows = _aref(shift);

	return $confDB->{'meta-db'}->addGroup($valRows);
}

sub removeGroup
{
	my $confDB = shift;
	my $groupIDs = _aref(shift);

	return $confDB->{'meta-db'}->removeGroup($groupIDs);
}

sub changeGroup
{
	my $confDB = shift;
	my $groupIDs = _aref(shift);
	my $valRows = _aref(shift);

	return $confDB->{'meta-db'}->changeGroup($groupIDs, $valRows);
}

sub setClientIDsOfGroup
{
	my $confDB = shift;
	my $groupID = shift;
	my $clientIDs = _aref(shift);

	my %seen;
	my @uniqueClientIDs = grep { !$seen{$_}++ } @$clientIDs;
	return $confDB->{'meta-db'}->setClientIDsOfGroup($groupID,
													 \@uniqueClientIDs);
}

sub addClientIDsToGroup
{
	my $confDB = shift;
	my $groupID = shift;
	my $newClientIDs = _aref(shift);

	my @clientIDs = $confDB->{'meta-db'}->fetchAllClientIDsOfGroup($groupID);
	push @clientIDs, @$newClientIDs;
	return setClientIDsOfGroup($confDB, $groupID, \@clientIDs);
}

sub removeClientIDsFromGroup
{
	my $confDB = shift;
	my $groupID = shift;
	my $removedClientIDs = _aref(shift);

	my %toBeRemoved;
	@toBeRemoved{@$removedClientIDs} = ();
	my @clientIDs
		= grep { !exists $toBeRemoved{$_} }
			   $confDB->{'meta-db'}->fetchAllClientIDsOfGroup($groupID);
	return setClientIDsOfGroup($confDB, $groupID, \@clientIDs);
}

sub setSystemIDsOfGroup
{
	my $confDB = shift;
	my $groupID = shift;
	my $systemIDs = _aref(shift);

	my %seen;
	my @uniqueSystemIDs = grep { !$seen{$_}++ } @$systemIDs;
	return $confDB->{'meta-db'}->setSystemIDsOfGroup($groupID,
													  \@uniqueSystemIDs);
}

sub addSystemIDsToGroup
{
	my $confDB = shift;
	my $groupID = shift;
	my $newSystemIDs = _aref(shift);

	my @systemIDs = $confDB->{'meta-db'}->fetchAllSystemIDsOfGroup($groupID);
	push @systemIDs, @$newSystemIDs;
	return setSystemIDsOfGroup($confDB, $groupID, \@systemIDs);
}

sub removeSystemIDsFromGroup
{
	my $confDB = shift;
	my $groupID = shift;
	my $removedSystemIDs = _aref(shift);

	my %toBeRemoved;
	@toBeRemoved{@$removedSystemIDs} = ();
	my @systemIDs
		= grep { !exists $toBeRemoved{$_} }
			   $confDB->{'meta-db'}->fetchAllSystemIDsOfGroup($groupID);
	return setSystemIDsOfGroup($confDB, $groupID, \@systemIDs);
}

1;