Author: arkurth
Date: Thu Mar 16 15:37:32 2017
New Revision: 1787209

URL: http://svn.apache.org/viewvc?rev=1787209&view=rev
Log:
VCL-1023
Reworked Semaphore.pm to use the new vcldsemaphore table instead of a lockfile 
on the management node. This allows semaphores to be obeyed for vcld processes 
running on different management nodes.

Added VMware.pm::get_datastore_directory_semaphore which retrieves a 
datastore's URL/UUID identifier and uses this to obtain a semaphore instead of 
the descriptive datastore name. This allows semaphores to be obeyed for a 
particular directory on a datastore, even if different hosts to mount the same 
datastore with using different names.

Updated VMware.pm::prepare_vmdk to use get_datastore_directory_semaphore.

Deleted no longer used subroutines:
* Module.pm::does_semaphore_exist
* Semaphore.pm::get_process_semaphore_ids
* Semaphore.pm::get_reservation_semaphore_ids
* Semaphore.pm::semaphore_exists
* Semaphore.pm::get_lockfile_paths
* Semaphore.pm::release_lockfile

Updated Module.pm to not call 'use VCL::Module::Semaphore' at the beginning. 
This causes subroutine redefined warnings because there's sort of a circular 
reference the way Module.pm uses Semaphore.pm and Semaphore.pm inherits from 
Module.pm. Added require and import statement inside of 
Module.pm::get_semaphore contained within an eval block as a replacement.

Updated new.pm::computer_not_being_used to use 
utils.pm::get_vcld_semaphore_info instead of calling 
Semaphore.pm::get_process_semaphore_ids.


Other
Added DataStructure.pm::get_connect_method_info_matching_name. It was used for 
some experimentation and isn't currently being called, but may be useful in the 
future.

Updated Linux.pm::get_network_bridge_info to check for exit statuses > 0 
instead of anything != 0. Perl occasionally returns -1 even though the command 
was successful.

Modified:
    vcl/trunk/managementnode/lib/VCL/DataStructure.pm
    vcl/trunk/managementnode/lib/VCL/Module.pm
    vcl/trunk/managementnode/lib/VCL/Module/OS/Linux.pm
    vcl/trunk/managementnode/lib/VCL/Module/OS/Linux/ManagementNode.pm
    vcl/trunk/managementnode/lib/VCL/Module/Provisioning/VMware/VMware.pm
    vcl/trunk/managementnode/lib/VCL/Module/Semaphore.pm
    vcl/trunk/managementnode/lib/VCL/new.pm

Modified: vcl/trunk/managementnode/lib/VCL/DataStructure.pm
URL: 
http://svn.apache.org/viewvc/vcl/trunk/managementnode/lib/VCL/DataStructure.pm?rev=1787209&r1=1787208&r2=1787209&view=diff
==============================================================================
--- vcl/trunk/managementnode/lib/VCL/DataStructure.pm (original)
+++ vcl/trunk/managementnode/lib/VCL/DataStructure.pm Thu Mar 16 15:37:32 2017
@@ -2332,6 +2332,60 @@ sub get_reservation_info_json_string {
        return $json;
 }
 
