📄 sharedsocket.java
字号:
* Retrieve the character set descriptor used to translate byte arrays to * or from Strings. */ CharsetInfo getCharsetInfo() { return charsetInfo; } /** * Retrieve the character set name used to translate byte arrays to * or from Strings. * * @return the character set name as a <code>String</code> */ String getCharset() { return charsetInfo.getCharset(); } /** * Obtain an instance of a server request stream for this socket. * * @param bufferSize the initial buffer size to be used by the * <code>RequestStream</code> * @return the server request stream as a <code>RequestStream</code> */ RequestStream getRequestStream(int bufferSize) { synchronized (socketTable) { int id; for (id = 0; id < socketTable.size(); id++) { if (socketTable.get(id) == null) { break; } } VirtualSocket vsock = new VirtualSocket(id); if (id >= socketTable.size()) { socketTable.add(vsock); } else { socketTable.set(id, vsock); } return new RequestStream(this, id, bufferSize); } } /** * Obtain an instance of a server response stream for this socket. * NB. getRequestStream() must be used first to obtain the RequestStream * needed as a parameter for this method. * * @param requestStream an existing server request stream object obtained * from this <code>SharedSocket</code> * @param bufferSize the initial buffer size to be used by the * <code>RequestStream</code> * @return the server response stream as a <code>ResponseStream</code> */ ResponseStream getResponseStream(RequestStream requestStream, int bufferSize) { return new ResponseStream(this, requestStream.getStreamId(), bufferSize); } /** * Retrieve the TDS version that is active on the connection * supported by this socket. * * @return the TDS version as an <code>int</code> */ int getTdsVersion() { return tdsVersion; } /** * Set the TDS version field. * * @param tdsVersion the TDS version as an <code>int</code> */ protected void setTdsVersion(int tdsVersion) { this.tdsVersion = tdsVersion; } /** * Set the global buffer memory limit for all instances of this driver. * * @param memoryBudget the global memory budget */ static void setMemoryBudget(int memoryBudget) { SharedSocket.memoryBudget = memoryBudget; } /** * Get the global buffer memory limit for all instancs of this driver. * * @return the memory limit as an <code>int</code> */ static int getMemoryBudget() { return SharedSocket.memoryBudget; } /** * Set the minimum number of packets to cache in memory before * writing to disk. * * @param minMemPkts the minimum number of packets to cache */ static void setMinMemPkts(int minMemPkts) { SharedSocket.minMemPkts = minMemPkts; } /** * Get the minimum number of memory cached packets. * * @return minimum memory packets as an <code>int</code> */ static int getMinMemPkts() { return SharedSocket.minMemPkts; } /** * Get the connected status of this socket. * * @return <code>true</code> if the underlying socket is connected */ boolean isConnected() { return this.socket != null; } /** * Send a TDS cancel packet to the server. * * @param streamId the <code>RequestStream</code> id * @return <code>boolean</code> true if a cancel is actually * issued by this method call. */ boolean cancel(int streamId) { // // Need to synchronize packet send to avoid race conditions on // responsOwner and cancelPending // synchronized (cancelMonitor) { // // Only send if response pending for the caller. // Caller must have aquired connection mutex first. // NB. This method will not work with local named pipes // as this thread will be blocked in the write until the // reading thread has returned from the read. // if (responseOwner == streamId && !cancelPending) { try { // // Send a cancel packet. // cancelPending = true; byte[] cancel = new byte[TDS_HDR_LEN]; cancel[0] = TdsCore.CANCEL_PKT; cancel[1] = 1; cancel[2] = 0; cancel[3] = 8; cancel[4] = 0; cancel[5] = 0; cancel[6] = (tdsVersion >= Driver.TDS70) ? (byte) 1 : 0; cancel[7] = 0; getOut().write(cancel, 0, TDS_HDR_LEN); getOut().flush(); if (Logger.isActive()) { Logger.logPacket(streamId, false, cancel); } return true; } catch (IOException e) { // Ignore error as network is probably dead anyway } } } return false; } /** * Close the socket and release all resources. * * @throws IOException if the socket close fails */ void close() throws IOException { if (Logger.isActive()) { Logger.println("TdsSocket: Max buffer memory used = " + (peakMemUsage / 1024) + "KB"); } synchronized (socketTable) { // See if any temporary files need deleting for (int i = 0; i < socketTable.size(); i++) { VirtualSocket vsock = (VirtualSocket) socketTable.get(i); if (vsock != null && vsock.diskQueue != null) { try { vsock.diskQueue.close(); vsock.queueFile.delete(); } catch (IOException ioe) { // Ignore errors } } } try { if (sslSocket != null) { sslSocket.close(); sslSocket = null; } } finally { // Close physical socket if (socket != null) { socket.close(); } } } } /** * Force close the socket causing any pending reads/writes to fail. * <p> * Used by the login timer to abort a login attempt. */ void forceClose() { if (socket != null) { try { socket.close(); } catch (IOException ioe) { // Ignore } finally { sslSocket = null; socket = null; } } } /** * Deallocate a stream linked to this socket. * * @param streamId the <code>ResponseStream</code> id */ void closeStream(int streamId) { synchronized (socketTable) { VirtualSocket vsock = lookup(streamId); if (vsock.diskQueue != null) { try { vsock.diskQueue.close(); vsock.queueFile.delete(); } catch (IOException ioe) { // Ignore errors } } socketTable.set(streamId, null); } } /** * Send a network packet. If output for another virtual socket is * in progress this packet will be sent later. * * @param streamId the originating <code>RequestStream</code> object * @param buffer the data to send * @return the same buffer received if emptied or another buffer w/ the * same size if the incoming buffer is cached (to avoid copying) * @throws IOException if an I/O error occurs */ byte[] sendNetPacket(int streamId, byte buffer[]) throws IOException { synchronized (socketTable) { VirtualSocket vsock = lookup(streamId); while (vsock.inputPkts > 0) { // // There is unread data in the input buffers. // As we are sending another packet we can just discard it now. // if (Logger.isActive()) { Logger.println("TdsSocket: Unread data in input packet queue"); } dequeueInput(vsock); } if (responseOwner != -1) { // // Complex case there is another stream's data in the network pipe // or we had our own incomplete request to discard first // Read and store other stream's data or flush our own. // VirtualSocket other = (VirtualSocket)socketTable.get(responseOwner); byte[] tmpBuf = null; boolean ourData = (other.owner == streamId); do { // Reuse the buffer if it's our data; we don't need it tmpBuf = readPacket(ourData ? tmpBuf : null); if (!ourData) { // We need to save this input as it belongs to // Another thread. enqueueInput(other, tmpBuf); } // Any of our input is discarded. } while (tmpBuf[1] == 0); // Read all data to complete TDS packet } // // At this point we know that we are able to send the first // or subsequent packet of a new request. // getOut().write(buffer, 0, getPktLen(buffer)); if (buffer[1] != 0) { getOut().flush(); // We are the response owner now responseOwner = streamId; } return buffer; } } /** * Get a network packet. This may be read from the network directly or from * previously cached buffers. * * @param streamId the originating ResponseStream object * @param buffer the data buffer to receive the object (may be replaced) * @return the data in a <code>byte[]</code> buffer * @throws IOException if an I/O error occurs */ byte[] getNetPacket(int streamId, byte buffer[]) throws IOException { synchronized (socketTable) { VirtualSocket vsock = lookup(streamId); // // Return any cached input // if (vsock.inputPkts > 0) { return dequeueInput(vsock); } // // Nothing cached see if we are expecting network data //
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -