#!/usr/bin/perl
#  $Id$
# -----------------------------------------------------------------------------
#  Backup node-specific files
#  Files are stored to master DB table obj_block as binary gzipped data
# -----------------------------------------------------------------------------
#  Author: Andrey Fomenko
#  Modified by: Alexey Tsibulnik
#  QA by:  
#  Copyright: videoNEXT Network solutions, Inc.
# -----------------------------------------------------------------------------

use strict;
use warnings;
use Node::Conf;
use SKM::DB;
use DBD::Pg qw(:pg_types);

# CONS
my $APL = $ENV{APL} || '/opt/sarch';
my $VAR = $ENV{APL_VAR};
my $CONF = "$VAR/conf";
my $MIME_GZIP = "application/x-gzip";

# VAR
my $NodeOBJ;
my $dbm;
my $Errors = 0;
my $Log = "";

# SUB
sub logger
{
	my $msg = shift;
	chomp $msg;
	print "$msg\n";
}

sub db_master
{
	eval {
		$dbm = DBMaster({PrintError => 0, RaiseError => 1});
		my $r = $dbm->selectrow_arrayref(
			"SELECT obj FROM _objs 
			WHERE otype='D' AND subtype='N' AND deleted=0 AND name=?",
			{}, UNI()
		);
		$NodeOBJ = $r->[0] || die "Node ObjId not found\n";
	};
	if ($@){ logger ($@) ; }
	return $@ ? 0 : 1;
}

sub pack_dirs
{
	my @dirs = shift;
	my $data = "";
	
	if (open TAR, "/bin/tar -C $CONF -cz @dirs 2>/dev/null |") {
		$data .= $_ while (<TAR>);
		close TAR;
	} else {
		die "Error packing dirs: @dirs\n";
	}
	my $exit_code = $? >> 8;
	die "Tar finished with errors (code=$exit_code)\n" if $exit_code;
	die "Empty archive\n" unless length $data;
	
	return $data;
}


sub store_block
{
	my ($name, $mime, $data) = @_;
	
	# Delete old value if any
	$dbm->do(
		"DELETE FROM obj_block 
		WHERE obj=? AND name=?", undef,
		$NodeOBJ, $name
	);
			
	# Need some preparations to insert bytea
	my $sth = $dbm->prepare(
		"INSERT INTO obj_block (obj,name,mime,block) 
		VALUES (?,?,?,?)"
	);
	
	$sth->bind_param(4, undef, { pg_type => DBD::Pg::PG_BYTEA });
	my $nrows = $sth->execute($NodeOBJ, $name, $mime, $data);
	
	return $nrows;
}

sub backup_cert
{
        my $ok = 1;
        my $err = "";
        my $keys_dir = ".keys";
        my $cert_dir = "certificate";
        if (-d "$CONF/$keys_dir" and -d "$CONF/$cert_dir") {
    		eval {
    			my $data = pack_dirs($keys_dir, $cert_dir);
			
			my $nrows = store_block("BACKUP_CERT", $MIME_GZIP, $data);
			die "Error storing certs" unless $nrows;
		};
		if ($@) {
			$ok = 0;
			$err = $@;
			chomp $err;
		}
	}
	
	logger("Backup certificate " . ($ok?"OK":"ERROR: $err"));
}

sub backup_vae
{
	eval {{
		opendir DH, $CONF or die "Cannot opendir $CONF: $!\n";
		my @cams = grep {/^\d+$/} readdir DH;
		close DH;
		
		my @vae_dirs;
		foreach my $camdir (@cams) {
			push @vae_dirs, "$camdir/vae" if -d "$CONF/$camdir/vae";
		}
		last unless @vae_dirs;
		
		my $data = pack_dirs(@vae_dirs);
		my $nrows = store_block("BACKUP_CONF_VAE", $MIME_GZIP, $data);
		die "Error storing VAE configuration" unless $nrows;
	}};
	logger("Backup VAE config " . ($@?"ERROR: $@":"OK"));
}

sub main
{
	# Connect to master database
	if (not db_master) {
		logger("Master connection failed");
		exit 1;
	}
	
	# Keys and certificates
	backup_cert;
	
	# VAE dirs inside each camera config dir
	backup_vae;	
}

# MAIN
main;


END 
{
	eval { $dbm->disconnect } if $dbm;
}
