#!/usr/bin/perl

use strict;
use warnings;

use Evms::Common;
use Evms::Log;
use Evms::Object;
use Evms::Dos;
use Evms::DM;
use Evms::MD;

my $pers = "LINEAR";
my $region = $pers . " region";
my $RegMgr = "MDLinearRegMgr";

my $EINVAL = 22;

sub check_disk_size
{
	my $disk = $_[0];
	my $size = $_[1];
	my $real_size;
	my $rc;

	$real_size = get_object_size($disk);

	$rc = compare_sizes($real_size, $size, 0);
	if ($rc < 0) {
		log_error("Disk $disk smaller than required size ($size).\n");
	} else {
		$rc = 0;
	}

	return $rc;
}

# Setup
#	This function assigns DOS SegMgr to the logical disk
#
#	PARAMETERS (1)
#	- logical disk
#	RETURN:
#	- error code if any
sub Setup
{
	my $disk = $_[0];
	my @query_output;
	my $mbr = $disk . "_mbr";
	my $rc;

	$rc = assign_dos_plugin($disk);
	if ($rc) {
		log_error("Error assigning DOS plugin to disk $disk.\n");
		goto out;
	}

	@query_output = query_object($mbr);
	if (@query_output == 0) {
		log_error("Error getting details for MBR on disk $disk.\n");
		$rc = 1;
		goto out;
	}

out:
	return $rc;
}

# Cleanup
#
sub Cleanup
{
	my $disk = $_[0];
	unassign_dos_plugin($disk);
}


# Create_DOS_Primary_Segments
#	This subroutine creates 1 or more (max 4) primary segments
#
#	PARAMETERS:
#	- logical disk
#	- 1 to 4 strings of desired sizes
#	(e.g. Create_DOS_Primary_Segments("hdc", "50MB", "100MB")
#	(I know that that passing references is better :)
#
#	RETURN:
#	- error code if any
sub Create_DOS_Primary_Segments
{
	my $disk = shift;
	my @sizes = @_;
	my $freespace = $disk . "_freespace1";
	my ($count, $rc);

	$count = scalar(@sizes);
	if (($count == 0) || ($count > 4)) {
		$rc = $EINVAL;
		goto out;
	}

	foreach (@sizes) {
		log_info("Creating a $_ primary segment...\n");
		$rc = create_dos_primary_segment($freespace, $_);
		if ($rc) {
			log_error("Error creating primary segment.\n");
			goto out;
		}
	}
out:
	return $rc;
}

# Query_LINEAR_Region
#	PARAMETERS:
#	- region name
#
#	RETURN:
#	error code if any
sub Query_LINEAR_Region
{
	my $region_name = shift;
	my ($rc, @output);

	$rc = query_md_region($region_name, \@output);
	if ($rc) {
		log_error("Error querying $region $region_name.\n");
		goto out;
	} else {
		foreach (@output) {
			chomp($_);
			next if (length($_) == 0);
			log_debug("$_\n");
		}
	}
out:
	return $rc;
}

# Test_Lookup_Children
#	PARAMETERS (2)
#	- region name
#	- array of children
#
#	RETURN:
#	return 1 if FOUND all children, 0 if any of children is NOT FOUND.
sub Test_Lookup_Children
{
	my $region_name = shift;
	my $children = shift;
	my ($rc, $child, @output);

	$rc =  query_md_region_children($region_name, \@output);
	goto not_found unless !$rc;

	foreach $child (@{$children}) {
		foreach (@output) {
			if ($_ =~ / $child/) {
				log_info("FOUND $child in $region_name.\n");
				goto found;
			}
		}
		# We could not find $child in @output
		log_info("Could not find $child in $region_name.\n");
		goto not_found;
found:
	}
	return 1;

not_found:
	return 0;
}


# Test1
#	This subroutine tests creation and deletion of a simple LINEAR region.
#
sub Test1
{
	my @raid_disks = @{$_[0]}; # Have our own array of segments
	my ($rc, $msg);
	my $region_name = "";
	my $err = 0;
	my @none;

	# We need only 2 segments for this test.
	@raid_disks = @raid_disks[0..1];
 
	$msg = "1. Creating $region with: ";
	$msg .= join ",",@raid_disks;
	$msg .= "...\n";
	log_info($msg);

	# Create MD region
	$rc = create_md_region($RegMgr,\@raid_disks,\@none, $region_name);
	if ($rc) {
		$err = $rc;
		log_error("Error creating $region.\n");
		goto out;
	}

	if ($region_name eq "") {
		$err = $EINVAL;
		log_error("New $region has no name!!!.\n");
		goto out;
	} else {
		log_info("$region $region_name has been created.\n");
	}

	# Make sure that we can query the LINEAR object
	log_info("2. Making sure that $region $region_name exists.\n");
	$rc = Query_LINEAR_Region($region_name);
	if ($rc) {
		$err = $rc;
		goto out;
	}

out:
	# delete MD region (region name is required)
	if ($region_name ne "") {
		log_info("3. Deleting $region $region_name.\n");
		$rc = delete_md_region($region_name);
		if ($rc) {
			$err ? ($err = $err) : ($err = $rc);
			log_error("Error deleting $region $region_name.\n");
		} else {
			log_info("$region $region_name has been deleted.\n");
		}
	}

	log_result($err);
	return $err;
}




MAIN:
{
	my $disk;
	my @segments;
	my $rc;

	# Only use the first disk specified.
	$disk = $ARGV[0];
	$disk || die("USAGE: $0 disk\n");

	# Check for minimum-sized disk.
	$rc = check_disk_size($disk, "2GB");
	if ($rc) {
		die("Disk $disk isn't large enough for this test.\n");
	}

	$rc = Setup($disk);
	goto out unless !$rc;

	#Create 3 primary segments
	$rc = Create_DOS_Primary_Segments($disk, "50MB", "50MB", "50MB");
	goto finish unless !$rc;

	# For segment names, call get_dos_data_segments()
	$rc = get_dos_data_segments($disk, \@segments);
	if ($rc) {
		log_error("Error retrieving name of segments.\n");
		goto finish;
	}

	$rc = Test1(\@segments);
	goto finish unless !$rc;



finish:
	Cleanup($disk);
out:
}

