db-derby-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Apache Wiki <wikidi...@apache.org>
Subject [Db-derby Wiki] Update of "Derby3192Writeup" by DyreTjeldvoll
Date Mon, 21 Jan 2008 09:54:29 GMT
Dear Wiki user,

You have subscribed to a wiki page or wiki category on "Db-derby Wiki" for change notification.

The following page has been changed by DyreTjeldvoll:
http://wiki.apache.org/db-derby/Derby3192Writeup

------------------------------------------------------------------------------
  that cached in the client. The latter optimization is not part of this
  patch since it would mean that `setTransactionIsolation()` no longer
  would be guaranteed to commit the current transaction. Including it
- would have made the client driver behave the same wasy as the embedded
+ would have made the client driver behave the same way as the embedded
  driver in this respect, but unfortunately it would also mean that a
  number of tests expecting the old behavior would fail.
  
@@ -91, +91 @@

  in (in this case the isolation level) has changed. The
  `DRDAConnThread` could then append this information to the next
  message being sent to the client. There are two problems with this
- approach that caused it not to be chosen for this patch.
+ approach:
  
-  1. AFAICT DRDA does not allow the server to add replies to a message that do not correspond
to a request from the client.
+  1. To my knowledge, DRDA does not allow the server to add replies to a message that do
not correspond to a request from the client.
  
   1. The server would need some way of verifying that the client is capable of interpreting
the piggy-backed information.
  
  Another approach is to let the client "poll" the server for cachable
  values that have changed. This can be implemented using the
  request-reply model of DRDA, and the server would only piggy-back
