|
|
using System; using System.Collections; using System.Collections.Specialized; using System.ComponentModel; using System.Data; using System.Data.SqlClient; using System.IO; using System.Text; using System.Xml; using System.Xml.Serialization; using UDDI; using UDDI.API; using UDDI.API.Binding; using UDDI.API.Business; using UDDI.API.Service; using UDDI.API.ServiceType; using UDDI.Diagnostics;
namespace UDDI.Replication { [XmlRoot( "changeRecords", Namespace=UDDI.Replication.Constants.Namespace )] public class ChangeRecordDetail { [XmlElement( "changeRecord" )] public ChangeRecordCollection ChangeRecords = new ChangeRecordCollection();
public ChangeRecordDetail() { } }
[XmlRoot( "highWaterMarks", Namespace=UDDI.Replication.Constants.Namespace )] public class HighWaterMarkDetail { [XmlElement( "highWaterMark" )] public ChangeRecordVectorCollection HighWaterMarks = new ChangeRecordVectorCollection(); }
[XmlRoot( "get_changeRecords", Namespace=UDDI.Replication.Constants.Namespace )] public class GetChangeRecords { //
// Element: requestingNode
//
[XmlElement( "requestingNode" )] public string RequestingNode;
//
// Element: changesAlreadySeen
//
private ChangeRecordVectorCollection changesAlreadySeen;
[XmlArray( "changesAlreadySeen" ), XmlArrayItem( "highWaterMark" )] public ChangeRecordVectorCollection ChangesAlreadySeen { get { if( null == changesAlreadySeen ) changesAlreadySeen = new ChangeRecordVectorCollection();
return changesAlreadySeen; }
set { changesAlreadySeen = value; } }
//
// Element: responseLimitCount
//
private int responseLimitCount = -1; [XmlElement( "responseLimitCount" ), DefaultValue( -1 )] public int ResponseLimitCount { get { return responseLimitCount; } set { responseLimitCount = value; } }
//
// Element: responseLimitVector
//
private ChangeRecordVectorCollection responseLimitVector;
[XmlArray( "responseLimitVector" ), XmlArrayItem( "highWaterMark" )] public ChangeRecordVectorCollection ResponseLimitVectorSerialize { get { if( -1 != ResponseLimitCount || Utility.CollectionEmpty( responseLimitVector ) ) return null;
return responseLimitVector; }
set { responseLimitVector = value; } }
[XmlIgnore] public ChangeRecordVectorCollection ResponseLimitVector { get { if( null == responseLimitVector ) responseLimitVector = new ChangeRecordVectorCollection();
return responseLimitVector; } }
/// ****************************************************************
/// public Get
/// ----------------------------------------------------------------
/// <summary>
/// </summary>
/// ****************************************************************
///
public ChangeRecordDetail Get() { Debug.VerifySetting( "OperatorKey" );
ChangeRecordDetail detail = new ChangeRecordDetail();
try { //
// Get the list of known operators.
//
StringCollection operators = new StringCollection();
SqlStoredProcedureAccessor sp = new SqlStoredProcedureAccessor();
sp.ProcedureName = "net_operators_get"; SqlDataReaderAccessor reader = sp.ExecuteReader();
try { while( reader.Read() ) { operators.Add( reader.GetGuidString( "operatorKey" ) ); } } finally { reader.Close(); }
//
// Set the search criteria for change records.
//
foreach( string operatorKey in operators ) { long startUSN; long stopUSN;
startUSN = 0; foreach( ChangeRecordVector mark in ChangesAlreadySeen ) { if( 0 == String.Compare( operatorKey, mark.NodeID, true ) ) { startUSN = mark.OriginatingUSN + 1; break; } }
stopUSN = System.Int64.MaxValue; foreach( ChangeRecordVector mark in ResponseLimitVector ) { if( 0 == String.Compare( operatorKey, mark.NodeID, true ) ) { stopUSN = mark.OriginatingUSN; break; } }
FindChangeRecords.SetRange( operatorKey, startUSN, stopUSN ); }
//
// Retrieve the change records.
//
int limit = Config.GetInt( "Replication.ResponseLimitCountDefault" );
if( ResponseLimitCount >= 0 && ResponseLimitCount <= limit ) limit = ResponseLimitCount; reader = FindChangeRecords.RetrieveResults( limit );
try { while( reader.Read() ) { XmlSerializer serializer = null;
switch( (ChangeRecordPayloadType)reader.GetShort( "changeTypeID" ) ) { case ChangeRecordPayloadType.ChangeRecordNull: serializer = XmlSerializerManager.GetSerializer( typeof( ChangeRecordNull ) ); break;
case ChangeRecordPayloadType.ChangeRecordNewData: serializer = XmlSerializerManager.GetSerializer( typeof( ChangeRecordNewData ) ); break;
case ChangeRecordPayloadType.ChangeRecordDelete: serializer = XmlSerializerManager.GetSerializer( typeof( ChangeRecordDelete ) ); break;
case ChangeRecordPayloadType.ChangeRecordPublisherAssertion: serializer = XmlSerializerManager.GetSerializer( typeof( ChangeRecordPublisherAssertion ) ); break;
case ChangeRecordPayloadType.ChangeRecordHide: serializer = XmlSerializerManager.GetSerializer( typeof( ChangeRecordHide ) ); break;
case ChangeRecordPayloadType.ChangeRecordDeleteAssertion: serializer = XmlSerializerManager.GetSerializer( typeof( ChangeRecordDeleteAssertion ) ); break;
case ChangeRecordPayloadType.ChangeRecordAcknowledgement: serializer = XmlSerializerManager.GetSerializer( typeof( ChangeRecordAcknowledgement ) ); break;
case ChangeRecordPayloadType.ChangeRecordCorrection: serializer = XmlSerializerManager.GetSerializer( typeof( ChangeRecordCorrection ) ); break; }
StringReader stringReader = new StringReader( reader.GetString( "changeData" ) ); try { ChangeRecord changeRecord = new ChangeRecord(); changeRecord.AcknowledgementRequested = ( reader.GetInt( "flag" ) & (int)ChangeRecordFlags.AcknowledgementRequested ) > 0; changeRecord.ChangeID.NodeID = reader.GetString( "OperatorKey" ); changeRecord.ChangeID.OriginatingUSN = reader.GetLong( "USN" ); ChangeRecordBase changeRecordBase = ( ChangeRecordBase ) serializer.Deserialize( stringReader ); if( changeRecordBase is ChangeRecordCorrection ) { //
// The query to find change records will do correction 'fixups'. That is, the changeData of this
// change record will be replaced with the changeData from the correction. The problem with this is
// that the original change data will now look like a correction. To distinguish these types of
// change records, we look to see if the OriginatingUSN's match. If the OriginatingUSN's match,
// we want they payload of the change record in this correction. This payload will contain the
// corrected data that we want.
//
ChangeRecordCorrection changeRecordCorrection = ( ChangeRecordCorrection ) changeRecordBase; if( changeRecordCorrection.ChangeRecord.ChangeID.OriginatingUSN == changeRecord.ChangeID.OriginatingUSN ) { changeRecordBase = changeRecordCorrection.ChangeRecord.Payload; } } changeRecord.Payload = changeRecordBase; detail.ChangeRecords.Add( changeRecord ); } finally { stringReader.Close(); } } } finally { reader.Close(); } } catch( Exception e ) { Debug.OperatorMessage( SeverityType.Error, CategoryType.Replication, OperatorMessageType.None, "Could not retrieve change records:\r\n" + e.ToString() ); FindChangeRecords.CleanUp(); throw; }
return detail; }
public override string ToString() { XmlSerializer serializer = new XmlSerializer( GetType() ); UTF8EncodedStringWriter stringWriter = new UTF8EncodedStringWriter();
try { serializer.Serialize( stringWriter, this ); return stringWriter.ToString(); } finally { stringWriter.Close(); } } }
public class FindChangeRecords { public static int SetRange( string operatorKey, long startUSN, long stopUSN ) { SqlStoredProcedureAccessor sp = new SqlStoredProcedureAccessor();
sp.ProcedureName = "net_find_changeRecords";
sp.Parameters.Add( "@contextID", SqlDbType.UniqueIdentifier ); sp.Parameters.Add( "@operatorKey", SqlDbType.UniqueIdentifier ); sp.Parameters.Add( "@startUSN", SqlDbType.BigInt ); sp.Parameters.Add( "@stopUSN", SqlDbType.BigInt ); sp.Parameters.Add( "@rows", SqlDbType.Int, ParameterDirection.Output ); sp.Parameters.SetGuid( "@contextID", Context.ContextID ); sp.Parameters.SetGuidFromString( "@operatorKey", operatorKey ); sp.Parameters.SetLong( "@startUSN", startUSN ); sp.Parameters.SetLong( "@stopUSN", stopUSN );
sp.ExecuteNonQuery();
return sp.Parameters.GetInt( "@rows" ); }
public static SqlDataReaderAccessor RetrieveResults( int maxRows ) { SqlStoredProcedureAccessor sp = new SqlStoredProcedureAccessor();
sp.ProcedureName = "net_find_changeRecords_commit";
sp.Parameters.Add( "@contextID", SqlDbType.UniqueIdentifier ); sp.Parameters.Add( "@responseLimitCount", SqlDbType.Int );
sp.Parameters.SetGuid( "@contextID", Context.ContextID ); sp.Parameters.SetInt( "@responseLimitCount", maxRows ); SqlDataReaderAccessor reader = sp.ExecuteReader();
return reader; }
public static void CleanUp() { SqlStoredProcedureAccessor sp = new SqlStoredProcedureAccessor();
sp.ProcedureName = "net_find_changeRecords_cleanup";
sp.Parameters.Add( "@contextID", SqlDbType.UniqueIdentifier ); sp.Parameters.SetGuid( "@contextID", Context.ContextID );
sp.ExecuteNonQuery(); } }
[XmlRoot( "notify_changeRecordsAvailable", Namespace=UDDI.Replication.Constants.Namespace )] public class NotifyChangeRecordsAvailable { //
// Element: notifyingNode
//
[XmlElement( "notifyingNode" )] public string NotifyingNode;
//
// Element: changesAvailable
//
private ChangeRecordVectorCollection highWaterMarks;
[XmlArray( "changesAvailable" ), XmlArrayItem( "highWaterMark" )] public ChangeRecordVectorCollection HighWaterMarks { get { if( null == highWaterMarks ) highWaterMarks = new ChangeRecordVectorCollection();
return highWaterMarks; }
set { highWaterMarks = new ChangeRecordVectorCollection(); } }
public void Notify() { ReplicationResult result = new ReplicationResult();
result.OperatorNodeID = NotifyingNode; result.Description = null; result.LastNodeID = null; result.LastUSN = 0; result.LastChange = DateTime.Now.Ticks; result.ReplicationStatus = ReplicationStatus.Notify; result.Save(); } }
[XmlRoot( "do_ping", Namespace=UDDI.Replication.Constants.Namespace )] public class DoPing { public string Ping() { Debug.VerifySetting( "OperatorKey" );
return Config.GetString( "OperatorKey" ); } }
[XmlRoot( "get_highWaterMarks", Namespace=UDDI.Replication.Constants.Namespace )] public class GetHighWaterMarks { public HighWaterMarkDetail Get() { HighWaterMarkDetail detail = new HighWaterMarkDetail();
SqlStoredProcedureAccessor sp = new SqlStoredProcedureAccessor();
sp.ProcedureName = "net_highWaterMarks_get";
SqlDataReaderAccessor reader = sp.ExecuteReader();
try { while( reader.Read() ) { detail.HighWaterMarks.Add( reader.GetString( "operatorKey" ), reader.GetLong( "USN" ) ); } } finally { reader.Close(); }
return detail; } } }
|