Files
spark/src/DataStreamSuite/DataStream/Primitives/Union/MutableAppendStream.cs
T

290 lines
9.0 KiB
C#

using System;
using System.Collections.Generic;
using mbts;
namespace BCG
{
internal class MutableAppendTable : IBlueRowCollection
{
private class MyRow : IBlueRow
{
private IBlueRow myRow;
private int myID;
public MyRow(IBlueRow r, int id)
{
myRow = r;
myID = id;
}
#region IBlueRow Members
public IBlueTableSchema schema { get { return myRow.schema; } }
public object this[int index]
{
get
{
if (myRow.schema[index].colName == "id")
return myID;
else
return myRow[index];
}
}
public object this[string colName] { get { return colName == "id" ? (object)myID : myRow[colName]; } }
#endregion
#region IDictionary Members
public void Add(object key, object value) { throw new Exception("Row is read only."); }
public void Clear() { throw new Exception("Row is read only."); }
public bool Contains(object key) { return myRow.Contains(key); }
public System.Collections.IDictionaryEnumerator GetEnumerator() { return new BlueRowDictionaryEnumerator(this); }
public bool IsFixedSize { get { return true; } }
public bool IsReadOnly { get { return true; } }
public System.Collections.ICollection Keys { get { return myRow.Keys; } }
public void Remove(object key) {throw new Exception("The method or operation is not implemented.");}
public System.Collections.ICollection Values
{
get
{
object[] vals = new object[myRow.Count];
CopyTo(vals, 0);
return vals;
}
}
public object this[object key]
{
get { return key is string ? this[key as string] : this[(int)key]; }
set { throw new Exception("The method or operation is not implemented."); }
}
#endregion
#region ICollection Members
public void CopyTo(Array array, int index)
{
myRow.CopyTo(array, index);
array.SetValue(myID, index + myRow.schema["id"].colNo);
}
public int Count { get { return myRow.Count; } }
public bool IsSynchronized { get { return myRow.IsSynchronized; } }
public object SyncRoot { get { return myRow.SyncRoot; } }
#endregion
#region IEnumerable Members
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
{ return new BlueRowEnumerator(this); }
#endregion
}
private BlueTable myRows;
private int myID = 0;
/// <summary>
/// maps the table no to a dictionary containing the
/// local IDs to a row in the final big table
/// </summary>
private Dictionary<int, Dictionary<int, IBlueRow>> myIDMap = new Dictionary<int, Dictionary<int, IBlueRow>>();
public MutableAppendTable(IBlueTableSchema schema) { myRows = new BlueTable(schema); }
public IBlueRow addRow(IBlueRow r, int tableNo)
{
if (!myIDMap.ContainsKey(tableNo))
myIDMap.Add(tableNo, new Dictionary<int, IBlueRow>());
IBlueRow nr = new MyRow(r, myID++); // BlueDataUtility.getNewReplacedRow(r, myID++, "id");
myRows.addRow(nr);
myIDMap[tableNo].Add((int)r["id"], nr);
return nr;
}
public IBlueRow removeRow(IBlueRow r, int tableNo)
{
IBlueRow dr = myIDMap[tableNo][(int)r["id"]];
myRows.deleteRow(dr);
myIDMap[tableNo].Remove((int)r["id"]);
return dr;
}
public IBlueRowCollection removeTable(int tableNo)
{
if (!myIDMap.ContainsKey(tableNo))
return null;
else
{
BlueTable rv = new BlueTable(myRows.schema);
foreach (IBlueRow r in myIDMap[tableNo].Values)
rv.addRow(r);
myRows.deleteRows(rv);
myIDMap.Remove(tableNo);
return rv;
}
}
public void clear()
{
myRows.clear();
myIDMap.Clear();
}
#region IBlueRowCollection Members
public IBlueRow this[int id] { get { return myRows[id]; } }
public IBlueTableSchema schema { get { return myRows.schema; } }
public bool containsID(int id) {return myRows.containsID(id);}
#endregion
#region ICollection Members
public void CopyTo(Array array, int index) { myRows.CopyTo(array, index); }
public int Count { get { return myRows.Count; } }
public bool IsSynchronized { get { return myRows.IsSynchronized; } }
public object SyncRoot { get { return myRows.SyncRoot; } }
#endregion
#region IEnumerable Members
public System.Collections.IEnumerator GetEnumerator() {return myRows.GetEnumerator();}
#endregion
}
/// <summary>
/// MutableStream can append multiple streams
/// as well as give the user the flexibility
/// to append (or remove) more streams at
/// runtime
/// </summary>
public class MutableAppendStream : ViewStream
{
private bool mySubscriptionActive = false;
private MutableAppendTable myTable;
private int myMovingIndex;
private Dictionary<int, Pair<ViewStream, ViewStream>> myStreamIndex = new Dictionary<int, Pair<ViewStream, ViewStream>>();
private bool _allign_col_orders = true;
public MutableAppendStream(params ViewStream[] streams)
: this(new List<ViewStream>(streams))
{ }
public MutableAppendStream(bool allign_col_order, params ViewStream[] streams)
: this(allign_col_order, new List<ViewStream>(streams))
{ }
public MutableAppendStream(ICollection<ViewStream> streams)
: this(true, streams)
{ }
public MutableAppendStream(bool allign_col_orders, ICollection<ViewStream> streams)
{
_allign_col_orders = allign_col_orders;
foreach (ViewStream vs in streams)
{
myMovingIndex++;
ViewStream pj = new ChangeTableNameStream(vs, myMovingIndex.ToString());
if (_allign_col_orders)
pj = new ProjectStream(pj, "!");
myStreamIndex.Add(myMovingIndex, new Pair<ViewStream, ViewStream>(vs, pj));
}
}
public void addStream(ViewStream vs)
{
myMovingIndex++;
///the change name is done to identify the callbacks, and the project to
///make all the schemas col orders the same
ViewStream pj = new ChangeTableNameStream(vs, myMovingIndex.ToString());
if (_allign_col_orders)
pj = new ProjectStream(pj, "!");
myStreamIndex.Add(myMovingIndex, new Pair<ViewStream, ViewStream>(vs, pj));
if (mySubscriptionActive)
pj.onChange += myHandleStreamChanges;
}
public void removeStream(ViewStream vs)
{
int index = -1;
foreach (KeyValuePair<int, Pair<ViewStream, ViewStream>> p in myStreamIndex)
{
if (p.Value.first == vs)
{
index = p.Key;
if (mySubscriptionActive)
{
p.Value.second.onChange -= myHandleStreamChanges;
if (myTable != null)
{
IBlueRowCollection delRows = myTable.removeTable(p.Key);
if (delRows != null)
myFireEvent(new DataPacket(myTable, new BlueTable(myTable.schema), delRows));
}
}
break;
}
if (index > 0)
myStreamIndex.Remove(index);
}
}
protected override void myOnFirstSubscriber()
{
mySubscriptionActive = true;
foreach (KeyValuePair<int, Pair<ViewStream, ViewStream>> p in myStreamIndex)
p.Value.second.onChange += myHandleStreamChanges;
}
protected override void myOnLastSubscriber()
{
mySubscriptionActive = false;
foreach (KeyValuePair<int, Pair<ViewStream, ViewStream>> p in myStreamIndex)
p.Value.second.onChange -= myHandleStreamChanges;
if (myTable != null)
myTable.clear();
}
private void myHandleStreamChanges(object newValue)
{
DataPacket dp = newValue as DataPacket;
myTable = myTable ?? new MutableAppendTable(new BlueTableSchema("MutableAppend", dp.schema.columnInfo));
BlueTable adds = new BlueTable(myTable.schema),
dels = new BlueTable(myTable.schema);
int index = Int32.Parse(dp.schema.tableName);
foreach (IBlueRow r in dp.deletedRows)
{
IBlueRow dr = myTable.removeRow(r, index);
dels.addRow(dr);
}
foreach (IBlueRow r in dp.addedRows)
{
IBlueRow nr = myTable.addRow(r, index);
adds.addRow(nr);
}
myFireEvent(new DataPacket(myTable, adds, dels));
}
}
}