- information to clients that actually requests it, so there is no need
+ information to clients that actually request it, so there is no need
  for a hand-shake protocol to find out what the client can handle. (The
  client would still need to make sure that it only sends these requests
  to servers that can handle them, but this is simply a test on the
@@ -113, +113 @@

  needs to contain the (possibly empty) reply. Each time a poll request
  is processed on the server it needs to check if the cachable
  information has changed since last poll. This approach was still
- chosen in this patch because the first approach seemed to be
+ chosen because the first approach seemed to be
  incompatible with DRDA.
  
  
@@ -121, +121 @@

  
  DRDA provides the EXCSQLSET command to "batch" (for lack of a better
  term) SET statements from a client to the server. This command is
+ currently used to implement the `setQueryTimeout()` functionality. This DRDA command can
also be used to poll for a changed
- currently used to implement the `setQueryTimeout()` functionality. Patch
- v1 also uses this DRDA command to implement polling for a changed
  isolation level. The client code provides a method
  (`Statement.writeSetSpecialRegister()`) for adding an EXCSQLSET command
- to a request. This is really a familiy of methods in various classes
+ to a request. This is really a family of methods in various classes
  and interfaces with the most action concentrated in
  `Statement.wrteSetSpecialRegister` and
- `NetStatementRequest.writeSetSpecialRegister()`. A large number of
+ `NetStatementRequest.writeSetSpecialRegister()`.
- changed lines in the patch can be attributed to the fact that the
- signature for this family of methods needed to be changed, (as well as
- the fact that javadoc was added for these methods, including the
- interface declarations).
  
  `setQueryTimeout()` implements its functionality by letting this command
  send a special statement which also encodes the timeout value to
- set. Patch v1 uses the same idea but uses a different dummy
+ set. Session data polling uses the same idea but with a different dummy
- statement which, just like in the setQueryTimeout case, is intercepted
+ statement which, just like in the `setQueryTimeout()` case, is intercepted
  by the server and given special treatment.
  
- The patch adds a new method to `EmbedConnection` and also to the
+ A new method is added to `EmbedConnection` and also to the
- `EngineConnection` interface (and thereby also to the BrokeredConnection
+ `EngineConnection` interface (and thereby also to the `BrokeredConnection`
  interface), that lets the caller iterate over the connection
  attributes that have changed since last time this method was called,
- (in patch v1 only the isolation level will ever be reported by this
- method). 
+ (Only the isolation level will be reported initially, but this should be extended to other
parameters, such as the current schema,
+ later).
  
  When the server receives the polling request it always adds
  the SQLCARD required by EXCSQLSET to the reply. If a cacheable connection
@@ -167, +162 @@

  The DRDA spec specifies that EXCSQLSET can have an optional
  instance variable RTNSETSTT, that essentially is a boolean flag which
  allows the requester (the client) to tell the server that it expects
- (and can handle) SQLSTT codepoints in the reply. Since v1 is using
+ (and can handle) SQLSTT code points in the reply. Since 
- such SQLSTT code points to transmit the cached attributes "diff", it
+ such SQLSTT code points are used to transmit the cached attributes "diff", it
- also needs to set the RTNSETSTT instance variable when sending the
+ is also necessary to set the RTNSETSTT instance variable when sending the
  request. Note that this is essentially "redundant" information since
  the server knows exactly what to do as soon as it has identified the
  special "statement" used in the polling request. It is only added to
@@ -183, +178 @@

  
  == Overhead Introduced by Piggy-backing ==
  
- As mentioned previously the polling approach will necessarily
+ As mentioned previously, the polling approach will necessarily
  introduce some overhead both on requests and replies. 
  
  === Request ===
@@ -192, +187 @@

  CNTQRY commands. Most of the overhead seems to come
  from the PKGNAMCSN instance variable which by itself uses 76 bytes, or
  59% of the total overhead:
+  
- 
- 
- || DRDA VARIABLE || SIZE (BYTES) || 
+  || DRDA VARIABLE || SIZE (BYTES) || 
- || DSS header || 6  ||
+  || DSS header || 6  ||
- || EXCSQLSET  || 4  ||
+  || EXCSQLSET  || 4  ||
- || PKGNAMCSN  || 76 ||
+  || PKGNAMCSN  || 76 ||
- || RTNSETSTT  || 4  ||
+  || RTNSETSTT  || 4  ||
- || HEXSTRDR   || 5  ||
+  || HEXSTRDR   || 5  ||
- || SQLSTT     || 4 + 1 + 4 + 23(strlen) + 1 ||
+  || SQLSTT     || 4 + 1 + 4 + 23(strlen) + 1 ||
- || TOTAL      || 128 ||
+  || TOTAL      || 128 ||
   
  This gives a total overhead of (a whopping) 128 bytes. 
  It can be reduced by shortening the name used for the "special
@@ -216, +210 @@

  The only mandatory variable in an EXCSQLSET reply is SQLCARD. When
  used to poll for modified session data, this variable has no real
  meaning, and null is passed in as the SQLException parameter to
- `DDMWriter.writeSQLCARD()`. For this patch is was (incorrectly) assumed
+ `DDMWriter.writeSQLCARD()`. Initially is was (incorrectly) assumed
  that passing null would result in a minimal increase of the
  message size. In reality, the DSS size (as reported by
  `getDSSLength()`) increases to 65 after adding the SQLCARD (which creates
@@ -243, +237 @@

  Following the example of `setQueryTimeout()`, calls to
  `writeSetSpecialRegister()` and `readSetSpecialRegister()` are made
  inside `Statement.flowExecute()`. The request is added in the first
- part of the method, prior to calling `agent_.flow(this)`, and the reply is
+ part of the method, prior to calling `agent_.flow()`, and the reply is
  read in the latter part of the method, after the blocking call to
- `agent_.flow(this)` returns.
+ `agent_.flow()` returns.
  
  In the case of `setQueryTimeout()`, the request is added to the
- beginning of the outgoing message (which is reasonable to ensure that
+ beginning of the outgoing message (which is reasonable, given that it needs to ensure that
- all the following actions observer the time limit), and the subsequent
+ all the following actions observe the time limit), and the subsequent
- reply is the first received and parsed after `agent_.flow(this)` returns. 
+ reply is the first received and parsed after `agent_.flow()` returns. 
  
  When polling for changed session data the situation is the exact
  opposite; the poll request needs to be the last thing added to the
  outgoing message to ensure that the poll picks up any changes in the
  session state that has happened as a consequence of the other commands
  in this message. As a result, the reply must be received and parsed at
- the end of `...flow()`, after all the other replies have been parsed.
+ the end of `agent_.flow()`, after all the other replies have been parsed.
  
  
- === Scrollable Result Sets ===
+ == Scrollable Result Sets ==
  
- Most of the time this works well because call to `agent_.flow(this)` is
+ Most of the time this works well because call to `agent_.flow()` is
  followed by a single reply, but for scrollable
  result sets this is not the case. If `Statement.isQuery__` is
- true and the `Statement.resultSet_' is not null, a call to
+ true and the `Statement.resultSet_` is not null, a call to
  `parseScrollableRowset()` is made:
  
  {{{#!java
@@ -282, +276 @@

      parseRowset_();
  }}}
  
- `net.NetResultSet.parseRowSet_()` _may_ call
+ `net.NetResultSet.parseRowSet_()` ''may'' call
  `flowFetchToCompleteRowset()` directly, or through
  `calculateColumnOffsetsForRow_()`, and this call initiates another
  roundtrip, while still inside `Statement.flowExecute()`:
@@ -308, +302 @@

  
   * The QRYDTA parsing does not expect anything to follow the last
   QRYDTA reply in a message, so if all QRYDTAs have not been received,
-  it will choke when reading the poll reply.
+  it will fail when reading the poll reply.
   * The new round-trip (CNTQRY) initiated by the parsing code will not
   add a new session data poll request, so even if the poll reply
   is handled or ignored by the QRYDTA parsing, there will be no
@@ -316, +310 @@

   reaches `readSetSpecialRegister()` in 
   `Statement.flowExecute()`, and the call will block forever.
  
- The problem is limited to *read only* result sets since *updatable*
+ The problem is limited to '''read only''' result sets since '''updatable'''
- result sets always have a fetchsize equal to 1, regardless of what the
+ result sets always have a fetch size of 1, regardless of what the
  suggested fetch size is.
  
  
  == Possible Solutions ==
  
  The initial idea was to handle this by trying to detect this situation
- on the server, and not send a session data reply until all calls to
+ on the server, and not send a poll reply until all calls to
  `flowFetchToCompleteRowset()` had been completed, so that the
- session data was handled when control returned to
+ poll reply would be handled correctly when control returned to
  `Statement.flowExecute()`.
  
  This approach does not work correctly when `fetchsize_` is smaller
  than the number of CNTQRYs needed to get a complete row set, because
  then the loop calling `flowFetchToCompleteRowset()` will terminate
- before the server sends the session data, and then the code
+ before the server sends the poll reply, and then the code
- inside `Statement.flowExecute()` trying to read the information will
+ inside `Statement.flowExecute()` trying to read the reply will
- hang waiting for data which never arrives.
+ hang waiting for data which will never arrive.
  
- At this point the best solutions seem to be 
+ At this point the best solutions seem to be: 
  
-  1. Add the piggy-back request command to every CNTQRY and parse it in every reply (also
those handled by `flowFetchToCompleteRowSet()`).
+  1. Add a poll request command to every CNTQRY and parse it in every reply (also those handled
by `flowFetchToCompleteRowSet()`).
  
-  1. Implement some kind of bookkeeping mechanism that tracks if a command was included in
the last request, and if the return value has been handled in the latest reply. This is more
complicated but reduces the number of unnecessary piggy-back commands.
+  1. Implement some kind of bookkeeping mechanism which tracks if a poll request was included
in the last message sent, and if any poll reply in the last incoming message has been handled.
This adds complexity, but reduces the number of unnecessary poll request/replies in some situations.
  

Mime
View raw message