UPDATE TABLE is not supported temporarily XD
This commit is contained in:
+5
-1
@@ -2,12 +2,16 @@
|
|||||||
"cassandra_addresses": ["127.0.0.1"],
|
"cassandra_addresses": ["127.0.0.1"],
|
||||||
"cassandra_port": 9042,
|
"cassandra_port": 9042,
|
||||||
"cassandra_keyspace": "distributedunionfind",
|
"cassandra_keyspace": "distributedunionfind",
|
||||||
|
"cassandra_catalog": "DUFCatalog",
|
||||||
|
|
||||||
"setup_db_dir": "config/db",
|
"setup_db_dir": "config/db",
|
||||||
"setup_tables_dir": "config/db/tables",
|
"setup_tables_dir": "config/db/tables",
|
||||||
"setup_keyspace_dir": "config/db/keyspace",
|
"setup_keyspace_dir": "config/db/keyspace",
|
||||||
|
|
||||||
"tx_table_name": "transactions",
|
"tx_table_name": "transactions",
|
||||||
"clusters_table_name": "clusters"
|
"clusters_table_name": "clusters",
|
||||||
|
|
||||||
|
"spark_master": "spark://osboxes:7077",
|
||||||
|
|
||||||
|
"debug": true
|
||||||
}
|
}
|
||||||
+149
-38
@@ -1,44 +1,89 @@
|
|||||||
from gc import collect
|
from gc import collect
|
||||||
from sqlite3 import Row
|
import json
|
||||||
from typing import Iterable
|
|
||||||
from operator import add
|
|
||||||
|
|
||||||
from pyspark.sql import SparkSession
|
from sqlite3 import Row
|
||||||
|
from typing import Iterable, List
|
||||||
|
|
||||||
|
from pyspark import RDD
|
||||||
|
|
||||||
|
from pyspark.sql import SparkSession, DataFrame, Row
|
||||||
from pyspark.sql import functions as F
|
from pyspark.sql import functions as F
|
||||||
|
|
||||||
|
config = json.load(open("./settings.json"))
|
||||||
|
debug = config['debug']
|
||||||
|
|
||||||
|
class Master:
|
||||||
|
spark: SparkSession
|
||||||
|
CLUSTERS_TABLE: str
|
||||||
|
TX_TABLE: str
|
||||||
|
|
||||||
spark = SparkSession.builder \
|
def __init__(self, config):
|
||||||
|
self.spark = self.makeSparkContext(config)
|
||||||
|
self.config = config
|
||||||
|
self.CLUSTERS_TABLE = f"{config['cassandra_catalog']}.{config['cassandra_keyspace']}.{config['clusters_table_name']}"
|
||||||
|
self.TX_TABLE = f"{config['cassandra_catalog']}.{config['cassandra_keyspace']}.{config['tx_table_name']}"
|
||||||
|
|
||||||
|
def makeSparkContext(self,config) -> SparkSession:
|
||||||
|
return SparkSession.builder \
|
||||||
.appName('SparkCassandraApp') \
|
.appName('SparkCassandraApp') \
|
||||||
.config('spark.cassandra.connection.host', 'localhost') \
|
.config('spark.cassandra.connection.host', ','.join(config['cassandra_addresses'])) \
|
||||||
.config('spark.cassandra.connection.port', '9042') \
|
.config('spark.cassandra.connection.port', config["cassandra_port"]) \
|
||||||
.config('spark.cassandra.output.consistency.level', 'ONE') \
|
.config('spark.cassandra.output.consistency.level', 'ONE') \
|
||||||
.config("spark.sql.extensions", "com.datastax.spark.connector.CassandraSparkExtensions") \
|
.config("spark.sql.extensions", "com.datastax.spark.connector.CassandraSparkExtensions") \
|
||||||
|
.config(f"spark.sql.catalog.{config['cassandra_catalog']}", "com.datastax.spark.connector.datasource.CassandraCatalog") \
|
||||||
.config('directJoinSetting', 'on') \
|
.config('directJoinSetting', 'on') \
|
||||||
.master('spark://osboxes:7077') \
|
.master(config['spark_master']) \
|
||||||
.getOrCreate()
|
.getOrCreate()
|
||||||
|
|
||||||
spark.conf.set("spark.sql.catalog.myCatalog",
|
def group_tx_addrs(self) -> DataFrame:
|
||||||
"com.datastax.spark.connector.datasource.CassandraCatalog")
|
return self.spark \
|
||||||
|
.read \
|
||||||
|
.table(self.TX_TABLE) \
|
||||||
tx_addr_groups = spark.read.table("myCatalog.distributedunionfind.transactions") \
|
|
||||||
.groupBy("tx_id") \
|
.groupBy("tx_id") \
|
||||||
.agg(F.collect_set('address').alias('addresses')) \
|
.agg(F.collect_set('address').alias('addresses'))
|
||||||
.toLocalIterator()
|
|
||||||
|
|
||||||
def insertCluster (row):
|
def group_cluster_addrs(self) -> DataFrame:
|
||||||
addrs: Iterable[str] = row['addresses']
|
return self.spark \
|
||||||
df = spark.createDataFrame(map(lambda addr: (addr, addrs[0]), addrs), schema=['address', 'parent'])
|
.read \
|
||||||
|
.table(self.CLUSTERS_TABLE) \
|
||||||
|
.groupBy("parent") \
|
||||||
|
.agg(F.collect_set('address').alias('addresses'))
|
||||||
|
|
||||||
|
def insertNewCluster (self, addrs: Iterable[str], root: str | None = None) -> str:
|
||||||
|
if(root == None):
|
||||||
|
root = addrs[0]
|
||||||
|
df = self.spark.createDataFrame(map(lambda addr: (addr, root), addrs), schema=['address', 'parent'])
|
||||||
|
df.writeTo(self.CLUSTERS_TABLE).append()
|
||||||
|
return root
|
||||||
|
|
||||||
|
def enumerate(self, data: DataFrame) -> DataFrame:
|
||||||
|
return data \
|
||||||
|
.rdd \
|
||||||
|
.zipWithIndex() \
|
||||||
|
.toDF(["tx_group", "index"])
|
||||||
|
|
||||||
|
def rewrite_cluster_parent(self, cluster_roots: Iterable[str], new_cluster_root: str) -> None:
|
||||||
|
sqlstr = f"""
|
||||||
|
UPDATE {self.CLUSTERS_TABLE}
|
||||||
|
SET parent='{new_cluster_root}'
|
||||||
|
WHERE parent IN ({','.join(map(lambda r: f"'{r}'", cluster_roots))})"""
|
||||||
|
|
||||||
|
if(debug):
|
||||||
|
print("UPDATE SQL")
|
||||||
|
print(sqlstr)
|
||||||
|
print()
|
||||||
|
|
||||||
|
self.spark.sql(sqlstr)
|
||||||
|
|
||||||
|
# end class Master
|
||||||
|
|
||||||
df.writeTo("myCatalog.distributedunionfind.clusters").overwrite()
|
|
||||||
|
|
||||||
"""
|
"""
|
||||||
tuple structure:
|
tuple structure:
|
||||||
Row => Row(parent=addr, addresses=list[addr]
|
Row => Row(parent=addr, addresses=list[addr] | the cluster
|
||||||
Iterable[str] => list[addr]
|
Iterable[str] => list[addr] | the transaction addresses
|
||||||
"""
|
"""
|
||||||
def find(data: tuple[Row, Iterable[str]]):
|
def find(data: tuple[Row, Iterable[str]]) -> str | None:
|
||||||
cluster = data[0]
|
cluster = data[0]
|
||||||
tx = data[1]
|
tx = data[1]
|
||||||
|
|
||||||
@@ -49,28 +94,94 @@ def find(data: tuple[Row, Iterable[str]]):
|
|||||||
else:
|
else:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
for addr_group in tx_addr_groups:
|
def handleTx(tx_addr_group: Row):
|
||||||
clusters_df = spark.read.table("myCatalog.distributedunionfind.clusters")
|
|
||||||
|
|
||||||
clusters = clusters_df \
|
|
||||||
.groupBy("parent") \
|
|
||||||
.agg(F.collect_set('address').alias('addresses'))
|
|
||||||
|
|
||||||
if (clusters.count() == 0):
|
found_clusters: "RDD[str]" = clusters.rdd \
|
||||||
insertCluster(addr_group)
|
.map(lambda cluster: (cluster, tx_addr_group['addresses'])) \
|
||||||
|
.map(find) \
|
||||||
|
.filter(lambda x: x != None)
|
||||||
|
|
||||||
|
|
||||||
|
if(found_clusters.count() == 0):
|
||||||
|
insertNewCluster(tx_addr_group)
|
||||||
|
return
|
||||||
|
|
||||||
|
cluster_roots = found_clusters.collect()
|
||||||
|
|
||||||
|
cl = clusters \
|
||||||
|
.select('addresses') \
|
||||||
|
.where(
|
||||||
|
F.col('parent').isin(cluster_roots)
|
||||||
|
) \
|
||||||
|
.agg(F.collect_set('addresses').alias('agg')) \
|
||||||
|
.select(F.flatten('agg').alias('addresses')) \
|
||||||
|
.select(F.explode('addresses')) \
|
||||||
|
.rdd \
|
||||||
|
.map(lambda addr: (addr, cluster_roots[0])) \
|
||||||
|
.toDF(['address', 'parent']) \
|
||||||
|
.show()
|
||||||
|
#.writeTo(CLUSTERS_TABLE) \
|
||||||
|
#.append()
|
||||||
|
|
||||||
|
|
||||||
|
master = Master(config)
|
||||||
|
|
||||||
|
tx_addr_groups = master.group_tx_addrs()
|
||||||
|
tx_groups_indexed = master.enumerate(tx_addr_groups)
|
||||||
|
|
||||||
|
for i in range(0, tx_addr_groups.count()):
|
||||||
|
cluster_addr_groups = master.group_cluster_addrs()
|
||||||
|
|
||||||
|
if(debug):
|
||||||
|
print("KNOWN CLUSTERS")
|
||||||
|
cluster_addr_groups.show(truncate=False)
|
||||||
|
print()
|
||||||
|
|
||||||
|
tx_addrs: Iterable[str] = tx_groups_indexed \
|
||||||
|
.where(tx_groups_indexed.index == i) \
|
||||||
|
.select('tx_group') \
|
||||||
|
.collect()[0]['tx_group']['addresses']
|
||||||
|
|
||||||
|
if(debug):
|
||||||
|
print("CURRENT TX")
|
||||||
|
print(tx_addrs)
|
||||||
|
print()
|
||||||
|
|
||||||
|
if (cluster_addr_groups.count() == 0):
|
||||||
|
master.insertNewCluster(tx_addrs)
|
||||||
continue
|
continue
|
||||||
|
|
||||||
df = clusters.rdd \
|
cluster_tx_mapping = cluster_addr_groups \
|
||||||
.map(lambda cluster: (cluster, addr_group['addresses'])) \
|
.rdd \
|
||||||
|
.map(lambda cluster: (cluster, tx_addrs))
|
||||||
|
|
||||||
|
if(debug):
|
||||||
|
print("cluster_tx_mapping")
|
||||||
|
cluster_tx_mapping \
|
||||||
|
.toDF(['cluster', 'tx']) \
|
||||||
|
.show(truncate=False)
|
||||||
|
print()
|
||||||
|
|
||||||
|
|
||||||
|
matched_roots: "List[str]" = cluster_tx_mapping \
|
||||||
.map(find) \
|
.map(find) \
|
||||||
.filter(lambda x: x != None) \
|
.filter(lambda root: root != None) \
|
||||||
.collect()
|
.collect()
|
||||||
|
|
||||||
if(len(df) == 0):
|
if(debug):
|
||||||
insertCluster(addr_group)
|
print("FOUND ROOTS")
|
||||||
continue
|
print(matched_roots)
|
||||||
|
print()
|
||||||
|
|
||||||
print(addr_group)
|
|
||||||
print(df)
|
|
||||||
|
|
||||||
break
|
if(len(matched_roots) == 0):
|
||||||
|
new_root = master.insertNewCluster(tx_addrs)
|
||||||
|
elif(len(matched_roots) == 1):
|
||||||
|
master.insertNewCluster(tx_addrs, matched_roots[0])
|
||||||
|
else:
|
||||||
|
master.rewrite_cluster_parent(matched_roots[1:], matched_roots[0])
|
||||||
|
master.insertNewCluster(tx_addrs, matched_roots[0])
|
||||||
|
|
||||||
|
if(debug):
|
||||||
|
print("==============")
|
||||||
@@ -1,6 +1,9 @@
|
|||||||
SPARK_HOME="/home/osboxes/Downloads/spark-3.2.2-bin-hadoop3.2"
|
SPARK_HOME="/home/osboxes/Downloads/spark-3.2.2-bin-hadoop3.2"
|
||||||
SPARK_MASTER="spark://osboxes:7077"
|
SPARK_MASTER="spark://osboxes:7077"
|
||||||
|
|
||||||
|
echo "Starting spark master..."
|
||||||
"$SPARK_HOME"/sbin/start-master.sh
|
"$SPARK_HOME"/sbin/start-master.sh
|
||||||
|
echo "Starting spark workers..."
|
||||||
SPARK_WORKER_INSTANCES=5 "$SPARK_HOME"/sbin/start-worker.sh "$SPARK_MASTER"
|
SPARK_WORKER_INSTANCES=5 "$SPARK_HOME"/sbin/start-worker.sh "$SPARK_MASTER"
|
||||||
|
echo "Starting cassandra container..."
|
||||||
docker run -d -p 9042:9042 cassandra
|
docker run -d -p 9042:9042 cassandra
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
SPARK_HOME="/home/osboxes/Downloads/spark-3.2.2-bin-hadoop3.2"
|
SPARK_HOME="/home/osboxes/Downloads/spark-3.2.2-bin-hadoop3.2"
|
||||||
MEMORY="4g"
|
MEMORY="1g"
|
||||||
SPARK_MASTER="spark://osboxes:7077"
|
SPARK_MASTER="spark://osboxes:7077"
|
||||||
CASSANDRA_HOST="localhost"
|
CASSANDRA_HOST="localhost"
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user