Army wrote:


Bryan Pendleton updated DERBY-125:
----------------------------------

    Attachment: changes2.html
                svn-dec_28_2005.diff


[ snip ]

I think these changes are now fully ready for review. Please let me know your comments as I am very interested to hear what you think.


I plan to review this patch, hopefully by the end of tomorrow (Wednesday).

Well I'm a day late, but I've finished my review of the patch...

After reading through the (excellent) description of the changes that you wrote and comparing your notes with my own understanding of the protocol, I couldn't see anything wrong with your server changes. I ran both the derbynetmats and the derbynetclientmats suite with your patch, and both suites ran clean. I also ran some ODBC versions of the repros using the DB2 ODBC client (which is how I discovered all of these issues in the first place), and it appears that all went well there, too.

So I happily composed an email saying "looks good to me", and then, just before sending the email off, I decided to try running your new test cases withOUT your server changes--and that's where I came across some questions...

1) DERBY-491 test case (in procedure.java)

For the test for DERBY-491, we print a failure message if the retrieved string doesn't match the expected string; else we don't print anything. However, when I tried to run the test without your changes applied, this particular test case still passed. So I'm wondering what part of your patch this test case (the check for "s.equals(expected)") is actually testing? Is this related to the off-by-one error that you described for DDMWriter (for DERBY-125)? In your document, you wrote:

"The current code is missing the + 1, which means that we are starting one byte too early [...] This problem manifests itself as a very tiny corruption of the large object's data."

Is the "s.equals(expected)" in your test case used to check for this "tiny corruption"? If so, then it definitely seems like this check _should_ fail without your changes--but apparently that's not the case. So now I'm confused as to a) what this part of the test is actually testing, and b) why we are not (and haven't been) seeing incorrect results due to this off-by-one error, even when your patch is not applied...?

In any event, I think it might be helpful to add more comments to this particular part of the test, since it's not obvious how the actual-vs-expected-string test is related to the error reported for DERBY-491. For more (minor) comments on this test case, see the "Additional minor comments" section below...

2) DERBY-170 test case (in prepStmt.java)

Without your changes, this test case still passes with the Derby Client (though it fails with JCC). Is this expected? Does DERBY-170 only manifest itself with JCC? That might very well be the case--and if so, you needn't worry about this anymore--but I just thought I'd ask.

Note that this failure also shows up with the DB2 ODBC client, and with your patch applied, it no longer occurs--so I think the fix is correct. I just want to confirm that, even without your patch, the test isn't expected to fail for Derby Client.

3) DERBY-125 test case (in prepStmt.java)

When I ran the DERBY-125 test case without your changes, it still passes, both with JCC and the Derby Client. I guess this isn't surprising since, as your comment for DERBY-125 says, "there is no exception or other 'hard' evidence of the problem"--at least, not with JCC nor Derby Client (the DB2 ODBC client will fail because of it).

In the ideal world, this test case would fail without your patch and succeed with it, so that if this area of code is changed, we can easily catch any regressions. Is there a (clean) way to do that with your changes? For example, is there some condition in the server code for which we can check and then throw, say, an assertion failure if it is not met? In your test case you noticed that, before your patch, the server was writing a SQLDARD message that was 118,300+ bytes long, which (I think?) was the cause of the problem. Is there some place where we can check for this kind of thing in the server code and fail (on the server side) if we find it? Then your test case for DERBY-125 would fail without your patch, which is the desired behavior. Of course, if you can think of a better way to achieve the same result, feel free to go with what you think is best.

--------------------------
Additional minor comments
--------------------------

= 0 = General comment.

I think that, as a general rule, it's nice if patches for different issues can be checked in separately, instead of as a single patch like this one. That makes it easier to track the changes/fixes, and in the event that a change for one issue needs to be backed out for whatever reason, the other changes for other issues can still remain in the codeline. That said, I'm not asking you to break this particular patch up--I'm just giving a suggestion for future patches. In this case, I think the changes are all very much inter-related, as you describe in your document, so I personally am okay with having a single patch. If anyone out there feels like you should break this patch up into four separate patches (one for each issue being fixed), then I'll leave it up to him/her to post saying so...

