Author: arkurth Date: Mon Oct 5 15:25:33 2009 New Revision: 821841 URL: http://svn.apache.org/viewvc?rev=821841&view=rev Log: VCL-184 Reworked the get_variable() and set_variable() subroutines in DataStructure.pm to handle the serialization column.
Modified: incubator/vcl/trunk/managementnode/lib/VCL/DataStructure.pm Modified: incubator/vcl/trunk/managementnode/lib/VCL/DataStructure.pm URL: http://svn.apache.org/viewvc/incubator/vcl/trunk/managementnode/lib/VCL/DataStructure.pm?rev=821841&r1=821840&r2=821841&view=diff ============================================================================== --- incubator/vcl/trunk/managementnode/lib/VCL/DataStructure.pm (original) +++ incubator/vcl/trunk/managementnode/lib/VCL/DataStructure.pm Mon Oct 5 15:25:33 2009 @@ -694,7 +694,7 @@ # Make sure the value was set in the hash my $check_value = eval $hash_path; if ($check_value eq $set_data) { - notify($ERRORS{'DEBUG'}, 0, "data structure updated: $data_identifier = $set_data"); + notify($ERRORS{'DEBUG'}, 0, "data structure updated: $hash_path\n$data_identifier = $set_data"); return sub {1;}; } else { @@ -1501,18 +1501,22 @@ =head2 get_variable - Parameters : $variable_name - Returns : If successful: reference to the data stored in the variable table for - the variable name specified + Parameters : variable name + Returns : If successful: data stored in the variable table for the variable name specified If failed: false - Description : Queries the variable table for the variable with the name specified by the subroutine argument. - Returns a reference to the data. + Description : Queries the variable table for the variable with the name + specified by the argument. Returns the data stored for the + variable. Values are deserialized before being returned if the + value stored was a reference. + + Undefined is returned if the variable name does not exist in the + variable table. =cut sub get_variable { my $self = shift; - my $name = shift; + my $variable_name = shift; # Check if subroutine was called as an object method unless (ref($self) && $self->isa('VCL::DataStructure')) { @@ -1521,7 +1525,7 @@ } # Check the arguments - if (!defined($name)) { + if (!defined($variable_name)) { notify($ERRORS{'WARNING'}, 0, "variable name argument was not supplied"); return; } @@ -1529,50 +1533,66 @@ # Construct the select statement my $select_statement .= <<"EOF"; SELECT -variable.value +variable.value, +variable.serialization FROM variable WHERE -variable.name = '$name' +variable.name = '$variable_name' EOF # Call the database select subroutine my @selected_rows = database_select($select_statement); # Check to make 1 sure row was returned - if (!...@selected_rows) { - notify($ERRORS{'WARNING'}, 0, "unable to execute select statement to retrieve variable '$name' from the database"); - return; - } - elsif (@selected_rows == 0){ - notify($ERRORS{'WARNING'}, 0, "variable '$name' does not exist in the database"); + if (!...@selected_rows){ + notify($ERRORS{'WARNING'}, 0, "unable to get value of variable '$variable_name', it does not exist in the database"); return; } elsif (@selected_rows > 1){ - notify($ERRORS{'WARNING'}, 0, "multiple rows exist in the database for variable '$name':\n" . format_data(\...@selected_rows)); + notify($ERRORS{'WARNING'}, 0, "unable to get value of variable '$variable_name', multiple rows exist in the database for variable:\n" . format_data(\...@selected_rows)); return; } # Get the serialized value from the variable row - my $serialized_value = $selected_rows[0]{value}; - - # Attempt to deserialize the value - # Use eval because Load() will call die() if it encounters an error + my $serialization_type = $selected_rows[0]{serialization}; + my $database_value = $selected_rows[0]{value}; my $deserialized_value; - eval '$deserialized_value = YAML::Load($serialized_value)'; - if ($EVAL_ERROR) { - notify($ERRORS{'WARNING'}, 0, "unable to deserialize the value using YAML::Load(): $serialized_value"); - return; - } - # Display the data type of the value retrieved from the variable table - if (my $deserialized_data_type = ref($deserialized_value)) { - notify($ERRORS{'DEBUG'}, 0, "returning $deserialized_data_type reference"); + # Deserialize the variable value if necessary + if ($serialization_type eq 'none') { + $deserialized_value = $database_value; + } + elsif ($serialization_type eq 'yaml') { + # Attempt to deserialize the value + # Use eval because Load() will call die() if it encounters an error + eval '$deserialized_value = YAML::Load($database_value)'; + if ($EVAL_ERROR) { + notify($ERRORS{'WARNING'}, 0, "unable to get value of variable '$variable_name', unable to deserialize value using YAML::Load(): $database_value"); + return; + } + + # Display the data type of the value retrieved from the variable table + if (my $deserialized_data_type = ref($deserialized_value)) { + notify($ERRORS{'DEBUG'}, 0, "data type of variable '$variable_name': $deserialized_data_type reference"); + } + else { + notify($ERRORS{'DEBUG'}, 0, "data type of variable '$variable_name': scalar"); + } + } + elsif ($serialization_type eq 'phpserialize') { + # TODO: find Perl module to handle PHP serialized data + # Add module to list of dependencies + # Add code here to call PHP deserialize function + notify($ERRORS{'CRITICAL'}, 0, "unable to get value of variable '$variable_name', PHP serialized data is NOT supported yet by the VCL backend, returning null"); + return; } else { - notify($ERRORS{'DEBUG'}, 0, "returning scalar ($deserialized_value)"); + notify($ERRORS{'CRITICAL'}, 0, "unable to get value of variable '$variable_name', serialization type '$serialization_type' is NOT supported by the VCL backend, returning null"); + return; } + notify($ERRORS{'DEBUG'}, 0, "retrieved variable '$variable_name', serialization: $serialization_type"); return $deserialized_value; } @@ -1580,20 +1600,33 @@ =head2 set_variable - Parameters : $variable_name, $variable_value + Parameters : variable name, variable value Returns : If successful: true If failed: false - Description : Inserts or updates a row in the variable table. This subroutine - will also update the variable.timestamp column. The - variable.setby column is automatically set to the filename and - line number which called this subroutine. + Description : Inserts or updates a row in the variable table. The variable name + and value arguments must be specified. + + The value can be a simple scalar such as a string or a reference + to a complex data structure such as an array of hashes. + + Simple scalar values are stored in the variable.value column + as-is and the variable.serialization column will be set to + 'none'. + + References are serialized using YAML before being stored. The + variable.value column will contain the YAML representation of the + data and the variable.serialization column will be set to 'yaml'. + + This subroutine will also update the variable.timestamp column. + The variable.setby column is automatically set to the filename + and line number which called this subroutine. =cut sub set_variable { my $self = shift; - my $name_argument = shift; - my $value_argument = shift; + my $variable_name = shift; + my $variable_value = shift; # Check if subroutine was called as an object method unless (ref($self) && $self->isa('VCL::DataStructure')) { @@ -1602,52 +1635,72 @@ } # Check the arguments - if (!defined($name_argument)) { + if (!defined($variable_name)) { notify($ERRORS{'WARNING'}, 0, "variable name argument was not supplied"); return; } - elsif (!defined($value_argument)) { + elsif (!defined($variable_value)) { notify($ERRORS{'WARNING'}, 0, "variable value argument was not supplied"); return; } + # Set serialization type to yaml if the value being stored is a reference + # Otherwise, a simple scalar is being stored and serialization is not necessary + my $serialization_type; + if (ref($variable_value)) { + $serialization_type = 'yaml'; + } + else { + $serialization_type = 'none'; + } + # Construct a string indicating where the variable was set from my @caller = caller(0); (my $calling_file) = $caller[1] =~ /([^\/]*)$/; my $calling_line = $caller[2]; my $caller_string = "$calling_file:$calling_line"; - # Attempt to serialize the value using YAML::Dump() - # Use eval because Dump() will call die() if it encounters an error - my $serialized_value; - eval '$serialized_value = YAML::Dump($value_argument)'; - if ($EVAL_ERROR) { - notify($ERRORS{'WARNING'}, 0, "unable to serialize the value using YAML::Dump(): $value_argument"); - return; + # Attempt to serialize the value if necessary + my $database_value; + if ($serialization_type eq 'none') { + $database_value = $variable_value; } - + else { + # Attempt to serialize the value using YAML::Dump() + # Use eval because Dump() will call die() if it encounters an error + + eval '$database_value = YAML::Dump($variable_value)'; + if ($EVAL_ERROR) { + notify($ERRORS{'WARNING'}, 0, "unable to serialize variable '$variable_name' using YAML::Dump(), value: $variable_value"); + return; + } + } + # Escape all single quote characters with a backslash # or else the SQL statement will fail becuase it is wrapped in single quotes - $serialized_value =~ s/'/\\'/g;; + $database_value =~ s/'/\\'/g;; # Assemble an insert statement, if the variable already exists, update the existing row my $insert_statement .= <<"EOF"; INSERT INTO variable ( name, +serialization, value, setby, timestamp ) VALUES ( -'$name_argument', -'$serialized_value', +'$variable_name', +'$serialization_type', +'$database_value', '$caller_string', NOW() ) ON DUPLICATE KEY UPDATE name=VALUES(name), +serialization=VALUES(serialization), value=VALUES(value), setby=VALUES(setby), timestamp=VALUES(timestamp) @@ -1656,10 +1709,10 @@ # Execute the insert statement, the return value should be the id of the row my $inserted_id = database_execute($insert_statement); if ($inserted_id) { - notify($ERRORS{'OK'}, 0, "set variable '$name_argument', id: $inserted_id"); + notify($ERRORS{'OK'}, 0, "set variable '$variable_name', variable id: $inserted_id, serialization: $serialization_type"); } else { - notify($ERRORS{'WARNING'}, 0, "failed to set variable '$name_argument'"); + notify($ERRORS{'WARNING'}, 0, "failed to set variable '$variable_name', serialization: $serialization_type"); return; }