use strict;use warnings;use threads; use threads::shared; use File::Slurp; use Digest::MD5; use Thread::Queue;use Thread::Semaphore; main(@ARGV); sub main { my ($dir,$limit) = @_; my $q= Thread::Queue->new(); unless ($dir) {$dir = 'F:/';} unless($limit){$limit = 3145728; } #example my $done:shared; my %mem:shared; $done = 'n'; %mem = ( limit => $limit, total => 0, t_sem=> Thread::Semaphore->new(), f_count => 0, ); my $thread = threads->create(\&slurp_directory_as_bin,$dir,\$q,\%mem,\$done); my $thread2 = threads->create(\&procqueue,\$q,\$done,\%mem); #my $thread3 = threads->create(\&procqueue,\$q,\$done,\%mem); #my $thread4 = threads->create(\&procqueue,\$q,\$done,\%mem); $thread->join(); print("concluded directory listing\n"); $thread2->join(); #$thread3->join(); #$thread4->join(); print("\nit is done, move on.") } sub procqueue{ my ($q,$done,$mem) = @_; while ($$done eq 'n'){ while ( my $bl = $$q->dequeue_nb()){ #to be replaced with darker magic once this works print("$$bl{name} ($$bl{fpath}) is $$bl{size} and it's md5 is : " . Digest::MD5::md5_hex($$bl{bin}) . "\n"); $$mem{t_sem}->down(); $$mem{total} = $$mem{total} - $$bl{size}; print("popped to $$mem{total} with ". $$q->pending()."left\n"); $$mem{t_sem}->up(); if($$mem{total} < 0){print("HAAALT!"); exit;} } sleep 1; print("thread waiting...\n"); } } sub slurp_directory_as_bin{ my ($dir,$queue,$mem,$r) = @_; unless($dir and (-d $dir)){die("first parameter to slurp_directory_as_bin must be a valid directory [$!]"); } unless($dir =~ m|/$|){$dir .= '/';} # add on trailing slash for good measure my @subdirs = ();#list of subdirectories found in the directory, only used in [r]ecursive mode opendir(DIR,$dir); while (my $file = readdir(DIR)){ next if ($file eq '.'|| $file eq '..' ); #skip self and parent dir next if ($file eq 'RECYCLER' || $file eq 'System Volume Information'); #skip problem directories on windows root paths my $fpath =$dir.$file; if (-d $fpath){#if the current specimen is a directory if ($r){#if in recursive mode push (@subdirs,$fpath); #put the reference to the subdirectory in storage for later } next;#dont try to process (yet) } my $bina = File::Slurp::read_file( $fpath, binmode => ':raw' ); #consume the file as it's component parts into memory my %data = ( bin => $bina, name => $file, fpath => $fpath, size => -s $fpath, ); my $nqd = 1; while ($nqd == 1){ #wait here until we can add the file into the queue unless($data{size} < $$mem{limit}){die("$data{fpath} is larger than the total memory limit"); } my $new_total = $$mem{total} += $data{size}; if ($new_total <= $$mem{limit} ){ $$mem{t_sem}->down(); $$mem{total} += $data{size}; $$queue->enqueue(\%data); $$mem{t_sem}->up(); $$mem{f_count}++; $nqd = 0; }else{ print("waiting for space in the queue for $data{fpath}, trying to add $data{size} to $$mem{total} to make $new_total with a limit of $$mem{limit} \n"); print($$queue->pending() . "items left \n"); #sleep 1; $new_total = $$mem{total} + $data{size}; # recheck in case it's changed since then... } } } # end of files in directory foreach my $sdir (@subdirs){ slurp_directory_as_bin($sdir,$queue,$mem,$r); } }