On a different note, it looks like the indentation for some of the changes you've made differ from the surrounding code. I know that people on the lists have said they prefer spaces over tabs, and that's fine with me if one is adding a new class or method--but in cases where one is adding code to existing blocks, I think it's cleaner to mimic the indentation of the block that's being modified. For example, in DDMReader.java:

@@ -1710,8 +1712,11 @@
                                                               "fill",
                                                               5);
                        }
-                       count += actualBytesRead;
-                       totalBytesRead += actualBytesRead;
+            if (actualBytesRead != -1)
+            {
+                count += actualBytesRead;
+                totalBytesRead += actualBytesRead;
+            }

                }

The lines that were deleted, along with the rest of the code in this procedure, all begin with tabs; but the lines that were added with this patch all begin with spaces, which makes the format of the above code a bit awkward. I think it'd be nice if the new lines matched the indentation of the existing lines...

----
= 1 = procedure.java

I think it would be good to add a try-catch block around the do-while loop, since the error reported for DERBY-491 was a protocol exception. Then in the catch block, print an explicit error saying that DERBY-491 failed with an exception; this clarifies where in the new code we're testing the problem described in DERBY-491, and it will also help debugging in the future if something breaks your fix. So I'd say do something along the lines of (this is untested code):

        cSt.setInt(1, 3);
        try {

          cSt.execute();
          String expected = new String(cData);
          boolean success = true;
          do {
              ResultSet rs = cSt.getResultSet();
              while (rs.next()) {
                  String s = rs.getString(2);
                  if (!s.equals(expected)) {
                      System.out.println("JIRA-491 FAILURE: " + s + " is not " +
                              expected);
                      success = false;
                  }
              }
          } while (cSt.getMoreResults());
          if (success)
              System.out.println("JIRA-491 successful.");

        } catch (Exception e) {
            System.out.println("JIRA-491 FAILURE: Caugh exception:");
            e.printStackTrace(System.out);
        }

This approach will also allow the JIRA-492 test to execute even if the test for JIRA-491 fails; currently, if JIRA-491 fails with a protocol exception, we'll exit the method before JIRA-492 is run.

----
= 2 = procedure.java

Could we just remove the following line since it's commented out, or is it there for a reason?

+        //cSt.registerOutParameter(1, Types.INTEGER);

----
= 3 = procedure.java

There are a couple of places where we have things like:

+        } catch (SQLException se) { System.out.println(se.getSQLState()); }

I realize these lines came from the repro I posted, but for purposes of these tests, I think it'd be good to add some kind of indication that these sqlstates are NOT expected. A tag like "FAILED: UNEXPECTED SQLException: " (and then print SQLException) is more likely to catch someone's eye and make them double-check their work.

----
= 5 = prepStmt.java

+            if (e.getMessage().indexOf("JIRA170") > 0)
+                System.out.println("Jira170: caught expected table not found");

I think it'd be safer to check the SQLState of the error message, instead of searching for a specific string:

if (e.getSQLState().equals(SQLState.LANG_TABLE_NOT_FOUND))
  System.out.println("...");

--------

Overall, the code changes you've made look good to me, and the explanations that you gave for your changes are both thorough and convincing--and, so far as I can tell, correct :) The tests (derbynetmats, derbynetclientmats, and some ODBC tests that I ran) all seem to agree.

So in short, if you can address the comments above re: the test cases that you've added, I think this patch will be ready for commit.

Thanks for the excellent investigation, explanation, and code changes. I think this will be a _great_ patch for Derby Network Server once it's finalized: not only will it fix several current server issues, but it will also help to make the server much more reliable when dealing with large data flow in general. So thanks for the hard work!

Army

Reply via email to