+
+#/////////////////////////////////////////////////////////////////////////////
+
+=head2 get_connect_method_info_matching_name
+
+ Parameters  : $regex_pattern
+ Returns     : hash reference
+ Description : Checks the name of all connect methods mapped to the current
+               reservation's image revision. Returns info for all connect
+               methods with a connectmethod.name value matching the pattern
+               argument. This is useful for finding a particular connect 
method.
+               
+               For example:
+               $self->data->get_connect_method_info_matching_name('vmware');
+               
+               A hash reference is returned. The only hash element would be
+               information about a "VMwareVNC" connect method.
+
+=cut
+
+sub get_connect_method_info_matching_name {
+       my $self = shift;
+       if (ref($self) !~ /VCL::/i) {
+               notify($ERRORS{'CRITICAL'}, 0, "subroutine was called as a 
function, it must be called as a class method");
+               return;
+       }
+       
+       my $regex_pattern = shift;
+       if (!defined($regex_pattern)) {
+               notify($ERRORS{'WARNING'}, 0, "connect method name regex 
pattern argument was not supplied");
+               return;
+       }
+       
+       my $matching_connect_method_info = {};
+       
+       my $connect_method_info = $self->get_connect_methods();
+       for my $connect_method_id (sort {$a <=> $b} keys %$connect_method_info) 
{
+               my $connect_method = $connect_method_info->{$connect_method_id};
+               my $connect_method_name = $connect_method->{name};
+               if ($connect_method_name =~ /$regex_pattern/i) {
+                       $matching_connect_method_info->{$connect_method_id} = 
$connect_method;
+               }
+       }
+       
+       my $matching_count = scalar(keys %$matching_connect_method_info);
+       if (!$matching_count) {
+               notify($ERRORS{'DEBUG'}, 0, "no connect methods with name 
matching pattern '$regex_pattern' are mapped to image revision assigned to 
reservation");
+       }
+       else {
+               notify($ERRORS{'DEBUG'}, 0, "found $matching_count connect 
method(s) with name matching pattern '$regex_pattern' mapped to image revision 
assigned to reservation:\n" . format_data($matching_connect_method_info));
+       }
+       return $matching_connect_method_info;
+}
+
 #/////////////////////////////////////////////////////////////////////////////
 
 1;

Modified: vcl/trunk/managementnode/lib/VCL/Module.pm
URL: 
http://svn.apache.org/viewvc/vcl/trunk/managementnode/lib/VCL/Module.pm?rev=1787209&r1=1787208&r2=1787209&view=diff
==============================================================================
--- vcl/trunk/managementnode/lib/VCL/Module.pm (original)
+++ vcl/trunk/managementnode/lib/VCL/Module.pm Thu Mar 16 15:37:32 2017
@@ -90,7 +90,6 @@ use Digest::SHA1 qw(sha1_hex);
 
 use VCL::utils;
 use VCL::DataStructure;
-use VCL::Module::Semaphore;
 
 ##############################################################################
 
@@ -1533,7 +1532,7 @@ sub code_loop_timeout {
 
 =head2 get_semaphore
 
- Parameters  : $semaphore_id, $total_wait_seconds (optional), 
$attempt_delay_seconds (optional)
+ Parameters  : $semaphore_identifier, $semaphore_expire_seconds (optional), 
$attempt_delay_seconds (optional)
  Returns     : VCL::Module::Semaphore object
  Description : This subroutine is used to ensure that only 1 process performs a
                particular task at a time. An example would be the retrieval of
@@ -1544,32 +1543,24 @@ sub code_loop_timeout {
                others will wait until the semaphore is released by the
                retrieving process.
                
-               Attempts to open and obtain an exclusive lock on the file
-               specified by the file path argument. If unable to obtain an
-               exclusive lock, it will wait up to the value specified by the
-               total wait seconds argument (default: 30 seconds). The number of
-               seconds to wait in between retries can be specified (default: 15
-               seconds).
-               
-               A semaphore object is returned. The exclusive lock will be
-               retained as long as the semaphore object remains defined. Once
-               undefined, the exclusive lock is released and the file is
-               deleted.
+               A semaphore object is returned. The semaphore will be retained 
as
+               long as the semaphore object remains defined. Once undefined, 
the
+               semaphore is released.
                
                Examples:
                
                Semaphore is released when it is undefined:
                my $semaphore = $self->get_semaphore('test');
-               ... <exclusive lock is in place>
+               ... <semaphore in place>
                undef $semaphore;
-               ... <exclusive lock released>
+               ... <semaphore released>
                
                Semaphore is released when it goes out of scope:
                if (blah) {
                   my $semaphore = $self->get_semaphore('test');
-                  ... <exclusive lock is in place>
+                  ... <semaphore in place>
                }
-               ... <exclusive lock released>
+               ... <semaphore released>
 
 =cut
 
@@ -1581,67 +1572,38 @@ sub get_semaphore {
        }
        
        # Get the file path argument
-       my ($semaphore_id, $total_wait_seconds, $attempt_delay_seconds) = @_;
-       if (!$semaphore_id) {
-               notify($ERRORS{'WARNING'}, 0, "semaphore ID argument was not 
supplied");
+       my ($semaphore_identifier, $semaphore_expire_seconds, 
$attempt_delay_seconds) = @_;
+       if (!$semaphore_identifier) {
+               notify($ERRORS{'WARNING'}, 0, "semaphore identifier argument 
was not supplied");
                return;
        }
        
        # Attempt to create a new semaphore object
+       # Load Semaphore.pm here instead of calling use
+       # This prevents "Subroutine ... redefined" warnings
+       eval {
+               require "VCL/Module/Semaphore.pm";
+               import VCL::Module::Semaphore;
+       };
        my $semaphore = VCL::Module::Semaphore->new({'data_structure' => 
$self->data, mn_os => $self->mn_os});
        if (!$semaphore) {
                notify($ERRORS{'WARNING'}, 0, "failed to create semaphore 
object");
                return;
        }
        
-       # Attempt to open and exclusively lock the file
-       if ($semaphore->get_lockfile($semaphore_id, $total_wait_seconds, 
$attempt_delay_seconds)) {
-               # Return the semaphore object
-               my $address = sprintf('%x', $semaphore);
-               notify($ERRORS{'DEBUG'}, 0, "created '$semaphore_id' Semaphore 
object, memory address: $address");
+       my $semaphore_object_address = sprintf('%x', $semaphore);
+       
+       if ($semaphore->obtain($semaphore_identifier, 
$semaphore_expire_seconds, $attempt_delay_seconds)) {
+               notify($ERRORS{'DEBUG'}, 0, "obtained semaphore with 
identifier: '$semaphore_identifier', memory address: 
$semaphore_object_address");
                return $semaphore;
        }
        else {
-               notify($ERRORS{'DEBUG'}, 0, "failed to create '$semaphore_id' 
Semaphore object");
+               notify($ERRORS{'DEBUG'}, 0, "failed to obtain semaphore with 
identifier: '$semaphore_identifier'");
                return;
        }
 }
 
 #/////////////////////////////////////////////////////////////////////////////
-
-=head2 does_semaphore_exist
-
- Parameters  : $semaphore_id
- Returns     : boolean
- Description : Determines if an open Semaphore exists on this management node
-               matching the $semaphore_id.
-
-=cut
-
-sub does_semaphore_exist {
-       my $self = shift;
-       unless (ref($self) && $self->isa('VCL::Module')) {
-               notify($ERRORS{'CRITICAL'}, 0, "subroutine was called as a 
function, it must be called as a class method");
-               return;
-       }
-       
-       my ($semaphore_id) = @_;
-       if (!$semaphore_id) {
-               notify($ERRORS{'WARNING'}, 0, "semaphore ID argument was not 
supplied");
-               return;
-       }
-       
-       # Attempt to create a new semaphore object
-       my $semaphore = VCL::Module::Semaphore->new({'data_structure' => 
$self->data, mn_os => $self->mn_os});
-       if (!$semaphore) {
-               notify($ERRORS{'WARNING'}, 0, "failed to create semaphore 
object");
-               return;
-       }
-       
-       return $semaphore->semaphore_exists($semaphore_id);
-}
-
-#/////////////////////////////////////////////////////////////////////////////
 
 =head2 set_admin_message_variable
 

Modified: vcl/trunk/managementnode/lib/VCL/Module/OS/Linux.pm
URL: 
http://svn.apache.org/viewvc/vcl/trunk/managementnode/lib/VCL/Module/OS/Linux.pm?rev=1787209&r1=1787208&r2=1787209&view=diff
==============================================================================
--- vcl/trunk/managementnode/lib/VCL/Module/OS/Linux.pm (original)
+++ vcl/trunk/managementnode/lib/VCL/Module/OS/Linux.pm Thu Mar 16 15:37:32 2017
@@ -3519,7 +3519,7 @@ sub get_network_bridge_info {
                $self->{network_bridge_info} = {};
                return $self->{network_bridge_info};
        }
-       elsif ($exit_status ne '0') {
+       elsif ($exit_status > 0) {
                notify($ERRORS{'WARNING'}, 0, "failed to retrieve network 
bridge configuration from $computer_name, exit status: $exit_status, 
command:\n$command\noutput:\n" . join("\n", @$output));
                return;
        }

Modified: vcl/trunk/managementnode/lib/VCL/Module/OS/Linux/ManagementNode.pm
URL: 
http://svn.apache.org/viewvc/vcl/trunk/managementnode/lib/VCL/Module/OS/Linux/ManagementNode.pm?rev=1787209&r1=1787208&r2=1787209&view=diff
==============================================================================
--- vcl/trunk/managementnode/lib/VCL/Module/OS/Linux/ManagementNode.pm 
(original)
+++ vcl/trunk/managementnode/lib/VCL/Module/OS/Linux/ManagementNode.pm Thu Mar 
16 15:37:32 2017
@@ -383,14 +383,13 @@ sub delete_management_node_reservation_i
                configure something such as a storage unit or firewall device
                specifically for each reservation.
                
-               The stage argument may be any of the
-               following:
-               -pre_capture
-               -post_capture
-               -post_load
-               -post_reserve
-               -post_initial_connection
-               -post_reservation
+               The stage argument may be any of the following:
+               * pre_capture
+               * post_capture
+               * post_load
+               * post_reserve
+               * post_initial_connection
+               * post_reservation
                
                The scripts are stored on the management node under:
                /usr/local/vcl/tools/mn_stage_scripts

Modified: vcl/trunk/managementnode/lib/VCL/Module/Provisioning/VMware/VMware.pm
URL: 
http://svn.apache.org/viewvc/vcl/trunk/managementnode/lib/VCL/Module/Provisioning/VMware/VMware.pm?rev=1787209&r1=1787208&r2=1787209&view=diff
==============================================================================
--- vcl/trunk/managementnode/lib/VCL/Module/Provisioning/VMware/VMware.pm 
(original)
+++ vcl/trunk/managementnode/lib/VCL/Module/Provisioning/VMware/VMware.pm Thu 
Mar 16 15:37:32 2017
@@ -594,7 +594,7 @@ sub load {
        my $computer_name = $self->data->get_computer_short_name() || return;
        my $image_name = $self->data->get_image_name() || return;
        my $vmhost_name = $self->data->get_vmhost_short_name() || return;
-
+       
        
        insertloadlog($reservation_id, $computer_id, "startload", 
"$computer_name $image_name");
        
@@ -1995,6 +1995,7 @@ sub prepare_vmdk {
        my $host_vmdk_file_path_shared = $self->get_vmdk_file_path_shared() || 
return;
        my $host_vmdk_directory_path_shared = 
$self->get_vmdk_directory_path_shared() || return;
        
+       my $request_state_name = $self->data->get_request_state_name(0) || 
'unknown';
        my $image_name = $self->data->get_image_name() || return;
        my $vm_computer_name = $self->data->get_computer_short_name() || return;
        my $vmhost_name = $self->data->get_vmhost_short_name() || return;
@@ -2004,31 +2005,28 @@ sub prepare_vmdk {
        # Semaphores are created when exclusive access to a file/directory is 
needed to avoid conflicts
        # A semaphore ID is a string identifying a semaphore object when created
        # Only 1 process at a time may create a semaphore with a given ID - 
other processes must wait if they attempt to do so
-       # If the VM profile disk type is NOT network, include the VM host name 
in the semaphore ID
-       # This means exclusive access to a directory is only restricted to the 
same VM host
-       # If the disk type is network, multiple VM hosts may use the same 
directory so access should be restricted across hosts
-       my $vmdk_semaphore_id;
-       my $shared_vmdk_semaphore_id;
-       my $vmprofile_disk_type = $self->data->get_vmhost_profile_vmdisk();
-       if ($vmprofile_disk_type =~ /network/i) {
-               $vmdk_semaphore_id = $host_vmdk_directory_path;
-               $shared_vmdk_semaphore_id = $host_vmdk_directory_path_shared;
-       }
-       else {
-               $vmdk_semaphore_id = "$vmhost_name-$host_vmdk_directory_path";
-               $shared_vmdk_semaphore_id = 
"$vmhost_name-$host_vmdk_directory_path_shared";
-       }
        
        # Establish a semaphore for the shared vmdk directory before checking 
if it exists
        # This causes this process to wait if another process is copying to the 
shared directory
        # Wait a long time to create the semaphore in case another process is 
copying a large vmdk to the directory
-       my $vmdk_semaphore = $self->get_semaphore($shared_vmdk_semaphore_id, 
(60 * 20), 5) || return;
-       my $shared_vmdk_exists = 
$self->vmhost_os->file_exists($host_vmdk_file_path_shared);
        
-       # Return 1 if the VM is not dedicated and the shared vmdk already 
exists on the host
-       if ($shared_vmdk_exists && !$is_vm_dedicated) {
-               notify($ERRORS{'DEBUG'}, 0, "VM is not dedicated and shared 
vmdk file already exists on VM host $vmhost_name: $host_vmdk_file_path");
-               return 1;
+       my $shared_vmdk_semaphore = 
$self->get_datastore_directory_semaphore($host_vmdk_directory_path_shared, (60 
* 30)) || return;
+       
+       my $dedicated_vmdk_semaphore;
+       if ($host_vmdk_directory_path_shared ne $host_vmdk_directory_path) {
+               $dedicated_vmdk_semaphore = 
$self->get_datastore_directory_semaphore($host_vmdk_directory_path, (60 * 30)) 
|| return;
+       }
+       
+       # Return  if the VM is not dedicated and the shared vmdk already exists 
on the host
+       my $shared_vmdk_exists = 
$self->vmhost_os->file_exists($host_vmdk_file_path_shared);
+       if ($shared_vmdk_exists) {
+               # Release the shared vmdk semaphore - image should be 
completely copied to correct location
+               undef $shared_vmdk_semaphore;
+               
+               if (!$is_vm_dedicated) {
+                       notify($ERRORS{'DEBUG'}, 0, "VM is not dedicated and 
shared vmdk file already exists on VM host $vmhost_name: $host_vmdk_file_path");
+                       return 1;
+               }
        }
        
        # VM is either:
@@ -2037,32 +2035,27 @@ sub prepare_vmdk {
        #        -vmdk directory should be created and vmdk files copied to it
        #    -shared and the directory doesn't exist
        #        -shared vmdk directory should be retrieved from the image 
repository
-       # Update the semaphore for exclusive access to the vmdk directory if 
this is not the same directory as the shared directory
-       # The original semaphore is automatically released when the variable is 
reassigned
-       if ($vmdk_semaphore_id ne $shared_vmdk_semaphore_id) {
-               $vmdk_semaphore = $self->get_semaphore($vmdk_semaphore_id, (60 
* 1)) || return;
-       }
+       
        
        # If the VM is dedicated, check if the dedicated vmdk already exists on 
the host, delete it if necessary
-       if ($is_vm_dedicated && 
$self->vmhost_os->file_exists($host_vmdk_directory_path)) {
-               my $request_state_name = $self->data->get_request_state_name(0);
-               if ($request_state_name && $request_state_name =~ 
/(new|reload)/) {
-                       notify($ERRORS{'WARNING'}, 0, "VM is dedicated and vmdk 
directory already exists on VM host $vmhost_name: $host_vmdk_directory_path, 
existing directory will be deleted");
-                       if 
(!$self->vmhost_os->delete_file($host_vmdk_directory_path)) {
-                               notify($ERRORS{'WARNING'}, 0, "failed to delete 
existing dedicated vmdk directory on VM host $vmhost_name: 
$host_vmdk_directory_path");
-                               return;
+       if ($is_vm_dedicated) {
+               if ($self->vmhost_os->file_exists($host_vmdk_directory_path)) {
+                       if ($request_state_name =~ /(new|reload)/) {
+                               notify($ERRORS{'WARNING'}, 0, "VM is dedicated 
and vmdk directory already exists on VM host $vmhost_name: 
$host_vmdk_directory_path, existing directory will be deleted");
+                               if 
(!$self->vmhost_os->delete_file($host_vmdk_directory_path)) {
+                                       notify($ERRORS{'WARNING'}, 0, "failed 
to delete existing dedicated vmdk directory on VM host $vmhost_name: 
$host_vmdk_directory_path");
+                                       return;
+                               }
+                       }
+                       else {
+                               # Don't delete the directory, it may be in use 
by a VM
+                               # Attempting to delete it will likely delete 
some files but not all, leaving a mess to reconstruct
+                               notify($ERRORS{'OK'}, 0, "VM is dedicated and 
vmdk directory already exists on VM host $vmhost_name: 
$host_vmdk_directory_path, request state is not new or reload, directory will 
not be deleted, returning true");
+                               return 1;
                        }
                }
-               else {
-                       # Don't delete the directory, it may be in use by a VM
-                       # Attempting to delete it will likely delete some files 
but not all, leaving a mess to reconstruct
-                       notify($ERRORS{'OK'}, 0, "VM is dedicated and vmdk 
directory already exists on VM host $vmhost_name: $host_vmdk_directory_path, 
request state is not new or reload, directory will not be deleted, returning 
true");
-                       return 1;
-               }
-       }
-       
-       # Check if the VM is dedicated, if so, attempt to copy files from the 
shared vmdk directory if it exists
-       if ($is_vm_dedicated) {
+               
+               # Attempt to copy files from the shared vmdk directory if it 
exists
                if ($shared_vmdk_exists) {
                        notify($ERRORS{'DEBUG'}, 0, "VM is dedicated and shared 
vmdk exists on the VM host $vmhost_name, attempting to make a copy");
                        if ($self->copy_vmdk($host_vmdk_file_path_shared, 
$host_vmdk_file_path)) {
@@ -4922,7 +4915,7 @@ sub get_vm_os_configuration {
        my $image_os_name = $self->data->get_image_os_name() || return;
        my $image_os_type = $self->data->get_image_os_type();
        my $image_architecture = $self->data->get_image_architecture() || 
return;
-       
+
        # Figure out the key name in the %VM_OS_CONFIGURATION hash for the 
guest OS
        for my $vm_os_configuration_key (keys(%VM_OS_CONFIGURATION)) {
                my ($os_product_name, $os_architecture) = 
$vm_os_configuration_key =~ /(.+)-(.+)/;
@@ -5457,7 +5450,7 @@ sub get_vmx_info {
                        next;
                }
                elsif ($vmdk_file_path !~ /\.vmdk$/i) {
-                       notify($ERRORS{'DEBUG'}, 0, "ignoring 
$storage_identifier, filename property does not end with .vmdk: 
$vmdk_file_path");
+                       notify($ERRORS{'DEBUG'}, 0, "ignoring 
$storage_identifier, filename property does not end with .vmdk: 
$vmdk_file_path\n" . format_data($vmx_info{vmdk}{$storage_identifier}));
                        delete $vmx_info{vmdk}{$storage_identifier};
                        next;
                }
@@ -9995,6 +9988,72 @@ sub migrate_revert_source {
        }
 }
 
+#/////////////////////////////////////////////////////////////////////////////
+
+=head2 get_datastore_directory_semaphore
+
+ Parameters  : $path, $total_wait_seconds (optional)
+ Returns     : VCL::Module::Semaphore object, false, or undefined
+ Description : Obtains a semaphore for exclusive access to the directory on the
+               datastore.
+
+=cut
+
+sub get_datastore_directory_semaphore {
+       my $self = shift;
+       if (ref($self) !~ /vmware/i) {
+               notify($ERRORS{'CRITICAL'}, 0, "subroutine was called as a 
function, it must be called as a class method");
+               return;
+       }
+       
+       my ($datastore_directory_path, $total_wait_seconds) = @_;
+       if (!defined($datastore_directory_path)) {
+               notify($ERRORS{'WARNING'}, 0, "datastore directory path 
argument was not supplied");
+               return;
+       }
+       
+       $total_wait_seconds = 300 unless $total_wait_seconds;
+       
+       notify($ERRORS{'DEBUG'}, 0, "attempting to obtain semaphore for 
datastore directory: $datastore_directory_path");
+       
+       my $datastore_url = 
$self->_get_datastore_url($datastore_directory_path);
+       if (!$datastore_url) {
+               notify($ERRORS{'WARNING'}, 0, "failed to obtain semaphore, 
datastore URL could not be determined for path: $datastore_directory_path");
+               return;
+       }
+       notify($ERRORS{'DEBUG'}, 0, "determined datastore URL: $datastore_url");
+       
+       my $directory_name;
+       if ($datastore_directory_path =~ /\.[^\/]+$/) {
+               # Argument appears to be a file path, use the parent directory 
name
+               $directory_name = 
$self->_get_parent_directory_name($datastore_directory_path);
+               if (!$directory_name) {
+                       notify($ERRORS{'WARNING'}, 0, "failed to obtain 
semaphore, argument appears to be a file path: $datastore_directory_path, 
parent directory name could not be determined");
+                       return;
+               }
+               notify($ERRORS{'DEBUG'}, 0, "argument appears to be a file 
path: $datastore_directory_path, using parent directory name for semaphore ID: 
$directory_name");
+       }
+       else {
+               $directory_name = 
$self->_get_file_base_name($datastore_directory_path);
+               if (!$directory_name) {
+                       notify($ERRORS{'WARNING'}, 0, "failed to obtain 
semaphore, argument appears to be a directory path: $datastore_directory_path, 
base name could not be determined");
+                       return;
+               }
+               notify($ERRORS{'DEBUG'}, 0, "argument appears to be a directory 
path: $datastore_directory_path, using directory name for semaphore ID: 
$directory_name");
+       }
+       
+       my $semaphore_identifier = $datastore_url . '/' . $directory_name;
+       my $semaphore = $self->get_semaphore($semaphore_identifier, 
$total_wait_seconds);
+       if ($semaphore) {
+               notify($ERRORS{'DEBUG'}, 0, "obtained semaphore with identifier 
'$semaphore_identifier', returning semaphore object");
+               return $semaphore;
+       }
+       else {
+               notify($ERRORS{'WARNING'}, 0, "failed to obtain semaphore with 
identifier '$semaphore_identifier', returning 0");
+               return 0;
+       }
+}
+
 #/////////////////////////////////////////////////////////////////////////////
 
 1;

Modified: vcl/trunk/managementnode/lib/VCL/Module/Semaphore.pm
URL: 
http://svn.apache.org/viewvc/vcl/trunk/managementnode/lib/VCL/Module/Semaphore.pm?rev=1787209&r1=1787208&r2=1787209&view=diff
==============================================================================
--- vcl/trunk/managementnode/lib/VCL/Module/Semaphore.pm (original)
+++ vcl/trunk/managementnode/lib/VCL/Module/Semaphore.pm Thu Mar 16 15:37:32 
2017
@@ -25,7 +25,7 @@ VCL::Module::Semaphore - VCL module to c
 =head1 SYNOPSIS
 
  my $semaphore = VCL::Module::Semaphore->new({data_structure => $self->data});
- $semaphore->get_lockfile($semaphore_id, $total_wait_seconds, 
$attempt_delay_seconds);
+ $semaphore->obtain('something-unique', 240, $3);
 
 =head1 DESCRIPTION
 
@@ -67,478 +67,123 @@ use VCL::utils;
 
 ##############################################################################
 
-=head1 CLASS VARIABLES
-
-=cut
-
-=head2 $LOCKFILE_DIRECTORY_PATH
-
- Data type   : String
- Description : Location on the management node of the lockfiles are stored.
-
-=cut
-
-our $LOCKFILE_DIRECTORY_PATH = "/tmp";
-
-=head2 $LOCKFILE_EXTENSION
-
- Data type   : String
- Description : File extension to be used for lockfiles.
-
-=cut
-
-our $LOCKFILE_EXTENSION = "semaphore";
-
-##############################################################################
-
 =head1 OBJECT METHODS
 
 =cut
 
 #/////////////////////////////////////////////////////////////////////////////
 
-=head2 get_lockfile
+=head2 obtain
 
- Parameters  : $semaphore_id, $total_wait_seconds (optional), 
$attempt_delay_seconds (optional)
- Returns     : filehandle
- Description : Attempts to open and obtain an exclusive lock on the file
-               specified by the file path argument. If unable to obtain an
-               exclusive lock, it will wait up to the value specified by the
-               total wait seconds argument (default: 30 seconds). The number of
-               seconds to wait in between retries can be specified (default: 15
-               seconds).
+ Parameters  : $semaphore_identifier, $semaphore_expire_seconds (optional), 
$attempt_delay_seconds (optional)
+ Returns     : string
+ Description : Obtains a semaphore by inserting a row into the vcldsemaphore
+               database table.
+                                       
+                                       The $semaphore_expire_seconds is used 
to both determine when the
+                                       semaphore should be considered orphaned 
and to determine how long
+                                       the current process attempts to obtain 
a semaphore if blocked by
+                                       another process.
 
 =cut
 
-sub get_lockfile {
+sub obtain {
        my $self = shift;
        unless (ref($self) && $self->isa('VCL::Module')) {
                notify($ERRORS{'CRITICAL'}, 0, "subroutine was called as a 
function, it must be called as a class method");
                return;
        }
        
-       # Get the semaphore ID argument
-       my ($semaphore_id, $total_wait_seconds, $attempt_delay_seconds) = @_;
-       if (!$semaphore_id) {
-               notify($ERRORS{'WARNING'}, 0, "semaphore ID argument was not 
supplied");
-               return;
-       }
-       
-       $semaphore_id =~ s/\W+/-/g;
-       $semaphore_id =~ s/(^-|-$)//g;
-       
-       my $file_path = 
"$LOCKFILE_DIRECTORY_PATH/$semaphore_id.$LOCKFILE_EXTENSION";
-       
-       # Set the wait defaults if not supplied as arguments
-       $total_wait_seconds = 30 if !defined($total_wait_seconds);
-       $attempt_delay_seconds = 5 if !$attempt_delay_seconds;
-       
-       # Attempt to lock the file
-       my $wait_message = "attempting to open lockfile";
-       if ($self->code_loop_timeout(\&open_lockfile, [$self, $file_path], 
$wait_message, $total_wait_seconds, $attempt_delay_seconds)) {
-               return $file_path;
-       }
-       else {
-               notify($ERRORS{'DEBUG'}, 0, "failed to open lockfile: 
$file_path");
-               return;
-       }
-}
-
-#/////////////////////////////////////////////////////////////////////////////
-
-=head2 open_lockfile
-
- Parameters  : $file_path
- Returns     : If successful: IO::File file handle object
-               If failed: false
- Description : Opens and obtains an exclusive lock on the file specified by the
-               argument.
-
-=cut
-
-sub open_lockfile {
-       my $self = shift;
-       unless (ref($self) && $self->isa('VCL::Module')) {
-               notify($ERRORS{'CRITICAL'}, 0, "subroutine was called as a 
function, it must be called as a class method");
+       my ($semaphore_identifier, $semaphore_expire_seconds, 
$attempt_delay_seconds) = @_;
+       if (!$semaphore_identifier) {
+               notify($ERRORS{'WARNING'}, 0, "semaphore identifier argument 
was not supplied");
                return;
        }
-       
-       # Get the file path argument
-       my ($file_path) = @_;
-       if (!$file_path) {
-               notify($ERRORS{'WARNING'}, 0, "file path argument was not 
supplied");
+       elsif (defined($semaphore_expire_seconds) && $semaphore_expire_seconds 
!~ /^\d+$/) {
+               notify($ERRORS{'WARNING'}, 0, "semaphore expire seconds 
argument is not a valid integer: $semaphore_expire_seconds");
                return;
        }
        
-       # Attempt to open and lock the file
-       if (my $file_handle = new IO::File($file_path, O_WRONLY|O_CREAT)) {
-               if (flock($file_handle, LOCK_EX | LOCK_NB)) {
-                       notify($ERRORS{'DEBUG'}, 0, "opened and obtained an 
exclusive lock on file: $file_path");
-                       
-                       # Truncate and print the process information to the file
-                       $file_handle->truncate(0);
-                       print $file_handle "$$ $0\n";
-                       $file_handle->setpos($file_handle->getpos());
-                       
-                       notify($ERRORS{'DEBUG'}, 0, "wrote to file: $file_path, 
contents:\n '$$ $0'");
-                       
-                       $self->{file_handles}{$file_path} = $file_handle;
-                       return $file_handle;
-               }
-               else {
-                       notify($ERRORS{'DEBUG'}, 0, "unable to obtain exclusive 
lock on file: $file_path");
-                       $file_handle->close;
-               }
-       }
-       else {
-               notify($ERRORS{'WARNING'}, 0, "failed to open file: $file_path, 
error:\n$!");
-               return;
-       }
-       
-       # Don't use get_lockfile_owning_pid or anything that uses lsof on the 
management node
-       # Not safe - seems to send ALRM some time after command seems to have 
run
-       ## Determine which process is locking the file
-       #my @locking_pids = $self->get_lockfile_owning_pid($file_path);
-       #if (@locking_pids) {
-       #       if (grep { $_ eq $PID } @locking_pids) {
-       #               # The current process already has an exclusive lock on 
the file
-       #               # This could happen if open_lockfile is called more 
than once for the same file in the same scope
-       #               notify($ERRORS{'WARNING'}, 0, "file is already locked 
by this process: @locking_pids");
-       #               return;
-       #       }
-       #       else {
-       #               # Attempt to retrieve the names of the locking 
process(es)
-       #               my ($ps_exit_status, $ps_output) = run_command("ps -o 
pid=,cmd= @locking_pids", 1);
-       #               if (defined($ps_output) && !grep(/(ps:)/, @$ps_output)) 
{
-       #                       notify($ERRORS{'DEBUG'}, 0, "file is locked by 
another process: @locking_pids\n" . join("\n", @$ps_output));
-       #               }
-       #               else {
-       #                       notify($ERRORS{'DEBUG'}, 0, "file is locked by 
another process: @locking_pids");
-       #               }
-       #               return;
-       #       }
-       #}
-       #else {
-       #       notify($ERRORS{'DEBUG'}, 0, "unable to determine PIDs of 
processes which prevented an exclusive lock to be obtained on $file_path, lock 
may have been released before lsof command was executed");
-       #}
-       
-       return;
-}
-
-#/////////////////////////////////////////////////////////////////////////////
-#
-#=head2 get_lockfile_owning_pid
-#
-# Parameters  : $file_path
-# Returns     : integer
-# Description : Runs lsof to determine if a process has an exclusive lock on 
the
-#               lockfile.
-#
-#=cut
-#
-#sub get_lockfile_owning_pid {
-#      my $self = shift;
-#      unless (ref($self) && $self->isa('VCL::Module')) {
-#              notify($ERRORS{'CRITICAL'}, 0, "subroutine was called as a 
function, it must be called as a class method");
-#              return;
-#      }
-#      
-#      # Get the file path argument
-#      my ($file_path) = @_;
-#      if (!$file_path) {
-#              notify($ERRORS{'WARNING'}, 0, "file path argument was not 
supplied");
-#              return;
-#      }
-#      
-#      # Run lsof to determine which process is locking the file
-#      #my ($exit_status, $output) = $self->mn_os->execute("/usr/sbin/lsof -S 
2 -O -Fp $file_path", 1, 10);
-#      my ($exit_status, $output) = $self->mn_os->execute("/usr/sbin/lsof -Fp 
$file_path", 0, 10);
-#      if (!defined($output)) {
-#              notify($ERRORS{'WARNING'}, 0, "failed to run lsof command to 
determine which process is locking the file: $file_path");
-#              return;
-#      }
-#      elsif (grep(/no such file/i, @$output)) {
-#              notify($ERRORS{'WARNING'}, 0, "lsof command reports that the 
file does not exist: $file_path");
-#              return;
-#      }
-#      
-#      # Parse the lsof output to determine the PID
-#      my @locking_pids = map { /^p(\d+)/ } @$output;
-#      my $locking_pid_count = scalar(@locking_pids);
-#      if (@locking_pids) {
-#              notify($ERRORS{'DEBUG'}, 0, "$file_path is locked by process" . 
($locking_pid_count == 1 ? '' : 'es') . ": @locking_pids");
-#              return @locking_pids;
-#      }
-#      elsif (grep(/\w/, @$output)) {
-#              notify($ERRORS{'WARNING'}, 0, "failed to determine owning PID 
of lockfile: $file_path, unable to determine PIDs from lsof output\n:" . 
join("\n", @$output));
-#              return;
-#      }
-#      else {
-#              notify($ERRORS{'DEBUG'}, 0, "file is not locked: $file_path");
-#              return ();
-#      }
-#}
-
-#/////////////////////////////////////////////////////////////////////////////
-
-=head2 release_lockfile
-
- Parameters  : $file_path
- Returns     : boolean
- Description : Releases the exclusive lock and closes the lockfile handle
-               specified by the argument.
-
-=cut
-
-sub release_lockfile {
-       my $self = shift;
-       unless (ref($self) && $self->isa('VCL::Module')) {
-               notify($ERRORS{'CRITICAL'}, 0, "subroutine was called as a 
function, it must be called as a class method");
-               return;
-       }
-       
-       # Get the file path argument
-       my $file_path = shift;
-       if (!$file_path) {
-               notify($ERRORS{'WARNING'}, 0, "file path argument was not 
supplied");
-               return;
-       }
-       
-       my $file_handle = $self->{file_handles}{$file_path};
-       if (!$file_handle) {
-               notify($ERRORS{'WARNING'}, 0, "file handle is not saved in this 
object for file path: $file_path");
-               return;
-       }
-       
-       # Make sure the file handle is opened
-       my $fileno = $file_handle->fileno;
-       if (!$fileno) {
-               notify($ERRORS{'WARNING'}, 0, "file is not opened: $file_path");
-       }
-       
-       if (!flock($file_handle, LOCK_UN)) {
-               notify($ERRORS{'WARNING'}, 0, "failed to unlock file: 
$file_path, reason: $!");
-       }
-       
-       # Close the file
-       if (!close($file_handle)) {
-               notify($ERRORS{'WARNING'}, 0, "failed to close file: 
$file_path, reason: $!");
-       }
+       $semaphore_expire_seconds = 300 unless 
defined($semaphore_expire_seconds);
+       $attempt_delay_seconds = 5 if !$attempt_delay_seconds;
        
-       # Delete the file
-       if (unlink($file_path)) {
-               notify($ERRORS{'DEBUG'}, 0, "deleted file: $file_path");
+       # Attempt to set the variable
+       my $wait_message = "attempting to add a row to the vcldsemaphore table 
with identifier: '$semaphore_identifier'";
+       if ($self->code_loop_timeout(\&_obtain, [$self, $semaphore_identifier, 
$semaphore_expire_seconds], $wait_message, $semaphore_expire_seconds, 
$attempt_delay_seconds)) {
+               notify($ERRORS{'OK'}, 0, "*** created semaphore by adding a row 
to the vcldsemaphore table with identifier: '$semaphore_identifier' ***");
+               $self->{vcldsemaphore_table_identifiers}{$semaphore_identifier} 
= 1;
+               return 1;
        }
        else {
-               notify($ERRORS{'WARNING'}, 0, "failed to delete file: 
$file_path, reason: $!");
-       }
-       
-       delete $self->{file_handles}{$file_path};
-       return 1;
-}
-
-#/////////////////////////////////////////////////////////////////////////////
-
-=head2 get_lockfile_paths
-
- Parameters  : none
- Returns     : array
- Description : Returns the paths to all lockfiles.
-
-=cut
-
-sub get_lockfile_paths {
-       my $self = shift;
-       unless (ref($self) && $self->isa('VCL::Module')) {
-               notify($ERRORS{'CRITICAL'}, 0, "subroutine was called as a 
function, it must be called as a class method");
+               notify($ERRORS{'WARNING'}, 0, "failed to obtain semaphore by 
adding a row to the vcldsemaphore table after attempting for 
$semaphore_expire_seconds seconds: '$semaphore_identifier'");
                return;
        }
-       
-       my @lockfile_paths = $self->mn_os->find_files($LOCKFILE_DIRECTORY_PATH, 
"*.$LOCKFILE_EXTENSION");
-       
-       my $lockfile_path_count = scalar(@lockfile_paths);
-       notify($ERRORS{'DEBUG'}, 0, "retreived $lockfile_path_count lockfile 
path" . ($lockfile_path_count == 1 ? '' : 's') . ":\n" . join("\n", 
@lockfile_paths));
-       return @lockfile_paths;
 }
 
 #/////////////////////////////////////////////////////////////////////////////
 
-=head2 semaphore_exists
+=head2 _obtain
 
- Parameters  : $semaphore_id
+ Parameters  : $semaphore_identifier, $semaphore_expire_seconds
  Returns     : boolean
- Description : Determines if an open Semaphore exists on this management node
-               matching the $semaphore_id.
+ Description : Helper function for Semaphore.pm::obtain. Attempts to call
+               insert_vcld_semaphore. If this fails, it retrieves existing
+               vcldsemaphore table entries and deletes expired rows.
 
 =cut
 
-sub semaphore_exists {
+sub _obtain {
        my $self = shift;
        unless (ref($self) && $self->isa('VCL::Module')) {
                notify($ERRORS{'CRITICAL'}, 0, "subroutine was called as a 
function, it must be called as a class method");
                return;
        }
        
-       my ($semaphore_id) = @_;
-       if (!$semaphore_id) {
-               notify($ERRORS{'WARNING'}, 0, "semaphore ID argument was not 
supplied");
-               return;
-       }
-       
-       my @lockfile_paths = $self->get_lockfile_paths();
-       if (!@lockfile_paths) {
-               notify($ERRORS{'DEBUG'}, 0, "did not find any lockfiles on this 
management node");
-               return ();
-       }
+       my ($semaphore_identifier, $semaphore_expire_seconds) = @_;
        
-       for my $lockfile_path (@lockfile_paths) {
-               my ($lockfile_semaphore_id) = $lockfile_path =~ 
/([^\/]+)\.$LOCKFILE_EXTENSION/;
-               if ($lockfile_semaphore_id ne $semaphore_id) {
-                       next;
-               }
-               
-               # Check if the lockfile is actually locked by another process
-               # It may have been released or deleted
-               my @lockfile_owning_pids = 
$self->get_lockfile_owning_pid($lockfile_path);
-               if (@lockfile_owning_pids) {
-                       notify($ERRORS{'DEBUG'}, 0, "'$semaphore_id' semaphore 
exists, lockfile path: $lockfile_path, owning PID: @lockfile_owning_pids");
-                       return 1;
-               }
-               else {
-                       notify($ERRORS{'DEBUG'}, 0, "ignoring lockfile not 
locked by another process: $lockfile_path");
-                       next;
-               }
-       }
+       my $reservation_id = $self->data->get_reservation_id();
        
-       notify($ERRORS{'DEBUG'}, 0, "'$semaphore_id' semaphore does not exist");
-       return 0;
-}
-
-#/////////////////////////////////////////////////////////////////////////////
-
-=head2 get_reservation_semaphore_ids
-
- Parameters  : $reservation_id
- Returns     : array
- Description : Returns the Semaphore IDs opened by the reservation specified by
-               the argument. An empty list is returned if no Semaphores are
-               open.
-
-=cut
-
-sub get_reservation_semaphore_ids {
-       my $self = shift;
-       unless (ref($self) && $self->isa('VCL::Module')) {
-               notify($ERRORS{'CRITICAL'}, 0, "subroutine was called as a 
function, it must be called as a class method");
-               return;
+       if (insert_vcld_semaphore($semaphore_identifier, $reservation_id, 
$semaphore_expire_seconds)) {
+               return 1;
        }
        
-       my $reservation_id = shift || $self->data->get_reservation_id();
-       if (!$reservation_id) {
-               notify($ERRORS{'WARNING'}, 0, "reservation ID argument was not 
supplied");
-               return;
-       }
+       my $current_datetime = makedatestring();
+       my $current_epoch = convert_to_epoch_seconds($current_datetime);
        
-       my @lockfile_paths = $self->get_lockfile_paths();
-       if (!@lockfile_paths) {
-               notify($ERRORS{'DEBUG'}, 0, "did not find any lockfiles on this 
management node");
-               return ();
-       }
-       
-       my @reservation_semaphore_ids;
-       for my $lockfile_path (@lockfile_paths) {
-               my ($semaphore_id) = $lockfile_path =~ 
/([^\/]+)\.$LOCKFILE_EXTENSION/;
-               
-               my @lockfile_contents = 
$self->mn_os->get_file_contents($lockfile_path);
-               if (!@lockfile_contents) {
-                       notify($ERRORS{'WARNING'}, 0, "failed to retrieve 
contents of lockfile: $lockfile_path");
+       my $semaphore_info = get_vcld_semaphore_info();
+       for my $existing_semaphore_identifier (keys %$semaphore_info) {
+               # Ignore if identifier is different
+               if ($existing_semaphore_identifier ne $semaphore_identifier) {
                        next;
                }
                
-               my $lockfile_line = $lockfile_contents[0];
+               my $existing_reservation_id = 
$semaphore_info->{$existing_semaphore_identifier}{reservationid};
+               my $existing_expires_datetime = 
$semaphore_info->{$existing_semaphore_identifier}{expires};
+               my $existing_expires_epoch = 
convert_to_epoch_seconds($existing_expires_datetime);
                
-               # Line should contain a string similar to this:
-               # 31862 vclark 2376:3116 tomaintenance 
vclv1-42>vclh3-12.hpc.ncsu.edu vmwarewinxp-base234-v14 admin
-               my ($lockfile_reservation_id) = $lockfile_line =~ / \d+:(\d+) /;
-               
-               if (!defined($lockfile_reservation_id)) {
-                       notify($ERRORS{'WARNING'}, 0, "failed to determine 
reservation ID from 1st line in $lockfile_path: '$lockfile_line'");
-                       next;
+               # Make sure existing semaphore wasn't created for this 
reservation - this should never happen
+               if ($existing_reservation_id eq $reservation_id) {
+                       notify($ERRORS{'WARNING'}, 0, "semaphore with same 
identifier already exists for this reservation: $existing_semaphore_identifier, 
attempting to forcefully update existing vclsemaphore entry:\n" . 
format_data($semaphore_info->{$existing_semaphore_identifier}));
+                       if (insert_vcld_semaphore($semaphore_identifier, 
$reservation_id, $semaphore_expire_seconds, 1)) {
+                               return 1;
+                       }
                }
                
-               if ($lockfile_reservation_id == $reservation_id) {
-                       notify($ERRORS{'DEBUG'}, 0, "semaphore '$semaphore_id' 
belongs to reservation $reservation_id");
-                       push @reservation_semaphore_ids, $semaphore_id;
+               if ($existing_expires_epoch < $current_epoch) {
+                       notify($ERRORS{'WARNING'}, 0, "attempting to delete 
expired vcldsemaphore table entry:\n" .
+                               "current time: $current_datetime 
($current_epoch)\n" .
+                               "expire time: $existing_expires_datetime 
($existing_expires_epoch)"
+                       );
+                       delete_vcld_semaphore($existing_semaphore_identifier, 
$existing_expires_datetime);
                }
                else {
-                       notify($ERRORS{'DEBUG'}, 0, "semaphore '$semaphore_id' 
does NOT belong to reservation $reservation_id");
+                       notify($ERRORS{'DEBUG'}, 0, "existing vcldsemaphore 
table entry has NOT expired:\n" .
+                               "current time: $current_datetime 
($current_epoch)\n" .
+                               "expire time: $existing_expires_datetime 
($existing_expires_epoch)"
+                       );
                }
        }
-       return @reservation_semaphore_ids;
-}
-
-#/////////////////////////////////////////////////////////////////////////////
-
-=head2 get_process_semaphore_ids
-
- Parameters  : $pid
- Returns     : array
- Description : Returns the Semaphore IDs opened by the process PID specified by
-               the argument. An empty list is returned if no Semaphores are
-               open.
-
-=cut
-
-sub get_process_semaphore_ids {
-       my $self = shift;
-       unless (ref($self) && $self->isa('VCL::Module')) {
-               notify($ERRORS{'CRITICAL'}, 0, "subroutine was called as a 
function, it must be called as a class method");
-               return;
-       }
-       
-       my $pid = shift;
-       if (!$pid) {
-               notify($ERRORS{'WARNING'}, 0, "process PID argument was not 
supplied");
-               return;
-       }
-       
-       my @lockfile_paths = $self->get_lockfile_paths();
-       if (!@lockfile_paths) {
-               notify($ERRORS{'DEBUG'}, 0, "did not find any lockfiles on this 
management node");
-               return ();
-       }
-       
-       my @process_semaphore_ids;
-       
-       for my $lockfile_path (@lockfile_paths) {
-               my ($semaphore_id) = $lockfile_path =~ 
/([^\/]+)\.$LOCKFILE_EXTENSION/;
-               
-               my @lockfile_contents = 
$self->mn_os->get_file_contents($lockfile_path);
-               if (!@lockfile_contents) {
-                       notify($ERRORS{'WARNING'}, 0, "failed to retrieve 
contents of lockfile: $lockfile_path");
-                       next;
-               }
-               
-               my $lockfile_line = $lockfile_contents[0];
-               
-               # Line should contain a string similar to this:
-               # 31862 vclark 2376:3116 tomaintenance 
vclv1-42>vclh3-12.hpc.ncsu.edu vmwarewinxp-base234-v14 admin
-               my ($lockfile_pid) = $lockfile_line =~ /^(\d+) /;
-               
-               if (!defined($lockfile_pid)) {
-                       notify($ERRORS{'WARNING'}, 0, "failed to determine PID 
from 1st line in $lockfile_path: '$lockfile_line'");
-                       next;
-               }
-               
-               if ($lockfile_pid == $pid) {
-                       notify($ERRORS{'DEBUG'}, 0, "semaphore '$semaphore_id' 
belongs to process $pid");
-                       push @process_semaphore_ids, $semaphore_id;
-               }
-               else {
-                       notify($ERRORS{'DEBUG'}, 0, "semaphore '$semaphore_id' 
does NOT belong to process $pid");
-               }
-       }
-       return @process_semaphore_ids;
+       return 0;
 }
 
 #/////////////////////////////////////////////////////////////////////////////
@@ -547,8 +192,8 @@ sub get_process_semaphore_ids {
 
  Parameters  : none
  Returns     : nothing
- Description : Destroys the semaphore object. The files opened and exclusively
-               locked by the semaphore object are closed and deleted.
+ Description : Destroys the semaphore object. Database vcldsemaphore table
+               entries created for this object are deleted.
 
 =cut
 
@@ -556,8 +201,8 @@ sub DESTROY {
        my $self = shift;
        my $address = sprintf('%x', $self);
        
-       for my $file_path (keys %{$self->{file_handles}}) {
-               $self->release_lockfile($file_path);
+       for my $semaphore_identifier (keys 
%{$self->{vcldsemaphore_table_identifiers}}) {
+               delete_vcld_semaphore($semaphore_identifier);
        }
        
        # Check for an overridden destructor

Modified: vcl/trunk/managementnode/lib/VCL/new.pm
URL: 
http://svn.apache.org/viewvc/vcl/trunk/managementnode/lib/VCL/new.pm?rev=1787209&r1=1787208&r2=1787209&view=diff
==============================================================================
--- vcl/trunk/managementnode/lib/VCL/new.pm (original)
+++ vcl/trunk/managementnode/lib/VCL/new.pm Thu Mar 16 15:37:32 2017
@@ -788,14 +788,16 @@ sub computer_not_being_used {
                                if (my @competing_reservation_pids = 
reservation_being_processed($competing_reservation_id)) {
                                        notify($ERRORS{'OK'}, 0, "reservation 
$competing_reservation_id is currently being processed by PID(s): " . join(', 
', @competing_reservation_pids) . ", making sure the process doesn't have any 
Semaphore objects open before attempting to kill it");
                                        
-                                       # Create a Semaphore object and check 
if the competing process owns any of its own Semaphore objects
+                                       # Check if the competing process owns 
any semaphores
                                        # This would indicate it's doing 
something such as retrieving an image
                                        # Don't kill it or a partial image may 
be copied
-                                       my $semaphore = 
VCL::Module::Semaphore->new();
-                                       for my $competing_reservation_pid 
(@competing_reservation_pids) {
-                                               if 
($semaphore->get_process_semaphore_ids($competing_reservation_pid)) {
-                                                       
notify($ERRORS{'CRITICAL'}, 0, "computer $computer_short_name is NOT available, 
reservation $competing_reservation_id is still being processed and owns a 
Semaphore object, not killing the competing process, it may be transferring an 
image:\n$competing_request_info_string");
-                                                       return;
+                                       my $semaphore_info = 
get_vcld_semaphore_info();
+                                       for my $semaphore_identifier (keys 
%$semaphore_info) {
+                                               for my 
$competing_reservation_pid (@competing_reservation_pids) {
+                                                       if 
($semaphore_info->{$semaphore_identifier}{reservationid} == 
$competing_reservation_id && $semaphore_info->{$semaphore_identifier}{pid} == 
$competing_reservation_pid) {
+                                                               
notify($ERRORS{'CRITICAL'}, 0, "computer $computer_short_name is NOT available, 
reservation $competing_reservation_id is still being processed and owns a 
semaphore with identifier '$semaphore_identifier', not killing the competing 
process, it may be transferring an image:\n$competing_request_info_string, 
semaphore info:\n" . format_data($semaphore_info->{$semaphore_identifier}));
+                                                               return;
+                                                       }
                                                }
                                        }
                                        


Reply via email to