#!/usr/bin/perl

use strict;
use warnings;
use Cache::Memcached;
use Cache::Memcached::Fast;

$| = 1;

# Constants
my $memcached_class   = 'Cache::Memcached::Fast';
my $memcached_servers = [
  '127.0.0.1:11211'
 ];
#my $reconnect_on_fail = 1;
my $reconnect_on_fail = 0;

my $loops             = 10000;
my $op_attempts       = 10;
my $die_on_error      = 0;

# Globals
my $memcached         = undef;
my $data              = undef;

# Connect to Memcached.
memcached_connect();

foreach my $loop (1..$loops) {

  print "Loop: $loop - ";

  my $attempt_add = 1;
  my $attempt_get = 1;
  my $attempt_del = 1;

  my $key         = 'test_key_' . $$;
  my $value       = 'test_value_' . $$ . '_' . $loop;

  # Add
  while (not $memcached->add($key, $value, 1)) {
#  while (not $memcached->add($key, $value)) {
	print "ADD_ERROR\n";
    if ($attempt_add++ == $op_attempts) {
      handle_error ('Failed to add data on loop ' . $loop . ' in ' . $op_attempts . ' attempts');
    }
	print "Going to Reconnect...";
    memcached_connect()
      if ($reconnect_on_fail);
	print "Reconnected\n";
  }
  if ($attempt_add > 1) {
    warn ('Required ' . $attempt_add . ' attempts to add data on loop ' . $loop);
  }

  print "add, ";

  # Get
  while (not defined($data = $memcached->get($key))) {
	print "GET_ERROR\n";
    if ($attempt_get++ == $op_attempts) {
      handle_error ('Failed to get data on loop ' . $loop . ' in ' . $op_attempts . ' attempts');
    }
	print "Going to Reconnect...";
    memcached_connect()
      if ($reconnect_on_fail);
	print "Reconnected\n";
  }
  if ($attempt_get > 1) {
    warn ('Required ' . $attempt_get . ' attempts to get data on loop ' . $loop);
  }
  if ($data ne $value) {
    handle_error ('Data invalid on loop ' . $loop);
  }

  print "get, ";

  # Delete
  while (not $memcached->delete($key)) {
	print "DELETE_ERROR\n";
    if ($attempt_del++ == $op_attempts) {
      handle_error ('Failed to delete data on loop ' . $loop . ' in ' . $op_attempts . ' attempts');
    }
	print "Going to Reconnect...";
    memcached_connect()
      if ($reconnect_on_fail);
	print "Reconnected\n";
  }
  if ($attempt_del > 1) {
    warn ('Required ' . $attempt_del . ' attempts to delete data on loop ' . $loop);
  }

  print "delete\n";

}

print 'Test completed' . "\n";


sub memcached_connect {

  $memcached = undef;
  $memcached = $memcached_class->new({
    servers => $memcached_servers
  });

  if (not (defined($memcached) && $memcached->set('connect_test_key_' . $$, 'test_' . $$) && $memcached->delete('connect_test_key_' . $$))) {
    die ('Failed to connect to Memcached and test successfully');
  }

}

sub handle_error {

  my $errstr = shift || die('Required argument not supplied');
  if ($die_on_error) {
    die($errstr);
  } else {
    warn($errstr);
  }

}

