2010-06-22 9 views
2

Quelqu'un peut-il me dire pourquoi j'ai des erreurs en ouvrant le fichier dans le code ci-dessous? Les erreurs commencent à la moitié de la 9ème itération de 25 threads, et sont des erreurs "Trop de fichiers ouverts". L'erreur se produit uniquement lors de l'exécution dans les threads et uniquement lorsque DBI connect/disconnect est utilisé. Cela ne devrait pas affecter le nombre de fichiers ouverts du tout devrait-il? Je suis assez nouveau à Perl donc je ne sais pas si j'ai fait quelque chose de bizarre. C'est sur Perl 5.8.8. sur Solaris 10.Perl - Trop d'erreur de fichiers lors de l'utilisation de DBD Oracle

use threads(); 
use DBI; 
use DBD::Oracle; 

my $thrds=25; 
my $iter=10; 
my @threads; 

for (my $j=0; $j<$iter; $j++) { 
    &start($j); 
} 

sub start { 
    my $k=$_[0]; 
    for (my $i=0; $i<$thrds; $i++) { 
     $threads[$i] = threads->new(\&RunThread,$k, $i); 
    } 
    for (my $i=0; $i<$thrds; $i++) { $threads[$i]->join; } 
} 

sub RunThread { 
    my $dbh = DBI->connect("dbi:Oracle:lnrmsd9.world", "rms_reader", "rms_reader") or die "failed connect"; 
    my ($x, $y)[email protected]_; 
    open (my $fh, ">/tmp/da") or die "failed $! at iter $x thread $y"; 
    close ($fh); 
    $dbh->disconnect; 
} 
+1

La petite icône binaire de l'éditeur sert à coller du code. (Voir le guide d'aide du balisage.) – Ether

+0

J'ai utilisé cela et cela n'a pas fonctionné pour une raison quelconque. Quoi qu'il en soit, OK maintenant, merci –

Répondre

5

Vous devez utiliser:

use warnings; 
use strict; 

Ceux-ci vous dire que vous utilisez des variables globales $ i et j $ dans le sous-programme. Puisque vous avez plusieurs threads accédant aux variables, tout l'enfer se déchaîne. En outre, ils partagent tous un seul fichier, une autre source de problèmes. Et avez-vous réalisé que vous aviez à la fois un '$ threads scalaire' et un tableau '@threads'?

Avec les threads, les variables globales sont ... bien, sinon exactement l'ennemi, extrêmement problématique. Evitez le format de poignée FILE (open); utilisez my beaucoup plus généreusement.

Et vous n'avez pas besoin de dire 'use DBD :: Oracle;' déjà. Vous devrez parfois utiliser la variante:

use DBD::Oracle qw(:ora_types); 

pour accéder aux types de données spécifiques à Oracle.


révision Untested:

use strict; 
use warnings; 
use threads(); 
use DBI; 
use DBD::Oracle; 

my $threads=25; 
my $iter=10; 

for ($j = 0; $j < $iter; $j++) { 
    &start($j); 
} 

sub start { 
    my($j) = @_; 
    my(@threads); 
    for (my $i = 0; $i < $threads; $i++) { 
     $threads[$i] = threads->new(\&RunThread,$j, $i); 
    } 
    for ($i=0; $i < $threads; $i++) { $threads[$i]->join; } 
} 

sub RunThread { 
    my $dbh = DBI->connect("dbi:Oracle:ora", "user", "pass") or die "failed connect"; 
    my($j, $i) = @_; 
    open(my $fh, ">/tmp/da") or die "failed $! at iter $j thread $i"; 
    close $fh; 
    $dbh->disconnect; 
} 

Une chose que je ne comprenais pas - pourquoi je ne devrais pas utiliser use DBD::Oracle;?

Si vous regardez le 'perldoc DBD :: Oracle', vous verrez le Synopsis:

use DBI; 

$dbh = DBI->connect("dbi:Oracle:$dbname", $user, $passwd); 

Ainsi, la documentation principale du module DBD :: Oracle montre que vous n'utilisez pas directement.

Il n'y a pas de mal à l'utiliser; il n'y a pas besoin de l'utiliser. Le module DBI charge automatiquement le pilote impliqué par la chaîne de connexion dans l'appel à DBI->connect(). En écrivant use DBD::Oracle;, vous évitez à DBI d'effectuer le chargement (c'est déjà fait). Je suppose que vous obtenez également Perl pour vérifier que le module est disponible pour être chargé avec la clause use.

+0

+1. Perl est l'un des langages les plus faciles pour se tirer une balle dans le pied: Il y a tellement de façons de se tirer une balle dans le pied que vous postez une requête sur comp.lang.perl.misc pour déterminer l'approche optimale.Après avoir passé au crible 500 réponses (que vous accomplissez avec un court script Perl), vous vous êtes fixé comme objectif de vous photographier simplement et élégamment dans le pied, jusqu'à ce que vous découvriez que, dans la plupart des cas, Windows, VMS et divers Les saveurs de Linux vous permettent de vous shooter plus vite que votre script Perl. ;-) – DCookie

+0

Perl donne également de bons diagnostics pour la fixation des coups de pied - si le programmeur choisit de les utiliser. – Ether

+0

Aucun argument ici! – DCookie

1

Essayez

my $FILE; 
open ($FILE, ">/tmp/da") or die "failed $! at iter $j thread $i"; 
close ($FILE); 

Ceci est la meilleure pratique.

+0

Merci, essayé, mais pas de changement –