Forum: Building VoltDB Applications

Post: Exception: SinglePartitionTxnState doesn't support receiving dependencies

Exception: SinglePartitionTxnState doesn't support receiving dependencies
skashikar
Mar 3, 2011
Hi Guys,
Hope you folks are doing fine.
I have made much progress since we last met.
I was trying to run my version of voter and get following exception during VoltExecuteSQL - likely something wrong in my code but couldn't figure it out from this cryptic message:
"java.lang.UnsupportedOperationException: The current transaction context of type org.voltdb.dtxn.SinglePartitionTxnState doesn't support receiving dependencies."
The exception is thrown in SP VOTE during VoltExecuteSQL of query:
"SELECT CONTESTANT_NUMBER FROM CONTESTANTS WHERE CONTESTANT_NUMBER = ? ;"
The issue does not happen in the voter example that comes with voltdb.
I can send my code, if needed.
Thanks,
Swapnil
re: Exception:...
tcallaghan
Mar 3, 2011
Swapnil,
Good to hear from you. I haven't seen that exception before. Could you please send your application code to support@voltdb.com so I can debug it?
-Tim
SOLVED: You cannot extract SQLStmt declarations just "anywhere"
sebc
Mar 8, 2011
Hi Swapnil,
You've added a lot of abstraction on top of the default VoltDB code there. I sent you a more detailed e-mail with some ideas and recommendations for your consideration.
As it turns out, your gutting out of the procedures is the cause of your problem.
If you go back to the Voter example source, you can reproduce this problem by doing this:
In Initialize.java, modify the procedure (add the third line line: definition of "voteCheckContestant") so you now have:

public class Initialize extends VoltProcedure { public static final SQLStmt voteCheckContestant = new SQLStmt("select contestant_number from contestants where contestant_number = ?;"); // Add this line ... etc... Then go change the Vote procedure and modify the line:
voltQueueSQL(checkContestant, contestantNumber);
To:
voltQueueSQL(Initialize.voteCheckContestant, contestantNumber); // You are now calling the statement defined in the Initialize class - not the one defined in Vote class
This will reproduce your problem:

[java] ===============================================================================
[java] VOLTDB ERROR: UNEXPECTED FAILURE:
[java] The current transaction context of type org.voltdb.dtxn.SinglePartitionTxnState doesn't support receiving dependencies.
[java] at com.procedures.Vote.run(Vote.java:59)
[java] ===============================================================================
And it is totally normal. Think about it: the Initialize.voteCheckContestant was compiled by the Volt procedure compiler as a multi-partition statement, but you are now trying to use that prepared statement in a single-partition procedure => error.
You can get all sorts of funny errors moving those SQLStmt declarations around - generally when you define then outside of a VoltProcedure body, or if you attempt to declare them inside the run method, you'll get a runtime error in the form:

[java] ===============================================================================
[java] VOLTDB ERROR: UNEXPECTED FAILURE:
[java] SQLStmt objects cannot be instantiated after VoltDB initialization. User may have instantiated a SQLStmt inside a stored procedure's run method.
[java] at com.procedures.Initialize.run(Initialize.java:51)
[java] ===============================================================================

... because wherever your SQLStmt was defined, there was no @Procinfo for the Volt compiler to know how to prepare the statement *AT COMPILE TIME*. There are a few other variants all more confusing than the next until you realize you are breaking the rule! The SQLStmt MUST be in the BODY of your procedure definition, as *final* declarations (they don't so much have to be final than to be clearly defined at COMPILE TIME: the SQL statement itself MUST be a constant), and your procedure MUST have a @ProcInfo declaration. In truth, it would almost help if you consider that the source code for your procedures isn't "truly" Java: it is Volt-Java (however you want to name it). The point is: the SQL statements are compiled by a special "Volt Procedure Compiler" (these are the "INFO COMPILER" lines you see when calling the catalog compilation), THEN the java code is compiled *using those prepared statements*. So if you "play" in any way that makes it impossible for the statement to actually be compiled (extracting the SQLStmt definitions in a class that does not have a @ProcInfo matching the procedure you intend to call those statements in), or in any way that you may mis-use the statements (using a statement belonging to another @ProcInfo definition), you will get those two errors.
The conclusion:
- Keep the SQLStmt definition INSIDE the procedure definition.
- Ensure you have the adequate @ProcInfo definition
I sent you some ideas on how to achieve the type of proxy you're trying to get, but that's outside of the scope of this thread.
Cheers,
Seb
Thanks!
skashikar
Mar 9, 2011
Hi Swapnil,
You've added a lot of abstraction on top of the default VoltDB code there. I sent you a more detailed e-mail with some ideas and recommendations for your consideration.
As it turns out, your gutting out of the procedures is the cause of your problem.
If you go back to the Voter example source, you can reproduce this problem by doing this:
In Initialize.java, modify the procedure (add the third line line: definition of "voteCheckContestant") so you now have...


Seb,
Thanks for the explanation.
Regards,
Swapnil