[padb-devel] [padb] r148 committed - Strip out all the range code I wrote yesterday and replace it ...

codesite-noreply at google.com codesite-noreply at google.com
Tue Aug 25 11:03:15 BST 2009


Revision: 148
Author: apittman
Date: Tue Aug 25 03:02:09 2009
Log: Strip out all the range code I wrote yesterday and replace it
with something simpler and faster.  Add a new set of rng_ functions that
work with ranges in a array rather than converting back to a string each
time.

http://code.google.com/p/padb/source/detail?r=148

Modified:
  /trunk/src/padb

=======================================
--- /trunk/src/padb	Tue Aug 25 02:51:02 2009
+++ /trunk/src/padb	Tue Aug 25 03:02:09 2009
@@ -3188,7 +3188,7 @@
          PeerAddr => $host,
          PeerPort => $port,
          Proto    => 'tcp',
-    ) or die("Failed to connect to child ($host:port)");
+    ) or die("Failed to connect to child ($host:$port)");

      print $socket "hello $word\n";

@@ -3474,7 +3474,8 @@
      if ( defined $d->{target_error} ) {
          printf("Warning: errors reported by some ranks\n========\n");
          foreach my $error ( sort( keys( %{ $d->{target_error} } ) ) ) {
-            printf("$d->{target_error}{$error}: $error\n");
+            printf( "%s: $error\n",
+                rng_convert_to_user( $d->{target_error}{$error} ) );
          }
          printf("========\n");
      }
@@ -3588,175 +3589,154 @@
      $comm_data->{sockets}{$new} = \%cdata;
  }

