You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
442 lines
12 KiB
442 lines
12 KiB
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;
|
|
}
|
|
}
|
|
}
|