From a6f8f26249cc3c2f1fbb66c58a18b969b31534c1 Mon Sep 17 00:00:00 2001
From: chenshijun <csj_sky@126.com>
Date: 星期五, 06 九月 2019 17:43:46 +0800
Subject: [PATCH] 首次提交

---
 sync.go    |  252 ++++++++++++++++++++++++++++++++++++
 testdb.db  |    0 
 cluster.go |  147 +++++++++++++++++++++
 3 files changed, 399 insertions(+), 0 deletions(-)

diff --git a/cluster.go b/cluster.go
new file mode 100644
index 0000000..7a48bb0
--- /dev/null
+++ b/cluster.go
@@ -0,0 +1,147 @@
+package androidSync
+
+import (
+	sdb "basic.com/Android/syncdb.git"
+	"basic.com/valib/logger.git"
+	"encoding/json"
+	"github.com/hashicorp/memberlist"
+	"os"
+	"time"
+)
+
+const (
+	syncClusterKeyPrefix = "bjbasic123"
+)
+const (
+	defaultSqliteDBPath = "./testdb.db"
+
+	dBNameCluster      = "cluster"
+	dBNameClusterNode  = "cluster_node"
+	dBNameTables       = "dbTables"
+	dBNameTablePersons = "dbtablepersons"
+)
+
+var syncTables = []string{dBNameCluster, dBNameClusterNode, dBNameTables, dBNameTablePersons}
+var agent *sdb.Agent
+var members *memberlist.Memberlist
+var sqliteDBPath string = defaultSqliteDBPath
+
+func init(){
+	var logFile = "./logger/androidSync.log"
+	var logSaveDays = 15	// 鏃ュ織鍒濆鍖�
+	logger.Config(logFile, logger.DebugLevel)
+	logger.SetSaveDays(logSaveDays)
+	err := sdb.InitDbConn(sqliteDBPath)
+	if err != nil{
+		logger.Error("sdb.InitDbConn ERROR: sqliteDBPath:", sqliteDBPath)
+		os.Exit(-1)
+	}
+}
+
+/*
+	璁剧疆鏁版嵁搴撹矾寰�
+ */
+func setDBPath(path string){
+	sqliteDBPath = path
+}
+
+/*
+	鑾峰彇鏁版嵁搴撹矾寰�
+*/
+func getDBPath() string {
+	return sqliteDBPath
+}
+
+func clearSearchResult(ml *memberlist.Memberlist) {
+	time.Sleep(10 * time.Second)
+	sdb.CloseSearchNode(ml)
+}
+
+/*
+	鍒涘缓鏌ヨ闆嗙兢鐨勪复鏃惰妭鐐癸紝闇�瑕佷紶鍏ラ泦缇ゅ瘑鐮侊紝6瀛楄妭锛屾暟瀛楁垨瀛楁瘝
+	姣忎釜涓�绉掕皟鐢ㄤ竴娆etSearchNodes锛屾嬁鍒版悳绱㈠埌鐨勮妭鐐逛俊鎭暟鎹�
+	鏈�鍚庤皟鐢–loseSearchNode锛屽叧闂复鏃跺垱寤虹殑鎼滅储鑺傜偣
+	pwd = password must six bytes
+*/
+func CreateSearchNodeByPwd(pwd string) bool{
+
+	pwdFull := syncClusterKeyPrefix + pwd
+	var err error
+	members, err = sdb.CreateSearchNode(pwdFull)
+	if err != nil {
+		logger.Error("sdb.CreateSearchNode:", err)
+		return false
+	}
+
+	go clearSearchResult(members)
+
+	return true
+}
+
+/*
+	鍒涘缓鏌ヨ闆嗙兢鐨勪复鏃惰妭鐐癸紝闇�瑕佷紶鍏ラ泦缇ゅ瘑鐮侊紝16瀛楄妭
+	key = password
+*/
+func createSearchNode(key string) bool {
+	var err error
+	members, err = sdb.CreateSearchNode(key)
+	if err != nil {
+		logger.Error("sdb.CreateSearchNode:", err)
+		return false
+	}
+
+	return true
+}
+
+/*
+	闃诲鏂瑰紡鍒涘缓鎼滅储闆嗙兢鐨勮妭鐐癸紝浼氱洿鎺ヨ繑鍥炴悳绱㈠埌鐨勮妭鐐�
+	map[string]NodeInfo
+	nodes[NodeInfo.NodeID] = NodeInfo
+ */
+func createSearchNodeWhitClose(key string, delay int) []byte {
+	nodes := sdb.CreateSearchNodeWhitClose(key, time.Duration(delay))
+	strNodes, err := json.Marshal(nodes)
+	if err != nil {
+		logger.Error("json.Marshal:", err)
+		return nil
+	}
+	return strNodes
+}
+
+/*
+	鍏抽棴涓存椂鍒涘缓鐨勮妭鐐�
+*/
+func CloseSearchNode() bool {
+	err := sdb.CloseSearchNode(members)
+	if err != nil {
+		logger.Error("sdb.CloseSearchNode:", err)
+		return false
+	}
+	return true
+}
+
+/*
+	鑾峰彇鎼滅储鍒扮殑鑺傜偣淇℃伅
+json vector
+[
+{Node1},
+{Node2},
+...
+{Noden}
+]
+type NodeInfo struct {
+	ClusterID   string `json:"clusterID"`
+	NodeID      string `json:"nodeID"`
+	NodeAddress string `json:"nodeAddress"`
+	IsAlive     int    `json:"isAlive"`  //StatusNone:0, StatusAlive:1, StatusLeaving:2, StatusLeft:3, StatusFailed:4
+}
+*/
+func GetSearchNodes() []byte {
+	nodes := sdb.GetSearchNodes()
+	strNodes, err := json.Marshal(nodes)
+	if err != nil {
+		logger.Error("json.Marshal:", err)
+		return nil
+	}
+	return strNodes
+}
diff --git a/sync.go b/sync.go
new file mode 100755
index 0000000..328683b
--- /dev/null
+++ b/sync.go
@@ -0,0 +1,252 @@
+package androidSync
+
+import (
+	sdb "basic.com/Android/syncdb.git"
+	"basic.com/valib/logger.git"
+	"encoding/json"
+	"strconv"
+	"strings"
+	"time"
+)
+
+/*
+	姣忔寮�鏈哄悗閮戒細璋冪敤璇ユ帴鍙o紝璇ユ帴鍙d細鍘绘煡璇㈡暟鎹簱锛岀‘瀹炰箣鍓嶆槸鍚﹀凡缁忓姞鍏ヨ繃闆嗙兢锛岃嫢鏄凡缁忓姞鍏ラ泦缇わ紝鍒欏紑鏈鸿嚜鍔ㄥ姞鍏�
+ */
+func InitAgent(devID string) bool {
+	sqlFindAllCluster := string("select * from " + dBNameCluster)
+	clusters, err := sdb.ExecuteQuerySql([]string{sqlFindAllCluster})
+	if err == nil && clusters != nil && len(clusters) > 0 {
+		c := clusters[0]
+		sqlFindNodesByClusterId := string("select * from " + dBNameClusterNode + " where cluster_id='" + c.Values[0][1].(string) + "'")
+		nodes, err := sdb.ExecuteQuerySql([]string{sqlFindNodesByClusterId})
+		if err == nil && nodes != nil && len(nodes) > 0 {
+			var nodeIps []string
+			for _, n := range nodes {
+				if n.Values[0][3].(string) != devID {
+					nodeIps = append(nodeIps, n.Values[0][4].(string))
+				}
+			}
+			agent, err = sdb.Init(c.Values[0][0].(string), c.Values[0][2].(string), devID, nodeIps)
+			if agent != nil {
+				logger.Debug("sync.Agent init success!")
+			} else {
+				logger.Debug("sync.Agent init fail!")
+			}
+		}
+	}
+
+	return true
+}
+
+/*
+	涔嬪墠娌℃湁闆嗙兢銆傝皟鐢ㄦ鎺ュ彛杩涜闆嗙兢鍒濆鍖栵紝浼犲叆闆嗙兢鍏朵粬鑺傜偣鐨刬p锛屼究浜庡垵濮嬪寲鍚庣洿鎺ュ姞鍏ラ泦缇�
+	strAddrs = "ip1:port1;ip2:port2;ip3:port3"
+*/
+func SyncInit(clusterID string, password string, nodeID string, strAddrs string) bool {
+	var ips []string
+	if strAddrs == "" {
+		ips = nil
+	} else {
+		ips = strings.Split(strAddrs, ";")
+	}
+
+	pwdFull := syncClusterKeyPrefix + password
+
+	agent, _ = sdb.Init(clusterID, pwdFull, nodeID, ips)
+	if agent == nil {
+		logger.Error("sdb.Init")
+		return false
+	}
+
+	return true
+}
+
+/*
+	鍒濆鍖栨椂锛岃嫢娌¤兘鍔犲叆闆嗙兢锛屽彲浠ラ�氳繃璇ユ帴鍙e姞鍏ラ泦缇ゃ��
+	strAddrs = "ip1:port1;ip2:port2;ip3:port3"
+*/
+func JoinByNodeAddrs(strAddrs string) bool {
+	if strAddrs == "" {
+		logger.Error("strAddrs == \"\"")
+		return false
+	}
+	addrs := strings.Split(strAddrs, ";")
+	err := agent.JoinByNodeAddrs(addrs)
+	if err != nil {
+		logger.Error("agent.JoinByNodeAddrs err:", err)
+		return false
+	}
+
+	return true
+}
+
+/*
+	鍔犲叆闆嗙兢锛屽寘鍚垵濮嬪寲鑺傜偣SyncInit锛屽苟鏍规嵁浼犲叆鐨勯泦缇ゅ叾浠栬妭鐐瑰垪琛ㄨ嚜鍔ㄥ姞鍏ラ泦缇�
+	strAddrs = "ip1:port1;ip2:port2;ip3:port3"
+*/
+func JoinCluster(clusterID, password, strAddrs, devID, devIP, devName string) bool {
+
+	isOk := SyncInit(clusterID, password, devID, strAddrs)
+
+	if isOk { //鍔犲叆鎴愬姛
+		logger.Debug("dbSync.Init success")
+
+		if ! syncTableDataFromCluster(clusterID, devID, devIP, devName) {
+			logger.Error("鍔犲叆闆嗙兢澶辫触锛侊紒锛�")
+			return false
+		}
+	} else {
+		logger.Error("dbSync.Init error")
+		if agent != nil {
+			err := agent.Shutdown()
+			if err != nil {
+				logger.Error("dbSync.Init err,shutdown err:", err)
+			}
+		}
+		return false
+	}
+
+	return true
+}
+
+/*
+	鍔犲叆闆嗙兢鍚庯紝鍙互閫氳繃璇ユ帴鍙h幏鍙栭泦缇ょ殑鑺傜偣淇℃伅锛屼笉杩囨渶濂界洿鎺ユ煡鍚屾搴撶殑闆嗙兢鑺傜偣琛�
+json vector
+[
+{Node1},
+{Node2},
+...
+{Noden}
+]
+type NodeInfo struct {
+	ClusterID   string `json:"clusterID"`
+	NodeID      string `json:"nodeID"`
+	NodeAddress string `json:"nodeAddress"`
+	IsAlive     int    `json:"isAlive"` //StatusNone:0, StatusAlive:1, StatusLeaving:2, StatusLeft:3, StatusFailed:4
+}
+*/
+func GetNodes() []byte {
+	nodes := agent.GetNodes()
+	strNode, err := json.Marshal(nodes)
+	if err != nil {
+		logger.Error("json.Marshal err:", err)
+		return nil
+	}
+	return strNode
+}
+
+/*
+	鍔犲叆闆嗙兢鍚�, 娓呯┖鏈湴鐨勫悓姝ュ簱鏁版嵁,骞朵粠闆嗙兢鎷夊彇鏈�鏂扮殑鍚屾搴撴暟鎹�
+ */
+func syncTableDataFromCluster(clusterID, devID, devIP, devName string) bool {
+	var err error
+
+	//0.鍏抽棴reference
+	foreignSql := string("PRAGMA foreign_keys=OFF")
+	_, err = sdb.ExecuteWriteSql([]string{foreignSql}, false)
+	if err != nil {
+		return false
+	}
+
+	//1.鍒犻櫎鏈湴鐨勫悓姝ュ簱鏁版嵁
+	var sqls []string
+	var delSql string
+	for _, t := range syncTables {
+		if t == dBNameTables {
+			delSql = "delete from " + t + " where (analyServerId='' or analyServerId=NULL)"
+		} else if t == dBNameTablePersons {
+			delSql = "delete from " + t + " where tableId in (select id from dbtables where (analyServerId='' or analyServerId=NULL))"
+		} else {
+			delSql = "delete from " + t
+		}
+		sqls = append(sqls, delSql)
+	}
+
+	//2.鎷夊彇闆嗙兢鍐呯殑鍚屾搴撴暟鎹埌鏈湴鏁版嵁搴撹〃涓�
+	var dumpSqls *[]string
+	dumpSqls, err = agent.GetTableDataFromCluster(syncTables)
+	if dumpSqls != nil {
+		for _, dumpSql := range *dumpSqls {
+			sqls = append(sqls, dumpSql)
+		}
+	}
+
+	logger.Debug("鎴愬姛娣诲姞褰撳墠鑺傜偣鍒伴泦缇よ妭鐐逛腑")
+
+	//3.灏嗘湰鑺傜偣鍔犲叆鍒拌妭鐐瑰垪琛ㄤ腑
+	timeUnix := time.Now().Unix()
+	fmtTimeStr := time.Unix(timeUnix, 0).Format("2006-01-02 15:04:05")
+
+	sqlSync := "insert into cluster_node(id,cluster_id,node_name,node_id,node_ip,create_time) values ('" +
+		devID + "','" + clusterID + "','" + devName + "','" + devID + "','" +
+		(devIP + ":" + strconv.Itoa(sdb.DefaultBindPort)) + "','" + fmtTimeStr + "')"
+	sqls = append(sqls, sqlSync)
+
+	//4. 鍐欏叆鏁版嵁搴�
+	_, err = sdb.ExecuteWriteSql(sqls, true)
+	if err != nil {
+		logger.Debug("sdb.ExecuteWriteSql ERROR:", err)
+		return false
+	}
+
+	//5. 鍚屾璇ヨ妭鐐瑰埌闆嗙兢
+	agent.SyncSql([]string{sqlSync})
+
+	//6.寮�鍚痳eference
+	foreignSql = string("PRAGMA foreign_keys=ON")
+	_, err = sdb.ExecuteWriteSql([]string{foreignSql}, false)
+	if err != nil {
+		return false
+	}
+
+	return true
+}
+
+/*
+	鎿嶄綔鏁版嵁搴撳悗锛岄渶瑕佽皟鐢ㄨ鎺ュ彛灏嗗搴旂殑sql璇彞鍚屾鍒伴泦缇�
+	strSql = "sql1;sql2;sql3;...;sqln"
+ */
+func SyncSql(strSql string) {
+
+	sqls := strings.Split(strSql, ";")
+
+	agent.SyncSql(sqls)
+}
+
+/*
+	鏇存柊闆嗙兢鐨勫悕瀛�
+ */
+func UpdateClusterName(clusterName, clusterID string) bool {
+	sql := string("update cluster set cluster_name='" + clusterName + "' where cluster_id='" + clusterID + "'")
+	_, err := sdb.ExecuteWriteSql([]string{sql}, false)
+	if err != nil {
+		return false
+	}
+
+	return true
+}
+
+/*
+	閫�鍑洪泦缇�
+ */
+func Leave() bool {
+
+	if agent != nil {
+		err := agent.Leave()
+		if err != nil {
+			logger.Debug("cluster leave err")
+			return false
+		}
+		agent.Shutdown()
+		agent = nil
+
+		sqls := []string{"delete from cluster_node", "delete from cluster"}
+
+		_, err = sdb.ExecuteWriteSql(sqls, false)
+		if err != nil {
+			return false
+		}
+	}
+
+	return true
+}
diff --git a/testdb.db b/testdb.db
new file mode 100644
index 0000000..d20c73e
--- /dev/null
+++ b/testdb.db
Binary files differ

--
Gitblit v1.8.0