nagivreddy93 has asked for the wisdom of the Perl Monks concerning the following question:

Hi Monks,

We have multiple host servers which are pinging continuously and stored in a hash format like key and value pairs.

Key and Values are different Hosts.

If the host is not pinging(DOWN), We have to remove the element from the hash and after removing the element from the hash we have opened the thread , which will run continuously till the host is pining(UP).

Once the host is pinging(UP), We need to add the pinging host element into the hash and thread will be closed for this host.

We have successfully updated(remove/add) the hash element before opening of any thread but after opening the thread we are unable to update(add/remove) the hash element.

Please help me why the hash element is not updating inside the thread loop?

below is the flow of code:
while(1)
{
   foreach $ESX (keys %hash)
   {
      &ping();
    }
}


sub ping()
{
   if(pinging)
   {
      return. ### host is pinging
   }
   else
   {
      1) We have removed the element from the hash
      UPDATE THE HASH ELEMENT
      3) Opened the thread, &ping_thread() (this thread will run continuously till the host is pinging.
   }
}


sub ping_thread()
{
    if(pinging)
   {
      add the elements to the hash
      UNABLE TO UPDATE THE HASH?
      return up;
   }
   else
   {
      while(1)
      {
         pinging time intervals
         val=&ping_thread();
         if(val eq up)
         {
             return the thread;
         }
       }
   }
}


Please help me why the hash element is not updating inside the thread loop?


TIA.
  • Comment on update the hash element in side the thread loop

Replies are listed 'Best First'.
Re: update the hash element in side the thread loop
by zentara (Cardinal) on Nov 30, 2009 at 14:22 UTC
    .... in addition to what BrowserUk said about shared variables..... remember only first level hash keys get shared when you thread share a hash....deeper levels need to be explicitly shared .... just in case you switch your design to a multi-level hash later..... it would be a hidden bug

    I'm not really a human, but I play one on earth.
    Old Perl Programmer Haiku
