func GetAFromMySQLBackend(dst, srcIP string, regionTree *RegionTree) (bool, []dns.RR, uint16, *MyError.MyError) {
	domainId, e := RRMySQL.GetDomainIDFromMySQL(dst)
	if e != nil {
		//todo:
		//fmt.Println(utils.GetDebugLine(), "Error, GetDomainIDFromMySQL:", e)
		return false, nil, uint16(0), e
	}
	region, ee := RRMySQL.GetRegionWithIPFromMySQL(utils.Ip4ToInt32(utils.StrToIP(srcIP)))
	if ee != nil {
		//fmt.Println(utils.GetDebugLine(), "Error GetRegionWithIPFromMySQL:", ee)
		return false, nil, uint16(0), MyError.NewError(ee.ErrorNo, "GetRegionWithIPFromMySQL return "+ee.Error())
	}
	RR, eee := RRMySQL.GetRRFromMySQL(uint32(domainId), region.IdRegion)
	if eee != nil && eee.ErrorNo == MyError.ERROR_NORESULT {
		//fmt.Println(utils.GetDebugLine(), "Error GetRRFromMySQL with DomainID:", domainId,
		//	"RegionID:", region.IdRegion, eee)
		//fmt.Println(utils.GetDebugLine(), "Try to GetRRFromMySQL with Default Region")
		utils.ServerLogger.Debug("Try to GetRRFromMySQL with Default Region")
		RR, eee = RRMySQL.GetRRFromMySQL(uint32(domainId), uint32(0))
		if eee != nil {
			//fmt.Println(utils.GetDebugLine(), "Error GetRRFromMySQL with DomainID:", domainId,
			//	"RegionID:", 0, eee)
			return false, nil, uint16(0), MyError.NewError(eee.ErrorNo, "Error GetRRFromMySQL with DomainID:"+strconv.Itoa(domainId)+eee.Error())
		}
	} else if eee != nil {
		utils.ServerLogger.Error(eee.Error())
		return false, nil, uint16(0), eee
	}
	//fmt.Println(utils.GetDebugLine(), "GetRRFromMySQL Succ!:", RR)
	utils.ServerLogger.Debug("GetRRFromMySQL Succ!: ", RR)
	var R []dns.RR
	var rtype uint16
	var reE *MyError.MyError
	hdr := dns.RR_Header{
		Name:   dst,
		Class:  RR.RR.Class,
		Rrtype: RR.RR.RrType,
		Ttl:    RR.RR.Ttl,
	}

	//fmt.Println(utils.GetDebugLine(), mr.RR)
	if RR.RR.RrType == dns.TypeA {
		for _, mr := range RR.RR.Target {
			rh := &dns.A{
				Hdr: hdr,
				A:   utils.StrToIP(mr),
			}
			R = append(R, dns.RR(rh))
		}
		rtype = dns.TypeA
		//	fmt.Println(utils.GetDebugLine(), "Get A RR from MySQL, requery dst:", dst)
	} else if RR.RR.RrType == dns.TypeCNAME {
		for _, mr := range RR.RR.Target {
			rh := &dns.CNAME{
				Hdr:    hdr,
				Target: mr,
			}
			R = append(R, dns.RR(rh))
		}
		rtype = dns.TypeCNAME
		//fmt.Println(utils.GetDebugLine(), "Get CNAME RR from MySQL, requery dst:", dst)
		reE = MyError.NewError(MyError.ERROR_NOTVALID,
			"Got CNAME result for dst : "+dst+" with srcIP : "+srcIP)
	}

	if len(R) > 0 {
		//Add timer for auto refrech the RegionCache
		go func(dst, srcIP string, r dns.RR, regionTree *RegionTree) {
			//fmt.Println(utils.GetDebugLine(), " Refresh record after ", r.Header().Ttl-5,
			//	" Second, dst: ", dst, " srcIP: ", srcIP, "add timer ")
			time.AfterFunc(time.Duration(r.Header().Ttl-5)*time.Second,
				func() { GetAFromMySQLBackend(dst, srcIP, regionTree) })
		}(dst, srcIP, R[0], regionTree)

		go func(regionTree *RegionTree, R []dns.RR, srcIP string) {
			//fmt.Println(utils.GetDebugLine(), "GetAFromMySQLBackend: ", e)

			startIP, endIP := region.Region.StarIP, region.Region.EndIP
			cidrmask := utils.GetCIDRMaskWithUint32Range(startIP, endIP)

			//fmt.Println(utils.GetDebugLine(), " GetRegionWithIPFromMySQL with srcIP: ",
			//	srcIP, " StartIP : ", startIP, "==", utils.Int32ToIP4(startIP).String(),
			//	" EndIP: ", endIP, "==", utils.Int32ToIP4(endIP).String(), " cidrmask : ", cidrmask)
			//				netaddr, mask := DefaultNetaddr, DefaultMask
			r, _ := NewRegion(R, startIP, cidrmask)
			regionTree.AddRegionToCache(r)
			//fmt.Println(utils.GetDebugLine(), "GetAFromMySQLBackend: ", r)
			//				fmt.Println(regionTree.GetRegionFromCacheWithAddr(startIP, cidrmask))
		}(regionTree, R, srcIP)
		return true, R, rtype, reE
	}
	return false, nil, uint16(0), MyError.NewError(MyError.ERROR_UNKNOWN, utils.GetDebugLine()+"Unknown Error ")

}
func GetAFromDNSBackend(
	dst, srcIP string) (bool, []dns.RR, uint16, *MyError.MyError) {

	var reE *MyError.MyError = nil
	var rtype uint16
	soa, e := GetSOARecord(dst)
	utils.ServerLogger.Debug("GetSOARecord return: ", soa, " error: ", e)
	if e != nil || len(soa.NS) <= 0 {
		//GetSOA failed , need log and return
		utils.ServerLogger.Error("GetSOARecord error: %s", e.Error())
		return false, nil, dns.TypeNone, MyError.NewError(MyError.ERROR_UNKNOWN,
			"GetARecord func GetSOARecord failed: "+dst)
	}

	var ns_a []string
	//todo: is that soa.NS may nil ?
	for _, x := range soa.NS {
		ns_a = append(ns_a, x.Ns)
	}

	rr, edns_h, edns, e := QueryA(dst, srcIP, ns_a, query.NS_SERVER_PORT)
	//todo: ends_h ends need to be parsed and returned!
	utils.QueryLogger.Info("QueryA(): dst:", dst, "srcIP:", srcIP, "ns_a:", ns_a, " returned rr:", rr, "edns_h:", edns_h,
		"edns:", edns, "e:", e)
	if e == nil && rr != nil {
		var rr_i []dns.RR
		//todo:if you add both "A" and "CNAME" record to a domain name,this should be wrong!
		if a, ok := ParseA(rr, dst); ok {
			//rr is A record
			utils.ServerLogger.Debug("GetAFromDNSBackend : typeA record: ", a, " dns.TypeA: ", ok)
			for _, i := range a {
				rr_i = append(rr_i, dns.RR(i))
			}
			//if A ,need parse edns client subnet
			//			return true,rr_i,nil
			rtype = dns.TypeA
		} else if b, ok := ParseCNAME(rr, dst); ok {
			//rr is CNAME record
			//fmt.Println(utils.GetDebugLine(), "GetAFromDNSBackend: typeCNAME record: ", b, " dns.TypeCNAME: ", ok)
			utils.ServerLogger.Debug("GetAFromDNSBackend: typeCNAME record: ", b, " dns.TypeCNAME: ", ok)
			//todo: if you add more than one "CNAME" record to a domain name ,this should be wrong,only the first one will be used!
			//dst = b[0].Target
			for _, i := range b {
				rr_i = append(rr_i, dns.RR(i))
			}
			rtype = dns.TypeCNAME
			reE = MyError.NewError(MyError.ERROR_NOTVALID,
				"Got CNAME result for dst : "+dst+" with srcIP : "+srcIP)
			//if CNAME need parse edns client subnet
		} else {
			//error return and retry
			//fmt.Println(utils.GetDebugLine(), "GetAFromDNSBackend: ", rr)
			utils.ServerLogger.Debug("GetAFromDNSBackend: ", rr)
			return false, nil, dns.TypeNone, MyError.NewError(MyError.ERROR_NORESULT,
				"Got error result, need retry for dst : "+dst+" with srcIP : "+srcIP)
		}
		utils.ServerLogger.Debug("Add A record to Region Cache: dst:", dst, "srcIP:", srcIP,
			"rr_i:", rr_i, "ends_h", edns_h, "edns:", edns)
		go AddAToRegionCache(dst, srcIP, rr_i, edns_h, edns)

		return true, rr_i, rtype, reE
	}
	return false, nil, dns.TypeNone, MyError.NewError(MyError.ERROR_UNKNOWN, utils.GetDebugLine()+"Unknown error")
}
func TestMubitRadix(t *testing.T) {
	cidrNet := []string{
		"10.0.0.2/8",
		"10.20.0.0/14",
		"10.21.0.0/16",
		"192.168.0.0/16",
		"192.168.2.0/24",
		"8.0.0.0/9",
		"8.8.8.0/24",
		"0.0.0.0/0",
		//		"128.0.0.0/1",
	}
	ip2Find := []string{
		"10.20.1.2",
		"10.22.1.2",
		"10.19.0.1",
		"10.21.0.1",
		"192.168.2.3",
		"10.22.0.5",
		"202.106.0.20",
		"172.16.3.133",
		"8.8.8.8",
		"8.8.7.1",
	}
	RadixTree := NewDomainRegionTree()
	for _, x := range cidrNet {
		i, n, e := net.ParseCIDR(x)
		if e != nil {
			t.Log(e.Error())
			t.Fail()
			continue
		}
		a, m := utils.IpNetToInt32(n)
		RadixTree.AddRegionToCache(&Region{
			NetworkAddr: a,
			NetworkMask: m,
			RR: []dns.RR{
				dns.RR(&dns.A{
					A: i,
					Hdr: dns.RR_Header{
						Rrtype: 1,
						Class:  1,
						Ttl:    60,
					},
				}),
			},
		})
	}
	// For default route
	RadixTree.AddRegionToCache(&Region{
		NetworkAddr: DefaultRadixNetaddr,
		NetworkMask: DefaultRadixNetMask,
		RR: []dns.RR{
			dns.RR(&dns.A{
				A: utils.Int32ToIP4(DefaultRadixNetaddr),
				Hdr: dns.RR_Header{
					Rrtype: 1,
					Class:  1,
					Ttl:    60,
				},
			}),
		},
	})
	for _, i := range ip2Find {

		ii := utils.Ip4ToInt32(utils.StrToIP(i))
		r, e := RadixTree.GetRegionFromCacheWithAddr(ii, DefaultRadixSearchMask)
		if e != nil {
			t.Log(e)
			t.Log(i)
			t.Fail()
		} else {
			t.Log(r)
		}

	}

	RadixTree.Radix32.Do(func(r1 *bitradix.Radix32, i int) {
		t.Log(r1.Key(), r1.Value, r1.Bits())
	})
}