mirror of
https://github.com/valitydev/thrift.git
synced 2024-11-07 10:48:51 +00:00
THRIFT-4535: XML docs; code cleanup (tabs->spaces; String->string)
Client: C# Patch: Christian Weiss This closes #1524
This commit is contained in:
parent
d4fb364d30
commit
8fb719efb1
@ -79,7 +79,7 @@ namespace Thrift.Collections
|
||||
}
|
||||
|
||||
int hashcode = 0;
|
||||
foreach (Object obj in enumerable)
|
||||
foreach (object obj in enumerable)
|
||||
{
|
||||
IEnumerable enum2 = obj as IEnumerable;
|
||||
int objHash = enum2 == null ? obj.GetHashCode () : GetHashCode (enum2);
|
||||
@ -91,4 +91,4 @@ namespace Thrift.Collections
|
||||
return hashcode;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -21,9 +21,9 @@ namespace Thrift.Protocol
|
||||
{
|
||||
public interface TAbstractBase
|
||||
{
|
||||
///
|
||||
/// Writes the objects out to the protocol
|
||||
///
|
||||
/// <summary>
|
||||
/// Writes the objects out to the protocol.
|
||||
/// </summary>
|
||||
void Write(TProtocol tProtocol);
|
||||
}
|
||||
}
|
||||
|
@ -21,9 +21,9 @@ namespace Thrift.Protocol
|
||||
{
|
||||
public interface TBase : TAbstractBase
|
||||
{
|
||||
///
|
||||
/// <summary>
|
||||
/// Reads the TObject from the given input protocol.
|
||||
///
|
||||
/// </summary>
|
||||
void Read(TProtocol tProtocol);
|
||||
}
|
||||
}
|
||||
|
@ -36,29 +36,28 @@ namespace Thrift.Protocol
|
||||
protected bool strictWrite_ = true;
|
||||
|
||||
#region BinaryProtocol Factory
|
||||
/**
|
||||
* Factory
|
||||
*/
|
||||
public class Factory : TProtocolFactory {
|
||||
|
||||
protected bool strictRead_ = false;
|
||||
protected bool strictWrite_ = true;
|
||||
public class Factory : TProtocolFactory
|
||||
{
|
||||
protected bool strictRead_ = false;
|
||||
protected bool strictWrite_ = true;
|
||||
|
||||
public Factory()
|
||||
:this(false, true)
|
||||
{
|
||||
}
|
||||
|
||||
public Factory(bool strictRead, bool strictWrite)
|
||||
{
|
||||
strictRead_ = strictRead;
|
||||
strictWrite_ = strictWrite;
|
||||
}
|
||||
|
||||
public TProtocol GetProtocol(TTransport trans) {
|
||||
return new TBinaryProtocol(trans, strictRead_, strictWrite_);
|
||||
public Factory()
|
||||
: this(false, true)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
public Factory(bool strictRead, bool strictWrite)
|
||||
{
|
||||
strictRead_ = strictRead;
|
||||
strictWrite_ = strictWrite;
|
||||
}
|
||||
|
||||
public TProtocol GetProtocol(TTransport trans)
|
||||
{
|
||||
return new TBinaryProtocol(trans, strictRead_, strictWrite_);
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
@ -68,7 +67,7 @@ namespace Thrift.Protocol
|
||||
}
|
||||
|
||||
public TBinaryProtocol(TTransport trans, bool strictRead, bool strictWrite)
|
||||
:base(trans)
|
||||
: base(trans)
|
||||
{
|
||||
strictRead_ = strictRead;
|
||||
strictWrite_ = strictWrite;
|
||||
@ -345,16 +344,17 @@ namespace Thrift.Protocol
|
||||
public override long ReadI64()
|
||||
{
|
||||
ReadAll(i64in, 0, 8);
|
||||
unchecked {
|
||||
return (long)(
|
||||
((long)(i64in[0] & 0xff) << 56) |
|
||||
((long)(i64in[1] & 0xff) << 48) |
|
||||
((long)(i64in[2] & 0xff) << 40) |
|
||||
((long)(i64in[3] & 0xff) << 32) |
|
||||
((long)(i64in[4] & 0xff) << 24) |
|
||||
((long)(i64in[5] & 0xff) << 16) |
|
||||
((long)(i64in[6] & 0xff) << 8) |
|
||||
((long)(i64in[7] & 0xff)));
|
||||
unchecked
|
||||
{
|
||||
return (long)(
|
||||
((long)(i64in[0] & 0xff) << 56) |
|
||||
((long)(i64in[1] & 0xff) << 48) |
|
||||
((long)(i64in[2] & 0xff) << 40) |
|
||||
((long)(i64in[3] & 0xff) << 32) |
|
||||
((long)(i64in[4] & 0xff) << 24) |
|
||||
((long)(i64in[5] & 0xff) << 16) |
|
||||
((long)(i64in[6] & 0xff) << 8) |
|
||||
((long)(i64in[7] & 0xff)));
|
||||
}
|
||||
}
|
||||
|
||||
@ -378,7 +378,7 @@ namespace Thrift.Protocol
|
||||
trans.ReadAll(buf, 0, size);
|
||||
return buf;
|
||||
}
|
||||
private string ReadStringBody(int size)
|
||||
private string ReadStringBody(int size)
|
||||
{
|
||||
byte[] buf = new byte[size];
|
||||
trans.ReadAll(buf, 0, size);
|
||||
|
@ -44,9 +44,9 @@ namespace Thrift.Protocol
|
||||
private const byte TYPE_BITS = 0x07; // 0000 0111
|
||||
private const int TYPE_SHIFT_AMOUNT = 5;
|
||||
|
||||
/**
|
||||
* All of the on-wire type codes.
|
||||
*/
|
||||
/// <summary>
|
||||
/// All of the on-wire type codes.
|
||||
/// </summary>
|
||||
private static class Types
|
||||
{
|
||||
public const byte STOP = 0x00;
|
||||
@ -64,32 +64,29 @@ namespace Thrift.Protocol
|
||||
public const byte STRUCT = 0x0C;
|
||||
}
|
||||
|
||||
/**
|
||||
* Used to keep track of the last field for the current and previous structs,
|
||||
* so we can do the delta stuff.
|
||||
*/
|
||||
/// <summary>
|
||||
/// Used to keep track of the last field for the current and previous structs,
|
||||
/// so we can do the delta stuff.
|
||||
/// </summary>
|
||||
private Stack<short> lastField_ = new Stack<short>(15);
|
||||
|
||||
private short lastFieldId_ = 0;
|
||||
|
||||
/**
|
||||
* If we encounter a boolean field begin, save the TField here so it can
|
||||
* have the value incorporated.
|
||||
*/
|
||||
/// <summary>
|
||||
/// If we encounter a boolean field begin, save the TField here so it can
|
||||
/// have the value incorporated.
|
||||
/// </summary>
|
||||
private Nullable<TField> booleanField_;
|
||||
|
||||
/**
|
||||
* If we Read a field header, and it's a boolean field, save the boolean
|
||||
* value here so that ReadBool can use it.
|
||||
*/
|
||||
private Nullable<Boolean> boolValue_;
|
||||
/// <summary>
|
||||
/// If we Read a field header, and it's a boolean field, save the boolean
|
||||
/// value here so that ReadBool can use it.
|
||||
/// </summary>
|
||||
private Nullable<Boolean> boolValue_;
|
||||
|
||||
|
||||
#region CompactProtocol Factory
|
||||
|
||||
/**
|
||||
* Factory
|
||||
*/
|
||||
public class Factory : TProtocolFactory
|
||||
{
|
||||
public Factory() { }
|
||||
@ -127,31 +124,32 @@ namespace Thrift.Protocol
|
||||
|
||||
#region Write Methods
|
||||
|
||||
|
||||
/**
|
||||
* Writes a byte without any possibility of all that field header nonsense.
|
||||
* Used internally by other writing methods that know they need to Write a byte.
|
||||
*/
|
||||
/// <summary>
|
||||
/// Writes a byte without any possibility of all that field header nonsense.
|
||||
/// Used internally by other writing methods that know they need to Write a byte.
|
||||
/// </summary>
|
||||
private byte[] byteDirectBuffer = new byte[1];
|
||||
|
||||
private void WriteByteDirect(byte b)
|
||||
{
|
||||
byteDirectBuffer[0] = b;
|
||||
trans.Write(byteDirectBuffer);
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes a byte without any possibility of all that field header nonsense.
|
||||
*/
|
||||
/// <summary>
|
||||
/// Writes a byte without any possibility of all that field header nonsense.
|
||||
/// </summary>
|
||||
private void WriteByteDirect(int n)
|
||||
{
|
||||
WriteByteDirect((byte)n);
|
||||
}
|
||||
|
||||
/**
|
||||
* Write an i32 as a varint. Results in 1-5 bytes on the wire.
|
||||
* TODO: make a permanent buffer like WriteVarint64?
|
||||
*/
|
||||
/// <summary>
|
||||
/// Write an i32 as a varint. Results in 1-5 bytes on the wire.
|
||||
/// TODO: make a permanent buffer like WriteVarint64?
|
||||
/// </summary>
|
||||
byte[] i32buf = new byte[5];
|
||||
|
||||
private void WriteVarint32(uint n)
|
||||
{
|
||||
int idx = 0;
|
||||
@ -174,10 +172,10 @@ namespace Thrift.Protocol
|
||||
trans.Write(i32buf, 0, idx);
|
||||
}
|
||||
|
||||
/**
|
||||
* Write a message header to the wire. Compact Protocol messages contain the
|
||||
* protocol version so we can migrate forwards in the future if need be.
|
||||
*/
|
||||
/// <summary>
|
||||
/// Write a message header to the wire. Compact Protocol messages contain the
|
||||
/// protocol version so we can migrate forwards in the future if need be.
|
||||
/// </summary>
|
||||
public override void WriteMessageBegin(TMessage message)
|
||||
{
|
||||
WriteByteDirect(PROTOCOL_ID);
|
||||
@ -186,33 +184,33 @@ namespace Thrift.Protocol
|
||||
WriteString(message.Name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Write a struct begin. This doesn't actually put anything on the wire. We
|
||||
* use it as an opportunity to put special placeholder markers on the field
|
||||
* stack so we can get the field id deltas correct.
|
||||
*/
|
||||
/// <summary>
|
||||
/// Write a struct begin. This doesn't actually put anything on the wire. We
|
||||
/// use it as an opportunity to put special placeholder markers on the field
|
||||
/// stack so we can get the field id deltas correct.
|
||||
/// </summary>
|
||||
public override void WriteStructBegin(TStruct strct)
|
||||
{
|
||||
lastField_.Push(lastFieldId_);
|
||||
lastFieldId_ = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Write a struct end. This doesn't actually put anything on the wire. We use
|
||||
* this as an opportunity to pop the last field from the current struct off
|
||||
* of the field stack.
|
||||
*/
|
||||
/// <summary>
|
||||
/// Write a struct end. This doesn't actually put anything on the wire. We use
|
||||
/// this as an opportunity to pop the last field from the current struct off
|
||||
/// of the field stack.
|
||||
/// </summary>
|
||||
public override void WriteStructEnd()
|
||||
{
|
||||
lastFieldId_ = lastField_.Pop();
|
||||
}
|
||||
|
||||
/**
|
||||
* Write a field header containing the field id and field type. If the
|
||||
* difference between the current field id and the last one is small (< 15),
|
||||
* then the field id will be encoded in the 4 MSB as a delta. Otherwise, the
|
||||
* field id will follow the type header as a zigzag varint.
|
||||
*/
|
||||
/// <summary>
|
||||
/// Write a field header containing the field id and field type. If the
|
||||
/// difference between the current field id and the last one is small (< 15),
|
||||
/// then the field id will be encoded in the 4 MSB as a delta. Otherwise, the
|
||||
/// field id will follow the type header as a zigzag varint.
|
||||
/// </summary>
|
||||
public override void WriteFieldBegin(TField field)
|
||||
{
|
||||
if (field.Type == TType.Bool)
|
||||
@ -226,11 +224,11 @@ namespace Thrift.Protocol
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The workhorse of WriteFieldBegin. It has the option of doing a
|
||||
* 'type override' of the type header. This is used specifically in the
|
||||
* boolean field case.
|
||||
*/
|
||||
/// <summary>
|
||||
/// The workhorse of WriteFieldBegin. It has the option of doing a
|
||||
/// 'type override' of the type header. This is used specifically in the
|
||||
/// boolean field case.
|
||||
/// </summary>
|
||||
private void WriteFieldBeginInternal(TField field, byte typeOverride)
|
||||
{
|
||||
// short lastField = lastField_.Pop();
|
||||
@ -255,18 +253,18 @@ namespace Thrift.Protocol
|
||||
// lastField_.push(field.id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Write the STOP symbol so we know there are no more fields in this struct.
|
||||
*/
|
||||
/// <summary>
|
||||
/// Write the STOP symbol so we know there are no more fields in this struct.
|
||||
/// </summary>
|
||||
public override void WriteFieldStop()
|
||||
{
|
||||
WriteByteDirect(Types.STOP);
|
||||
}
|
||||
|
||||
/**
|
||||
* Write a map header. If the map is empty, omit the key and value type
|
||||
* headers, as we don't need any additional information to skip it.
|
||||
*/
|
||||
/// <summary>
|
||||
/// Write a map header. If the map is empty, omit the key and value type
|
||||
/// headers, as we don't need any additional information to skip it.
|
||||
/// </summary>
|
||||
public override void WriteMapBegin(TMap map)
|
||||
{
|
||||
if (map.Count == 0)
|
||||
@ -280,28 +278,28 @@ namespace Thrift.Protocol
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Write a list header.
|
||||
*/
|
||||
/// <summary>
|
||||
/// Write a list header.
|
||||
/// </summary>
|
||||
public override void WriteListBegin(TList list)
|
||||
{
|
||||
WriteCollectionBegin(list.ElementType, list.Count);
|
||||
}
|
||||
|
||||
/**
|
||||
* Write a set header.
|
||||
*/
|
||||
/// <summary>
|
||||
/// Write a set header.
|
||||
/// </summary>
|
||||
public override void WriteSetBegin(TSet set)
|
||||
{
|
||||
WriteCollectionBegin(set.ElementType, set.Count);
|
||||
}
|
||||
|
||||
/**
|
||||
* Write a boolean value. Potentially, this could be a boolean field, in
|
||||
* which case the field header info isn't written yet. If so, decide what the
|
||||
* right type header is for the value and then Write the field header.
|
||||
* Otherwise, Write a single byte.
|
||||
*/
|
||||
/// <summary>
|
||||
/// Write a boolean value. Potentially, this could be a boolean field, in
|
||||
/// which case the field header info isn't written yet. If so, decide what the
|
||||
/// right type header is for the value and then Write the field header.
|
||||
/// Otherwise, Write a single byte.
|
||||
/// </summary>
|
||||
public override void WriteBool(Boolean b)
|
||||
{
|
||||
if (booleanField_ != null)
|
||||
@ -317,41 +315,41 @@ namespace Thrift.Protocol
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Write a byte. Nothing to see here!
|
||||
*/
|
||||
/// <summary>
|
||||
/// Write a byte. Nothing to see here!
|
||||
/// </summary>
|
||||
public override void WriteByte(sbyte b)
|
||||
{
|
||||
WriteByteDirect((byte)b);
|
||||
}
|
||||
|
||||
/**
|
||||
* Write an I16 as a zigzag varint.
|
||||
*/
|
||||
/// <summary>
|
||||
/// Write an I16 as a zigzag varint.
|
||||
/// </summary>
|
||||
public override void WriteI16(short i16)
|
||||
{
|
||||
WriteVarint32(intToZigZag(i16));
|
||||
}
|
||||
|
||||
/**
|
||||
* Write an i32 as a zigzag varint.
|
||||
*/
|
||||
/// <summary>
|
||||
/// Write an i32 as a zigzag varint.
|
||||
/// </summary>
|
||||
public override void WriteI32(int i32)
|
||||
{
|
||||
WriteVarint32(intToZigZag(i32));
|
||||
}
|
||||
|
||||
/**
|
||||
* Write an i64 as a zigzag varint.
|
||||
*/
|
||||
/// <summary>
|
||||
/// Write an i64 as a zigzag varint.
|
||||
/// </summary>
|
||||
public override void WriteI64(long i64)
|
||||
{
|
||||
WriteVarint64(longToZigzag(i64));
|
||||
}
|
||||
|
||||
/**
|
||||
* Write a double to the wire as 8 bytes.
|
||||
*/
|
||||
/// <summary>
|
||||
/// Write a double to the wire as 8 bytes.
|
||||
/// </summary>
|
||||
public override void WriteDouble(double dub)
|
||||
{
|
||||
byte[] data = new byte[] { 0, 0, 0, 0, 0, 0, 0, 0 };
|
||||
@ -359,18 +357,18 @@ namespace Thrift.Protocol
|
||||
trans.Write(data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Write a string to the wire with a varint size preceding.
|
||||
*/
|
||||
public override void WriteString(String str)
|
||||
/// <summary>
|
||||
/// Write a string to the wire with a varint size preceding.
|
||||
/// </summary>
|
||||
public override void WriteString(string str)
|
||||
{
|
||||
byte[] bytes = UTF8Encoding.UTF8.GetBytes(str);
|
||||
WriteBinary(bytes, 0, bytes.Length);
|
||||
}
|
||||
|
||||
/**
|
||||
* Write a byte array, using a varint for the size.
|
||||
*/
|
||||
/// <summary>
|
||||
/// Write a byte array, using a varint for the size.
|
||||
/// </summary>
|
||||
public override void WriteBinary(byte[] bin)
|
||||
{
|
||||
WriteBinary(bin, 0, bin.Length);
|
||||
@ -397,10 +395,10 @@ namespace Thrift.Protocol
|
||||
// Internal writing methods
|
||||
//
|
||||
|
||||
/**
|
||||
* Abstract method for writing the start of lists and sets. List and sets on
|
||||
* the wire differ only by the type indicator.
|
||||
*/
|
||||
/// <summary>
|
||||
/// Abstract method for writing the start of lists and sets. List and sets on
|
||||
/// the wire differ only by the type indicator.
|
||||
/// </summary>
|
||||
protected void WriteCollectionBegin(TType elemType, int size)
|
||||
{
|
||||
if (size <= 14)
|
||||
@ -414,9 +412,9 @@ namespace Thrift.Protocol
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Write an i64 as a varint. Results in 1-10 bytes on the wire.
|
||||
*/
|
||||
/// <summary>
|
||||
/// Write an i64 as a varint. Results in 1-10 bytes on the wire.
|
||||
/// </summary>
|
||||
byte[] varint64out = new byte[10];
|
||||
private void WriteVarint64(ulong n)
|
||||
{
|
||||
@ -437,28 +435,28 @@ namespace Thrift.Protocol
|
||||
trans.Write(varint64out, 0, idx);
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert l into a zigzag long. This allows negative numbers to be
|
||||
* represented compactly as a varint.
|
||||
*/
|
||||
/// <summary>
|
||||
/// Convert l into a zigzag long. This allows negative numbers to be
|
||||
/// represented compactly as a varint.
|
||||
/// </summary>
|
||||
private ulong longToZigzag(long n)
|
||||
{
|
||||
return (ulong)(n << 1) ^ (ulong)(n >> 63);
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert n into a zigzag int. This allows negative numbers to be
|
||||
* represented compactly as a varint.
|
||||
*/
|
||||
/// <summary>
|
||||
/// Convert n into a zigzag int. This allows negative numbers to be
|
||||
/// represented compactly as a varint.
|
||||
/// </summary>
|
||||
private uint intToZigZag(int n)
|
||||
{
|
||||
return (uint)(n << 1) ^ (uint)(n >> 31);
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert a long into little-endian bytes in buf starting at off and going
|
||||
* until off+7.
|
||||
*/
|
||||
/// <summary>
|
||||
/// Convert a long into little-endian bytes in buf starting at off and going
|
||||
/// until off+7.
|
||||
/// </summary>
|
||||
private void fixedLongToBytes(long n, byte[] buf, int off)
|
||||
{
|
||||
buf[off + 0] = (byte)(n & 0xff);
|
||||
@ -475,9 +473,9 @@ namespace Thrift.Protocol
|
||||
|
||||
#region ReadMethods
|
||||
|
||||
/**
|
||||
* Read a message header.
|
||||
*/
|
||||
/// <summary>
|
||||
/// Read a message header.
|
||||
/// </summary>
|
||||
public override TMessage ReadMessageBegin()
|
||||
{
|
||||
byte protocolId = (byte)ReadByte();
|
||||
@ -493,14 +491,14 @@ namespace Thrift.Protocol
|
||||
}
|
||||
byte type = (byte)((versionAndType >> TYPE_SHIFT_AMOUNT) & TYPE_BITS);
|
||||
int seqid = (int)ReadVarint32();
|
||||
String messageName = ReadString();
|
||||
string messageName = ReadString();
|
||||
return new TMessage(messageName, (TMessageType)type, seqid);
|
||||
}
|
||||
|
||||
/**
|
||||
* Read a struct begin. There's nothing on the wire for this, but it is our
|
||||
* opportunity to push a new struct begin marker onto the field stack.
|
||||
*/
|
||||
/// <summary>
|
||||
/// Read a struct begin. There's nothing on the wire for this, but it is our
|
||||
/// opportunity to push a new struct begin marker onto the field stack.
|
||||
/// </summary>
|
||||
public override TStruct ReadStructBegin()
|
||||
{
|
||||
lastField_.Push(lastFieldId_);
|
||||
@ -508,19 +506,19 @@ namespace Thrift.Protocol
|
||||
return ANONYMOUS_STRUCT;
|
||||
}
|
||||
|
||||
/**
|
||||
* Doesn't actually consume any wire data, just removes the last field for
|
||||
* this struct from the field stack.
|
||||
*/
|
||||
/// <summary>
|
||||
/// Doesn't actually consume any wire data, just removes the last field for
|
||||
/// this struct from the field stack.
|
||||
/// </summary>
|
||||
public override void ReadStructEnd()
|
||||
{
|
||||
// consume the last field we Read off the wire.
|
||||
lastFieldId_ = lastField_.Pop();
|
||||
}
|
||||
|
||||
/**
|
||||
* Read a field header off the wire.
|
||||
*/
|
||||
/// <summary>
|
||||
/// Read a field header off the wire.
|
||||
/// </summary>
|
||||
public override TField ReadFieldBegin()
|
||||
{
|
||||
byte type = (byte)ReadByte();
|
||||
@ -560,11 +558,11 @@ namespace Thrift.Protocol
|
||||
return field;
|
||||
}
|
||||
|
||||
/**
|
||||
* Read a map header off the wire. If the size is zero, skip Reading the key
|
||||
* and value type. This means that 0-length maps will yield TMaps without the
|
||||
* "correct" types.
|
||||
*/
|
||||
/// <summary>
|
||||
/// Read a map header off the wire. If the size is zero, skip Reading the key
|
||||
/// and value type. This means that 0-length maps will yield TMaps without the
|
||||
/// "correct" types.
|
||||
/// </summary>
|
||||
public override TMap ReadMapBegin()
|
||||
{
|
||||
int size = (int)ReadVarint32();
|
||||
@ -572,12 +570,12 @@ namespace Thrift.Protocol
|
||||
return new TMap(getTType((byte)(keyAndValueType >> 4)), getTType((byte)(keyAndValueType & 0xf)), size);
|
||||
}
|
||||
|
||||
/**
|
||||
* Read a list header off the wire. If the list size is 0-14, the size will
|
||||
* be packed into the element type header. If it's a longer list, the 4 MSB
|
||||
* of the element type header will be 0xF, and a varint will follow with the
|
||||
* true size.
|
||||
*/
|
||||
/// <summary>
|
||||
/// Read a list header off the wire. If the list size is 0-14, the size will
|
||||
/// be packed into the element type header. If it's a longer list, the 4 MSB
|
||||
/// of the element type header will be 0xF, and a varint will follow with the
|
||||
/// true size.
|
||||
/// </summary>
|
||||
public override TList ReadListBegin()
|
||||
{
|
||||
byte size_and_type = (byte)ReadByte();
|
||||
@ -590,22 +588,22 @@ namespace Thrift.Protocol
|
||||
return new TList(type, size);
|
||||
}
|
||||
|
||||
/**
|
||||
* Read a set header off the wire. If the set size is 0-14, the size will
|
||||
* be packed into the element type header. If it's a longer set, the 4 MSB
|
||||
* of the element type header will be 0xF, and a varint will follow with the
|
||||
* true size.
|
||||
*/
|
||||
/// <summary>
|
||||
/// Read a set header off the wire. If the set size is 0-14, the size will
|
||||
/// be packed into the element type header. If it's a longer set, the 4 MSB
|
||||
/// of the element type header will be 0xF, and a varint will follow with the
|
||||
/// true size.
|
||||
/// </summary>
|
||||
public override TSet ReadSetBegin()
|
||||
{
|
||||
return new TSet(ReadListBegin());
|
||||
}
|
||||
|
||||
/**
|
||||
* Read a boolean off the wire. If this is a boolean field, the value should
|
||||
* already have been Read during ReadFieldBegin, so we'll just consume the
|
||||
* pre-stored value. Otherwise, Read a byte.
|
||||
*/
|
||||
/// <summary>
|
||||
/// Read a boolean off the wire. If this is a boolean field, the value should
|
||||
/// already have been Read during ReadFieldBegin, so we'll just consume the
|
||||
/// pre-stored value. Otherwise, Read a byte.
|
||||
/// </summary>
|
||||
public override Boolean ReadBool()
|
||||
{
|
||||
if (boolValue_ != null)
|
||||
@ -618,42 +616,42 @@ namespace Thrift.Protocol
|
||||
}
|
||||
|
||||
byte[] byteRawBuf = new byte[1];
|
||||
/**
|
||||
* Read a single byte off the wire. Nothing interesting here.
|
||||
*/
|
||||
/// <summary>
|
||||
/// Read a single byte off the wire. Nothing interesting here.
|
||||
/// </summary>
|
||||
public override sbyte ReadByte()
|
||||
{
|
||||
trans.ReadAll(byteRawBuf, 0, 1);
|
||||
return (sbyte)byteRawBuf[0];
|
||||
}
|
||||
|
||||
/**
|
||||
* Read an i16 from the wire as a zigzag varint.
|
||||
*/
|
||||
/// <summary>
|
||||
/// Read an i16 from the wire as a zigzag varint.
|
||||
/// </summary>
|
||||
public override short ReadI16()
|
||||
{
|
||||
return (short)zigzagToInt(ReadVarint32());
|
||||
}
|
||||
|
||||
/**
|
||||
* Read an i32 from the wire as a zigzag varint.
|
||||
*/
|
||||
/// <summary>
|
||||
/// Read an i32 from the wire as a zigzag varint.
|
||||
/// </summary>
|
||||
public override int ReadI32()
|
||||
{
|
||||
return zigzagToInt(ReadVarint32());
|
||||
}
|
||||
|
||||
/**
|
||||
* Read an i64 from the wire as a zigzag varint.
|
||||
*/
|
||||
/// <summary>
|
||||
/// Read an i64 from the wire as a zigzag varint.
|
||||
/// </summary>
|
||||
public override long ReadI64()
|
||||
{
|
||||
return zigzagToLong(ReadVarint64());
|
||||
}
|
||||
|
||||
/**
|
||||
* No magic here - just Read a double off the wire.
|
||||
*/
|
||||
/// <summary>
|
||||
/// No magic here - just Read a double off the wire.
|
||||
/// </summary>
|
||||
public override double ReadDouble()
|
||||
{
|
||||
byte[] longBits = new byte[8];
|
||||
@ -661,10 +659,10 @@ namespace Thrift.Protocol
|
||||
return BitConverter.Int64BitsToDouble(bytesToLong(longBits));
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads a byte[] (via ReadBinary), and then UTF-8 decodes it.
|
||||
*/
|
||||
public override String ReadString()
|
||||
/// <summary>
|
||||
/// Reads a byte[] (via ReadBinary), and then UTF-8 decodes it.
|
||||
/// </summary>
|
||||
public override string ReadString()
|
||||
{
|
||||
int length = (int)ReadVarint32();
|
||||
|
||||
@ -676,9 +674,9 @@ namespace Thrift.Protocol
|
||||
return Encoding.UTF8.GetString(ReadBinary(length));
|
||||
}
|
||||
|
||||
/**
|
||||
* Read a byte[] from the wire.
|
||||
*/
|
||||
/// <summary>
|
||||
/// Read a byte[] from the wire.
|
||||
/// </summary>
|
||||
public override byte[] ReadBinary()
|
||||
{
|
||||
int length = (int)ReadVarint32();
|
||||
@ -689,9 +687,9 @@ namespace Thrift.Protocol
|
||||
return buf;
|
||||
}
|
||||
|
||||
/**
|
||||
* Read a byte[] of a known length from the wire.
|
||||
*/
|
||||
/// <summary>
|
||||
/// Read a byte[] of a known length from the wire.
|
||||
/// </summary>
|
||||
private byte[] ReadBinary(int length)
|
||||
{
|
||||
if (length == 0) return new byte[0];
|
||||
@ -715,10 +713,10 @@ namespace Thrift.Protocol
|
||||
// Internal Reading methods
|
||||
//
|
||||
|
||||
/**
|
||||
* Read an i32 from the wire as a varint. The MSB of each byte is set
|
||||
* if there is another byte to follow. This can Read up to 5 bytes.
|
||||
*/
|
||||
/// <summary>
|
||||
/// Read an i32 from the wire as a varint. The MSB of each byte is set
|
||||
/// if there is another byte to follow. This can Read up to 5 bytes.
|
||||
/// </summary>
|
||||
private uint ReadVarint32()
|
||||
{
|
||||
uint result = 0;
|
||||
@ -733,10 +731,10 @@ namespace Thrift.Protocol
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Read an i64 from the wire as a proper varint. The MSB of each byte is set
|
||||
* if there is another byte to follow. This can Read up to 10 bytes.
|
||||
*/
|
||||
/// <summary>
|
||||
/// Read an i64 from the wire as a proper varint. The MSB of each byte is set
|
||||
/// if there is another byte to follow. This can Read up to 10 bytes.
|
||||
/// </summary>
|
||||
private ulong ReadVarint64()
|
||||
{
|
||||
int shift = 0;
|
||||
@ -758,27 +756,27 @@ namespace Thrift.Protocol
|
||||
// encoding helpers
|
||||
//
|
||||
|
||||
/**
|
||||
* Convert from zigzag int to int.
|
||||
*/
|
||||
/// <summary>
|
||||
/// Convert from zigzag int to int.
|
||||
/// </summary>
|
||||
private int zigzagToInt(uint n)
|
||||
{
|
||||
return (int)(n >> 1) ^ (-(int)(n & 1));
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert from zigzag long to long.
|
||||
*/
|
||||
/// <summary>
|
||||
/// Convert from zigzag long to long.
|
||||
/// </summary>
|
||||
private long zigzagToLong(ulong n)
|
||||
{
|
||||
return (long)(n >> 1) ^ (-(long)(n & 1));
|
||||
}
|
||||
|
||||
/**
|
||||
* Note that it's important that the mask bytes are long literals,
|
||||
* otherwise they'll default to ints, and when you shift an int left 56 bits,
|
||||
* you just get a messed up int.
|
||||
*/
|
||||
/// <summary>
|
||||
/// Note that it's important that the mask bytes are long literals,
|
||||
/// otherwise they'll default to ints, and when you shift an int left 56 bits,
|
||||
/// you just get a messed up int.
|
||||
/// </summary>
|
||||
private long bytesToLong(byte[] bytes)
|
||||
{
|
||||
return
|
||||
@ -802,10 +800,10 @@ namespace Thrift.Protocol
|
||||
return lowerNibble == Types.BOOLEAN_TRUE || lowerNibble == Types.BOOLEAN_FALSE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Given a TCompactProtocol.Types constant, convert it to its corresponding
|
||||
* TType value.
|
||||
*/
|
||||
/// <summary>
|
||||
/// Given a TCompactProtocol.Types constant, convert it to its corresponding
|
||||
/// TType value.
|
||||
/// </summary>
|
||||
private TType getTType(byte type)
|
||||
{
|
||||
switch ((byte)(type & 0x0f))
|
||||
@ -840,9 +838,9 @@ namespace Thrift.Protocol
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Given a TType value, find the appropriate TCompactProtocol.Types constant.
|
||||
*/
|
||||
/// <summary>
|
||||
/// Given a TType value, find the appropriate TCompactProtocol.Types constant.
|
||||
/// </summary>
|
||||
private byte getCompactType(TType ttype)
|
||||
{
|
||||
return ttypeToCompactType[(int)ttype];
|
||||
|
@ -29,18 +29,18 @@ namespace Thrift.Protocol
|
||||
{
|
||||
/// <summary>
|
||||
/// JSON protocol implementation for thrift.
|
||||
///
|
||||
/// <para/>
|
||||
/// This is a full-featured protocol supporting Write and Read.
|
||||
///
|
||||
/// <para/>
|
||||
/// Please see the C++ class header for a detailed description of the
|
||||
/// protocol's wire format.
|
||||
///
|
||||
/// <para/>
|
||||
/// Adapted from the Java version.
|
||||
/// </summary>
|
||||
public class TJSONProtocol : TProtocol
|
||||
{
|
||||
/// <summary>
|
||||
/// Factory for JSON protocol objects
|
||||
/// Factory for JSON protocol objects.
|
||||
/// </summary>
|
||||
public class Factory : TProtocolFactory
|
||||
{
|
||||
@ -179,11 +179,11 @@ namespace Thrift.Protocol
|
||||
return result;
|
||||
}
|
||||
|
||||
///<summary>
|
||||
/// <summary>
|
||||
/// Base class for tracking JSON contexts that may require
|
||||
/// inserting/Reading additional JSON syntax characters
|
||||
/// This base context does nothing.
|
||||
///</summary>
|
||||
/// </summary>
|
||||
protected class JSONBaseContext
|
||||
{
|
||||
protected TJSONProtocol proto;
|
||||
@ -200,10 +200,10 @@ namespace Thrift.Protocol
|
||||
public virtual bool EscapeNumbers() { return false; }
|
||||
}
|
||||
|
||||
///<summary>
|
||||
/// <summary>
|
||||
/// Context for JSON lists. Will insert/Read commas before each item except
|
||||
/// for the first one
|
||||
///</summary>
|
||||
/// </summary>
|
||||
protected class JSONListContext : JSONBaseContext
|
||||
{
|
||||
public JSONListContext(TJSONProtocol protocol)
|
||||
@ -239,12 +239,12 @@ namespace Thrift.Protocol
|
||||
}
|
||||
}
|
||||
|
||||
///<summary>
|
||||
/// <summary>
|
||||
/// Context for JSON records. Will insert/Read colons before the value portion
|
||||
/// of each record pair, and commas before each key except the first. In
|
||||
/// addition, will indicate that numbers in the key position need to be
|
||||
/// escaped in quotes (since JSON keys must be strings).
|
||||
///</summary>
|
||||
/// </summary>
|
||||
protected class JSONPairContext : JSONBaseContext
|
||||
{
|
||||
public JSONPairContext(TJSONProtocol proto)
|
||||
@ -290,9 +290,9 @@ namespace Thrift.Protocol
|
||||
}
|
||||
}
|
||||
|
||||
///<summary>
|
||||
/// <summary>
|
||||
/// Holds up to one byte from the transport
|
||||
///</summary>
|
||||
/// </summary>
|
||||
protected class LookaheadReader
|
||||
{
|
||||
protected TJSONProtocol proto;
|
||||
@ -305,10 +305,10 @@ namespace Thrift.Protocol
|
||||
private bool hasData;
|
||||
private byte[] data = new byte[1];
|
||||
|
||||
///<summary>
|
||||
/// <summary>
|
||||
/// Return and consume the next byte to be Read, either taking it from the
|
||||
/// data buffer if present or getting it from the transport otherwise.
|
||||
///</summary>
|
||||
/// </summary>
|
||||
public byte Read()
|
||||
{
|
||||
if (hasData)
|
||||
@ -322,10 +322,10 @@ namespace Thrift.Protocol
|
||||
return data[0];
|
||||
}
|
||||
|
||||
///<summary>
|
||||
/// <summary>
|
||||
/// Return the next byte to be Read without consuming, filling the data
|
||||
/// buffer if it has not been filled alReady.
|
||||
///</summary>
|
||||
/// </summary>
|
||||
public byte Peek()
|
||||
{
|
||||
if (!hasData)
|
||||
@ -349,26 +349,26 @@ namespace Thrift.Protocol
|
||||
// Reader that manages a 1-byte buffer
|
||||
protected LookaheadReader reader;
|
||||
|
||||
///<summary>
|
||||
/// <summary>
|
||||
/// Push a new JSON context onto the stack.
|
||||
///</summary>
|
||||
/// </summary>
|
||||
protected void PushContext(JSONBaseContext c)
|
||||
{
|
||||
contextStack.Push(context);
|
||||
context = c;
|
||||
}
|
||||
|
||||
///<summary>
|
||||
/// <summary>
|
||||
/// Pop the last JSON context off the stack
|
||||
///</summary>
|
||||
/// </summary>
|
||||
protected void PopContext()
|
||||
{
|
||||
context = contextStack.Pop();
|
||||
}
|
||||
|
||||
///<summary>
|
||||
/// <summary>
|
||||
/// TJSONProtocol Constructor
|
||||
///</summary>
|
||||
/// </summary>
|
||||
public TJSONProtocol(TTransport trans)
|
||||
: base(trans)
|
||||
{
|
||||
@ -379,11 +379,11 @@ namespace Thrift.Protocol
|
||||
// Temporary buffer used by several methods
|
||||
private byte[] tempBuffer = new byte[4];
|
||||
|
||||
///<summary>
|
||||
/// <summary>
|
||||
/// Read a byte that must match b[0]; otherwise an exception is thrown.
|
||||
/// Marked protected to avoid synthetic accessor in JSONListContext.Read
|
||||
/// and JSONPairContext.Read
|
||||
///</summary>
|
||||
/// </summary>
|
||||
protected void ReadJSONSyntaxChar(byte[] b)
|
||||
{
|
||||
byte ch = reader.Read();
|
||||
@ -394,10 +394,10 @@ namespace Thrift.Protocol
|
||||
}
|
||||
}
|
||||
|
||||
///<summary>
|
||||
/// <summary>
|
||||
/// Convert a byte containing a hex char ('0'-'9' or 'a'-'f') into its
|
||||
/// corresponding hex value
|
||||
///</summary>
|
||||
/// </summary>
|
||||
private static byte HexVal(byte ch)
|
||||
{
|
||||
if ((ch >= '0') && (ch <= '9'))
|
||||
@ -416,9 +416,9 @@ namespace Thrift.Protocol
|
||||
}
|
||||
}
|
||||
|
||||
///<summary>
|
||||
/// <summary>
|
||||
/// Convert a byte containing a hex value to its corresponding hex character
|
||||
///</summary>
|
||||
/// </summary>
|
||||
private static byte HexChar(byte val)
|
||||
{
|
||||
val &= 0x0F;
|
||||
@ -433,9 +433,9 @@ namespace Thrift.Protocol
|
||||
}
|
||||
}
|
||||
|
||||
///<summary>
|
||||
/// <summary>
|
||||
/// Write the bytes in array buf as a JSON characters, escaping as needed
|
||||
///</summary>
|
||||
/// </summary>
|
||||
private void WriteJSONString(byte[] b)
|
||||
{
|
||||
context.Write();
|
||||
@ -479,14 +479,14 @@ namespace Thrift.Protocol
|
||||
trans.Write(QUOTE);
|
||||
}
|
||||
|
||||
///<summary>
|
||||
/// <summary>
|
||||
/// Write out number as a JSON value. If the context dictates so, it will be
|
||||
/// wrapped in quotes to output as a JSON string.
|
||||
///</summary>
|
||||
/// </summary>
|
||||
private void WriteJSONInteger(long num)
|
||||
{
|
||||
context.Write();
|
||||
String str = num.ToString();
|
||||
string str = num.ToString();
|
||||
|
||||
bool escapeNum = context.EscapeNumbers();
|
||||
if (escapeNum)
|
||||
@ -498,14 +498,14 @@ namespace Thrift.Protocol
|
||||
trans.Write(QUOTE);
|
||||
}
|
||||
|
||||
///<summary>
|
||||
/// <summary>
|
||||
/// Write out a double as a JSON value. If it is NaN or infinity or if the
|
||||
/// context dictates escaping, Write out as JSON string.
|
||||
///</summary>
|
||||
/// </summary>
|
||||
private void WriteJSONDouble(double num)
|
||||
{
|
||||
context.Write();
|
||||
String str = num.ToString("G17", CultureInfo.InvariantCulture);
|
||||
string str = num.ToString("G17", CultureInfo.InvariantCulture);
|
||||
bool special = false;
|
||||
|
||||
switch (str[0])
|
||||
@ -532,10 +532,10 @@ namespace Thrift.Protocol
|
||||
if (escapeNum)
|
||||
trans.Write(QUOTE);
|
||||
}
|
||||
///<summary>
|
||||
/// <summary>
|
||||
/// Write out contents of byte array b as a JSON string with base-64 encoded
|
||||
/// data
|
||||
///</summary>
|
||||
/// </summary>
|
||||
private void WriteJSONBase64(byte[] b)
|
||||
{
|
||||
context.Write();
|
||||
@ -698,7 +698,7 @@ namespace Thrift.Protocol
|
||||
WriteJSONDouble(dub);
|
||||
}
|
||||
|
||||
public override void WriteString(String str)
|
||||
public override void WriteString(string str)
|
||||
{
|
||||
byte[] b = utf8Encoding.GetBytes(str);
|
||||
WriteJSONString(b);
|
||||
@ -713,10 +713,10 @@ namespace Thrift.Protocol
|
||||
* Reading methods.
|
||||
*/
|
||||
|
||||
///<summary>
|
||||
/// <summary>
|
||||
/// Read in a JSON string, unescaping as appropriate.. Skip Reading from the
|
||||
/// context if skipContext is true.
|
||||
///</summary>
|
||||
/// </summary>
|
||||
private byte[] ReadJSONString(bool skipContext)
|
||||
{
|
||||
MemoryStream buffer = new MemoryStream();
|
||||
@ -803,9 +803,9 @@ namespace Thrift.Protocol
|
||||
return buffer.ToArray();
|
||||
}
|
||||
|
||||
///<summary>
|
||||
/// <summary>
|
||||
/// Return true if the given byte could be a valid part of a JSON number.
|
||||
///</summary>
|
||||
/// </summary>
|
||||
private bool IsJSONNumeric(byte b)
|
||||
{
|
||||
switch (b)
|
||||
@ -830,11 +830,11 @@ namespace Thrift.Protocol
|
||||
return false;
|
||||
}
|
||||
|
||||
///<summary>
|
||||
/// <summary>
|
||||
/// Read in a sequence of characters that are all valid in JSON numbers. Does
|
||||
/// not do a complete regex check to validate that this is actually a number.
|
||||
////</summary>
|
||||
private String ReadJSONNumericChars()
|
||||
/// </summary>
|
||||
private string ReadJSONNumericChars()
|
||||
{
|
||||
StringBuilder strbld = new StringBuilder();
|
||||
while (true)
|
||||
@ -849,9 +849,9 @@ namespace Thrift.Protocol
|
||||
return strbld.ToString();
|
||||
}
|
||||
|
||||
///<summary>
|
||||
/// <summary>
|
||||
/// Read in a JSON number. If the context dictates, Read in enclosing quotes.
|
||||
///</summary>
|
||||
/// </summary>
|
||||
private long ReadJSONInteger()
|
||||
{
|
||||
context.Read();
|
||||
@ -859,7 +859,7 @@ namespace Thrift.Protocol
|
||||
{
|
||||
ReadJSONSyntaxChar(QUOTE);
|
||||
}
|
||||
String str = ReadJSONNumericChars();
|
||||
string str = ReadJSONNumericChars();
|
||||
if (context.EscapeNumbers())
|
||||
{
|
||||
ReadJSONSyntaxChar(QUOTE);
|
||||
@ -875,17 +875,17 @@ namespace Thrift.Protocol
|
||||
}
|
||||
}
|
||||
|
||||
///<summary>
|
||||
/// <summary>
|
||||
/// Read in a JSON double value. Throw if the value is not wrapped in quotes
|
||||
/// when expected or if wrapped in quotes when not expected.
|
||||
///</summary>
|
||||
/// </summary>
|
||||
private double ReadJSONDouble()
|
||||
{
|
||||
context.Read();
|
||||
if (reader.Peek() == QUOTE[0])
|
||||
{
|
||||
byte[] arr = ReadJSONString(true);
|
||||
double dub = Double.Parse(utf8Encoding.GetString(arr,0,arr.Length), CultureInfo.InvariantCulture);
|
||||
double dub = Double.Parse(utf8Encoding.GetString(arr, 0, arr.Length), CultureInfo.InvariantCulture);
|
||||
|
||||
if (!context.EscapeNumbers() && !Double.IsNaN(dub) &&
|
||||
!Double.IsInfinity(dub))
|
||||
@ -915,9 +915,9 @@ namespace Thrift.Protocol
|
||||
}
|
||||
}
|
||||
|
||||
//<summary>
|
||||
/// <summary>
|
||||
/// Read in a JSON string containing base-64 encoded data and decode it.
|
||||
///</summary>
|
||||
/// </summary>
|
||||
private byte[] ReadJSONBase64()
|
||||
{
|
||||
byte[] b = ReadJSONString(false);
|
||||
@ -989,7 +989,7 @@ namespace Thrift.Protocol
|
||||
}
|
||||
|
||||
var buf = ReadJSONString(false);
|
||||
message.Name = utf8Encoding.GetString(buf,0,buf.Length);
|
||||
message.Name = utf8Encoding.GetString(buf, 0, buf.Length);
|
||||
message.Type = (TMessageType)ReadJSONInteger();
|
||||
message.SeqID = (int)ReadJSONInteger();
|
||||
return message;
|
||||
@ -1108,10 +1108,10 @@ namespace Thrift.Protocol
|
||||
return ReadJSONDouble();
|
||||
}
|
||||
|
||||
public override String ReadString()
|
||||
public override string ReadString()
|
||||
{
|
||||
var buf = ReadJSONString(false);
|
||||
return utf8Encoding.GetString(buf,0,buf.Length);
|
||||
return utf8Encoding.GetString(buf, 0, buf.Length);
|
||||
}
|
||||
|
||||
public override byte[] ReadBinary()
|
||||
|
@ -29,74 +29,77 @@ using System.IO;
|
||||
|
||||
namespace Thrift.Protocol
|
||||
{
|
||||
|
||||
/**
|
||||
* TMultiplexedProcessor is a TProcessor allowing a single TServer to provide multiple services.
|
||||
* To do so, you instantiate the processor and then register additional processors with it,
|
||||
* as shown in the following example:
|
||||
*
|
||||
* TMultiplexedProcessor processor = new TMultiplexedProcessor();
|
||||
*
|
||||
* processor.registerProcessor(
|
||||
* "Calculator",
|
||||
* new Calculator.Processor(new CalculatorHandler()));
|
||||
*
|
||||
* processor.registerProcessor(
|
||||
* "WeatherReport",
|
||||
* new WeatherReport.Processor(new WeatherReportHandler()));
|
||||
*
|
||||
* TServerTransport t = new TServerSocket(9090);
|
||||
* TSimpleServer server = new TSimpleServer(processor, t);
|
||||
*
|
||||
* server.serve();
|
||||
*/
|
||||
/// <summary>
|
||||
/// <see cref="TMultiplexedProcessor"/> is a <see cref="TProcessor"/> allowing a single <see cref="Thrift.Server.TServer"/>
|
||||
/// to provide multiple services.
|
||||
/// <para/>
|
||||
/// To do so, you instantiate the processor and then register additional processors with it,
|
||||
/// as shown in the following example:
|
||||
/// <para/>
|
||||
/// <code>
|
||||
/// TMultiplexedProcessor processor = new TMultiplexedProcessor();
|
||||
///
|
||||
/// processor.registerProcessor(
|
||||
/// "Calculator",
|
||||
/// new Calculator.Processor(new CalculatorHandler()));
|
||||
///
|
||||
/// processor.registerProcessor(
|
||||
/// "WeatherReport",
|
||||
/// new WeatherReport.Processor(new WeatherReportHandler()));
|
||||
///
|
||||
/// TServerTransport t = new TServerSocket(9090);
|
||||
/// TSimpleServer server = new TSimpleServer(processor, t);
|
||||
///
|
||||
/// server.serve();
|
||||
/// </code>
|
||||
/// </summary>
|
||||
public class TMultiplexedProcessor : TProcessor
|
||||
{
|
||||
private Dictionary<String,TProcessor> ServiceProcessorMap = new Dictionary<String,TProcessor>();
|
||||
private Dictionary<string, TProcessor> ServiceProcessorMap = new Dictionary<string, TProcessor>();
|
||||
|
||||
/**
|
||||
* 'Register' a service with this TMultiplexedProcessor. This allows us to broker
|
||||
* requests to individual services by using the service name to select them at request time.
|
||||
*
|
||||
* Args:
|
||||
* - serviceName Name of a service, has to be identical to the name
|
||||
* declared in the Thrift IDL, e.g. "WeatherReport".
|
||||
* - processor Implementation of a service, usually referred to as "handlers",
|
||||
* e.g. WeatherReportHandler implementing WeatherReport.Iface.
|
||||
*/
|
||||
public void RegisterProcessor(String serviceName, TProcessor processor)
|
||||
/// <summary>
|
||||
/// 'Register' a service with this TMultiplexedProcessor. This allows us to broker
|
||||
/// requests to individual services by using the service name to select them at request time.
|
||||
///
|
||||
/// Args:
|
||||
/// - serviceName Name of a service, has to be identical to the name
|
||||
/// declared in the Thrift IDL, e.g. "WeatherReport".
|
||||
/// - processor Implementation of a service, usually referred to as "handlers",
|
||||
/// e.g. WeatherReportHandler implementing WeatherReport.Iface.
|
||||
/// </summary>
|
||||
public void RegisterProcessor(string serviceName, TProcessor processor)
|
||||
{
|
||||
ServiceProcessorMap.Add(serviceName, processor);
|
||||
}
|
||||
|
||||
|
||||
private void Fail( TProtocol oprot, TMessage message, TApplicationException.ExceptionType extype, string etxt)
|
||||
private void Fail(TProtocol oprot, TMessage message, TApplicationException.ExceptionType extype, string etxt)
|
||||
{
|
||||
TApplicationException appex = new TApplicationException( extype, etxt);
|
||||
TApplicationException appex = new TApplicationException(extype, etxt);
|
||||
|
||||
TMessage newMessage = new TMessage(message.Name, TMessageType.Exception, message.SeqID);
|
||||
|
||||
oprot.WriteMessageBegin(newMessage);
|
||||
appex.Write( oprot);
|
||||
appex.Write(oprot);
|
||||
oprot.WriteMessageEnd();
|
||||
oprot.Transport.Flush();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* This implementation of process performs the following steps:
|
||||
*
|
||||
* - Read the beginning of the message.
|
||||
* - Extract the service name from the message.
|
||||
* - Using the service name to locate the appropriate processor.
|
||||
* - Dispatch to the processor, with a decorated instance of TProtocol
|
||||
* that allows readMessageBegin() to return the original TMessage.
|
||||
*
|
||||
* Throws an exception if
|
||||
* - the message type is not CALL or ONEWAY,
|
||||
* - the service name was not found in the message, or
|
||||
* - the service name has not been RegisterProcessor()ed.
|
||||
*/
|
||||
/// <summary>
|
||||
/// This implementation of process performs the following steps:
|
||||
///
|
||||
/// - Read the beginning of the message.
|
||||
/// - Extract the service name from the message.
|
||||
/// - Using the service name to locate the appropriate processor.
|
||||
/// - Dispatch to the processor, with a decorated instance of TProtocol
|
||||
/// that allows readMessageBegin() to return the original TMessage.
|
||||
/// <para/>
|
||||
/// Throws an exception if
|
||||
/// - the message type is not CALL or ONEWAY,
|
||||
/// - the service name was not found in the message, or
|
||||
/// - the service name has not been RegisterProcessor()ed.
|
||||
/// </summary>
|
||||
public bool Process(TProtocol iprot, TProtocol oprot)
|
||||
{
|
||||
/* Use the actual underlying protocol (e.g. TBinaryProtocol) to read the
|
||||
@ -155,17 +158,17 @@ namespace Thrift.Protocol
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Our goal was to work with any protocol. In order to do that, we needed
|
||||
* to allow them to call readMessageBegin() and get a TMessage in exactly
|
||||
* the standard format, without the service name prepended to TMessage.name.
|
||||
*/
|
||||
/// <summary>
|
||||
/// Our goal was to work with any protocol. In order to do that, we needed
|
||||
/// to allow them to call readMessageBegin() and get a TMessage in exactly
|
||||
/// the standard format, without the service name prepended to TMessage.name.
|
||||
/// </summary>
|
||||
private class StoredMessageProtocol : TProtocolDecorator
|
||||
{
|
||||
TMessage MsgBegin;
|
||||
|
||||
public StoredMessageProtocol(TProtocol protocol, TMessage messageBegin)
|
||||
:base(protocol)
|
||||
: base(protocol)
|
||||
{
|
||||
this.MsgBegin = messageBegin;
|
||||
}
|
||||
|
@ -29,63 +29,62 @@ using System.Collections.Generic;
|
||||
namespace Thrift.Protocol
|
||||
{
|
||||
|
||||
/**
|
||||
* TMultiplexedProtocol is a protocol-independent concrete decorator that allows a Thrift
|
||||
* client to communicate with a multiplexing Thrift server, by prepending the service name
|
||||
* to the function name during function calls.
|
||||
*
|
||||
* NOTE: THIS IS NOT TO BE USED BY SERVERS.
|
||||
* On the server, use TMultiplexedProcessor to handle requests from a multiplexing client.
|
||||
*
|
||||
* This example uses a single socket transport to invoke two services:
|
||||
*
|
||||
* TSocket transport = new TSocket("localhost", 9090);
|
||||
* transport.open();
|
||||
*
|
||||
* TBinaryProtocol protocol = new TBinaryProtocol(transport);
|
||||
*
|
||||
* TMultiplexedProtocol mp = new TMultiplexedProtocol(protocol, "Calculator");
|
||||
* Calculator.Client service = new Calculator.Client(mp);
|
||||
*
|
||||
* TMultiplexedProtocol mp2 = new TMultiplexedProtocol(protocol, "WeatherReport");
|
||||
* WeatherReport.Client service2 = new WeatherReport.Client(mp2);
|
||||
*
|
||||
* System.out.println(service.add(2,2));
|
||||
* System.out.println(service2.getTemperature());
|
||||
*
|
||||
*/
|
||||
/// <summary>
|
||||
/// TMultiplexedProtocol is a protocol-independent concrete decorator that allows a Thrift
|
||||
/// client to communicate with a multiplexing Thrift server, by prepending the service name
|
||||
/// to the function name during function calls.
|
||||
/// <para/>
|
||||
/// NOTE: THIS IS NOT TO BE USED BY SERVERS.
|
||||
/// On the server, use TMultiplexedProcessor to handle requests from a multiplexing client.
|
||||
/// <para/>
|
||||
/// This example uses a single socket transport to invoke two services:
|
||||
/// <code>
|
||||
/// TSocket transport = new TSocket("localhost", 9090);
|
||||
/// transport.open();
|
||||
///
|
||||
/// TBinaryProtocol protocol = new TBinaryProtocol(transport);
|
||||
///
|
||||
/// TMultiplexedProtocol mp = new TMultiplexedProtocol(protocol, "Calculator");
|
||||
/// Calculator.Client service = new Calculator.Client(mp);
|
||||
///
|
||||
/// TMultiplexedProtocol mp2 = new TMultiplexedProtocol(protocol, "WeatherReport");
|
||||
/// WeatherReport.Client service2 = new WeatherReport.Client(mp2);
|
||||
///
|
||||
/// System.out.println(service.add(2,2));
|
||||
/// System.out.println(service2.getTemperature());
|
||||
/// </code>
|
||||
/// </summary>
|
||||
public class TMultiplexedProtocol : TProtocolDecorator
|
||||
{
|
||||
|
||||
/** Used to delimit the service name from the function name */
|
||||
public static String SEPARATOR = ":";
|
||||
/// <summary>
|
||||
/// Used to delimit the service name from the function name.
|
||||
/// </summary>
|
||||
public static string SEPARATOR = ":";
|
||||
|
||||
private String ServiceName;
|
||||
private string ServiceName;
|
||||
|
||||
/**
|
||||
* Wrap the specified protocol, allowing it to be used to communicate with a
|
||||
* multiplexing server. The <code>serviceName</code> is required as it is
|
||||
* prepended to the message header so that the multiplexing server can broker
|
||||
* the function call to the proper service.
|
||||
*
|
||||
* Args:
|
||||
* protocol Your communication protocol of choice, e.g. TBinaryProtocol
|
||||
* serviceName The service name of the service communicating via this protocol.
|
||||
*/
|
||||
public TMultiplexedProtocol(TProtocol protocol, String serviceName)
|
||||
/// <summary>
|
||||
/// Wrap the specified protocol, allowing it to be used to communicate with a
|
||||
/// multiplexing server. The <paramref name="serviceName"/> is required as it is
|
||||
/// prepended to the message header so that the multiplexing server can broker
|
||||
/// the function call to the proper service.
|
||||
/// </summary>
|
||||
/// <param name="protocol">Your communication protocol of choice, e.g. <see cref="TBinaryProtocol"/>.</param>
|
||||
/// <param name="serviceName">The service name of the service communicating via this protocol.</param>
|
||||
public TMultiplexedProtocol(TProtocol protocol, string serviceName)
|
||||
: base(protocol)
|
||||
{
|
||||
ServiceName = serviceName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepends the service name to the function name, separated by TMultiplexedProtocol.SEPARATOR.
|
||||
* Args:
|
||||
* tMessage The original message.
|
||||
*/
|
||||
/// <summary>
|
||||
/// Prepends the service name to the function name, separated by TMultiplexedProtocol.SEPARATOR.
|
||||
/// </summary>
|
||||
/// <param name="tMessage">The original message.</param>
|
||||
public override void WriteMessageBegin(TMessage tMessage)
|
||||
{
|
||||
switch(tMessage.Type)
|
||||
switch (tMessage.Type)
|
||||
{
|
||||
case TMessageType.Call:
|
||||
case TMessageType.Oneway:
|
||||
@ -101,5 +100,4 @@ namespace Thrift.Protocol
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -108,7 +108,8 @@ namespace Thrift.Protocol
|
||||
public abstract void WriteI32(int i32);
|
||||
public abstract void WriteI64(long i64);
|
||||
public abstract void WriteDouble(double d);
|
||||
public virtual void WriteString(string s) {
|
||||
public virtual void WriteString(string s)
|
||||
{
|
||||
WriteBinary(Encoding.UTF8.GetBytes(s));
|
||||
}
|
||||
public abstract void WriteBinary(byte[] b);
|
||||
@ -131,7 +132,8 @@ namespace Thrift.Protocol
|
||||
public abstract int ReadI32();
|
||||
public abstract long ReadI64();
|
||||
public abstract double ReadDouble();
|
||||
public virtual string ReadString() {
|
||||
public virtual string ReadString()
|
||||
{
|
||||
var buf = ReadBinary();
|
||||
return Encoding.UTF8.GetString(buf, 0, buf.Length);
|
||||
}
|
||||
|
@ -28,26 +28,25 @@ using System.Collections.Generic;
|
||||
|
||||
namespace Thrift.Protocol
|
||||
{
|
||||
|
||||
/**
|
||||
* TProtocolDecorator forwards all requests to an enclosed TProtocol instance,
|
||||
* providing a way to author concise concrete decorator subclasses. While it has
|
||||
* no abstract methods, it is marked abstract as a reminder that by itself,
|
||||
* it does not modify the behaviour of the enclosed TProtocol.
|
||||
*
|
||||
* See p.175 of Design Patterns (by Gamma et al.)
|
||||
* See TMultiplexedProtocol
|
||||
*/
|
||||
/// <summary>
|
||||
/// <see cref="TProtocolDecorator"/> forwards all requests to an enclosed <see cref="TProtocol"/> instance,
|
||||
/// providing a way to author concise concrete decorator subclasses. While it has
|
||||
/// no abstract methods, it is marked abstract as a reminder that by itself,
|
||||
/// it does not modify the behaviour of the enclosed <see cref="TProtocol"/>.
|
||||
/// <para/>
|
||||
/// See p.175 of Design Patterns (by Gamma et al.)
|
||||
/// </summary>
|
||||
/// <seealso cref="TMultiplexedProtocol"/>
|
||||
public abstract class TProtocolDecorator : TProtocol
|
||||
{
|
||||
private TProtocol WrappedProtocol;
|
||||
|
||||
/**
|
||||
* Encloses the specified protocol.
|
||||
* @param protocol All operations will be forward to this protocol. Must be non-null.
|
||||
*/
|
||||
/// <summary>
|
||||
/// Encloses the specified protocol.
|
||||
/// </summary>
|
||||
/// <param name="protocol">All operations will be forward to this protocol. Must be non-null.</param>
|
||||
public TProtocolDecorator(TProtocol protocol)
|
||||
: base( protocol.Transport)
|
||||
: base(protocol.Transport)
|
||||
{
|
||||
|
||||
WrappedProtocol = protocol;
|
||||
@ -104,7 +103,7 @@ namespace Thrift.Protocol
|
||||
}
|
||||
|
||||
public override void WriteListEnd()
|
||||
{
|
||||
{
|
||||
WrappedProtocol.WriteListEnd();
|
||||
}
|
||||
|
||||
@ -148,7 +147,7 @@ namespace Thrift.Protocol
|
||||
WrappedProtocol.WriteDouble(v);
|
||||
}
|
||||
|
||||
public override void WriteString(String s)
|
||||
public override void WriteString(string s)
|
||||
{
|
||||
WrappedProtocol.WriteString(s);
|
||||
}
|
||||
@ -248,7 +247,7 @@ namespace Thrift.Protocol
|
||||
return WrappedProtocol.ReadDouble();
|
||||
}
|
||||
|
||||
public override String ReadString()
|
||||
public override string ReadString()
|
||||
{
|
||||
return WrappedProtocol.ReadString();
|
||||
}
|
||||
|
@ -48,13 +48,13 @@ namespace Thrift.Protocol
|
||||
type_ = type;
|
||||
}
|
||||
|
||||
public TProtocolException(int type, String message)
|
||||
public TProtocolException(int type, string message)
|
||||
: base(message)
|
||||
{
|
||||
type_ = type;
|
||||
}
|
||||
|
||||
public TProtocolException(String message)
|
||||
public TProtocolException(string message)
|
||||
: base(message)
|
||||
{
|
||||
}
|
||||
|
@ -98,7 +98,6 @@ namespace Thrift.Protocol
|
||||
default:
|
||||
throw new TProtocolException(TProtocolException.INVALID_DATA, "Unknown data type " + type.ToString("d"));
|
||||
}
|
||||
|
||||
}
|
||||
finally
|
||||
{
|
||||
|
@ -28,128 +28,128 @@ using System.IO;
|
||||
|
||||
namespace Thrift.Server
|
||||
{
|
||||
public abstract class TServer
|
||||
{
|
||||
//Attributes
|
||||
protected TProcessorFactory processorFactory;
|
||||
protected TServerTransport serverTransport;
|
||||
protected TTransportFactory inputTransportFactory;
|
||||
protected TTransportFactory outputTransportFactory;
|
||||
protected TProtocolFactory inputProtocolFactory;
|
||||
protected TProtocolFactory outputProtocolFactory;
|
||||
protected TServerEventHandler serverEventHandler = null;
|
||||
public abstract class TServer
|
||||
{
|
||||
//Attributes
|
||||
protected TProcessorFactory processorFactory;
|
||||
protected TServerTransport serverTransport;
|
||||
protected TTransportFactory inputTransportFactory;
|
||||
protected TTransportFactory outputTransportFactory;
|
||||
protected TProtocolFactory inputProtocolFactory;
|
||||
protected TProtocolFactory outputProtocolFactory;
|
||||
protected TServerEventHandler serverEventHandler = null;
|
||||
|
||||
//Methods
|
||||
public void setEventHandler(TServerEventHandler seh)
|
||||
{
|
||||
serverEventHandler = seh;
|
||||
}
|
||||
public TServerEventHandler getEventHandler()
|
||||
{
|
||||
return serverEventHandler;
|
||||
}
|
||||
//Methods
|
||||
public void setEventHandler(TServerEventHandler seh)
|
||||
{
|
||||
serverEventHandler = seh;
|
||||
}
|
||||
public TServerEventHandler getEventHandler()
|
||||
{
|
||||
return serverEventHandler;
|
||||
}
|
||||
|
||||
//Log delegation
|
||||
public delegate void LogDelegate(string str);
|
||||
private LogDelegate _logDelegate;
|
||||
protected LogDelegate logDelegate
|
||||
{
|
||||
get { return _logDelegate; }
|
||||
set { _logDelegate = (value != null) ? value : DefaultLogDelegate; }
|
||||
}
|
||||
protected static void DefaultLogDelegate(string s)
|
||||
{
|
||||
Console.Error.WriteLine(s);
|
||||
}
|
||||
//Log delegation
|
||||
public delegate void LogDelegate(string str);
|
||||
private LogDelegate _logDelegate;
|
||||
protected LogDelegate logDelegate
|
||||
{
|
||||
get { return _logDelegate; }
|
||||
set { _logDelegate = (value != null) ? value : DefaultLogDelegate; }
|
||||
}
|
||||
protected static void DefaultLogDelegate(string s)
|
||||
{
|
||||
Console.Error.WriteLine(s);
|
||||
}
|
||||
|
||||
//Construction
|
||||
public TServer(TProcessor processor,
|
||||
TServerTransport serverTransport)
|
||||
: this(processor, serverTransport,
|
||||
new TTransportFactory(),
|
||||
new TTransportFactory(),
|
||||
new TBinaryProtocol.Factory(),
|
||||
new TBinaryProtocol.Factory(),
|
||||
DefaultLogDelegate)
|
||||
{
|
||||
}
|
||||
//Construction
|
||||
public TServer(TProcessor processor,
|
||||
TServerTransport serverTransport)
|
||||
: this(processor, serverTransport,
|
||||
new TTransportFactory(),
|
||||
new TTransportFactory(),
|
||||
new TBinaryProtocol.Factory(),
|
||||
new TBinaryProtocol.Factory(),
|
||||
DefaultLogDelegate)
|
||||
{
|
||||
}
|
||||
|
||||
public TServer(TProcessor processor,
|
||||
public TServer(TProcessor processor,
|
||||
TServerTransport serverTransport,
|
||||
LogDelegate logDelegate)
|
||||
: this(processor,
|
||||
serverTransport,
|
||||
new TTransportFactory(),
|
||||
new TTransportFactory(),
|
||||
new TBinaryProtocol.Factory(),
|
||||
new TBinaryProtocol.Factory(),
|
||||
logDelegate)
|
||||
{
|
||||
}
|
||||
|
||||
public TServer(TProcessor processor,
|
||||
TServerTransport serverTransport,
|
||||
TTransportFactory transportFactory)
|
||||
: this(processor,
|
||||
serverTransport,
|
||||
transportFactory,
|
||||
transportFactory,
|
||||
new TBinaryProtocol.Factory(),
|
||||
new TBinaryProtocol.Factory(),
|
||||
DefaultLogDelegate)
|
||||
{
|
||||
}
|
||||
|
||||
public TServer(TProcessor processor,
|
||||
TServerTransport serverTransport,
|
||||
TTransportFactory transportFactory,
|
||||
TProtocolFactory protocolFactory)
|
||||
: this(processor,
|
||||
serverTransport,
|
||||
transportFactory,
|
||||
transportFactory,
|
||||
protocolFactory,
|
||||
protocolFactory,
|
||||
DefaultLogDelegate)
|
||||
{
|
||||
}
|
||||
|
||||
public TServer(TProcessor processor,
|
||||
TServerTransport serverTransport,
|
||||
TTransportFactory inputTransportFactory,
|
||||
TTransportFactory outputTransportFactory,
|
||||
TProtocolFactory inputProtocolFactory,
|
||||
TProtocolFactory outputProtocolFactory,
|
||||
LogDelegate logDelegate)
|
||||
: this(processor,
|
||||
serverTransport,
|
||||
new TTransportFactory(),
|
||||
new TTransportFactory(),
|
||||
new TBinaryProtocol.Factory(),
|
||||
new TBinaryProtocol.Factory(),
|
||||
logDelegate)
|
||||
{
|
||||
}
|
||||
{
|
||||
this.processorFactory = new TSingletonProcessorFactory(processor);
|
||||
this.serverTransport = serverTransport;
|
||||
this.inputTransportFactory = inputTransportFactory;
|
||||
this.outputTransportFactory = outputTransportFactory;
|
||||
this.inputProtocolFactory = inputProtocolFactory;
|
||||
this.outputProtocolFactory = outputProtocolFactory;
|
||||
this.logDelegate = (logDelegate != null) ? logDelegate : DefaultLogDelegate;
|
||||
}
|
||||
|
||||
public TServer(TProcessor processor,
|
||||
TServerTransport serverTransport,
|
||||
TTransportFactory transportFactory)
|
||||
: this(processor,
|
||||
serverTransport,
|
||||
transportFactory,
|
||||
transportFactory,
|
||||
new TBinaryProtocol.Factory(),
|
||||
new TBinaryProtocol.Factory(),
|
||||
DefaultLogDelegate)
|
||||
{
|
||||
}
|
||||
public TServer(TProcessorFactory processorFactory,
|
||||
TServerTransport serverTransport,
|
||||
TTransportFactory inputTransportFactory,
|
||||
TTransportFactory outputTransportFactory,
|
||||
TProtocolFactory inputProtocolFactory,
|
||||
TProtocolFactory outputProtocolFactory,
|
||||
LogDelegate logDelegate)
|
||||
{
|
||||
this.processorFactory = processorFactory;
|
||||
this.serverTransport = serverTransport;
|
||||
this.inputTransportFactory = inputTransportFactory;
|
||||
this.outputTransportFactory = outputTransportFactory;
|
||||
this.inputProtocolFactory = inputProtocolFactory;
|
||||
this.outputProtocolFactory = outputProtocolFactory;
|
||||
this.logDelegate = (logDelegate != null) ? logDelegate : DefaultLogDelegate;
|
||||
}
|
||||
|
||||
public TServer(TProcessor processor,
|
||||
TServerTransport serverTransport,
|
||||
TTransportFactory transportFactory,
|
||||
TProtocolFactory protocolFactory)
|
||||
: this(processor,
|
||||
serverTransport,
|
||||
transportFactory,
|
||||
transportFactory,
|
||||
protocolFactory,
|
||||
protocolFactory,
|
||||
DefaultLogDelegate)
|
||||
{
|
||||
//Abstract Interface
|
||||
public abstract void Serve();
|
||||
public abstract void Stop();
|
||||
}
|
||||
|
||||
public TServer(TProcessor processor,
|
||||
TServerTransport serverTransport,
|
||||
TTransportFactory inputTransportFactory,
|
||||
TTransportFactory outputTransportFactory,
|
||||
TProtocolFactory inputProtocolFactory,
|
||||
TProtocolFactory outputProtocolFactory,
|
||||
LogDelegate logDelegate)
|
||||
{
|
||||
this.processorFactory = new TSingletonProcessorFactory(processor);
|
||||
this.serverTransport = serverTransport;
|
||||
this.inputTransportFactory = inputTransportFactory;
|
||||
this.outputTransportFactory = outputTransportFactory;
|
||||
this.inputProtocolFactory = inputProtocolFactory;
|
||||
this.outputProtocolFactory = outputProtocolFactory;
|
||||
this.logDelegate = (logDelegate != null) ? logDelegate : DefaultLogDelegate;
|
||||
}
|
||||
|
||||
public TServer(TProcessorFactory processorFactory,
|
||||
TServerTransport serverTransport,
|
||||
TTransportFactory inputTransportFactory,
|
||||
TTransportFactory outputTransportFactory,
|
||||
TProtocolFactory inputProtocolFactory,
|
||||
TProtocolFactory outputProtocolFactory,
|
||||
LogDelegate logDelegate)
|
||||
{
|
||||
this.processorFactory = processorFactory;
|
||||
this.serverTransport = serverTransport;
|
||||
this.inputTransportFactory = inputTransportFactory;
|
||||
this.outputTransportFactory = outputTransportFactory;
|
||||
this.inputProtocolFactory = inputProtocolFactory;
|
||||
this.outputProtocolFactory = outputProtocolFactory;
|
||||
this.logDelegate = (logDelegate != null) ? logDelegate : DefaultLogDelegate;
|
||||
}
|
||||
|
||||
//Abstract Interface
|
||||
public abstract void Serve();
|
||||
public abstract void Stop();
|
||||
}
|
||||
}
|
||||
|
@ -25,26 +25,29 @@ using System;
|
||||
|
||||
namespace Thrift.Server
|
||||
{
|
||||
/// <summary>
|
||||
/// Interface implemented by server users to handle events from the server
|
||||
/// </summary>
|
||||
public interface TServerEventHandler
|
||||
{
|
||||
/// <summary>
|
||||
/// Called before the server begins */
|
||||
/// Interface implemented by server users to handle events from the server.
|
||||
/// </summary>
|
||||
void preServe();
|
||||
/// <summary>
|
||||
/// Called when a new client has connected and is about to being processing */
|
||||
/// </summary>
|
||||
Object createContext(Thrift.Protocol.TProtocol input, Thrift.Protocol.TProtocol output);
|
||||
/// <summary>
|
||||
/// Called when a client has finished request-handling to delete server context */
|
||||
/// </summary>
|
||||
void deleteContext(Object serverContext, Thrift.Protocol.TProtocol input, Thrift.Protocol.TProtocol output);
|
||||
/// <summary>
|
||||
/// Called when a client is about to call the processor */
|
||||
/// </summary>
|
||||
void processContext(Object serverContext, Thrift.Transport.TTransport transport);
|
||||
};
|
||||
public interface TServerEventHandler
|
||||
{
|
||||
/// <summary>
|
||||
/// Called before the server begins.
|
||||
/// </summary>
|
||||
void preServe();
|
||||
|
||||
/// <summary>
|
||||
/// Called when a new client has connected and is about to being processing.
|
||||
/// </summary>
|
||||
object createContext(Thrift.Protocol.TProtocol input, Thrift.Protocol.TProtocol output);
|
||||
|
||||
/// <summary>
|
||||
/// Called when a client has finished request-handling to delete server context.
|
||||
/// </summary>
|
||||
void deleteContext(object serverContext, Thrift.Protocol.TProtocol input, Thrift.Protocol.TProtocol output);
|
||||
|
||||
/// <summary>
|
||||
/// Called when a client is about to call the processor.
|
||||
/// </summary>
|
||||
void processContext(object serverContext, Thrift.Transport.TTransport transport);
|
||||
};
|
||||
}
|
||||
|
@ -27,154 +27,154 @@ using Thrift.Protocol;
|
||||
|
||||
namespace Thrift.Server
|
||||
{
|
||||
/// <summary>
|
||||
/// Simple single-threaded server for testing
|
||||
/// </summary>
|
||||
public class TSimpleServer : TServer
|
||||
{
|
||||
private bool stop = false;
|
||||
|
||||
public TSimpleServer(TProcessor processor,
|
||||
TServerTransport serverTransport)
|
||||
: base(processor, serverTransport, new TTransportFactory(), new TTransportFactory(), new TBinaryProtocol.Factory(), new TBinaryProtocol.Factory(), DefaultLogDelegate)
|
||||
/// <summary>
|
||||
/// Simple single-threaded server for testing.
|
||||
/// </summary>
|
||||
public class TSimpleServer : TServer
|
||||
{
|
||||
}
|
||||
private bool stop = false;
|
||||
|
||||
public TSimpleServer(TProcessor processor,
|
||||
TServerTransport serverTransport,
|
||||
LogDelegate logDel)
|
||||
: base(processor, serverTransport, new TTransportFactory(), new TTransportFactory(), new TBinaryProtocol.Factory(), new TBinaryProtocol.Factory(), logDel)
|
||||
{
|
||||
}
|
||||
|
||||
public TSimpleServer(TProcessor processor,
|
||||
TServerTransport serverTransport,
|
||||
TTransportFactory transportFactory)
|
||||
: base(processor,
|
||||
serverTransport,
|
||||
transportFactory,
|
||||
transportFactory,
|
||||
new TBinaryProtocol.Factory(),
|
||||
new TBinaryProtocol.Factory(),
|
||||
DefaultLogDelegate)
|
||||
{
|
||||
}
|
||||
|
||||
public TSimpleServer(TProcessor processor,
|
||||
TServerTransport serverTransport,
|
||||
TTransportFactory transportFactory,
|
||||
TProtocolFactory protocolFactory)
|
||||
: base(processor,
|
||||
serverTransport,
|
||||
transportFactory,
|
||||
transportFactory,
|
||||
protocolFactory,
|
||||
protocolFactory,
|
||||
DefaultLogDelegate)
|
||||
{
|
||||
}
|
||||
|
||||
public TSimpleServer(TProcessorFactory processorFactory,
|
||||
TServerTransport serverTransport,
|
||||
TTransportFactory transportFactory,
|
||||
TProtocolFactory protocolFactory)
|
||||
: base(processorFactory,
|
||||
serverTransport,
|
||||
transportFactory,
|
||||
transportFactory,
|
||||
protocolFactory,
|
||||
protocolFactory,
|
||||
DefaultLogDelegate)
|
||||
{
|
||||
}
|
||||
|
||||
public override void Serve()
|
||||
{
|
||||
try
|
||||
{
|
||||
serverTransport.Listen();
|
||||
}
|
||||
catch (TTransportException ttx)
|
||||
{
|
||||
logDelegate(ttx.ToString());
|
||||
return;
|
||||
}
|
||||
|
||||
//Fire the preServe server event when server is up but before any client connections
|
||||
if (serverEventHandler != null)
|
||||
serverEventHandler.preServe();
|
||||
|
||||
while (!stop)
|
||||
{
|
||||
TProcessor processor = null;
|
||||
TTransport client = null;
|
||||
TTransport inputTransport = null;
|
||||
TTransport outputTransport = null;
|
||||
TProtocol inputProtocol = null;
|
||||
TProtocol outputProtocol = null;
|
||||
Object connectionContext = null;
|
||||
try
|
||||
public TSimpleServer(TProcessor processor,
|
||||
TServerTransport serverTransport)
|
||||
: base(processor, serverTransport, new TTransportFactory(), new TTransportFactory(), new TBinaryProtocol.Factory(), new TBinaryProtocol.Factory(), DefaultLogDelegate)
|
||||
{
|
||||
using (client = serverTransport.Accept())
|
||||
{
|
||||
processor = processorFactory.GetProcessor(client);
|
||||
if (client != null)
|
||||
}
|
||||
|
||||
public TSimpleServer(TProcessor processor,
|
||||
TServerTransport serverTransport,
|
||||
LogDelegate logDel)
|
||||
: base(processor, serverTransport, new TTransportFactory(), new TTransportFactory(), new TBinaryProtocol.Factory(), new TBinaryProtocol.Factory(), logDel)
|
||||
{
|
||||
}
|
||||
|
||||
public TSimpleServer(TProcessor processor,
|
||||
TServerTransport serverTransport,
|
||||
TTransportFactory transportFactory)
|
||||
: base(processor,
|
||||
serverTransport,
|
||||
transportFactory,
|
||||
transportFactory,
|
||||
new TBinaryProtocol.Factory(),
|
||||
new TBinaryProtocol.Factory(),
|
||||
DefaultLogDelegate)
|
||||
{
|
||||
}
|
||||
|
||||
public TSimpleServer(TProcessor processor,
|
||||
TServerTransport serverTransport,
|
||||
TTransportFactory transportFactory,
|
||||
TProtocolFactory protocolFactory)
|
||||
: base(processor,
|
||||
serverTransport,
|
||||
transportFactory,
|
||||
transportFactory,
|
||||
protocolFactory,
|
||||
protocolFactory,
|
||||
DefaultLogDelegate)
|
||||
{
|
||||
}
|
||||
|
||||
public TSimpleServer(TProcessorFactory processorFactory,
|
||||
TServerTransport serverTransport,
|
||||
TTransportFactory transportFactory,
|
||||
TProtocolFactory protocolFactory)
|
||||
: base(processorFactory,
|
||||
serverTransport,
|
||||
transportFactory,
|
||||
transportFactory,
|
||||
protocolFactory,
|
||||
protocolFactory,
|
||||
DefaultLogDelegate)
|
||||
{
|
||||
}
|
||||
|
||||
public override void Serve()
|
||||
{
|
||||
try
|
||||
{
|
||||
using (inputTransport = inputTransportFactory.GetTransport(client))
|
||||
{
|
||||
using (outputTransport = outputTransportFactory.GetTransport(client))
|
||||
{
|
||||
inputProtocol = inputProtocolFactory.GetProtocol(inputTransport);
|
||||
outputProtocol = outputProtocolFactory.GetProtocol(outputTransport);
|
||||
|
||||
//Recover event handler (if any) and fire createContext server event when a client connects
|
||||
if (serverEventHandler != null)
|
||||
connectionContext = serverEventHandler.createContext(inputProtocol, outputProtocol);
|
||||
|
||||
//Process client requests until client disconnects
|
||||
while (!stop)
|
||||
{
|
||||
if (!inputTransport.Peek())
|
||||
break;
|
||||
|
||||
//Fire processContext server event
|
||||
//N.B. This is the pattern implemented in C++ and the event fires provisionally.
|
||||
//That is to say it may be many minutes between the event firing and the client request
|
||||
//actually arriving or the client may hang up without ever makeing a request.
|
||||
if (serverEventHandler != null)
|
||||
serverEventHandler.processContext(connectionContext, inputTransport);
|
||||
//Process client request (blocks until transport is readable)
|
||||
if (!processor.Process(inputProtocol, outputProtocol))
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
serverTransport.Listen();
|
||||
}
|
||||
catch (TTransportException ttx)
|
||||
{
|
||||
logDelegate(ttx.ToString());
|
||||
return;
|
||||
}
|
||||
|
||||
//Fire the preServe server event when server is up but before any client connections
|
||||
if (serverEventHandler != null)
|
||||
serverEventHandler.preServe();
|
||||
|
||||
while (!stop)
|
||||
{
|
||||
TProcessor processor = null;
|
||||
TTransport client = null;
|
||||
TTransport inputTransport = null;
|
||||
TTransport outputTransport = null;
|
||||
TProtocol inputProtocol = null;
|
||||
TProtocol outputProtocol = null;
|
||||
object connectionContext = null;
|
||||
try
|
||||
{
|
||||
using (client = serverTransport.Accept())
|
||||
{
|
||||
processor = processorFactory.GetProcessor(client);
|
||||
if (client != null)
|
||||
{
|
||||
using (inputTransport = inputTransportFactory.GetTransport(client))
|
||||
{
|
||||
using (outputTransport = outputTransportFactory.GetTransport(client))
|
||||
{
|
||||
inputProtocol = inputProtocolFactory.GetProtocol(inputTransport);
|
||||
outputProtocol = outputProtocolFactory.GetProtocol(outputTransport);
|
||||
|
||||
//Recover event handler (if any) and fire createContext server event when a client connects
|
||||
if (serverEventHandler != null)
|
||||
connectionContext = serverEventHandler.createContext(inputProtocol, outputProtocol);
|
||||
|
||||
//Process client requests until client disconnects
|
||||
while (!stop)
|
||||
{
|
||||
if (!inputTransport.Peek())
|
||||
break;
|
||||
|
||||
//Fire processContext server event
|
||||
//N.B. This is the pattern implemented in C++ and the event fires provisionally.
|
||||
//That is to say it may be many minutes between the event firing and the client request
|
||||
//actually arriving or the client may hang up without ever makeing a request.
|
||||
if (serverEventHandler != null)
|
||||
serverEventHandler.processContext(connectionContext, inputTransport);
|
||||
//Process client request (blocks until transport is readable)
|
||||
if (!processor.Process(inputProtocol, outputProtocol))
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (TTransportException ttx)
|
||||
{
|
||||
if (!stop || ttx.Type != TTransportException.ExceptionType.Interrupted)
|
||||
{
|
||||
logDelegate(ttx.ToString());
|
||||
}
|
||||
}
|
||||
catch (Exception x)
|
||||
{
|
||||
//Unexpected
|
||||
logDelegate(x.ToString());
|
||||
}
|
||||
|
||||
//Fire deleteContext server event after client disconnects
|
||||
if (serverEventHandler != null)
|
||||
serverEventHandler.deleteContext(connectionContext, inputProtocol, outputProtocol);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (TTransportException ttx)
|
||||
{
|
||||
if (!stop || ttx.Type != TTransportException.ExceptionType.Interrupted)
|
||||
{
|
||||
logDelegate(ttx.ToString());
|
||||
}
|
||||
}
|
||||
catch (Exception x)
|
||||
{
|
||||
//Unexpected
|
||||
logDelegate(x.ToString());
|
||||
}
|
||||
|
||||
//Fire deleteContext server event after client disconnects
|
||||
if (serverEventHandler != null)
|
||||
serverEventHandler.deleteContext(connectionContext, inputProtocol, outputProtocol);
|
||||
}
|
||||
public override void Stop()
|
||||
{
|
||||
stop = true;
|
||||
serverTransport.Close();
|
||||
}
|
||||
}
|
||||
|
||||
public override void Stop()
|
||||
{
|
||||
stop = true;
|
||||
serverTransport.Close();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -28,268 +28,268 @@ using Thrift.Transport;
|
||||
|
||||
namespace Thrift.Server
|
||||
{
|
||||
/// <summary>
|
||||
/// Server that uses C# built-in ThreadPool to spawn threads when handling requests
|
||||
/// </summary>
|
||||
public class TThreadPoolServer : TServer
|
||||
{
|
||||
private const int DEFAULT_MIN_THREADS = -1; // use .NET ThreadPool defaults
|
||||
private const int DEFAULT_MAX_THREADS = -1; // use .NET ThreadPool defaults
|
||||
private volatile bool stop = false;
|
||||
|
||||
public struct Configuration
|
||||
{
|
||||
public int MinWorkerThreads;
|
||||
public int MaxWorkerThreads;
|
||||
public int MinIOThreads;
|
||||
public int MaxIOThreads;
|
||||
|
||||
public Configuration(int min = DEFAULT_MIN_THREADS, int max = DEFAULT_MAX_THREADS)
|
||||
{
|
||||
MinWorkerThreads = min;
|
||||
MaxWorkerThreads = max;
|
||||
MinIOThreads = min;
|
||||
MaxIOThreads = max;
|
||||
}
|
||||
|
||||
public Configuration(int minWork, int maxWork, int minIO, int maxIO)
|
||||
{
|
||||
MinWorkerThreads = minWork;
|
||||
MaxWorkerThreads = maxWork;
|
||||
MinIOThreads = minIO;
|
||||
MaxIOThreads = maxIO;
|
||||
}
|
||||
}
|
||||
|
||||
public TThreadPoolServer(TProcessor processor, TServerTransport serverTransport)
|
||||
: this(new TSingletonProcessorFactory(processor), serverTransport,
|
||||
new TTransportFactory(), new TTransportFactory(),
|
||||
new TBinaryProtocol.Factory(), new TBinaryProtocol.Factory(),
|
||||
new Configuration(), DefaultLogDelegate)
|
||||
{
|
||||
}
|
||||
|
||||
public TThreadPoolServer(TProcessor processor, TServerTransport serverTransport, LogDelegate logDelegate)
|
||||
: this(new TSingletonProcessorFactory(processor), serverTransport,
|
||||
new TTransportFactory(), new TTransportFactory(),
|
||||
new TBinaryProtocol.Factory(), new TBinaryProtocol.Factory(),
|
||||
new Configuration(), logDelegate)
|
||||
{
|
||||
}
|
||||
|
||||
public TThreadPoolServer(TProcessor processor,
|
||||
TServerTransport serverTransport,
|
||||
TTransportFactory transportFactory,
|
||||
TProtocolFactory protocolFactory)
|
||||
: this(new TSingletonProcessorFactory(processor), serverTransport,
|
||||
transportFactory, transportFactory,
|
||||
protocolFactory, protocolFactory,
|
||||
new Configuration(), DefaultLogDelegate)
|
||||
{
|
||||
}
|
||||
|
||||
public TThreadPoolServer(TProcessorFactory processorFactory,
|
||||
TServerTransport serverTransport,
|
||||
TTransportFactory transportFactory,
|
||||
TProtocolFactory protocolFactory)
|
||||
: this(processorFactory, serverTransport,
|
||||
transportFactory, transportFactory,
|
||||
protocolFactory, protocolFactory,
|
||||
new Configuration(), DefaultLogDelegate)
|
||||
{
|
||||
}
|
||||
|
||||
public TThreadPoolServer(TProcessorFactory processorFactory,
|
||||
TServerTransport serverTransport,
|
||||
TTransportFactory inputTransportFactory,
|
||||
TTransportFactory outputTransportFactory,
|
||||
TProtocolFactory inputProtocolFactory,
|
||||
TProtocolFactory outputProtocolFactory,
|
||||
int minThreadPoolThreads, int maxThreadPoolThreads, LogDelegate logDel)
|
||||
: this(processorFactory, serverTransport, inputTransportFactory, outputTransportFactory,
|
||||
inputProtocolFactory, outputProtocolFactory,
|
||||
new Configuration(minThreadPoolThreads, maxThreadPoolThreads),
|
||||
logDel)
|
||||
{
|
||||
}
|
||||
|
||||
public TThreadPoolServer(TProcessorFactory processorFactory,
|
||||
TServerTransport serverTransport,
|
||||
TTransportFactory inputTransportFactory,
|
||||
TTransportFactory outputTransportFactory,
|
||||
TProtocolFactory inputProtocolFactory,
|
||||
TProtocolFactory outputProtocolFactory,
|
||||
Configuration threadConfig,
|
||||
LogDelegate logDel)
|
||||
: base(processorFactory, serverTransport, inputTransportFactory, outputTransportFactory,
|
||||
inputProtocolFactory, outputProtocolFactory, logDel)
|
||||
{
|
||||
lock (typeof(TThreadPoolServer))
|
||||
{
|
||||
if ((threadConfig.MaxWorkerThreads > 0) || (threadConfig.MaxIOThreads > 0))
|
||||
{
|
||||
int work, comm;
|
||||
ThreadPool.GetMaxThreads(out work, out comm);
|
||||
if (threadConfig.MaxWorkerThreads > 0)
|
||||
work = threadConfig.MaxWorkerThreads;
|
||||
if (threadConfig.MaxIOThreads > 0)
|
||||
comm = threadConfig.MaxIOThreads;
|
||||
if (!ThreadPool.SetMaxThreads(work, comm))
|
||||
throw new Exception("Error: could not SetMaxThreads in ThreadPool");
|
||||
}
|
||||
|
||||
if ((threadConfig.MinWorkerThreads > 0) || (threadConfig.MinIOThreads > 0))
|
||||
{
|
||||
int work, comm;
|
||||
ThreadPool.GetMinThreads(out work, out comm);
|
||||
if (threadConfig.MinWorkerThreads > 0)
|
||||
work = threadConfig.MinWorkerThreads;
|
||||
if (threadConfig.MinIOThreads > 0)
|
||||
comm = threadConfig.MinIOThreads;
|
||||
if (!ThreadPool.SetMinThreads(work, comm))
|
||||
throw new Exception("Error: could not SetMinThreads in ThreadPool");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Use new ThreadPool thread for each new client connection
|
||||
/// Server that uses C# built-in ThreadPool to spawn threads when handling requests.
|
||||
/// </summary>
|
||||
public override void Serve()
|
||||
public class TThreadPoolServer : TServer
|
||||
{
|
||||
try
|
||||
{
|
||||
serverTransport.Listen();
|
||||
}
|
||||
catch (TTransportException ttx)
|
||||
{
|
||||
logDelegate("Error, could not listen on ServerTransport: " + ttx);
|
||||
return;
|
||||
}
|
||||
private const int DEFAULT_MIN_THREADS = -1; // use .NET ThreadPool defaults
|
||||
private const int DEFAULT_MAX_THREADS = -1; // use .NET ThreadPool defaults
|
||||
private volatile bool stop = false;
|
||||
|
||||
//Fire the preServe server event when server is up but before any client connections
|
||||
if (serverEventHandler != null)
|
||||
serverEventHandler.preServe();
|
||||
|
||||
while (!stop)
|
||||
{
|
||||
int failureCount = 0;
|
||||
try
|
||||
public struct Configuration
|
||||
{
|
||||
TTransport client = serverTransport.Accept();
|
||||
ThreadPool.QueueUserWorkItem(this.Execute, client);
|
||||
public int MinWorkerThreads;
|
||||
public int MaxWorkerThreads;
|
||||
public int MinIOThreads;
|
||||
public int MaxIOThreads;
|
||||
|
||||
public Configuration(int min = DEFAULT_MIN_THREADS, int max = DEFAULT_MAX_THREADS)
|
||||
{
|
||||
MinWorkerThreads = min;
|
||||
MaxWorkerThreads = max;
|
||||
MinIOThreads = min;
|
||||
MaxIOThreads = max;
|
||||
}
|
||||
|
||||
public Configuration(int minWork, int maxWork, int minIO, int maxIO)
|
||||
{
|
||||
MinWorkerThreads = minWork;
|
||||
MaxWorkerThreads = maxWork;
|
||||
MinIOThreads = minIO;
|
||||
MaxIOThreads = maxIO;
|
||||
}
|
||||
}
|
||||
catch (TTransportException ttx)
|
||||
{
|
||||
if (!stop || ttx.Type != TTransportException.ExceptionType.Interrupted)
|
||||
{
|
||||
++failureCount;
|
||||
logDelegate(ttx.ToString());
|
||||
}
|
||||
|
||||
public TThreadPoolServer(TProcessor processor, TServerTransport serverTransport)
|
||||
: this(new TSingletonProcessorFactory(processor), serverTransport,
|
||||
new TTransportFactory(), new TTransportFactory(),
|
||||
new TBinaryProtocol.Factory(), new TBinaryProtocol.Factory(),
|
||||
new Configuration(), DefaultLogDelegate)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
if (stop)
|
||||
{
|
||||
try
|
||||
public TThreadPoolServer(TProcessor processor, TServerTransport serverTransport, LogDelegate logDelegate)
|
||||
: this(new TSingletonProcessorFactory(processor), serverTransport,
|
||||
new TTransportFactory(), new TTransportFactory(),
|
||||
new TBinaryProtocol.Factory(), new TBinaryProtocol.Factory(),
|
||||
new Configuration(), logDelegate)
|
||||
{
|
||||
serverTransport.Close();
|
||||
}
|
||||
catch (TTransportException ttx)
|
||||
{
|
||||
logDelegate("TServerTransport failed on close: " + ttx.Message);
|
||||
}
|
||||
stop = false;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Loops on processing a client forever
|
||||
/// threadContext will be a TTransport instance
|
||||
/// </summary>
|
||||
/// <param name="threadContext"></param>
|
||||
private void Execute(Object threadContext)
|
||||
{
|
||||
using( TTransport client = (TTransport)threadContext)
|
||||
{
|
||||
TProcessor processor = processorFactory.GetProcessor(client, this);
|
||||
TTransport inputTransport = null;
|
||||
TTransport outputTransport = null;
|
||||
TProtocol inputProtocol = null;
|
||||
TProtocol outputProtocol = null;
|
||||
Object connectionContext = null;
|
||||
try
|
||||
public TThreadPoolServer(TProcessor processor,
|
||||
TServerTransport serverTransport,
|
||||
TTransportFactory transportFactory,
|
||||
TProtocolFactory protocolFactory)
|
||||
: this(new TSingletonProcessorFactory(processor), serverTransport,
|
||||
transportFactory, transportFactory,
|
||||
protocolFactory, protocolFactory,
|
||||
new Configuration(), DefaultLogDelegate)
|
||||
{
|
||||
try
|
||||
{
|
||||
inputTransport = inputTransportFactory.GetTransport(client);
|
||||
outputTransport = outputTransportFactory.GetTransport(client);
|
||||
inputProtocol = inputProtocolFactory.GetProtocol(inputTransport);
|
||||
outputProtocol = outputProtocolFactory.GetProtocol(outputTransport);
|
||||
|
||||
//Recover event handler (if any) and fire createContext server event when a client connects
|
||||
}
|
||||
|
||||
public TThreadPoolServer(TProcessorFactory processorFactory,
|
||||
TServerTransport serverTransport,
|
||||
TTransportFactory transportFactory,
|
||||
TProtocolFactory protocolFactory)
|
||||
: this(processorFactory, serverTransport,
|
||||
transportFactory, transportFactory,
|
||||
protocolFactory, protocolFactory,
|
||||
new Configuration(), DefaultLogDelegate)
|
||||
{
|
||||
}
|
||||
|
||||
public TThreadPoolServer(TProcessorFactory processorFactory,
|
||||
TServerTransport serverTransport,
|
||||
TTransportFactory inputTransportFactory,
|
||||
TTransportFactory outputTransportFactory,
|
||||
TProtocolFactory inputProtocolFactory,
|
||||
TProtocolFactory outputProtocolFactory,
|
||||
int minThreadPoolThreads, int maxThreadPoolThreads, LogDelegate logDel)
|
||||
: this(processorFactory, serverTransport, inputTransportFactory, outputTransportFactory,
|
||||
inputProtocolFactory, outputProtocolFactory,
|
||||
new Configuration(minThreadPoolThreads, maxThreadPoolThreads),
|
||||
logDel)
|
||||
{
|
||||
}
|
||||
|
||||
public TThreadPoolServer(TProcessorFactory processorFactory,
|
||||
TServerTransport serverTransport,
|
||||
TTransportFactory inputTransportFactory,
|
||||
TTransportFactory outputTransportFactory,
|
||||
TProtocolFactory inputProtocolFactory,
|
||||
TProtocolFactory outputProtocolFactory,
|
||||
Configuration threadConfig,
|
||||
LogDelegate logDel)
|
||||
: base(processorFactory, serverTransport, inputTransportFactory, outputTransportFactory,
|
||||
inputProtocolFactory, outputProtocolFactory, logDel)
|
||||
{
|
||||
lock (typeof(TThreadPoolServer))
|
||||
{
|
||||
if ((threadConfig.MaxWorkerThreads > 0) || (threadConfig.MaxIOThreads > 0))
|
||||
{
|
||||
int work, comm;
|
||||
ThreadPool.GetMaxThreads(out work, out comm);
|
||||
if (threadConfig.MaxWorkerThreads > 0)
|
||||
work = threadConfig.MaxWorkerThreads;
|
||||
if (threadConfig.MaxIOThreads > 0)
|
||||
comm = threadConfig.MaxIOThreads;
|
||||
if (!ThreadPool.SetMaxThreads(work, comm))
|
||||
throw new Exception("Error: could not SetMaxThreads in ThreadPool");
|
||||
}
|
||||
|
||||
if ((threadConfig.MinWorkerThreads > 0) || (threadConfig.MinIOThreads > 0))
|
||||
{
|
||||
int work, comm;
|
||||
ThreadPool.GetMinThreads(out work, out comm);
|
||||
if (threadConfig.MinWorkerThreads > 0)
|
||||
work = threadConfig.MinWorkerThreads;
|
||||
if (threadConfig.MinIOThreads > 0)
|
||||
comm = threadConfig.MinIOThreads;
|
||||
if (!ThreadPool.SetMinThreads(work, comm))
|
||||
throw new Exception("Error: could not SetMinThreads in ThreadPool");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Use new ThreadPool thread for each new client connection.
|
||||
/// </summary>
|
||||
public override void Serve()
|
||||
{
|
||||
try
|
||||
{
|
||||
serverTransport.Listen();
|
||||
}
|
||||
catch (TTransportException ttx)
|
||||
{
|
||||
logDelegate("Error, could not listen on ServerTransport: " + ttx);
|
||||
return;
|
||||
}
|
||||
|
||||
//Fire the preServe server event when server is up but before any client connections
|
||||
if (serverEventHandler != null)
|
||||
connectionContext = serverEventHandler.createContext(inputProtocol, outputProtocol);
|
||||
|
||||
//Process client requests until client disconnects
|
||||
serverEventHandler.preServe();
|
||||
|
||||
while (!stop)
|
||||
{
|
||||
if (!inputTransport.Peek())
|
||||
break;
|
||||
|
||||
//Fire processContext server event
|
||||
//N.B. This is the pattern implemented in C++ and the event fires provisionally.
|
||||
//That is to say it may be many minutes between the event firing and the client request
|
||||
//actually arriving or the client may hang up without ever makeing a request.
|
||||
if (serverEventHandler != null)
|
||||
serverEventHandler.processContext(connectionContext, inputTransport);
|
||||
//Process client request (blocks until transport is readable)
|
||||
if (!processor.Process(inputProtocol, outputProtocol))
|
||||
break;
|
||||
}
|
||||
}
|
||||
catch (TTransportException)
|
||||
{
|
||||
//Usually a client disconnect, expected
|
||||
}
|
||||
catch (Exception x)
|
||||
{
|
||||
//Unexpected
|
||||
logDelegate("Error: " + x);
|
||||
}
|
||||
|
||||
//Fire deleteContext server event after client disconnects
|
||||
if (serverEventHandler != null)
|
||||
serverEventHandler.deleteContext(connectionContext, inputProtocol, outputProtocol);
|
||||
|
||||
}
|
||||
finally
|
||||
{
|
||||
//Close transports
|
||||
if (inputTransport != null)
|
||||
inputTransport.Close();
|
||||
if (outputTransport != null)
|
||||
outputTransport.Close();
|
||||
|
||||
// disposable stuff should be disposed
|
||||
if( inputProtocol != null)
|
||||
inputProtocol.Dispose();
|
||||
if( outputProtocol != null)
|
||||
outputProtocol.Dispose();
|
||||
if( inputTransport != null)
|
||||
inputTransport.Dispose();
|
||||
if( outputTransport != null)
|
||||
outputTransport.Dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
int failureCount = 0;
|
||||
try
|
||||
{
|
||||
TTransport client = serverTransport.Accept();
|
||||
ThreadPool.QueueUserWorkItem(this.Execute, client);
|
||||
}
|
||||
catch (TTransportException ttx)
|
||||
{
|
||||
if (!stop || ttx.Type != TTransportException.ExceptionType.Interrupted)
|
||||
{
|
||||
++failureCount;
|
||||
logDelegate(ttx.ToString());
|
||||
}
|
||||
|
||||
public override void Stop()
|
||||
{
|
||||
stop = true;
|
||||
serverTransport.Close();
|
||||
}
|
||||
}
|
||||
|
||||
if (stop)
|
||||
{
|
||||
try
|
||||
{
|
||||
serverTransport.Close();
|
||||
}
|
||||
catch (TTransportException ttx)
|
||||
{
|
||||
logDelegate("TServerTransport failed on close: " + ttx.Message);
|
||||
}
|
||||
stop = false;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Loops on processing a client forever
|
||||
/// threadContext will be a TTransport instance
|
||||
/// </summary>
|
||||
/// <param name="threadContext"></param>
|
||||
private void Execute(object threadContext)
|
||||
{
|
||||
using (TTransport client = (TTransport)threadContext)
|
||||
{
|
||||
TProcessor processor = processorFactory.GetProcessor(client, this);
|
||||
TTransport inputTransport = null;
|
||||
TTransport outputTransport = null;
|
||||
TProtocol inputProtocol = null;
|
||||
TProtocol outputProtocol = null;
|
||||
object connectionContext = null;
|
||||
try
|
||||
{
|
||||
try
|
||||
{
|
||||
inputTransport = inputTransportFactory.GetTransport(client);
|
||||
outputTransport = outputTransportFactory.GetTransport(client);
|
||||
inputProtocol = inputProtocolFactory.GetProtocol(inputTransport);
|
||||
outputProtocol = outputProtocolFactory.GetProtocol(outputTransport);
|
||||
|
||||
//Recover event handler (if any) and fire createContext server event when a client connects
|
||||
if (serverEventHandler != null)
|
||||
connectionContext = serverEventHandler.createContext(inputProtocol, outputProtocol);
|
||||
|
||||
//Process client requests until client disconnects
|
||||
while (!stop)
|
||||
{
|
||||
if (!inputTransport.Peek())
|
||||
break;
|
||||
|
||||
//Fire processContext server event
|
||||
//N.B. This is the pattern implemented in C++ and the event fires provisionally.
|
||||
//That is to say it may be many minutes between the event firing and the client request
|
||||
//actually arriving or the client may hang up without ever makeing a request.
|
||||
if (serverEventHandler != null)
|
||||
serverEventHandler.processContext(connectionContext, inputTransport);
|
||||
//Process client request (blocks until transport is readable)
|
||||
if (!processor.Process(inputProtocol, outputProtocol))
|
||||
break;
|
||||
}
|
||||
}
|
||||
catch (TTransportException)
|
||||
{
|
||||
//Usually a client disconnect, expected
|
||||
}
|
||||
catch (Exception x)
|
||||
{
|
||||
//Unexpected
|
||||
logDelegate("Error: " + x);
|
||||
}
|
||||
|
||||
//Fire deleteContext server event after client disconnects
|
||||
if (serverEventHandler != null)
|
||||
serverEventHandler.deleteContext(connectionContext, inputProtocol, outputProtocol);
|
||||
|
||||
}
|
||||
finally
|
||||
{
|
||||
//Close transports
|
||||
if (inputTransport != null)
|
||||
inputTransport.Close();
|
||||
if (outputTransport != null)
|
||||
outputTransport.Close();
|
||||
|
||||
// disposable stuff should be disposed
|
||||
if (inputProtocol != null)
|
||||
inputProtocol.Dispose();
|
||||
if (outputProtocol != null)
|
||||
outputProtocol.Dispose();
|
||||
if (inputTransport != null)
|
||||
inputTransport.Dispose();
|
||||
if (outputTransport != null)
|
||||
outputTransport.Dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override void Stop()
|
||||
{
|
||||
stop = true;
|
||||
serverTransport.Close();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -26,258 +26,257 @@ using Thrift.Transport;
|
||||
|
||||
namespace Thrift.Server
|
||||
{
|
||||
/// <summary>
|
||||
/// Server that uses C# threads (as opposed to the ThreadPool) when handling requests
|
||||
/// </summary>
|
||||
public class TThreadedServer : TServer
|
||||
{
|
||||
private const int DEFAULT_MAX_THREADS = 100;
|
||||
private volatile bool stop = false;
|
||||
private readonly int maxThreads;
|
||||
|
||||
private Queue<TTransport> clientQueue;
|
||||
private THashSet<Thread> clientThreads;
|
||||
private object clientLock;
|
||||
private Thread workerThread;
|
||||
|
||||
public int ClientThreadsCount {
|
||||
get { return clientThreads.Count; }
|
||||
}
|
||||
|
||||
public TThreadedServer(TProcessor processor, TServerTransport serverTransport)
|
||||
: this(new TSingletonProcessorFactory(processor), serverTransport,
|
||||
new TTransportFactory(), new TTransportFactory(),
|
||||
new TBinaryProtocol.Factory(), new TBinaryProtocol.Factory(),
|
||||
DEFAULT_MAX_THREADS, DefaultLogDelegate)
|
||||
{
|
||||
}
|
||||
|
||||
public TThreadedServer(TProcessor processor, TServerTransport serverTransport, LogDelegate logDelegate)
|
||||
: this(new TSingletonProcessorFactory(processor), serverTransport,
|
||||
new TTransportFactory(), new TTransportFactory(),
|
||||
new TBinaryProtocol.Factory(), new TBinaryProtocol.Factory(),
|
||||
DEFAULT_MAX_THREADS, logDelegate)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
public TThreadedServer(TProcessor processor,
|
||||
TServerTransport serverTransport,
|
||||
TTransportFactory transportFactory,
|
||||
TProtocolFactory protocolFactory)
|
||||
: this(new TSingletonProcessorFactory(processor), serverTransport,
|
||||
transportFactory, transportFactory,
|
||||
protocolFactory, protocolFactory,
|
||||
DEFAULT_MAX_THREADS, DefaultLogDelegate)
|
||||
{
|
||||
}
|
||||
|
||||
public TThreadedServer(TProcessorFactory processorFactory,
|
||||
TServerTransport serverTransport,
|
||||
TTransportFactory transportFactory,
|
||||
TProtocolFactory protocolFactory)
|
||||
: this(processorFactory, serverTransport,
|
||||
transportFactory, transportFactory,
|
||||
protocolFactory, protocolFactory,
|
||||
DEFAULT_MAX_THREADS, DefaultLogDelegate)
|
||||
{
|
||||
}
|
||||
public TThreadedServer(TProcessorFactory processorFactory,
|
||||
TServerTransport serverTransport,
|
||||
TTransportFactory inputTransportFactory,
|
||||
TTransportFactory outputTransportFactory,
|
||||
TProtocolFactory inputProtocolFactory,
|
||||
TProtocolFactory outputProtocolFactory,
|
||||
int maxThreads, LogDelegate logDel)
|
||||
: base(processorFactory, serverTransport, inputTransportFactory, outputTransportFactory,
|
||||
inputProtocolFactory, outputProtocolFactory, logDel)
|
||||
{
|
||||
this.maxThreads = maxThreads;
|
||||
clientQueue = new Queue<TTransport>();
|
||||
clientLock = new object();
|
||||
clientThreads = new THashSet<Thread>();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Use new Thread for each new client connection. block until numConnections < maxThreads
|
||||
/// Server that uses C# threads (as opposed to the ThreadPool) when handling requests.
|
||||
/// </summary>
|
||||
public override void Serve()
|
||||
public class TThreadedServer : TServer
|
||||
{
|
||||
try
|
||||
{
|
||||
//start worker thread
|
||||
workerThread = new Thread(new ThreadStart(Execute));
|
||||
workerThread.Start();
|
||||
serverTransport.Listen();
|
||||
}
|
||||
catch (TTransportException ttx)
|
||||
{
|
||||
logDelegate("Error, could not listen on ServerTransport: " + ttx);
|
||||
return;
|
||||
}
|
||||
private const int DEFAULT_MAX_THREADS = 100;
|
||||
private volatile bool stop = false;
|
||||
private readonly int maxThreads;
|
||||
|
||||
//Fire the preServe server event when server is up but before any client connections
|
||||
if (serverEventHandler != null)
|
||||
serverEventHandler.preServe();
|
||||
private Queue<TTransport> clientQueue;
|
||||
private THashSet<Thread> clientThreads;
|
||||
private object clientLock;
|
||||
private Thread workerThread;
|
||||
|
||||
while (!stop)
|
||||
{
|
||||
int failureCount = 0;
|
||||
try
|
||||
public int ClientThreadsCount
|
||||
{
|
||||
TTransport client = serverTransport.Accept();
|
||||
lock (clientLock)
|
||||
{
|
||||
clientQueue.Enqueue(client);
|
||||
Monitor.Pulse(clientLock);
|
||||
}
|
||||
get { return clientThreads.Count; }
|
||||
}
|
||||
catch (TTransportException ttx)
|
||||
{
|
||||
if (!stop || ttx.Type != TTransportException.ExceptionType.Interrupted)
|
||||
{
|
||||
++failureCount;
|
||||
logDelegate(ttx.ToString());
|
||||
}
|
||||
|
||||
public TThreadedServer(TProcessor processor, TServerTransport serverTransport)
|
||||
: this(new TSingletonProcessorFactory(processor), serverTransport,
|
||||
new TTransportFactory(), new TTransportFactory(),
|
||||
new TBinaryProtocol.Factory(), new TBinaryProtocol.Factory(),
|
||||
DEFAULT_MAX_THREADS, DefaultLogDelegate)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
if (stop)
|
||||
{
|
||||
try
|
||||
public TThreadedServer(TProcessor processor, TServerTransport serverTransport, LogDelegate logDelegate)
|
||||
: this(new TSingletonProcessorFactory(processor), serverTransport,
|
||||
new TTransportFactory(), new TTransportFactory(),
|
||||
new TBinaryProtocol.Factory(), new TBinaryProtocol.Factory(),
|
||||
DEFAULT_MAX_THREADS, logDelegate)
|
||||
{
|
||||
serverTransport.Close();
|
||||
}
|
||||
catch (TTransportException ttx)
|
||||
|
||||
|
||||
public TThreadedServer(TProcessor processor,
|
||||
TServerTransport serverTransport,
|
||||
TTransportFactory transportFactory,
|
||||
TProtocolFactory protocolFactory)
|
||||
: this(new TSingletonProcessorFactory(processor), serverTransport,
|
||||
transportFactory, transportFactory,
|
||||
protocolFactory, protocolFactory,
|
||||
DEFAULT_MAX_THREADS, DefaultLogDelegate)
|
||||
{
|
||||
logDelegate("TServeTransport failed on close: " + ttx.Message);
|
||||
}
|
||||
stop = false;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Loops on processing a client forever
|
||||
/// threadContext will be a TTransport instance
|
||||
/// </summary>
|
||||
/// <param name="threadContext"></param>
|
||||
private void Execute()
|
||||
{
|
||||
while (!stop)
|
||||
{
|
||||
TTransport client;
|
||||
Thread t;
|
||||
lock (clientLock)
|
||||
public TThreadedServer(TProcessorFactory processorFactory,
|
||||
TServerTransport serverTransport,
|
||||
TTransportFactory transportFactory,
|
||||
TProtocolFactory protocolFactory)
|
||||
: this(processorFactory, serverTransport,
|
||||
transportFactory, transportFactory,
|
||||
protocolFactory, protocolFactory,
|
||||
DEFAULT_MAX_THREADS, DefaultLogDelegate)
|
||||
{
|
||||
//don't dequeue if too many connections
|
||||
while (clientThreads.Count >= maxThreads)
|
||||
{
|
||||
Monitor.Wait(clientLock);
|
||||
}
|
||||
|
||||
while (clientQueue.Count == 0)
|
||||
{
|
||||
Monitor.Wait(clientLock);
|
||||
}
|
||||
|
||||
client = clientQueue.Dequeue();
|
||||
t = new Thread(new ParameterizedThreadStart(ClientWorker));
|
||||
clientThreads.Add(t);
|
||||
}
|
||||
//start processing requests from client on new thread
|
||||
t.Start(client);
|
||||
}
|
||||
}
|
||||
|
||||
private void ClientWorker(Object context)
|
||||
{
|
||||
using( TTransport client = (TTransport)context)
|
||||
{
|
||||
TProcessor processor = processorFactory.GetProcessor(client);
|
||||
TTransport inputTransport = null;
|
||||
TTransport outputTransport = null;
|
||||
TProtocol inputProtocol = null;
|
||||
TProtocol outputProtocol = null;
|
||||
Object connectionContext = null;
|
||||
try
|
||||
public TThreadedServer(TProcessorFactory processorFactory,
|
||||
TServerTransport serverTransport,
|
||||
TTransportFactory inputTransportFactory,
|
||||
TTransportFactory outputTransportFactory,
|
||||
TProtocolFactory inputProtocolFactory,
|
||||
TProtocolFactory outputProtocolFactory,
|
||||
int maxThreads, LogDelegate logDel)
|
||||
: base(processorFactory, serverTransport, inputTransportFactory, outputTransportFactory,
|
||||
inputProtocolFactory, outputProtocolFactory, logDel)
|
||||
{
|
||||
try
|
||||
{
|
||||
inputTransport = inputTransportFactory.GetTransport(client);
|
||||
outputTransport = outputTransportFactory.GetTransport(client);
|
||||
inputProtocol = inputProtocolFactory.GetProtocol(inputTransport);
|
||||
outputProtocol = outputProtocolFactory.GetProtocol(outputTransport);
|
||||
|
||||
//Recover event handler (if any) and fire createContext server event when a client connects
|
||||
this.maxThreads = maxThreads;
|
||||
clientQueue = new Queue<TTransport>();
|
||||
clientLock = new object();
|
||||
clientThreads = new THashSet<Thread>();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Use new Thread for each new client connection. block until numConnections < maxThreads.
|
||||
/// </summary>
|
||||
public override void Serve()
|
||||
{
|
||||
try
|
||||
{
|
||||
//start worker thread
|
||||
workerThread = new Thread(new ThreadStart(Execute));
|
||||
workerThread.Start();
|
||||
serverTransport.Listen();
|
||||
}
|
||||
catch (TTransportException ttx)
|
||||
{
|
||||
logDelegate("Error, could not listen on ServerTransport: " + ttx);
|
||||
return;
|
||||
}
|
||||
|
||||
//Fire the preServe server event when server is up but before any client connections
|
||||
if (serverEventHandler != null)
|
||||
connectionContext = serverEventHandler.createContext(inputProtocol, outputProtocol);
|
||||
|
||||
//Process client requests until client disconnects
|
||||
serverEventHandler.preServe();
|
||||
|
||||
while (!stop)
|
||||
{
|
||||
if (!inputTransport.Peek())
|
||||
break;
|
||||
|
||||
//Fire processContext server event
|
||||
//N.B. This is the pattern implemented in C++ and the event fires provisionally.
|
||||
//That is to say it may be many minutes between the event firing and the client request
|
||||
//actually arriving or the client may hang up without ever makeing a request.
|
||||
if (serverEventHandler != null)
|
||||
serverEventHandler.processContext(connectionContext, inputTransport);
|
||||
//Process client request (blocks until transport is readable)
|
||||
if (!processor.Process(inputProtocol, outputProtocol))
|
||||
break;
|
||||
int failureCount = 0;
|
||||
try
|
||||
{
|
||||
TTransport client = serverTransport.Accept();
|
||||
lock (clientLock)
|
||||
{
|
||||
clientQueue.Enqueue(client);
|
||||
Monitor.Pulse(clientLock);
|
||||
}
|
||||
}
|
||||
catch (TTransportException ttx)
|
||||
{
|
||||
if (!stop || ttx.Type != TTransportException.ExceptionType.Interrupted)
|
||||
{
|
||||
++failureCount;
|
||||
logDelegate(ttx.ToString());
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (TTransportException)
|
||||
{
|
||||
//Usually a client disconnect, expected
|
||||
}
|
||||
catch (Exception x)
|
||||
{
|
||||
//Unexpected
|
||||
logDelegate("Error: " + x);
|
||||
}
|
||||
|
||||
//Fire deleteContext server event after client disconnects
|
||||
if (serverEventHandler != null)
|
||||
serverEventHandler.deleteContext(connectionContext, inputProtocol, outputProtocol);
|
||||
|
||||
lock (clientLock)
|
||||
{
|
||||
clientThreads.Remove(Thread.CurrentThread);
|
||||
Monitor.Pulse(clientLock);
|
||||
}
|
||||
|
||||
}
|
||||
finally
|
||||
{
|
||||
//Close transports
|
||||
if (inputTransport != null)
|
||||
inputTransport.Close();
|
||||
if (outputTransport != null)
|
||||
outputTransport.Close();
|
||||
|
||||
// disposable stuff should be disposed
|
||||
if (inputProtocol != null)
|
||||
inputProtocol.Dispose();
|
||||
if (outputProtocol != null)
|
||||
outputProtocol.Dispose();
|
||||
if (stop)
|
||||
{
|
||||
try
|
||||
{
|
||||
serverTransport.Close();
|
||||
}
|
||||
catch (TTransportException ttx)
|
||||
{
|
||||
logDelegate("TServeTransport failed on close: " + ttx.Message);
|
||||
}
|
||||
stop = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override void Stop()
|
||||
{
|
||||
stop = true;
|
||||
serverTransport.Close();
|
||||
//clean up all the threads myself
|
||||
workerThread.Abort();
|
||||
foreach (Thread t in clientThreads)
|
||||
{
|
||||
t.Abort();
|
||||
}
|
||||
/// <summary>
|
||||
/// Loops on processing a client forever
|
||||
/// </summary>
|
||||
private void Execute()
|
||||
{
|
||||
while (!stop)
|
||||
{
|
||||
TTransport client;
|
||||
Thread t;
|
||||
lock (clientLock)
|
||||
{
|
||||
//don't dequeue if too many connections
|
||||
while (clientThreads.Count >= maxThreads)
|
||||
{
|
||||
Monitor.Wait(clientLock);
|
||||
}
|
||||
|
||||
while (clientQueue.Count == 0)
|
||||
{
|
||||
Monitor.Wait(clientLock);
|
||||
}
|
||||
|
||||
client = clientQueue.Dequeue();
|
||||
t = new Thread(new ParameterizedThreadStart(ClientWorker));
|
||||
clientThreads.Add(t);
|
||||
}
|
||||
//start processing requests from client on new thread
|
||||
t.Start(client);
|
||||
}
|
||||
}
|
||||
|
||||
private void ClientWorker(object context)
|
||||
{
|
||||
using (TTransport client = (TTransport)context)
|
||||
{
|
||||
TProcessor processor = processorFactory.GetProcessor(client);
|
||||
TTransport inputTransport = null;
|
||||
TTransport outputTransport = null;
|
||||
TProtocol inputProtocol = null;
|
||||
TProtocol outputProtocol = null;
|
||||
object connectionContext = null;
|
||||
try
|
||||
{
|
||||
try
|
||||
{
|
||||
inputTransport = inputTransportFactory.GetTransport(client);
|
||||
outputTransport = outputTransportFactory.GetTransport(client);
|
||||
inputProtocol = inputProtocolFactory.GetProtocol(inputTransport);
|
||||
outputProtocol = outputProtocolFactory.GetProtocol(outputTransport);
|
||||
|
||||
//Recover event handler (if any) and fire createContext server event when a client connects
|
||||
if (serverEventHandler != null)
|
||||
connectionContext = serverEventHandler.createContext(inputProtocol, outputProtocol);
|
||||
|
||||
//Process client requests until client disconnects
|
||||
while (!stop)
|
||||
{
|
||||
if (!inputTransport.Peek())
|
||||
break;
|
||||
|
||||
//Fire processContext server event
|
||||
//N.B. This is the pattern implemented in C++ and the event fires provisionally.
|
||||
//That is to say it may be many minutes between the event firing and the client request
|
||||
//actually arriving or the client may hang up without ever makeing a request.
|
||||
if (serverEventHandler != null)
|
||||
serverEventHandler.processContext(connectionContext, inputTransport);
|
||||
//Process client request (blocks until transport is readable)
|
||||
if (!processor.Process(inputProtocol, outputProtocol))
|
||||
break;
|
||||
}
|
||||
}
|
||||
catch (TTransportException)
|
||||
{
|
||||
//Usually a client disconnect, expected
|
||||
}
|
||||
catch (Exception x)
|
||||
{
|
||||
//Unexpected
|
||||
logDelegate("Error: " + x);
|
||||
}
|
||||
|
||||
//Fire deleteContext server event after client disconnects
|
||||
if (serverEventHandler != null)
|
||||
serverEventHandler.deleteContext(connectionContext, inputProtocol, outputProtocol);
|
||||
|
||||
lock (clientLock)
|
||||
{
|
||||
clientThreads.Remove(Thread.CurrentThread);
|
||||
Monitor.Pulse(clientLock);
|
||||
}
|
||||
|
||||
}
|
||||
finally
|
||||
{
|
||||
//Close transports
|
||||
if (inputTransport != null)
|
||||
inputTransport.Close();
|
||||
if (outputTransport != null)
|
||||
outputTransport.Close();
|
||||
|
||||
// disposable stuff should be disposed
|
||||
if (inputProtocol != null)
|
||||
inputProtocol.Dispose();
|
||||
if (outputProtocol != null)
|
||||
outputProtocol.Dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override void Stop()
|
||||
{
|
||||
stop = true;
|
||||
serverTransport.Close();
|
||||
//clean up all the threads myself
|
||||
workerThread.Abort();
|
||||
foreach (Thread t in clientThreads)
|
||||
{
|
||||
t.Abort();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -103,7 +103,7 @@ namespace Thrift
|
||||
|
||||
oprot.WriteStructBegin(struc);
|
||||
|
||||
if (!String.IsNullOrEmpty(Message))
|
||||
if (!string.IsNullOrEmpty(Message))
|
||||
{
|
||||
field.Name = "message";
|
||||
field.Type = TType.String;
|
||||
|
@ -31,7 +31,7 @@ namespace Thrift
|
||||
{
|
||||
}
|
||||
|
||||
public TException( string message)
|
||||
public TException(string message)
|
||||
: base(message)
|
||||
{
|
||||
}
|
||||
|
@ -42,7 +42,7 @@ namespace Thrift
|
||||
|
||||
public TProcessor GetProcessor(TTransport trans, TServer server = null)
|
||||
{
|
||||
H handler = (H) Activator.CreateInstance(typeof(H), handlerArgs);
|
||||
H handler = (H)Activator.CreateInstance(typeof(H), handlerArgs);
|
||||
|
||||
TControllingHandler handlerServerRef = handler as TControllingHandler;
|
||||
if (handlerServerRef != null)
|
||||
|
@ -17,7 +17,7 @@
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
@ -154,11 +154,11 @@ namespace Thrift.Transport
|
||||
{
|
||||
if (disposing)
|
||||
{
|
||||
if(inputBuffer != null)
|
||||
if (inputBuffer != null)
|
||||
inputBuffer.Dispose();
|
||||
if(outputBuffer != null)
|
||||
if (outputBuffer != null)
|
||||
outputBuffer.Dispose();
|
||||
if(transport != null)
|
||||
if (transport != null)
|
||||
transport.Dispose();
|
||||
}
|
||||
}
|
||||
|
@ -116,8 +116,8 @@ namespace Thrift.Transport
|
||||
byte[] buf = writeBuffer.GetBuffer();
|
||||
int len = (int)writeBuffer.Length;
|
||||
int data_len = len - HeaderSize;
|
||||
if ( data_len < 0 )
|
||||
throw new System.InvalidOperationException (); // logic error actually
|
||||
if (data_len < 0)
|
||||
throw new System.InvalidOperationException(); // logic error actually
|
||||
|
||||
// Inject message header into the reserved buffer space
|
||||
EncodeFrameSize(data_len, buf);
|
||||
@ -130,7 +130,7 @@ namespace Thrift.Transport
|
||||
transport.Flush();
|
||||
}
|
||||
|
||||
private void InitWriteBuffer ()
|
||||
private void InitWriteBuffer()
|
||||
{
|
||||
// Reserve space for message header to be put right before sending it out
|
||||
writeBuffer.SetLength(HeaderSize);
|
||||
@ -150,7 +150,7 @@ namespace Thrift.Transport
|
||||
return
|
||||
((buf[0] & 0xff) << 24) |
|
||||
((buf[1] & 0xff) << 16) |
|
||||
((buf[2] & 0xff) << 8) |
|
||||
((buf[2] & 0xff) << 8) |
|
||||
((buf[3] & 0xff));
|
||||
}
|
||||
|
||||
@ -171,11 +171,11 @@ namespace Thrift.Transport
|
||||
{
|
||||
if (disposing)
|
||||
{
|
||||
if(readBuffer != null)
|
||||
if (readBuffer != null)
|
||||
readBuffer.Dispose();
|
||||
if(writeBuffer != null)
|
||||
if (writeBuffer != null)
|
||||
writeBuffer.Dispose();
|
||||
if(transport != null)
|
||||
if (transport != null)
|
||||
transport.Dispose();
|
||||
}
|
||||
}
|
||||
|
@ -30,7 +30,6 @@ using System.IO.Compression;
|
||||
|
||||
namespace Thrift.Transport
|
||||
{
|
||||
|
||||
public class THttpClient : TTransport, IDisposable
|
||||
{
|
||||
private readonly Uri uri;
|
||||
@ -43,7 +42,7 @@ namespace Thrift.Transport
|
||||
|
||||
private int readTimeout = 30000;
|
||||
|
||||
private IDictionary<String, String> customHeaders = new Dictionary<string, string>();
|
||||
private IDictionary<string, string> customHeaders = new Dictionary<string, string>();
|
||||
|
||||
#if !SILVERLIGHT
|
||||
private IWebProxy proxy = WebRequest.DefaultWebProxy;
|
||||
@ -64,7 +63,7 @@ namespace Thrift.Transport
|
||||
{
|
||||
set
|
||||
{
|
||||
connectTimeout = value;
|
||||
connectTimeout = value;
|
||||
}
|
||||
}
|
||||
|
||||
@ -76,7 +75,7 @@ namespace Thrift.Transport
|
||||
}
|
||||
}
|
||||
|
||||
public IDictionary<String, String> CustomHeaders
|
||||
public IDictionary<string, string> CustomHeaders
|
||||
{
|
||||
get
|
||||
{
|
||||
@ -325,7 +324,7 @@ namespace Thrift.Transport
|
||||
{
|
||||
try
|
||||
{
|
||||
var flushAsyncResult = (FlushAsyncResult) asyncResult;
|
||||
var flushAsyncResult = (FlushAsyncResult)asyncResult;
|
||||
|
||||
if (!flushAsyncResult.IsCompleted)
|
||||
{
|
||||
@ -338,7 +337,8 @@ namespace Thrift.Transport
|
||||
{
|
||||
throw flushAsyncResult.AsyncException;
|
||||
}
|
||||
} finally
|
||||
}
|
||||
finally
|
||||
{
|
||||
outputStream = new MemoryStream();
|
||||
}
|
||||
@ -387,9 +387,9 @@ namespace Thrift.Transport
|
||||
private volatile Boolean _isCompleted;
|
||||
private ManualResetEvent _evt;
|
||||
private readonly AsyncCallback _cbMethod;
|
||||
private readonly Object _state;
|
||||
private readonly object _state;
|
||||
|
||||
public FlushAsyncResult(AsyncCallback cbMethod, Object state)
|
||||
public FlushAsyncResult(AsyncCallback cbMethod, object state)
|
||||
{
|
||||
_cbMethod = cbMethod;
|
||||
_state = state;
|
||||
@ -415,7 +415,7 @@ namespace Thrift.Transport
|
||||
{
|
||||
get { return _isCompleted; }
|
||||
}
|
||||
private readonly Object _locker = new Object();
|
||||
private readonly object _locker = new object();
|
||||
private ManualResetEvent GetEvtHandle()
|
||||
{
|
||||
lock (_locker)
|
||||
@ -452,7 +452,7 @@ namespace Thrift.Transport
|
||||
}
|
||||
}
|
||||
|
||||
#region " IDisposable Support "
|
||||
#region " IDisposable Support "
|
||||
private bool _IsDisposed;
|
||||
|
||||
// IDisposable
|
||||
@ -470,6 +470,6 @@ namespace Thrift.Transport
|
||||
}
|
||||
_IsDisposed = true;
|
||||
}
|
||||
#endregion
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
@ -22,45 +22,56 @@ using System.IO;
|
||||
using System.Reflection;
|
||||
using Thrift.Protocol;
|
||||
|
||||
namespace Thrift.Transport {
|
||||
public class TMemoryBuffer : TTransport {
|
||||
namespace Thrift.Transport
|
||||
{
|
||||
public class TMemoryBuffer : TTransport
|
||||
{
|
||||
|
||||
private readonly MemoryStream byteStream;
|
||||
|
||||
public TMemoryBuffer() {
|
||||
public TMemoryBuffer()
|
||||
{
|
||||
byteStream = new MemoryStream();
|
||||
}
|
||||
|
||||
public TMemoryBuffer(byte[] buf) {
|
||||
public TMemoryBuffer(byte[] buf)
|
||||
{
|
||||
byteStream = new MemoryStream(buf);
|
||||
}
|
||||
|
||||
public override void Open() {
|
||||
public override void Open()
|
||||
{
|
||||
/** do nothing **/
|
||||
}
|
||||
|
||||
public override void Close() {
|
||||
public override void Close()
|
||||
{
|
||||
/** do nothing **/
|
||||
}
|
||||
|
||||
public override int Read(byte[] buf, int off, int len) {
|
||||
public override int Read(byte[] buf, int off, int len)
|
||||
{
|
||||
return byteStream.Read(buf, off, len);
|
||||
}
|
||||
|
||||
public override void Write(byte[] buf, int off, int len) {
|
||||
public override void Write(byte[] buf, int off, int len)
|
||||
{
|
||||
byteStream.Write(buf, off, len);
|
||||
}
|
||||
|
||||
public byte[] GetBuffer() {
|
||||
public byte[] GetBuffer()
|
||||
{
|
||||
return byteStream.ToArray();
|
||||
}
|
||||
|
||||
|
||||
public override bool IsOpen {
|
||||
public override bool IsOpen
|
||||
{
|
||||
get { return true; }
|
||||
}
|
||||
|
||||
public static byte[] Serialize(TAbstractBase s) {
|
||||
public static byte[] Serialize(TAbstractBase s)
|
||||
{
|
||||
var t = new TMemoryBuffer();
|
||||
var p = new TBinaryProtocol(t);
|
||||
|
||||
@ -69,26 +80,33 @@ namespace Thrift.Transport {
|
||||
return t.GetBuffer();
|
||||
}
|
||||
|
||||
public static T DeSerialize<T>(byte[] buf) where T : TAbstractBase {
|
||||
public static T DeSerialize<T>(byte[] buf) where T : TAbstractBase
|
||||
{
|
||||
var trans = new TMemoryBuffer(buf);
|
||||
var p = new TBinaryProtocol(trans);
|
||||
if (typeof (TBase).IsAssignableFrom(typeof (T))) {
|
||||
var method = typeof (T).GetMethod("Read", BindingFlags.Instance | BindingFlags.Public);
|
||||
if (typeof(TBase).IsAssignableFrom(typeof(T)))
|
||||
{
|
||||
var method = typeof(T).GetMethod("Read", BindingFlags.Instance | BindingFlags.Public);
|
||||
var t = Activator.CreateInstance<T>();
|
||||
method.Invoke(t, new object[] {p});
|
||||
method.Invoke(t, new object[] { p });
|
||||
return t;
|
||||
} else {
|
||||
var method = typeof (T).GetMethod("Read", BindingFlags.Static | BindingFlags.Public);
|
||||
return (T) method.Invoke(null, new object[] {p});
|
||||
}
|
||||
else
|
||||
{
|
||||
var method = typeof(T).GetMethod("Read", BindingFlags.Static | BindingFlags.Public);
|
||||
return (T)method.Invoke(null, new object[] { p });
|
||||
}
|
||||
}
|
||||
|
||||
private bool _IsDisposed;
|
||||
|
||||
// IDisposable
|
||||
protected override void Dispose(bool disposing) {
|
||||
if (!_IsDisposed) {
|
||||
if (disposing) {
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
if (!_IsDisposed)
|
||||
{
|
||||
if (disposing)
|
||||
{
|
||||
if (byteStream != null)
|
||||
byteStream.Dispose();
|
||||
}
|
||||
@ -96,4 +114,4 @@ namespace Thrift.Transport {
|
||||
_IsDisposed = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -108,4 +108,4 @@ namespace Thrift.Transport
|
||||
client.Dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -27,150 +27,150 @@ using System.Net.Sockets;
|
||||
|
||||
namespace Thrift.Transport
|
||||
{
|
||||
public class TServerSocket : TServerTransport
|
||||
{
|
||||
/**
|
||||
* Underlying server with socket
|
||||
*/
|
||||
private TcpListener server = null;
|
||||
public class TServerSocket : TServerTransport
|
||||
{
|
||||
/// <summary>
|
||||
/// Underlying server with socket.
|
||||
/// </summary>
|
||||
private TcpListener server = null;
|
||||
|
||||
/**
|
||||
* Port to listen on
|
||||
*/
|
||||
private int port = 0;
|
||||
/// <summary>
|
||||
/// Port to listen on.
|
||||
/// </summary>
|
||||
private int port = 0;
|
||||
|
||||
/**
|
||||
* Timeout for client sockets from accept
|
||||
*/
|
||||
private int clientTimeout = 0;
|
||||
/// <summary>
|
||||
/// Timeout for client sockets from accept.
|
||||
/// </summary>
|
||||
private int clientTimeout = 0;
|
||||
|
||||
/**
|
||||
* Whether or not to wrap new TSocket connections in buffers
|
||||
*/
|
||||
private bool useBufferedSockets = false;
|
||||
/// <summary>
|
||||
/// Whether or not to wrap new TSocket connections in buffers.
|
||||
/// </summary>
|
||||
private bool useBufferedSockets = false;
|
||||
|
||||
/**
|
||||
* Creates a server socket from underlying socket object
|
||||
*/
|
||||
public TServerSocket(TcpListener listener)
|
||||
:this(listener, 0)
|
||||
{
|
||||
}
|
||||
/// <summary>
|
||||
/// Creates a server socket from underlying socket object.
|
||||
/// </summary>
|
||||
public TServerSocket(TcpListener listener)
|
||||
: this(listener, 0)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a server socket from underlying socket object
|
||||
*/
|
||||
public TServerSocket(TcpListener listener, int clientTimeout)
|
||||
{
|
||||
this.server = listener;
|
||||
this.clientTimeout = clientTimeout;
|
||||
}
|
||||
/// <summary>
|
||||
/// Creates a server socket from underlying socket object.
|
||||
/// </summary>
|
||||
public TServerSocket(TcpListener listener, int clientTimeout)
|
||||
{
|
||||
this.server = listener;
|
||||
this.clientTimeout = clientTimeout;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates just a port listening server socket
|
||||
*/
|
||||
public TServerSocket(int port)
|
||||
: this(port, 0)
|
||||
{
|
||||
}
|
||||
/// <summary>
|
||||
/// Creates just a port listening server socket.
|
||||
/// </summary>
|
||||
public TServerSocket(int port)
|
||||
: this(port, 0)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates just a port listening server socket
|
||||
*/
|
||||
public TServerSocket(int port, int clientTimeout)
|
||||
:this(port, clientTimeout, false)
|
||||
{
|
||||
}
|
||||
/// <summary>
|
||||
/// Creates just a port listening server socket.
|
||||
/// </summary>
|
||||
public TServerSocket(int port, int clientTimeout)
|
||||
: this(port, clientTimeout, false)
|
||||
{
|
||||
}
|
||||
|
||||
public TServerSocket(int port, int clientTimeout, bool useBufferedSockets)
|
||||
{
|
||||
this.port = port;
|
||||
this.clientTimeout = clientTimeout;
|
||||
this.useBufferedSockets = useBufferedSockets;
|
||||
try
|
||||
{
|
||||
// Make server socket
|
||||
this.server = TSocketVersionizer.CreateTcpListener(this.port);
|
||||
this.server.Server.NoDelay = true;
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
server = null;
|
||||
throw new TTransportException("Could not create ServerSocket on port " + this.port + ".");
|
||||
}
|
||||
}
|
||||
public TServerSocket(int port, int clientTimeout, bool useBufferedSockets)
|
||||
{
|
||||
this.port = port;
|
||||
this.clientTimeout = clientTimeout;
|
||||
this.useBufferedSockets = useBufferedSockets;
|
||||
try
|
||||
{
|
||||
// Make server socket
|
||||
this.server = TSocketVersionizer.CreateTcpListener(this.port);
|
||||
this.server.Server.NoDelay = true;
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
server = null;
|
||||
throw new TTransportException("Could not create ServerSocket on port " + this.port + ".");
|
||||
}
|
||||
}
|
||||
|
||||
public override void Listen()
|
||||
{
|
||||
// Make sure not to block on accept
|
||||
if (server != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
server.Start();
|
||||
}
|
||||
catch (SocketException sx)
|
||||
{
|
||||
throw new TTransportException("Could not accept on listening socket: " + sx.Message);
|
||||
}
|
||||
}
|
||||
}
|
||||
public override void Listen()
|
||||
{
|
||||
// Make sure not to block on accept
|
||||
if (server != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
server.Start();
|
||||
}
|
||||
catch (SocketException sx)
|
||||
{
|
||||
throw new TTransportException("Could not accept on listening socket: " + sx.Message);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected override TTransport AcceptImpl()
|
||||
{
|
||||
if (server == null)
|
||||
{
|
||||
throw new TTransportException(TTransportException.ExceptionType.NotOpen, "No underlying server socket.");
|
||||
}
|
||||
try
|
||||
{
|
||||
TSocket result2 = null;
|
||||
TcpClient result = server.AcceptTcpClient();
|
||||
try
|
||||
{
|
||||
result2 = new TSocket(result);
|
||||
result2.Timeout = clientTimeout;
|
||||
if (useBufferedSockets)
|
||||
{
|
||||
TBufferedTransport result3 = new TBufferedTransport(result2);
|
||||
return result3;
|
||||
}
|
||||
else
|
||||
{
|
||||
return result2;
|
||||
}
|
||||
}
|
||||
catch (System.Exception)
|
||||
{
|
||||
// If a TSocket was successfully created, then let
|
||||
// it do proper cleanup of the TcpClient object.
|
||||
if (result2 != null)
|
||||
result2.Dispose();
|
||||
else // Otherwise, clean it up ourselves.
|
||||
((IDisposable)result).Dispose();
|
||||
throw;
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
throw new TTransportException(ex.ToString());
|
||||
}
|
||||
}
|
||||
protected override TTransport AcceptImpl()
|
||||
{
|
||||
if (server == null)
|
||||
{
|
||||
throw new TTransportException(TTransportException.ExceptionType.NotOpen, "No underlying server socket.");
|
||||
}
|
||||
try
|
||||
{
|
||||
TSocket result2 = null;
|
||||
TcpClient result = server.AcceptTcpClient();
|
||||
try
|
||||
{
|
||||
result2 = new TSocket(result);
|
||||
result2.Timeout = clientTimeout;
|
||||
if (useBufferedSockets)
|
||||
{
|
||||
TBufferedTransport result3 = new TBufferedTransport(result2);
|
||||
return result3;
|
||||
}
|
||||
else
|
||||
{
|
||||
return result2;
|
||||
}
|
||||
}
|
||||
catch (System.Exception)
|
||||
{
|
||||
// If a TSocket was successfully created, then let
|
||||
// it do proper cleanup of the TcpClient object.
|
||||
if (result2 != null)
|
||||
result2.Dispose();
|
||||
else // Otherwise, clean it up ourselves.
|
||||
((IDisposable)result).Dispose();
|
||||
throw;
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
throw new TTransportException(ex.ToString());
|
||||
}
|
||||
}
|
||||
|
||||
public override void Close()
|
||||
{
|
||||
if (server != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
server.Stop();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
throw new TTransportException("WARNING: Could not close server socket: " + ex);
|
||||
}
|
||||
server = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
public override void Close()
|
||||
{
|
||||
if (server != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
server.Stop();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
throw new TTransportException("WARNING: Could not close server socket: " + ex);
|
||||
}
|
||||
server = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -34,10 +34,11 @@ namespace Thrift.Transport
|
||||
public TTransport Accept()
|
||||
{
|
||||
TTransport transport = AcceptImpl();
|
||||
if (transport == null) {
|
||||
throw new TTransportException("accept() may not return NULL");
|
||||
if (transport == null)
|
||||
{
|
||||
throw new TTransportException("accept() may not return NULL");
|
||||
}
|
||||
return transport;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -112,7 +112,7 @@ namespace Thrift.Transport
|
||||
throw new TTransportException(TTransportException.ExceptionType.AlreadyOpen, "Socket already connected");
|
||||
}
|
||||
|
||||
if (String.IsNullOrEmpty(host))
|
||||
if (string.IsNullOrEmpty(host))
|
||||
{
|
||||
throw new TTransportException(TTransportException.ExceptionType.NotOpen, "Cannot open null host");
|
||||
}
|
||||
@ -282,9 +282,9 @@ namespace Thrift.Transport
|
||||
private volatile Boolean _isCompleted;
|
||||
private ManualResetEvent _evt;
|
||||
private readonly AsyncCallback _cbMethod;
|
||||
private readonly Object _state;
|
||||
private readonly object _state;
|
||||
|
||||
public FlushAsyncResult(AsyncCallback cbMethod, Object state)
|
||||
public FlushAsyncResult(AsyncCallback cbMethod, object state)
|
||||
{
|
||||
_cbMethod = cbMethod;
|
||||
_state = state;
|
||||
@ -314,7 +314,7 @@ namespace Thrift.Transport
|
||||
get { return _isCompleted; }
|
||||
}
|
||||
|
||||
private readonly Object _locker = new Object();
|
||||
private readonly object _locker = new object();
|
||||
|
||||
private ManualResetEvent GetEvtHandle()
|
||||
{
|
||||
@ -362,7 +362,7 @@ namespace Thrift.Transport
|
||||
}
|
||||
}
|
||||
|
||||
#region " IDisposable Support "
|
||||
#region " IDisposable Support "
|
||||
private bool _IsDisposed;
|
||||
|
||||
// IDisposable
|
||||
@ -385,7 +385,7 @@ namespace Thrift.Transport
|
||||
}
|
||||
_IsDisposed = true;
|
||||
}
|
||||
#endregion
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -26,216 +26,220 @@ using System.Net.Sockets;
|
||||
|
||||
namespace Thrift.Transport
|
||||
{
|
||||
public class TSocket : TStreamTransport
|
||||
{
|
||||
private TcpClient client = null;
|
||||
private string host = null;
|
||||
private int port = 0;
|
||||
private int timeout = 0;
|
||||
public class TSocket : TStreamTransport
|
||||
{
|
||||
private TcpClient client = null;
|
||||
private string host = null;
|
||||
private int port = 0;
|
||||
private int timeout = 0;
|
||||
|
||||
public TSocket(TcpClient client)
|
||||
{
|
||||
this.client = client;
|
||||
public TSocket(TcpClient client)
|
||||
{
|
||||
this.client = client;
|
||||
|
||||
if (IsOpen)
|
||||
{
|
||||
inputStream = client.GetStream();
|
||||
outputStream = client.GetStream();
|
||||
}
|
||||
}
|
||||
if (IsOpen)
|
||||
{
|
||||
inputStream = client.GetStream();
|
||||
outputStream = client.GetStream();
|
||||
}
|
||||
}
|
||||
|
||||
public TSocket(string host, int port)
|
||||
: this(host, port, 0)
|
||||
{
|
||||
}
|
||||
public TSocket(string host, int port)
|
||||
: this(host, port, 0)
|
||||
{
|
||||
}
|
||||
|
||||
public TSocket(string host, int port, int timeout)
|
||||
{
|
||||
this.host = host;
|
||||
this.port = port;
|
||||
this.timeout = timeout;
|
||||
public TSocket(string host, int port, int timeout)
|
||||
{
|
||||
this.host = host;
|
||||
this.port = port;
|
||||
this.timeout = timeout;
|
||||
|
||||
InitSocket();
|
||||
}
|
||||
InitSocket();
|
||||
}
|
||||
|
||||
private void InitSocket()
|
||||
{
|
||||
this.client = TSocketVersionizer.CreateTcpClient();
|
||||
this.client.ReceiveTimeout = client.SendTimeout = timeout;
|
||||
this.client.Client.NoDelay = true;
|
||||
}
|
||||
private void InitSocket()
|
||||
{
|
||||
this.client = TSocketVersionizer.CreateTcpClient();
|
||||
this.client.ReceiveTimeout = client.SendTimeout = timeout;
|
||||
this.client.Client.NoDelay = true;
|
||||
}
|
||||
|
||||
public int Timeout
|
||||
{
|
||||
set
|
||||
{
|
||||
client.ReceiveTimeout = client.SendTimeout = timeout = value;
|
||||
}
|
||||
}
|
||||
public int Timeout
|
||||
{
|
||||
set
|
||||
{
|
||||
client.ReceiveTimeout = client.SendTimeout = timeout = value;
|
||||
}
|
||||
}
|
||||
|
||||
public TcpClient TcpClient
|
||||
{
|
||||
get
|
||||
{
|
||||
return client;
|
||||
}
|
||||
}
|
||||
public TcpClient TcpClient
|
||||
{
|
||||
get
|
||||
{
|
||||
return client;
|
||||
}
|
||||
}
|
||||
|
||||
public string Host
|
||||
{
|
||||
get
|
||||
{
|
||||
return host;
|
||||
}
|
||||
}
|
||||
public string Host
|
||||
{
|
||||
get
|
||||
{
|
||||
return host;
|
||||
}
|
||||
}
|
||||
|
||||
public int Port
|
||||
{
|
||||
get
|
||||
{
|
||||
return port;
|
||||
}
|
||||
}
|
||||
public int Port
|
||||
{
|
||||
get
|
||||
{
|
||||
return port;
|
||||
}
|
||||
}
|
||||
|
||||
public override bool IsOpen
|
||||
{
|
||||
get
|
||||
{
|
||||
if (client == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
public override bool IsOpen
|
||||
{
|
||||
get
|
||||
{
|
||||
if (client == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return client.Connected;
|
||||
}
|
||||
}
|
||||
return client.Connected;
|
||||
}
|
||||
}
|
||||
|
||||
public override void Open()
|
||||
{
|
||||
if (IsOpen)
|
||||
{
|
||||
throw new TTransportException(TTransportException.ExceptionType.AlreadyOpen, "Socket already connected");
|
||||
}
|
||||
public override void Open()
|
||||
{
|
||||
if (IsOpen)
|
||||
{
|
||||
throw new TTransportException(TTransportException.ExceptionType.AlreadyOpen, "Socket already connected");
|
||||
}
|
||||
|
||||
if (String.IsNullOrEmpty(host))
|
||||
{
|
||||
throw new TTransportException(TTransportException.ExceptionType.NotOpen, "Cannot open null host");
|
||||
}
|
||||
if (string.IsNullOrEmpty(host))
|
||||
{
|
||||
throw new TTransportException(TTransportException.ExceptionType.NotOpen, "Cannot open null host");
|
||||
}
|
||||
|
||||
if (port <= 0)
|
||||
{
|
||||
throw new TTransportException(TTransportException.ExceptionType.NotOpen, "Cannot open without port");
|
||||
}
|
||||
if (port <= 0)
|
||||
{
|
||||
throw new TTransportException(TTransportException.ExceptionType.NotOpen, "Cannot open without port");
|
||||
}
|
||||
|
||||
if (client == null)
|
||||
{
|
||||
InitSocket();
|
||||
}
|
||||
if (client == null)
|
||||
{
|
||||
InitSocket();
|
||||
}
|
||||
|
||||
if( timeout == 0) // no timeout -> infinite
|
||||
{
|
||||
client.Connect(host, port);
|
||||
}
|
||||
else // we have a timeout -> use it
|
||||
{
|
||||
ConnectHelper hlp = new ConnectHelper(client);
|
||||
IAsyncResult asyncres = client.BeginConnect(host, port, new AsyncCallback(ConnectCallback), hlp);
|
||||
bool bConnected = asyncres.AsyncWaitHandle.WaitOne(timeout) && client.Connected;
|
||||
if (!bConnected)
|
||||
{
|
||||
lock (hlp.Mutex)
|
||||
{
|
||||
if( hlp.CallbackDone)
|
||||
{
|
||||
asyncres.AsyncWaitHandle.Close();
|
||||
client.Close();
|
||||
}
|
||||
else
|
||||
{
|
||||
hlp.DoCleanup = true;
|
||||
client = null;
|
||||
}
|
||||
}
|
||||
throw new TTransportException(TTransportException.ExceptionType.TimedOut, "Connect timed out");
|
||||
}
|
||||
}
|
||||
if (timeout == 0) // no timeout -> infinite
|
||||
{
|
||||
client.Connect(host, port);
|
||||
}
|
||||
else // we have a timeout -> use it
|
||||
{
|
||||
ConnectHelper hlp = new ConnectHelper(client);
|
||||
IAsyncResult asyncres = client.BeginConnect(host, port, new AsyncCallback(ConnectCallback), hlp);
|
||||
bool bConnected = asyncres.AsyncWaitHandle.WaitOne(timeout) && client.Connected;
|
||||
if (!bConnected)
|
||||
{
|
||||
lock (hlp.Mutex)
|
||||
{
|
||||
if (hlp.CallbackDone)
|
||||
{
|
||||
asyncres.AsyncWaitHandle.Close();
|
||||
client.Close();
|
||||
}
|
||||
else
|
||||
{
|
||||
hlp.DoCleanup = true;
|
||||
client = null;
|
||||
}
|
||||
}
|
||||
throw new TTransportException(TTransportException.ExceptionType.TimedOut, "Connect timed out");
|
||||
}
|
||||
}
|
||||
|
||||
inputStream = client.GetStream();
|
||||
outputStream = client.GetStream();
|
||||
}
|
||||
inputStream = client.GetStream();
|
||||
outputStream = client.GetStream();
|
||||
}
|
||||
|
||||
|
||||
static void ConnectCallback(IAsyncResult asyncres)
|
||||
{
|
||||
ConnectHelper hlp = asyncres.AsyncState as ConnectHelper;
|
||||
lock (hlp.Mutex)
|
||||
{
|
||||
hlp.CallbackDone = true;
|
||||
static void ConnectCallback(IAsyncResult asyncres)
|
||||
{
|
||||
ConnectHelper hlp = asyncres.AsyncState as ConnectHelper;
|
||||
lock (hlp.Mutex)
|
||||
{
|
||||
hlp.CallbackDone = true;
|
||||
|
||||
try
|
||||
{
|
||||
if( hlp.Client.Client != null)
|
||||
hlp.Client.EndConnect(asyncres);
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
// catch that away
|
||||
}
|
||||
try
|
||||
{
|
||||
if (hlp.Client.Client != null)
|
||||
hlp.Client.EndConnect(asyncres);
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
// catch that away
|
||||
}
|
||||
|
||||
if (hlp.DoCleanup)
|
||||
{
|
||||
try {
|
||||
asyncres.AsyncWaitHandle.Close();
|
||||
} catch (Exception) {}
|
||||
if (hlp.DoCleanup)
|
||||
{
|
||||
try
|
||||
{
|
||||
asyncres.AsyncWaitHandle.Close();
|
||||
}
|
||||
catch (Exception) { }
|
||||
|
||||
try {
|
||||
if (hlp.Client is IDisposable)
|
||||
((IDisposable)hlp.Client).Dispose();
|
||||
} catch (Exception) {}
|
||||
hlp.Client = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
try
|
||||
{
|
||||
if (hlp.Client is IDisposable)
|
||||
((IDisposable)hlp.Client).Dispose();
|
||||
}
|
||||
catch (Exception) { }
|
||||
hlp.Client = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private class ConnectHelper
|
||||
{
|
||||
public object Mutex = new object();
|
||||
public bool DoCleanup = false;
|
||||
public bool CallbackDone = false;
|
||||
public TcpClient Client;
|
||||
public ConnectHelper(TcpClient client)
|
||||
{
|
||||
Client = client;
|
||||
}
|
||||
}
|
||||
private class ConnectHelper
|
||||
{
|
||||
public object Mutex = new object();
|
||||
public bool DoCleanup = false;
|
||||
public bool CallbackDone = false;
|
||||
public TcpClient Client;
|
||||
public ConnectHelper(TcpClient client)
|
||||
{
|
||||
Client = client;
|
||||
}
|
||||
}
|
||||
|
||||
public override void Close()
|
||||
{
|
||||
base.Close();
|
||||
if (client != null)
|
||||
{
|
||||
client.Close();
|
||||
client = null;
|
||||
}
|
||||
}
|
||||
public override void Close()
|
||||
{
|
||||
base.Close();
|
||||
if (client != null)
|
||||
{
|
||||
client.Close();
|
||||
client = null;
|
||||
}
|
||||
}
|
||||
|
||||
#region " IDisposable Support "
|
||||
private bool _IsDisposed;
|
||||
#region " IDisposable Support "
|
||||
private bool _IsDisposed;
|
||||
|
||||
// IDisposable
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
if (!_IsDisposed)
|
||||
{
|
||||
if (disposing)
|
||||
{
|
||||
if (client != null)
|
||||
((IDisposable)client).Dispose();
|
||||
base.Dispose(disposing);
|
||||
}
|
||||
}
|
||||
_IsDisposed = true;
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
// IDisposable
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
if (!_IsDisposed)
|
||||
{
|
||||
if (disposing)
|
||||
{
|
||||
if (client != null)
|
||||
((IDisposable)client).Dispose();
|
||||
base.Dispose(disposing);
|
||||
}
|
||||
}
|
||||
_IsDisposed = true;
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
@ -1,4 +1,27 @@
|
||||
using System;
|
||||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*
|
||||
* Contains some contributions under the Thrift Software License.
|
||||
* Please see doc/old-thrift-license.txt in the Thrift distribution for
|
||||
* details.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Net.Sockets;
|
||||
@ -10,46 +33,46 @@ using System.Threading.Tasks;
|
||||
|
||||
namespace Thrift.Transport
|
||||
{
|
||||
/**
|
||||
* PropertyInfo for the DualMode property of the System.Net.Sockets.Socket class. Used to determine if the sockets are capable of
|
||||
* automatic IPv4 and IPv6 handling. If DualMode is present the sockets automatically handle IPv4 and IPv6 connections.
|
||||
* If the DualMode is not available the system configuration determines whether IPv4 or IPv6 is used.
|
||||
*/
|
||||
internal static class TSocketVersionizer
|
||||
{
|
||||
/*
|
||||
* Creates a TcpClient according to the capabilitites of the used framework
|
||||
*/
|
||||
internal static TcpClient CreateTcpClient()
|
||||
{
|
||||
TcpClient client = null;
|
||||
/// <summary>
|
||||
/// PropertyInfo for the DualMode property of the System.Net.Sockets.Socket class. Used to determine if the sockets are capable of
|
||||
/// automatic IPv4 and IPv6 handling. If DualMode is present the sockets automatically handle IPv4 and IPv6 connections.
|
||||
/// If the DualMode is not available the system configuration determines whether IPv4 or IPv6 is used.
|
||||
/// </summary>
|
||||
internal static class TSocketVersionizer
|
||||
{
|
||||
/// <summary>
|
||||
/// Creates a TcpClient according to the capabilitites of the used framework
|
||||
/// </summary>
|
||||
internal static TcpClient CreateTcpClient()
|
||||
{
|
||||
TcpClient client = null;
|
||||
|
||||
#if NET45
|
||||
client = new TcpClient(AddressFamily.InterNetworkV6);
|
||||
client.Client.DualMode = true;
|
||||
client = new TcpClient(AddressFamily.InterNetworkV6);
|
||||
client.Client.DualMode = true;
|
||||
#else
|
||||
client = new TcpClient(AddressFamily.InterNetwork);
|
||||
#endif
|
||||
|
||||
return client;
|
||||
}
|
||||
return client;
|
||||
}
|
||||
|
||||
/*
|
||||
* Creates a TcpListener according to the capabilitites of the used framework
|
||||
*/
|
||||
internal static TcpListener CreateTcpListener(Int32 port)
|
||||
{
|
||||
TcpListener listener = null;
|
||||
/// <summary>
|
||||
/// Creates a TcpListener according to the capabilitites of the used framework.
|
||||
/// </summary>
|
||||
internal static TcpListener CreateTcpListener(Int32 port)
|
||||
{
|
||||
TcpListener listener = null;
|
||||
|
||||
#if NET45
|
||||
listener = new TcpListener(System.Net.IPAddress.IPv6Any, port);
|
||||
listener.Server.DualMode = true;
|
||||
listener = new TcpListener(System.Net.IPAddress.IPv6Any, port);
|
||||
listener.Server.DualMode = true;
|
||||
#else
|
||||
|
||||
listener = new TcpListener(System.Net.IPAddress.Any, port);
|
||||
listener = new TcpListener(System.Net.IPAddress.Any, port);
|
||||
#endif
|
||||
|
||||
return listener;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -105,24 +105,24 @@ namespace Thrift.Transport
|
||||
}
|
||||
|
||||
|
||||
#region " IDisposable Support "
|
||||
private bool _IsDisposed;
|
||||
#region " IDisposable Support "
|
||||
private bool _IsDisposed;
|
||||
|
||||
// IDisposable
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
if (!_IsDisposed)
|
||||
{
|
||||
if (disposing)
|
||||
// IDisposable
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
if (InputStream != null)
|
||||
InputStream.Dispose();
|
||||
if (OutputStream != null)
|
||||
OutputStream.Dispose();
|
||||
if (!_IsDisposed)
|
||||
{
|
||||
if (disposing)
|
||||
{
|
||||
if (InputStream != null)
|
||||
InputStream.Dispose();
|
||||
if (OutputStream != null)
|
||||
OutputStream.Dispose();
|
||||
}
|
||||
}
|
||||
_IsDisposed = true;
|
||||
}
|
||||
}
|
||||
_IsDisposed = true;
|
||||
#endregion
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
@ -76,7 +76,7 @@ namespace Thrift.Transport
|
||||
/// <param name="port">The port where the server runs.</param>
|
||||
/// <param name="certificate">The certificate object.</param>
|
||||
public TTLSServerSocket(int port, X509Certificate2 certificate)
|
||||
: this(port, 0, certificate)
|
||||
: this(port, 0, certificate)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -263,7 +263,7 @@ namespace Thrift.Transport
|
||||
/// <param name="sender">The sender-object.</param>
|
||||
/// <param name="certificate">The used certificate.</param>
|
||||
/// <param name="chain">The certificate chain.</param>
|
||||
/// <param name="sslPolicyErrors">An enum, which lists all the errors from the .NET certificate check.</param>
|
||||
/// <param name="sslValidationErrors">An enum, which lists all the errors from the .NET certificate check.</param>
|
||||
/// <returns></returns>
|
||||
private bool DefaultCertificateValidator(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslValidationErrors)
|
||||
{
|
||||
@ -280,7 +280,7 @@ namespace Thrift.Transport
|
||||
throw new TTransportException(TTransportException.ExceptionType.AlreadyOpen, "Socket already connected");
|
||||
}
|
||||
|
||||
if (String.IsNullOrEmpty(host))
|
||||
if (string.IsNullOrEmpty(host))
|
||||
{
|
||||
throw new TTransportException(TTransportException.ExceptionType.NotOpen, "Cannot open null host");
|
||||
}
|
||||
@ -307,7 +307,7 @@ namespace Thrift.Transport
|
||||
{
|
||||
RemoteCertificateValidationCallback validator = this.certValidator ?? DefaultCertificateValidator;
|
||||
|
||||
if( this.localCertificateSelectionCallback != null)
|
||||
if (this.localCertificateSelectionCallback != null)
|
||||
{
|
||||
this.secureStream = new SslStream(
|
||||
this.client.GetStream(),
|
||||
@ -335,7 +335,7 @@ namespace Thrift.Transport
|
||||
else
|
||||
{
|
||||
// Client authentication
|
||||
X509CertificateCollection certs = certificate != null ? new X509CertificateCollection { certificate } : new X509CertificateCollection();
|
||||
X509CertificateCollection certs = certificate != null ? new X509CertificateCollection { certificate } : new X509CertificateCollection();
|
||||
this.secureStream.AuthenticateAsClient(host, certs, sslProtocols, true);
|
||||
}
|
||||
}
|
||||
|
@ -53,7 +53,7 @@ namespace Thrift.Transport
|
||||
if (bytes == 0)
|
||||
return false;
|
||||
}
|
||||
catch( IOException)
|
||||
catch (IOException)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
@ -108,7 +108,7 @@ namespace Thrift.Transport
|
||||
|
||||
public virtual void Write(byte[] buf)
|
||||
{
|
||||
Write (buf, 0, buf.Length);
|
||||
Write(buf, 0, buf.Length);
|
||||
}
|
||||
|
||||
public abstract void Write(byte[] buf, int off, int len);
|
||||
|
@ -26,7 +26,7 @@ using System;
|
||||
namespace Thrift.Transport
|
||||
{
|
||||
/// <summary>
|
||||
/// From Mark Slee & Aditya Agarwal of Facebook:
|
||||
/// From Mark Slee & Aditya Agarwal of Facebook:
|
||||
/// Factory class used to create wrapped instance of Transports.
|
||||
/// This is used primarily in servers, which get Transports from
|
||||
/// a ServerTransport and then may want to mutate them (i.e. create
|
||||
|
Loading…
Reference in New Issue
Block a user