Re: update the hash element in side the thread loop
by moritz (Cardinal) on Nov 30, 2009 at 12:32 UTC

    Please show real, runnable code that exhibits your problem, not some pseudo code which forces us to guess what's wrong.

    Also take a look at threads::shared.

      below is the sample code:
      #! /usr/bin/perl #use strict; use threads; #use threads ( 'stack_size' => 64*4096 ); use threads::shared; use Net::Ping; use Data::Dumper; use DBD::Sybase; use Mail::Sendmail; use Net::SNMP; use DBI; require "./../routine/Vectr_Param.pl"; require "./../routine/Sql_Notify.pl"; require "./../routine/Log_Notify.pl"; ####################### # Retriving data using hash my %hash=(); my $dbh = DBI->connect("dbi:$Db_Product:$Db_Name","$Db_UserNam +e","$Db_Password"); my $show_select = "select * from ESX_INFO"; my $db_query1 = $dbh->prepare($show_select); $db_query1->execute(); my @hst_s=(); my @guest_s=(); my @get_svalues12=(); my ($hst,$guest,$server); while(@get_svalues12 = $db_query1->fetchrow_array()) { $server="@get_svalues12"; ($hst,$guest)= split(/\s/,$server); push(@hst_s,$hst); push(@guest_s,$guest); } for(my $i=0;$i<=$#hst_s;$i++) { my $m =0; if($hash{$hst_s[$i]} ne "") { $server=$hst_s[$i]; $m=$hash{$hst_s[$i]}; } if($m ne "0") { my $guest="$guest_s[$i]"." "."$m"; $hash{$hst_s[$i]}=$guest; } else { $hash{$hst_s[$i]}=$guest_s[$i]; } } #-----------------------USE of thread my $Main_Thread=1; my $Guest_Thread=1; $first=0; my ($k,$v,$l_href); my @arr_href=(); my @threads; while(1) { my $Main_Thread=1; my $Guest_Thread=1; foreach $ESX (keys %hash) { $date=`date +'%F:%R:%S:%N'`; $Guests = $hash{$ESX}; print "Key $ESX--->>> Values --->>>$Guests\n\n"; $Server_Ping=&Main_Pinging($ESX,$Main_Thread,"ESX_SERVER"); ($server_ip,$server_status)=split(/\-/,$Server_Ping); if($server_status eq "UP") { my @guest_server=split(/\s/,$Guests); foreach $guest (@guest_server) { $ESX_Guest_Thread="$Main_Thread"."-"."$Guest_T +hread"; $Guest_Ping=&Main_Pinging($guest,$ESX_Guest_Th +read,$ESX); $Guest_Thread++; } } $Main_Thread++; } $date1=`date +'%F:%R:%S:%N'`; ### print " Before time is --->$date After Time is ---> $date1\n"; sleep(10); $first++; } sub Main_Pinging() { $ESX_Guest_Server=shift; $ESX_Guest_Comb=shift; $ESX_Server=shift; my $p = Net::Ping->new(); if ($p->ping($ESX_Guest_Server,1)) { $p->close(); $Up="$ESX_Guest_Server"."-"."UP"; return $Up; } else { $Down="$ESX_Guest_Server"."-"."DOWN"."-"."$ESX +_Server"; print "Thread Opened -- $ESX_Guest_Server\n\n" +; $hash_hash=&Remove_Hash_Element(\%hash,$Down," +DS"); ### print "--REMOVE key and values --->$hash_hash\ +n\n"; push @thre,threads->new(\&pinging,$ESX_Guest_S +erver,$ESX_Server,$ESX_Guest_Comb); return $DOWN; } while($thread = shift (@thre)) { $res_close=$thread->join(); push(@res_c,$res_close); } print "--RES-->> @res_c\n\n"; } sub pinging() { $ESX_Guest=shift; $ESX_Ser=shift; $Thread_Count=shift; my $p = Net::Ping->new(); if ($p->ping($ESX_Guest,1)) { return "UP"; } else { while(1) { print "DOWN STATE\n\n"; sleep(10); $val=&pinging1($ESX_Guest,$ESX_Ser,$Th +read_Count); if($val eq "UP") { print "------------>>>>>>>Thre +ad goes to upstate--$ESX_Guest \n\n"; $UP="$ESX_Guest"."-"."UP"."-"."$ESX_Ser"; $add_hash=&Add_Hash_Element(\%hash,$UP,"US" +); return "UP"; } } } $p->close(); } sub pinging1() { $ESX_Guest1=shift; $ESX_Ser1=shift; $Thread_Count1=shift; my $p = Net::Ping->new(); if ($p->ping($ESX_Guest1,1)) { return "UP"; } else { return "DOWN"; } $p->close(); } sub Remove_Hash_Element() { $hash=shift; $down=shift; $status_value=shift; @res_m=(); @remove_g=(); @add_g=(); while(my( $ESX,$Guest) = each %{$hash} ) { #print "-->>SERVER IS $ESX-->>$Guest\n\n"; ### print "-->>>$down---$status_value\n"; ($Gue_ser_ip,$Status_ip,$Esx_S)=split(/\-/,$down); #### print "-->>SERVER IS $ESX-->>$Esx_S\n\n"; if($ESX eq "$Esx_S") { $res=$hash{$ESX}; @remove_g=split(/\s/,$res); foreach (@remove_g) { if($_ ne "$Gue_ser_ip") { push(@res_m,$_);} } $SERVER_GUEST=join(' ',@res_m); $$hash{$ESX} = $SERVER_GUEST; print "--->>REMOVING ELEMENT IS $Gue_ser_ip--$ +SERVER_GUEST-->>>@res_m\n"; } } }sub Add_Hash_Element() { $hash=shift; $down1=shift; $status_value1=shift; @res_m1=(); @add_g1=(); while(my( $ESX1,$Guest1) = each %{$hash} ) { #print "-->>SERVER IS $ESX-->>$Guest\n\n"; ### print "-->>>$down1---$status_value1\n"; ($Gue_ser_ip1,$Status_ip1,$Esx_S1)=split(/\-/,$down1); #### print "-->>SERVER IS $ESX-->>$Esx_S\n\n"; if($ESX1 eq "$Esx_S1") { $res1=$hash{$ESX1}; @add_g1=split(/\s/,$res1); push(@add_g1,$Gue_ser_ip1); ### print "NAGI--->>ADDING ELEMENT-----is ---$res1 +->@add_g1\n"; $SERVER_GUEST1=join(' ',@add_g1); ### $$hash{$ESX1} = $SERVER_GUEST1; &test_to_add($ESX1,$SERVER_GUEST1); print "-FFFFFFFF->ALLL-->>@add_g1\n---ALL1>>>$SERVER_GUEST1>>\nRES-->> +>$$hash{$ESX1}\n\n"; } } } sub test_to_add() { $v=shift; $g=shift; $hash{$v}=$g; print "--->>>MVOING --$hash{$v}\n"; return; }

        You've got use threads::shared; at the top of your code, but no where do you actually use it!

        Ie. You never mark anything shared using my %hash :shared;, nor do you call the exported subroutine share() anywhere.

        These are the only ways that threads can share variables. Without them, each thread will be operating on different variables (with the same name!).

        What difference does it make to how your program runs if you add?

        my %hash :shared;

        Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
        "Science is about questioning the status quo. Questioning authority".
        In the absence of evidence, opinion is indistinguishable from prejudice.