Adding JMCR-Stable version
[Benchmarks_CSolver.git] / JMCR-Stable / real-world application / derby-10.3.2.1 / java / drda / org / apache / derby / impl / drda / DssTrace.java
diff --git a/JMCR-Stable/real-world application/derby-10.3.2.1/java/drda/org/apache/derby/impl/drda/DssTrace.java b/JMCR-Stable/real-world application/derby-10.3.2.1/java/drda/org/apache/derby/impl/drda/DssTrace.java
new file mode 100644 (file)
index 0000000..832a3df
--- /dev/null
@@ -0,0 +1,449 @@
+/*\r
+\r
+   Derby - Class org.apache.derby.impl.drda.DssTrace\r
+\r
+   Licensed to the Apache Software Foundation (ASF) under one or more\r
+   contributor license agreements.  See the NOTICE file distributed with\r
+   this work for additional information regarding copyright ownership.\r
+   The ASF licenses this file to You under the Apache License, Version 2.0\r
+   (the "License"); you may not use this file except in compliance with\r
+   the License.  You may obtain a copy of the License at\r
+\r
+      http://www.apache.org/licenses/LICENSE-2.0\r
+\r
+   Unless required by applicable law or agreed to in writing, software\r
+   distributed under the License is distributed on an "AS IS" BASIS,\r
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+   See the License for the specific language governing permissions and\r
+   limitations under the License.\r
+\r
+ */\r
+package org.apache.derby.impl.drda;\r
+\r
+import java.io.IOException;\r
+import java.io.PrintWriter;\r
+import java.security.AccessController;\r
+import java.security.PrivilegedActionException;\r
+import java.security.PrivilegedExceptionAction;\r
+\r
+\r
+// Generic process and error tracing encapsulation.\r
+// This class also traces a DRDA communications buffer.\r
+// The value of the hex bytes are traced along with\r
+// the ascii and ebcdic translations.\r
+public class DssTrace\r
+{\r
+  // This class was implemented using character arrays to translate bytes\r
+  // into ascii and ebcdic.  The goal was to be able to quickly index into the\r
+  // arrays to find the characters.  Char arrays instead of strings were used as\r
+  // much as possible in an attempt to help speed up performance.\r
+  private static final String LIST_SEPARATOR = " # ";\r
+\r
+  // trace representation for a java null.\r
+  private static final String NULL_VALUE = "null";\r
+\r
+  // An array of characters used to translate bytes to ascii.\r
+  // The position in the array corresponds to the hex value of the\r
+  // character\r
+  private static final char asciiChar [] = {\r
+    // 0   1   2   3   4   5   6   7   8   9   A   B   C   D   E   F\r
+    '.','.','.','.','.','.','.','.','.','.','.','.','.','.','.','.',  //0\r
+    '.','.','.','.','.','.','.','.','.','.','.','.','.','.','.','.',  //1\r
+    ' ','!','"','#','$','%','&','\'','(',')','*','+',',','-','.','/', //2\r
+    '0','1','2','3','4','5','6','7','8','9',':',';','<','=','>','?',  //3\r
+    '@','A','B','C','D','E','F','G','H','I','J','K','L','M','N','O',  //4\r
+    'P','Q','R','S','T','U','V','W','X','Y','Z','[','\\',']','^','_', //5\r
+    '`','a','b','c','d','e','f','g','h','i','j','k','l','m','n','o',  //6\r
+    'p','q','r','s','t','u','v','w','x','y','z','{','|','}','~','.',  //7\r
+    '.','.','.','.','.','.','.','.','.','.','.','.','.','.','.','.',  //8\r
+    '.','.','.','.','.','.','.','.','.','.','.','.','.','.','.','.',  //9\r
+    '.','.','.','.','.','.','.','.','.','.','.','.','.','.','.','.',  //A\r
+    '.','.','.','.','.','.','.','.','.','.','.','.','.','.','.','.',  //B\r
+    '.','.','.','.','.','.','.','.','.','.','.','.','.','.','.','.',  //C\r
+    '.','.','.','.','.','.','.','.','.','.','.','.','.','.','.','.',  //D\r
+    '.','.','.','.','.','.','.','.','.','.','.','.','.','.','.','.',  //E\r
+    '.','.','.','.','.','.','.','.','.','.','.','.','.','.','.','.'   //F\r
+  };\r
+\r
+\r
+  // This mapping table associates a codepoint to a String describing the codepoint.\r
+  // This is needed because the trace prints the\r
+  // first codepoint in send and receive buffers.\r
+  // This could be final but there is no need to create the mapping\r
+  // if tracing isn't used.  So... this array will only be created when\r
+  // the com buffer trace is started.  Note this ref is not protected\r
+  // by final and care must be taken if it's value needs to change.\r
+  private static CodePointNameTable codePointNameTable = null;\r
+\r
+  // This column position header is used to mark offsets into the trace.\r
+  private static final String colPosHeader =\r
+  "       0 1 2 3 4 5 6 7   8 9 A B C D E F   0123456789ABCDEF  0123456789ABCDEF";\r
+\r
+  // An array of characters used to translate bytes to ebcdic.\r
+  // The position in the array corresponds to the hex value of the\r
+  // character.\r
+  private static final char ebcdicChar[] = {\r
+    // 0   1   2   3   4   5   6   7   8   9   A   B   C   D   E   F\r
+    '.','.','.','.','.','.','.','.','.','.','.','.','.','.','.','.',  //0\r
+    '.','.','.','.','.','.','.','.','.','.','.','.','.','.','.','.',  //1\r
+    '.','.','.','.','.','.','.','.','.','.','.','.','.','.','.','.',  //2\r
+    '.','.','.','.','.','.','.','.','.','.','.','.','.','.','.','.',  //3\r
+    ' ','.','.','.','.','.','.','.','.','.','.','.','<','(','+','|',  //4\r
+    '&','.','.','.','.','.','.','.','.','.','!','$','*',')',';','.',  //5\r
+    '-','/','.','.','.','.','.','.','.','.','|',',','%','_','>','?',  //6\r
+    '.','.','.','.','.','.','.','.','.','`',':','#','@','\'','=','"', //7\r
+    '.','a','b','c','d','e','f','g','h','i','.','.','.','.','.','.',  //8\r
+    '.','j','k','l','m','n','o','p','q','r','.','.','.','.','.','.',  //9\r
+    '.','~','s','t','u','v','w','x','y','z','.','.','.','.','.','.',  //A\r
+    '.','.','.','.','.','.','.','.','.','.','.','.','.','.','.','.',  //B\r
+    '{','A','B','C','D','E','F','G','H','I','.','.','.','.','.','.',  //C\r
+    '}','J','K','L','M','N','O','P','Q','R','.','.','.','.','.','.',  //D\r
+    '\\','.','S','T','U','V','W','X','Y','Z','.','.','.','.','.','.', //E\r
+    '0','1','2','3','4','5','6','7','8','9','.','.','.','.','.','.'   //F\r
+  };\r
+\r
+\r
+  // An array of characters representing hex numbers.\r
+ private static final char hexDigit [] = {\r
+    '0','1','2','3','4','5','6','7',\r
+    '8','9','A','B','C','D','E','F'\r
+  };\r
+\r
+\r
+  // A PrintWriter is used in printing the trace.\r
+  private java.io.PrintWriter comBufferWriter = null;\r
+\r
+\r
+  // The receive header comes befor bytes which would be read from\r
+  // a Stream.\r
+  private static final String receiveHeader =\r
+  "       RECEIVE BUFFER:                     (ASCII)           (EBCDIC)";\r
+\r
+\r
+  // The send header comes before bytes which would be written to\r
+  // a Stream.\r
+  private static final String sendHeader =\r
+  "       SEND BUFFER:                        (ASCII)           (EBCDIC)";\r
+\r
+\r
+  // The space character is defined for convience.\r
+  private static final char spaceChar = ' ';\r
+\r
+\r
+  // This boolean indicates if the trace is on.\r
+  // It has been declared private now but may be made public at\r
+  // a later time.\r
+  private boolean comBufferTraceOn = false;\r
+\r
+\r
+  // The comBufferSync is an object used for serialization.\r
+  // This separate object is used because this trace code may\r
+  // get eventually placed into another class which performs\r
+  // method entry and exit tracing.  Since each trace may be writing\r
+  // to different logs, separate objects will be used to perform the\r
+  // synchronization.\r
+  private Boolean comBufferSync = new Boolean (true);\r
+\r
+\r
+  // The zero character is defined for convinience.\r
+  private static final char zeroChar = '0';\r
+\r
+  // The recevie constant is used to indicate that the bytes were read to a Stream.\r
+  // It indicates to this class that a receive header should be used.\r
+  protected static final int TYPE_TRACE_RECEIVE = 2;\r
+\r
+  // The send constant is used to indicate that the bytes were written to\r
+  // a Stream.  It indicates to this class that a send header should be used.\r
+  protected static final int TYPE_TRACE_SEND = 1;\r
+\r
+  // Query if trace is on.\r
+  // This is currently needed since the comBufferTrcOn flag is private.\r
+  protected boolean isComBufferTraceOn()\r
+  {\r
+    // The trace flag indicates if tracing is on.\r
+    return comBufferTraceOn;\r
+  }\r
+\r
+  // Start the communications buffer trace.\r
+  // The name of the file to place the trace is passed to this method.\r
+  // After calling this method, calls to isComBufferTraceOn() will return true.\r
+  protected void startComBufferTrace (final String fileName) throws IOException \r
+  {\r
+    synchronized (comBufferSync) {\r
+        // Only start the trace if it is off.\r
+        if (comBufferTraceOn == false) {\r
+          // The writer will be buffered for effeciency.\r
+            try {\r
+                \r
+                comBufferWriter =  ((PrintWriter)AccessController.doPrivileged(\r
+                            new PrivilegedExceptionAction() {\r
+                                public Object run() throws SecurityException, IOException {\r
+                                    return new  PrintWriter (new java.io.BufferedWriter (new java.io.FileWriter (fileName), 4096));\r
+                                }\r
+                            }));\r
+            } catch (PrivilegedActionException pae) {\r
+               Exception e = pae.getException();\r
+               if (e instanceof SecurityException)\r
+                   throw (SecurityException)pae.getException();\r
+               else\r
+                   throw (IOException) pae.getException();\r
+            }\r
+          \r
+          // Turn on the trace flag.\r
+          comBufferTraceOn = true;\r
+          // initialize the codepoint name table if it is null.\r
+          // this is done here so that the CodePointName objects\r
+          // aren't created if the trace isn't used (save some memory).\r
+          // this process should only be done once\r
+          // since after the table is created the ref will\r
+          // no longer be null.\r
+          if (DssTrace.codePointNameTable == null) {\r
+            codePointNameTable = new CodePointNameTable();\r
+          }\r
+        }\r
+      }\r
+    }\r
+  \r
+\r
+  // Stop the communications buffer trace.\r
+  // The trace file is flushed and closed.  After calling this method,\r
+  // calls to isComBufferTraceOn () will return false.\r
+  protected void stopComBufferTrace ()\r
+  {\r
+    synchronized (comBufferSync) {\r
+      // Only stop the trace if it is actually on.\r
+      if (comBufferTraceOn == true) {\r
+        // Turn of the trace flag.\r
+        comBufferTraceOn = false;\r
+        // Flush and close the writer used for tracing.\r
+        if (comBufferWriter != null)\r
+        {\r
+            comBufferWriter.flush();\r
+            comBufferWriter.close();\r
+        }\r
+      }\r
+    }\r
+  }\r
+\r
+  // Write the communication buffer data to the trace.\r
+  // The data is passed in via a byte array.  The start and length of the data is given.\r
+  // The type is needed to indicate if the data is part of the send or receive buffer.\r
+  // The class name, method name, and trcPt number are also written to the trace.\r
+  // Not much checking is performed on the parameters.  This is done to help performance.\r
+  protected void writeComBufferData (byte[] buff,\r
+                                         int offset,\r
+                                         int len,\r
+                                         int type,\r
+                                         String className,\r
+                                         String methodName,\r
+                                         int trcPt)\r
+  {\r
+    // why don't we synchronize the method!!!\r
+\r
+    // Grab the lock to make sure another thread doesn't try to\r
+    // write data or close the writer.\r
+    synchronized (comBufferSync) {\r
+\r
+      // Only take action if the trace is on.\r
+      if (comBufferTraceOn) {\r
+\r
+        // Obtain an instance of the Calendar so a timestamp can be written.\r
+        // this call seems to slow things down a bit.\r
+        java.util.Calendar time = java.util.Calendar.getInstance();\r
+\r
+        // Print the timestamp, class name, method name, thread name, and tracepoint.\r
+        comBufferWriter.println ("       (" +\r
+                                 time.get (java.util.Calendar.YEAR) +\r
+                                 "." +\r
+                                 (time.get (java.util.Calendar.MONTH) + 1) +\r
+                                 "." +\r
+                                 time.get (java.util.Calendar.DAY_OF_MONTH) +\r
+                                 " " +\r
+                                 time.get (java.util.Calendar.HOUR_OF_DAY) +\r
+                                 ":" +\r
+                                 time.get (java.util.Calendar.MINUTE) +\r
+                                 ":" +\r
+                                 time.get (java.util.Calendar.SECOND) +\r
+                                 ") " +\r
+                                 className +\r
+                                 " " +\r
+                                 methodName +\r
+                                 " " +\r
+                                 Thread.currentThread().getName() +\r
+                                 " " +\r
+                                 trcPt);\r
+\r
+        // A newline is added for formatting.\r
+        comBufferWriter.println();\r
+\r
+        // The data will only be written if there is a non-zero positive length.\r
+        if (len != 0) {\r
+          String codePointName = null;\r
+          // If the length <= 10, lookup the first codepoint so it's name can be printed???\r
+          if (len >= 10) {\r
+            // Get the int value of the two byte unsigned codepoint.\r
+            int codePoint = getCodePoint (buff, offset+8);\r
+            codePointName = codePointNameTable.lookup (codePoint);\r
+          }\r
+\r
+          if (codePointName == null) {\r
+            // codePointName was still null so either < 10 bytes were given or\r
+            // the codepoint wasn't found in the table.  Just print the plain send header.\r
+            comBufferWriter.println (getHeader (type));\r
+          }\r
+          else {\r
+            // codePointName isn't null so the name of the codepoint will be printed.\r
+            printHeaderWithCodePointName (codePointName, type);\r
+          }\r
+\r
+          // Print the col position header in the trace.\r
+          comBufferWriter.println (colPosHeader);\r
+\r
+          // A char array will be used to translate the bytes to their character\r
+          // representations along with ascii and ebcdic representations.\r
+          char trcDump[] = new char[77];\r
+\r
+          // bCounter, aCounter, eCounter are offsets used to help position the characters\r
+          short bCounter = 7;\r
+          short aCounter = 43;\r
+          short eCounter = 61;\r
+\r
+          // The lines will be counted starting at zero.  This is hard coded since we are\r
+          // at the beginning.\r
+          trcDump[0] = DssTrace.zeroChar;\r
+          trcDump[1] = DssTrace.zeroChar;\r
+          trcDump[2] = DssTrace.zeroChar;\r
+          trcDump[3] = DssTrace.zeroChar;\r
+\r
+          // The 0's are already in the trace so bump the line counter up a row.\r
+          int lineCounter = 0x10;\r
+\r
+          // Make sure the character array has all blanks in it.\r
+          // Some of these blanks will be replaced later with values.\r
+          // The 0's were not wrote over.\r
+          for (int j = 4; j < 77; j++) {\r
+            trcDump[j] = DssTrace.spaceChar;\r
+          }\r
+\r
+          // i will maintain the position in the byte array to be traced.\r
+          int i = 0;\r
+\r
+          do {\r
+            // Get the unsigned value of the byte.\r
+            //                  int num = b[off++] & 0xff;\r
+            int num = (buff[offset] < 0)? buff[offset] + 256 : buff[offset]; // jev\r
+            offset++;\r
+            i++;\r
+            // Place the characters representing the bytes in the array.\r
+            trcDump[bCounter++] = DssTrace.hexDigit[((num >>> 4) & 0xf)];\r
+            trcDump[bCounter++] = DssTrace.hexDigit[(num & 0xf)];\r
+\r
+            // Place the ascii and ebcdc representations in the array.\r
+            trcDump[aCounter++] = DssTrace.asciiChar[num];\r
+            trcDump[eCounter++] = DssTrace.ebcdicChar[num];\r
+\r
+            if (((i%8) == 0)) {\r
+              if (((i%16) == 0)) {\r
+                // Print the array each time 16 bytes are processed.\r
+                comBufferWriter.println (trcDump);\r
+                if (i != len) {\r
+                  // Not yet at the end of the byte array.\r
+                  if ((len - i) < 16) {\r
+                    // This is the last line so blank it all out.\r
+                    // This keeps the last line looking pretty in case\r
+                    // < 16 bytes remain.\r
+                    for (int j = 0; j < trcDump.length; j++) {\r
+                      trcDump[j] = DssTrace.spaceChar;\r
+                    }\r
+                  }\r
+                  // Reset the counters.\r
+                  bCounter = 0;\r
+                  aCounter = 43;\r
+                  eCounter = 61;\r
+                  // Reset the lineCounter if it starts to get too large.\r
+                  if (lineCounter == 0xfff0) {\r
+                    lineCounter = 0;\r
+                  }\r
+                  // Place the characters representing the line counter in the array.\r
+                  trcDump[bCounter++] = DssTrace.hexDigit[((lineCounter >>> 12) & 0xf)];\r
+                  trcDump[bCounter++] = DssTrace.hexDigit[((lineCounter >>> 8) & 0xf)];\r
+                  trcDump[bCounter++] = DssTrace.hexDigit[((lineCounter >>> 4) & 0xf)];\r
+                  trcDump[bCounter++] = DssTrace.hexDigit[(lineCounter & 0xf)];\r
+                  bCounter += 3;\r
+                  // Bump up the line counter.\r
+                  lineCounter += 0x10;\r
+                }\r
+              }\r
+              else {\r
+                // 8 bytes were processed so move the counter to adjust for\r
+                // spaces between the columns of bytes.\r
+                bCounter += 2;\r
+              }\r
+            }\r
+            // do this until we all the data has been traced.\r
+          } while (i < len);\r
+\r
+          // print the last line and add some blank lines to make it easier to read.\r
+          if (len % 16 != 0) {\r
+            comBufferWriter.println (trcDump);\r
+          }\r
+          comBufferWriter.println();\r
+          comBufferWriter.println();\r
+        }\r
+        // Flush the writer.\r
+        comBufferWriter.flush();\r
+      }\r
+    }\r
+  }\r
+\r
+  // Gets the int value of the two byte unsigned codepoint.\r
+  private static int getCodePoint (byte[] buff, int offset)\r
+  {\r
+    return ((buff[offset++] & 0xff) << 8) +\r
+      ((buff[offset] & 0xff) << 0);\r
+  }\r
+\r
+  private static String getHeader (int type)\r
+  {\r
+    switch (type) {\r
+    case DssTrace.TYPE_TRACE_SEND:\r
+      return DssTrace.sendHeader;\r
+    case DssTrace.TYPE_TRACE_RECEIVE:\r
+      return DssTrace.receiveHeader;\r
+    default:\r
+      //  throw new !!!\r
+      return null;\r
+    }\r
+  }\r
+\r
+  private static int getStartPosition (int type)\r
+  {\r
+    switch (type) {\r
+    case DssTrace.TYPE_TRACE_SEND:\r
+      return 20; // This is right after 'SEND BUFFER: '.\r
+    case DssTrace.TYPE_TRACE_RECEIVE:\r
+      return 23; // This is right after 'RECEIVE BUFFER: '.\r
+    default:\r
+      //  throw new !!!\r
+      return 0;\r
+    }\r
+  }\r
+\r
+  private void printHeaderWithCodePointName (String codePointName, int type)\r
+  {\r
+    // Create a char array so some of the characters\r
+    // can be replaced with the name of the codepoint.\r
+    char headerArray[] = DssTrace.getHeader(type).toCharArray();\r
+\r
+    // At most, 16 character name will be used.  This is so\r
+    // the headers on top of the ascii and ebcdic rows aren't shifted.\r
+    int replaceLen = (codePointName.length() < 17) ? codePointName.length() : 16;\r
+\r
+    int offset = getStartPosition (type);\r
+    for (int i = 0; i < replaceLen; i++) {\r
+      headerArray[offset++] = codePointName.charAt (i); // make sure charAt() starts at 0!!!\r
+    }\r
+    comBufferWriter.println (headerArray);\r
+  }\r
+\r
+}\r