-sub sub_range_assemble {
-    my ( $lower, $upper ) = @_;
-
-    if ( $lower == $upper ) {
-        return $lower;
-    } else {
-        return "$lower-$upper";
-    }
-}
-
-sub add_value_to_range {
-    my ( $range, $value ) = @_;
-
-    if ( $range =~ m/^\[([\d\-\,]+)\]$/ ) {
-        $range = $1;
-    } else {
-        carp("Bad range $range");
-        printf("Bad range $range");
-        return undef;
-
-    }
-
-    my @parts;
-
-    my $added = 0;
-
-    # Walk through the individal contigous sub-ranges adding the
-    # value to any subrange it's adjacent to.  If it falls between two
-    # then insert it as a new subrange, if it's not found then add it
-    # after the last subrange.
-    # If a sub-range is extended upwards then it's possible it not
-    # meets the subsequent one so handle that case as well.
-
-    my $prev_part_upper;
-    my $prev_part_lower;
-
-    foreach my $part ( split( ",", $range ) ) {
-        my $lower;
-        my $upper;
-
-        if ( $part =~ m/^(\d+)$/ ) {
-            $lower = $1;
-            $upper = $1;
-        } elsif ( $part =~ m/^(\d+)\-(\d+)$/ ) {
-            $lower = $1;
-            $upper = $2;
-        } else {
-            carp("Bad range $range");
-            return undef;
-        }
-
-        if ( not $added ) {
-            if ( $lower == $value + 1 ) {
-                $lower--;
-                $added = 1;
-            } elsif ( $upper == $value - 1 ) {
-
-                # Extend the current part upwards to include the new value.
-                $upper++;
-                $added           = 1;
-                $prev_part_upper = $upper;
-                $prev_part_lower = $lower;
-                next;
-            } elsif ( $lower > $value ) {
-
-                # If we have skipped over the value then add it now.
-                # note that we are adding it here and hence cannot have  
extended
-                # the last sub-range.
-                push( @parts, $value );
-                $added = 1;
-            }
-        }
-
-        if ( defined $prev_part_upper ) {
-
-            # We have extended a segment.
-            if ( $prev_part_upper == $lower - 1 ) {
-                $part = sub_range_assemble( $prev_part_lower, $upper );
-                push( @parts, $part );
-            } else {
-                $part =
-                  sub_range_assemble( $prev_part_lower, $prev_part_upper );
-                push( @parts, $part );
-                $part = sub_range_assemble( $lower, $upper );
-                push( @parts, $part );
-            }
-            undef($prev_part_upper);
-            undef($prev_part_lower);
+###############################################################################
+#
+# Range mapping functions.
+#
+###############################################################################
+
+# A common set of functions for dealing with (integer based) ranges.
+#
+# Internally a array format is used for speed, functions exist to convert  
from
+# the normal list format "[0-12,15,16]" to the internal one and back again.
+
+# rng_convert_from_user($userrange)
+# rc_convert_to_user($range)
+# Convert to and from the normal type to the internal type.
+
+# rng_shift($range)
+# Pop the lowest value off the range.
+
+# rng_add_value($range,$value)
+# Add a value to the range.
+
+# rng_merge($range,$new)
+# Merge two ranges.
+
+# Potentially needed but not implemented yet
+
+# rng_user_verify()
+# is_value_in_range()
+# nvalues_in_range()
+
+# Convert from a user range to a internal one.
+sub rng_convert_from_user {
+    my ($range) = @_;
+
+    return undef unless defined $range;
+    return undef if $range eq "";
+    return undef if $range eq "[]";
+
+    my $newrange;
+
+    if ( $range =~ m/^\[([\d\-\,]+)\]$/ ) {
+        $newrange = $1;
+    } elsif ( $range =~ m/^(\d+)$/ ) {
+        $newrange = $1;
+    } else {
+        confess("Failed to recognise $range as range\n");
+    }
+
+    my @user_parts = split( ",", $newrange );
+
+    my @parts;
+
+    foreach my $part (@user_parts) {
+        my %part;
+        if ( $part =~ m/^(\d+)$/ ) {
+            $part{l} = $1;
+            $part{u} = $1;
+        } elsif ( $part =~ m/^(\d+)\-(\d+)$/ ) {
+            $part{l} = $1;
+            $part{u} = $2;
          } else {
-            $part = sub_range_assemble( $lower, $upper );
-            push( @parts, $part );
-        }
-    }
-
-    if ( defined $prev_part_upper ) {
-        my $part = sub_range_assemble( $prev_part_lower, $prev_part_upper  
);
-        push( @parts, $part );
-    }
-
-    # If we haven't add it stick it on the end now.
-    if ( not $added ) {
-        push( @parts, $value );
-    }
-
-    my $newrange = join( ",", @parts );
-
-    return "[$newrange]";
+            confess("Failed to recognise $part as range\n");
+        }
+        push( @parts, \%part );
+    }
+    return \@parts;
+}
+
+sub rng_convert_to_user {
+    my ($rg) = @_;
+
+    my @entries;
+    foreach my $part ( @{$rg} ) {
+        if ( $part->{l} == $part->{u} ) {
+            push( @entries, $part->{l} );
+        } else {
+            push( @entries, "$part->{l}-$part->{u}" );
+        }
+    }
+    my $range = join( ",", @entries );
+    return "[$range]";
  }

-# Merge two port ranges.  For now just do the simple thing,
-# this really needs to be re-visited from a scalability aspect however.
-sub merge_ranges {
-    my ( $left, $right ) = @_;
-
-    my ( $val, $range ) = shift_from_range($right);
-
-    while ( defined $val ) {
-        $left = add_value_to_range( $left, $val );
-        ( $val, $range ) = shift_from_range($range);
-    }
-
-    return "[$left]";
+sub rng_shift {
+    my ($rg) = @_;
+
+    # Return undef if this range is empty.
+    return undef if ( $#{$rg} == -1 );
+
+    my $value = $rg->[0]->{l};
+    if ( $rg->[0]->{l} == $rg->[0]->{u} ) {
+        shift( @{$rg} );
+    } else {
+        $rg->[0]->{l}++;
+    }
+    return $value;
  }

-# "shift" a rank or port number from the standard spec format, returns the  
id
-# and the range with the first entry removed.  Returns both the first  
entry and
-# the new range with the first removed.
-sub shift_from_range {
-    my ($range) = @_;
-
-    my $newrange;
-
-    return undef unless defined $range;
-    return undef if $range eq "";
-    return undef if $range eq "[]";
-
-    if ( $range =~ m/^\[([\d\-\,]+)\]$/ ) {
-        $newrange = $1;
-    } elsif ( $range =~ m/^(\d+)$/ ) {
-        $newrange = $1;
-    } else {
-        die("Failed to recognise $range as range\n");
-    }
-
-    my @parts = split( ",", $newrange );
-
-    my $part = shift(@parts);
-
-    my $id;
-
-    if ( $part =~ m/^(\d+)$/ ) {
-        $id = $1;
-    } elsif ( $part =~ m/^(\d+)\-(\d+)$/ ) {
-        my $lower = $1;
-        my $upper = $2;
-        $id = $lower;
-        if ( $lower > $upper ) {
-            die("Invalid range $lower-$upper\n");
-        }
-        if ( $lower++ != $upper ) {
-            unshift( @parts, "$lower-$upper" );
-        }
-    } else {
-        confess("Failed to recognise $part as range\n");
-    }
-
-    my $r = join( ",", @parts );
-
-    return ( $id, "[$r]" );
+sub rng_add_value {
+    my ( $rg, $value ) = @_;
+
+    # If it's after the last value then just add it.
+    if ( $value > $rg->[-1]->{u} + 1 ) {
+        push( @{$rg}, { 'l' => $value, 'u' => $value } );
+        return;
+    }
+
+    my $idx = 0;
+    foreach my $part ( @{$rg} ) {
+
+        if ( $value == $part->{l} - 1 ) {
+
+            # Extend the current entry downwards.
+            $part->{l}--;
+            return;
+        } elsif ( $value < $part->{l} ) {
+
+            # If it's before the current entry then insert it.
+            splice( @{$rg}, $idx, 0, { 'l' => $value, 'u' => $value } );
+            return;
+        } elsif ( $value == $part->{u} + 1 ) {
+
+            # Extend the current entry upwards.
+            $part->{u}++;
+
+            # If we meet the subsequent entry then merge the two.
+            if ( exists $rg->[ $idx + 1 ]
+                and $part->{u} + 1 == $rg->[ $idx + 1 ]->{l} )
+            {
+                $part->{u} = $rg->[ $idx + 1 ]->{u};
+                splice( @{$rg}, $idx + 1, 1 );
+            }
+            return;
+        }
+        $idx++;
+    }
+    confess("Failed to add value to range");
+}
+
+sub rng_merge {
+    my ( $rg, $new ) = @_;
+
+    # Need to use defined here as zero is a valid value to store
+    # in a range.
+    while ( defined( my $val = rng_shift($new) ) ) {
+        rng_add_value( $rg, $val );
+    }
+    return;
  }

  sub create_local_port {
@@ -3774,18 +3754,15 @@
          return $sl;
      }

-    my $irange = $range;
-    my $port;
-
-    while ( ( $port, $range ) = shift_from_range($range) and defined $port  
) {
+    my $rg = rng_convert_from_user($range);
+
+    while ( my $port = rng_shift($rg) ) {
          $options{LocalPort} = $port;
          my $sl = IO::Socket::INET->new(%options);
          return $sl if defined $sl;
-
-        #$range = $nrange;
      }

-    die("Failed to create local port, no free ports in range  
\"$irange\"\n");
+    die("Failed to create local port, no free ports in range  
\"$range\"\n");
  }

  sub go_parallel {
@@ -4413,10 +4390,9 @@
      my ( $rank, $error ) = @_;

      if ( defined $inner_error{$error} ) {
-        $inner_error{$error} =
-          add_value_to_range( $inner_error{$error}, $rank );
+        rng_add_value( $inner_error{$error}, $rank );
      } else {
-        $inner_error{$error} = "[$rank]";
+        $inner_error{$error} = rng_convert_from_user($rank);
      }
  }

@@ -6616,8 +6592,7 @@
      # Merge in local target responces.
      foreach my $key ( keys(%inner_error) ) {
          if ( defined $handle->{all_replys}->{target_error}{$key} ) {
-            $handle->{all_replys}->{target_error}{$key} =
-              merge_ranges( $handle->{all_replys}->{target_error}{$key},
+            rng_merge( $handle->{all_replys}->{target_error}{$key},
                  $inner_error{$key} );
          } else {
              $handle->{all_replys}->{target_error}{$key} =  
$inner_error{$key};




More information about the padb-devel mailing list