pastebin - collaborative debugging tool
kpaste.net RSS


flac test threaded
Posted by Anonymous on Mon 17th Sep 2012 21:59
raw | new post

  1. #!/usr/bin/perl
  2.  
  3. use 5.14.0;
  4. use strict;
  5. use warnings;
  6. use Cwd qw(abs_path);
  7.  
  8. use threads qw(yield);
  9. use threads::shared;
  10. use Thread::Queue;
  11. use Thread::Semaphore;
  12.  
  13. my $clear = `clear && echo`;
  14. chomp(my $cores = `grep -c ^processor /proc/cpuinfo`);
  15. my $library = "/home/sir/Music/Songbird Music";
  16. my $logf = "$ENV{HOME}/flac_test.log";
  17. my $n :shared = 0;
  18. my @err :shared;
  19. my $end :shared;
  20.  
  21. my %flac :shared;
  22. my %done :shared;
  23. my $total :shared = 0;
  24. my $disk_size = 1000000000;
  25.  
  26. # This will be used to control access to the logger subroutine.
  27. my $semaphore = Thread::Semaphore->new();
  28. my $semaphore2 = Thread::Semaphore->new();
  29. my $semaphore3 = Thread::Semaphore->new();
  30.  
  31. # Creating the thread queue.
  32. my $q = Thread::Queue->new();
  33.  
  34. open(my $LOG, '>>', $logf) or die "Can\'t open '$logf': $!"; # Open file handle for the log file
  35. $LOG->autoflush(1);     # Make the $LOG file handle unbuffered for instant logging.
  36. open(my $SE, ">&STDERR") or die "Can\'t duplicate STDERR: $!"; # Duplicate STDERR as a regular file handle
  37.  
  38. #sub msay {
  39. #       my @fh;
  40. #       push(@fh, shift) while (ref($_[0]) eq 'GLOB');
  41. #       say $_ @_ foreach (@fh);
  42. #}
  43.  
  44. sub getdirs {
  45.  
  46.         my $dn = $library;
  47.         my @dirs;
  48.  
  49.         open(FIND, '-|', qq{find -L "$dn" -name "*" -type d})
  50.         or die "Can't run 'find': $!";
  51.         push(@dirs, (<FIND>));
  52.         chomp(@dirs);
  53.         close(FIND) or die "Can't close 'find': $!";
  54.         return(@dirs);
  55. }
  56.  
  57. sub getfiles {
  58.         my $dn = shift;
  59.         my (@files, $fn);
  60.         opendir(my $dh, $dn) or die "Can\'t open directory '$_': $!";
  61.         foreach (readdir($dh)) {
  62.                 if (/.flac$/) {
  63.                         $fn = $dn . '/' . $_;
  64.                         push(@files, $fn) if -f $fn;
  65.                 }
  66.         }
  67.         closedir $dh or die "Can\'t close directory '$dn': $!";
  68.         return @files;
  69. }
  70.  
  71. #### Subroutine for controlling the log file
  72. sub logger {
  73.  
  74.         $semaphore->down();
  75.  
  76.         my($arg, $sw, $fn, $n);
  77.         my $now = localtime(time);
  78.         my @larg = qw{start int change end}; # Array of accepted switches to this subroutine
  79.        
  80.         #### Loop through all the arguments passed to this subroutine
  81.         #### Perform checks that decide which variable the arguments are to be assigned to
  82.         while (@_) {
  83.                        
  84.                         $arg = shift(@_);
  85.  
  86.                         foreach (@larg) {
  87.                                 if ($_ eq $arg) { $sw = $arg }
  88.                         }
  89.                         #### If $arg is a number assign it to $n, if it's a file assign it to $fn
  90.                         if ($arg =~ /^[0-9]*$/) { $n = $arg; }
  91.                         else { $fn = $arg; }
  92.         }
  93.        
  94.         given ($sw) {
  95.                 #### Starts writing the log
  96.                 when ('start') {
  97.                         say $LOG "\n**** Logging started on $now ****\n";
  98.                 }
  99.                 #### Called when file has been changed
  100.                 when ('change') {
  101.                         say $LOG $fn . "\n\t" . "has been corrupted.\n";
  102.                         lock(@err);
  103.                         push(@err, $fn);
  104.                 }
  105.                 #### Called when done, and to close the log
  106.                 #### If no errors occured write "Everything is OK!" to the log
  107.                 #### If errors occurred print the @err array
  108.                 #### Either way, print number of files processed
  109.                 when ('end') {
  110.                         if (!@err) {
  111.                                 say $LOG "\nEverything is OK!\n";
  112.                         } else {
  113.                                 foreach my $fn (@err) {
  114.                                         say $SE "ERROR: " . $fn;
  115.                                 }
  116.                         }
  117.  
  118.                         say $LOG $n . " file(s) were tested.\n" if ($n);
  119.                         say $LOG "\n**** Logging ended on $now ****\n";
  120.                         close $LOG or die "Can\'t close '$LOG': $!";
  121.                 }
  122.         }
  123.         $semaphore->up();
  124. }
  125.  
  126. sub ram {
  127.                 my $fn = shift;
  128.                 my $size = (stat($fn))[7];
  129.                 open(FILE, '<:raw', $fn) or die "Can't open '$fn': $!";
  130.                 read(FILE, $flac{$fn}, $size);
  131.                 close(FILE) or die "Can't close '$fn': $!";
  132.                 $semaphore2->down();
  133.                 $done{$fn} = 1;
  134.                 $total += length($flac{$fn});
  135.                 $semaphore2->up();
  136. }
  137.  
  138. sub test {
  139.  
  140.         while (!$q->pending() && !$end) {
  141.                 yield();
  142.         }
  143.  
  144.         my $tid = threads->tid();
  145.  
  146.         LOOP: while (my $fn = $q->dequeue_nb()) {
  147.  
  148.                 say "thread${tid} $fn: testing...";
  149.                 my $pid = open(FLAC, '|-:raw', qq{flac --totally-silent --test -})
  150.                 or die "can't run 'flac': $!";
  151.                 print FLAC $flac{$fn};
  152.                 close(FLAC);
  153.  
  154.                 my $status = ${^CHILD_ERROR_NATIVE};
  155.  
  156.                 if ($status != 0 && $status != 2) {
  157.                         say $pid;
  158.                         kill 9, $pid;
  159.                         close(FLAC) or die "Can't close 'flac': $!";
  160.                         logger('change', $fn);
  161.                 }
  162.  
  163.                 $semaphore3->down();
  164.                 $total -= length($flac{$fn});
  165.                 delete($flac{$fn});
  166.                 $n++;
  167.                 $semaphore3->up();
  168.         }
  169.  
  170.         if (!$q->pending() && !$end) {
  171.                 say "thread${tid}: yielding!";
  172.                 yield();
  173.                 goto(LOOP);
  174.         }
  175. }
  176.  
  177. say "Starting threads";
  178. my @threads;
  179. foreach (1 .. $cores) {
  180.         push(@threads, threads->create(\&test));
  181. }
  182.  
  183. logger('start');
  184.  
  185.  
  186. foreach my $dn (getdirs) {
  187.         my @files = getfiles($dn);
  188.  
  189.         foreach my $fn (@files) {
  190.                 my $running_threads = threads->list(threads::running);
  191.                 my $pending = $q->pending();
  192.                 say "$running_threads running threads : $pending pending files : $total bytes in RAM";
  193.  
  194.                 ram($fn);
  195.  
  196.                 # If the RAM disk is full, put decoded files in the queue,
  197.                 # and then yield until the LAME threads have cleared some RAM.
  198.  
  199.                 while ($total > $disk_size) {
  200.                         foreach my $fn (keys(%done)) {
  201.                                 $q->enqueue($fn);
  202.                                 lock(%done);
  203.                                 delete($done{$fn});
  204.                         }
  205.                         yield();
  206.                 }
  207.         }
  208.  
  209.         foreach my $fn (keys(%done)) {
  210.                 $q->enqueue($fn);
  211.                 lock(%done);
  212.                 delete($done{$fn});
  213.         }
  214. }
  215.  
  216. $end = 1;
  217. foreach my $t (threads->list()) { $t->join(); }
  218. say("All threads joined");
  219. logger('end', $n);

Submit a correction or amendment below (click here to make a fresh posting)
After submitting an amendment, you'll be able to view the differences between the old and new posts easily.

Syntax highlighting:

To highlight particular lines, prefix each line with {%HIGHLIGHT}




All content is user-submitted.
The administrators of this site (kpaste.net) are not responsible for their content.
Abuse reports should be emailed to us at