package com.linkedin.databus2.producers.gg;
/*
*
* Copyright 2013 LinkedIn Corp. All rights reserved
*
* Licensed 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.
*
*/
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.Map.Entry;
import com.linkedin.databus2.ggParser.XmlStateMachine.ColumnsState;
import com.linkedin.databus2.ggParser.XmlStateMachine.DbUpdateState;
import com.linkedin.databus2.ggParser.XmlStateMachine.DbUpdateState.DBUpdateImage;
import com.linkedin.databus2.ggParser.XmlStateMachine.TransactionState;
import com.linkedin.databus2.ggParser.XmlStateMachine.TransactionState.PerSourceTransactionalUpdate;
public class DBUpdatesMergeUtils
{
/**
* Merge 2 list of DBUpdates and return the merged list. The ordering of
* PerSourceTransactionalUpdates ( in the order of SourceIds) is guaranteed in the
* output list If two events have the same sourceId and same key, the event present in
* newDbUpdates is the winner and will be present in the output
*
* @param newTxnDbUpdates
* : New DbUpdates list to be merged
* @param oldDbUpdates
* : Old DbUpdates list to be merged.
* @return Merged list
*/
public static List<TransactionState.PerSourceTransactionalUpdate> mergeTransactionData(List<TransactionState.PerSourceTransactionalUpdate> newTxnDbUpdates,
List<TransactionState.PerSourceTransactionalUpdate> oldDbUpdates)
{
if ((null == oldDbUpdates) && (null == newTxnDbUpdates))
{
return null;
}
Map<Integer, TransactionState.PerSourceTransactionalUpdate> combinedTxnDbUpdatesMap =
new HashMap<Integer, TransactionState.PerSourceTransactionalUpdate>();
if (null != oldDbUpdates)
{
for (TransactionState.PerSourceTransactionalUpdate dbu : oldDbUpdates)
{
combinedTxnDbUpdatesMap.put(dbu.getSourceId(), dbu);
}
}
if (null != newTxnDbUpdates)
{
for (TransactionState.PerSourceTransactionalUpdate dbu : newTxnDbUpdates)
{
TransactionState.PerSourceTransactionalUpdate oldDbu =
combinedTxnDbUpdatesMap.get(dbu.getSourceId());
if (null == oldDbu)
{
// No old Entry present. We can just copy the newDbUpdate's entry to
// combinedTxnDbbUpdatesMap
combinedTxnDbUpdatesMap.put(dbu.getSourceId(), dbu);
}
else
{
// Do the merge
Set<DbUpdateState.DBUpdateImage> mergeUpdateImages =
mergeDbUpdates(dbu.getDbUpdatesSet(), oldDbu.getDbUpdatesSet());
TransactionState.PerSourceTransactionalUpdate mergedPerSourceTxnUpdate =
new TransactionState.PerSourceTransactionalUpdate(dbu.getSourceId(),
mergeUpdateImages);
combinedTxnDbUpdatesMap.put(dbu.getSourceId(), mergedPerSourceTxnUpdate);
}
}
}
List<PerSourceTransactionalUpdate> sourceTransactionalUpdates =
new ArrayList<PerSourceTransactionalUpdate>(combinedTxnDbUpdatesMap.size());
for (Entry<Integer, PerSourceTransactionalUpdate> entry : combinedTxnDbUpdatesMap.entrySet())
{
sourceTransactionalUpdates.add(entry.getValue());
}
// Sort by source id to make sure the window has event batches sorted by sourceIds
Collections.sort(sourceTransactionalUpdates);
return sourceTransactionalUpdates;
}
private static Set<DbUpdateState.DBUpdateImage> mergeDbUpdates(Set<DbUpdateState.DBUpdateImage> newDbUpdateImage,
Set<DbUpdateState.DBUpdateImage> oldDbUpdateImage)
{
Map<List<ColumnsState.KeyPair>, DbUpdateState.DBUpdateImage> result =
new HashMap<List<ColumnsState.KeyPair>, DbUpdateState.DBUpdateImage>();
for (DBUpdateImage dbi : oldDbUpdateImage)
{
result.put(dbi.getKeyPairs(), dbi);
}
// If duplicate entries are present, they will be overwritten with entries from
// newDbUpdateImage
for (DBUpdateImage dbi : newDbUpdateImage)
{
result.put(dbi.getKeyPairs(), dbi);
}
return new HashSet<DbUpdateState.DBUpdateImage>(result.values());
}
}