I am writing my Cassandra cache class in Perl 5.18.2 with Net::Async::CassandraCQL.
This is my just test example:
# in first subroutine
$self->_loop( new IO::Async::Loop );
$self->_cacheIO(new Net::Async::CassandraCQL(
host => $self->server->{ ip },
service => $self->server->{ port },
keyspace => $self->_keyspace,
default_consistency => CONSISTENCY_QUORUM,));
$self->_loop()->add( $self->_cacheIO );
$self->_cacheIO()->connect->get;
# in second subroutine
$self->_cacheIO()->query( "INSERT INTO cacheTable (key, value) VALUES ('keeeey1', 'you will pay');" )->get();
And i am getting this error on insert query:
IO::Async::Future=HASH(0x2e8a4b8) IO::Async::Future=HASH(0x2e8a4b8) lost a sequence Future at /usr/local/share/perl/5.18.2/Net/Async/CassandraCQL/Connection.pm line 231.
I already read this https://rt.cpan.org/Public/Bug/Display.html?id=97260
so it could be bug. But i think that maybe it could be overcome with IO::Async::Notifier adopt_future method. Do you have any experience with notifier and future. Any examples? Any ideas for the error and how to solve it.
Maybe it will be better to ask how to do this synchronous?
PERL_FUTURE_DEBUG=1 perl ./test.pl
(in cleanup) ERROR CODE #5
IO::Async::Future=HASH(0x5607cd8) was constructed at /usr/local/share/perl/5.18.2/Net/Async/CassandraCQL/Connection.pm line 595 and was lost near /usr/local/share/perl/5.18.2/Future.pm line 346 before it was ready.
IO::Async::Future=HASH(0x560f1a0) (constructed at /usr/local/share/perl/5.18.2/IO/Async/Loop.pm line 553) lost a sequence Future at /usr/local/share/perl/5.18.2/Net/Async/CassandraCQL/Connection.pm line 231.
(in cleanup)
IO::Async::Future=HASH(0x56030b8) was constructed at /usr/local/share/perl/5.18.2/Net/Async/CassandraCQL/Connection.pm line 504 and was lost near /usr/local/share/perl/5.18.2/Carp.pm line 168 before it was ready.
Its very strange, when i get this error and select the database i can see that inserted data are in table...
Update: ist not error but warning.
This was reported as a bug some time ago. It has since been fixed; see
https://rt.cpan.org/Ticket/Display.html?id=97260
Related
I have a server that also counts the number of distinct IPs connected in a minute. I get a "Modification of a read-only value attempted" in the marked line in the code below:
$lsock=new IO::Socket::INET(LocalPort=>$port,Proto=>'tcp',Listen=>1,Reuse=>1);
$clients={};
while (1) {
$sock=$lsock->accept();
if ($sock) {
$clients->{$sock->peerhost()}=1; # THIS LINE !!!
...
}
}
# then later from an alarm signal I do:
sub save_stats {
my $cnt=scalar keys %$clients;
$clients={};
...
}
The error appears very rarely, once a month or less, but it's driving me insane, can someone please explain it to me why and what can I do?
After a lot of investigation I found the answer. It can happen that the connection is lost between accept() and peerhost(). In this case the peeerhost() function's return value is not suitable as a hash key. The solution is very simple, if peerhost() returns a "false" ignore the connection alltogether.
When I asked a question last year about promises, my echo server was working (see this link: perl6 how to get specific identity of promises? ). However, with the new versions of perl6, my echo server is no longer working.
I guess I can try the example from the perl6 documentation site ( https://docs.perl6.org/type/IO::Socket::INET ), but I want to find out what mistake I have made in my code. My current level has precluded me from seeing the difference between my codes and the codes on the perl6 documentation site. Please give me a hint; thanks !
my #result;
for 0 .. 2 -> $index {
#result[$index] = start {
my $myPromiseID = $index;
say "======> $myPromiseID\n";
my $rsSocket = IO::Socket::INET.new:
localhost => 'localhost',
localport => 1234 + $index,
listen => 1;
while $rsSocket.accept -> $rsConnection {
say "Promise $myPromiseID accepted connection";
while $rsConnection.recv -> $stuff {
say "Promise $myPromiseID Echoing $stuff";
$rsConnection.print($stuff);
}
$rsConnection.close;
}
}
}
await #result;
And the error messages are:
Tried to get the result of a broken Promise
in block <unit> at p6EchoMulti.pl line 24
Original exception:
Nothing given for new socket to connect or bind to
in block at p6EchoMulti.pl line 8
Actually thrown at:
in block at p6EchoMulti.pl line 13
This commit, which was announced in the Jan 2017 section of Rakudo's changelog as "Fixed bug where IPv6 URIs were not parsed correctly" did a lot more that just fix a URI parsing bug. It also completely redid the parameter binding/validation of an IO::Socket::INET.new call, and one consequence is it broke your code because the updated code requires that listen be an actual Bool, not merely coerce to one.
The old code (the code on the left of the commit link above) had a simple method new (*%args is copy). This matched your call. The error (fail "Nothing given for new socket to connect or bind to") did not trigger because 1 evaluates to True in a boolean context so %args<host> || %args<listen> was also True. So the rest of the code ran with listen set to 1 and it all worked out fine.
Rakudos from 2017.01 have the code on the right at the commit link above. Note how there are now multiple new methods (i.e. multiple multi method new ... declarations).
The multi(s) intended to handle a call that specifies a listen argument is/are of the form multi method new (..., Bool:D :$listen!, ...). Note the Bool:D.
A call to new, with the listen parameter set to True, matches this multi and works as expected.
But a call with :listen(1) will just match the generic multi method new (*%args) signature instead. This latter does an unconditional fail "Nothing given for new socket to connect or bind to";.
Okay, after some struggling, it seems to have improved if I changed listen=>1 to listen=>True.
Can anyone care to explain why 1 was not evaluated to True, and why it worked before?
Thanks.
I'm checking with MongoDB application. There is application installed on my system, when I enter single quote(') in the input box it pop up the following error:
A problem occurred in a Python script. Here is the sequence of function calls leading up to the error, in the order they occurred.
/usr/lib/cgi-bin/mongo/2.2.3/dbparse.py in ()
41 print "</th>"
42 if where:
=> 43 for record in collection.find(where):
44 print "<tr>"
45 print "<td align=\"center\">"+record["test"]+"</td>"
record undefined, collection = Collection(Database(MongoClient('localhost', 27017), u'test_d'), u'london_garages'), collection.find = <bound method Collection.find of Collection(Data...', 27017), u'test_d'), u'l_g')>, where = {'$where': "this.test== ''--'"}
What is the meaning of the error? If you have another pointer to check the security of this application please let me know.
If you look at the error and the following part:
where = {'$where': "this.test== ''--'"}
I assume the single quote goes to the where clause (some sort of search), so your code is probably something like the following:
where = {'$where': "this.test== '[YOUR TEXT BOX INPUT]--'"}
A single quote terminated your where clause prematurely. This is a good demonstration for a NoSQL injection.
I wrote a procedure which imports data from an xml-file into a MariaDB using library DBI. The procedure works but I don't understand why the following code gives me the message:
use of uninitialized value $DBI::err in concatenation (.) or string at ...
Here the code (abbreviated):
my $insert_art = $dbh->prepare(
"INSERT INTO odbb_articles (creation_dt,ref_data,comp_no)".
"VALUES (?,?,?)"
);
....
my $comp_no = $xpc->findvalue('./sr:ARTCOMP/sr:COMPNO',$node1);
....
$insert_art->execute($creation_dt,$ref_data,$comp_no)
or die "Fehler bei der Ausfuehrung: ".
"$DBI::err -> $DBI::errstr (odbb_articles $DBI::state)\n";
If I insert the code
if ($comp_no eq "") { $comp_no = undef; }
just before $insert_art->execute the procedure works. This error happens when there is no entry in the xml-file for element COMPNO. I can avoid it if I define it as undef. I just wonder
why $comp_no cause this problem and
is there another solution than to control if $comp_no is "" and define it as undef?
The reason for the second question is to avoid the if statement if there are a lot of variables/columns which may have empty entries.
Thanks for help.
use of uninitialized value $DBI::err in concatenation (.) or string at ...
The error message you are seeing is Perl telling you that $DBI::err is undef. That is not because of the value of your $comp_no. It's just a result of what your program is doing.
So when you pass an empty string to the comp_no column, the database doesn't like that. It throws an error. DBI catches that error and passes it on. The $insert_art->execute returns a false value and the right-hand-side of the or gets called. That's your die.
Now in the string that you pass to die you put three variables:
$DBI::err
$DBI::errstr
$DBI::state
According to the DBI documentation, those are equivalent to the functions $h->err, $h->errstr and $h->state with $h being the last handle used. Let's look at the docs for those.
$h->err
Returns the native database engine error code from the last driver method called. The code is typically an integer but you should not assume that.
The DBI resets $h->err to undef before almost all DBI method calls, so the value only has a short lifespan. Also, for most drivers, the statement handles share the same error variable as the parent database handle, so calling a method on one handle may reset the error on the related handles. [...]
This does not explain when it can be undef.
$h->errstr
Returns the native database engine error message from the last DBI method called. This has the same lifespan issues as the "err" method described above.
The returned string may contain multiple messages separated by newline characters.
The errstr() method should not be used to test for errors, use err() for that, because drivers may return 'success with information' or warning messages via errstr() for methods that have not 'failed'.
Ok, so this is text. Don't use it to test for specific errors. You're not doing that. You just want to give debug output when the program fails.
$h->state
Returns a state code in the standard SQLSTATE five character format. Note that the specific success code 00000 is translated to any empty string (false). If the driver does not support SQLSTATE (and most don't), then state() will return S1000 (General Error) for all errors.
The driver is free to return any value via state, e.g., warning codes, even if it has not declared an error by returning a true value via the "err" method described above.
The state() method should not be used to test for errors, use err() for that, because drivers may return a 'success with information' or warning state code via state() for methods that have not 'failed'.
Again, this is not very clear about how useful it is.
My advice is to get rid of $DBI::err and $DBI::state. You don't need those to figure out what the problem is. Just output $DBI::errstr.
$insert_art->execute($creation_dt,$ref_data,$comp_no)
or die "Fehler bei der Ausfuehrung: " . $dbh->errstr;
Now your program will still fail, but at least you will have a meaningful error message that will explain what your database didn't like about the statement. That's better than being told how there is a bug in your error handling code.
Afterwards, the other answers will probably apply to fix the reason this is happening in the first case.
On another note, a word on die: If you provide a \n at the end of your arguments, it will not print your current script, line number and input handle line number. But those might be useful in your case. You can include them.
In a SQL database an empty string is very different to null.
If comp_no has a foreign key pointing to a record in another table, then the value "" is an accettable one only if there is a record with "" as primary key, very improbable.
Yu can fix this converting empty values to undef:
for ($creation_dt,$ref_data,$comp_no ){
defined $_ and $_ eq '' and $_ = undef;
}
$insert_art->execute($creation_dt,$ref_data,$comp_no);
or also
$insert_art->execute(map {defined($_) && length($_) ? $_ : undef} ($creation_dt,$ref_data,$comp_no));
This is a possible shortcut:
$comp_no ||= undef;
With the caveat that this will work in any case where $comp_no evaluates as false, meaning a value of 0 will actually cause the result to go undef also, which may or may not matter to you. If your field is numeric, I'd say it matters a lot.
I'm trying to create a new row using DBIx::Class from within Catalyst, with the following code:
$c->model('Session')->resultset('UserPreference')->create(
{
appname => 'rss_reader',
username => $username,
data => $data,
},
);
But, I hit this error every time:
Caught exception in App::Controller::rss->dbo "Can't call method "resolve" on an undefined value at /etg/source/Linux/pkg/perl-5.8.8/lib/site_perl/5.8.8/DBIx/Class/Row.pm line 1309."
I see a few mailing lists talking about this error being thrown as an incorrect blanket error when the query fails for whatever reason (perms, constraints,etc.), but it looks just fine AND even running with DBIC_TRACE=1, I don't even see the generated query in my console.
I should mention I don't think there's something bad with the permissions,etc. since using the database handle manually works:
my $stm=$c->model("Session")->storage->dbh->prepare("insert into user_preferences (username,appname,data) values ('mphillip','rss_reader','cookies')"); $stm->execute();
Have you tried update_or_create instead of create? If a row exists create will fail.