func convertUpdateDestRequestToInternal(updateRequest *c.UpdateDestinationRequest, destUUID string) *shared.UpdateDestinationRequest {
	internalUpdateRequest := shared.NewUpdateDestinationRequest()
	internalUpdateRequest.DestinationUUID = common.StringPtr(destUUID)
	if updateRequest.IsSetStatus() {
		internalUpdateRequest.Status = common.InternalDestinationStatusPtr(shared.DestinationStatus(updateRequest.GetStatus()))
	}
	if updateRequest.IsSetConsumedMessagesRetention() {
		internalUpdateRequest.ConsumedMessagesRetention = common.Int32Ptr(updateRequest.GetConsumedMessagesRetention())
	}
	if updateRequest.IsSetUnconsumedMessagesRetention() {
		internalUpdateRequest.UnconsumedMessagesRetention = common.Int32Ptr(updateRequest.GetUnconsumedMessagesRetention())
	}
	if updateRequest.IsSetOwnerEmail() {
		internalUpdateRequest.OwnerEmail = common.StringPtr(updateRequest.GetOwnerEmail())
	}
	if updateRequest.IsSetChecksumOption() {
		internalUpdateRequest.ChecksumOption = common.InternalChecksumOptionPtr(shared.ChecksumOption(updateRequest.GetChecksumOption()))
	}
	if updateRequest.IsSetZoneConfigs() {
		internalUpdateRequest.ZoneConfigs = make([]*shared.DestinationZoneConfig, 0, len(updateRequest.GetZoneConfigs().GetConfigs()))
		for _, destZoneCfg := range updateRequest.GetZoneConfigs().GetConfigs() {
			internalUpdateRequest.ZoneConfigs = append(internalUpdateRequest.ZoneConfigs, convertDestZoneConfigToInternal(destZoneCfg))
		}
	}
	return internalUpdateRequest
}
convertUpdateDestRequestToInternal converts Cherami UpdateDestinationRequest to internal shared UpdateDestinationRequest
package frontendhost
import (
	"context"
	"crypto/sha1"
	"encoding/base64"
	"fmt"
	"math"
	"net"
	"reflect"
	"regexp"
	"strconv"
	"strings"
	"sync"
	"time"
	ccli "github.com/uber/cherami-client-go/client/cherami"
	"github.com/uber/cherami-server/common"
	"github.com/uber/cherami-server/common/configure"
	dconfig "github.com/uber/cherami-server/common/dconfigclient"
	mm "github.com/uber/cherami-server/common/metadata"
	"github.com/uber/cherami-server/common/metrics"
	c "github.com/uber/cherami-thrift/.generated/go/cherami"
	"github.com/uber/cherami-thrift/.generated/go/controller"
	m "github.com/uber/cherami-thrift/.generated/go/metadata"
	"github.com/uber/cherami-thrift/.generated/go/shared"
	"github.com/uber-common/bark"
	"github.com/uber/tchannel-go/hyperbahn"
	"github.com/uber/tchannel-go/thrift"
)
const (
	maxSizeCacheDestinationPathForUUID = 1000
)
type ContextKey string
var ResourceUrnKey = ContextKey("resourceUrn")
var HeaderKey = ContextKey("header")
var nilRequestError = &c.BadRequestError{Message: `request must not be nil`}
var badRequestKafkaConfigError = &c.BadRequestError{Message: `kafka destination must set kafka cluster and topic, and may not be multi-zone`}
var badRequestNonKafkaConfigError = &c.BadRequestError{Message: `non-Kafka destination must not set kafka cluster and topic`}
var badRequestRecvOnlyPublishError = &c.BadRequestError{Message: `Cannot publish to RECEIVEONLY destinations`}
var badRequestKafkaPublishError = &c.BadRequestError{Message: `Cannot publish to Kafka destinations`}
type destinationUUID string
type Frontend struct {
	metaClnt          m.TChanMetadataService
	hostIDHeartbeater common.HostIDHeartbeater
	common.SCommon
	AppConfig                   configure.CommonAppConfig
	hyperbahnClient             *hyperbahn.Client
	cacheDestinationPathForUUID map[destinationUUID]string  
	lk                          sync.RWMutex
	logger                      bark.Logger
	cacheMutex                  sync.RWMutex
	cClient                     ccli.Client
	publishers                  map[string]*publisherInstance
	consumers                   map[string]*consumerInstance
	outputClientByUUID          map[string]c.TChanBOut
	m3Client                    metrics.Client
	dClient                     dconfig.Client
}
type publisherInstance struct {
	ccli.Publisher
	refCount int32
	idleTS time.Time
	receiptsChan chan *ccli.PublisherReceipt
}
type consumerInstance struct {
	ccli.Consumer
	refCount int32
	idleTS time.Time
	deliveryChan chan ccli.Delivery
}
var _ c.TChanBFrontend = &Frontend{}
func (h *Frontend) Shutdown() {
	h.logger.Info("Shutdown()")
	if h.hyperbahnClient != nil {
		h.hyperbahnClient.Close()
	}
}
func (h *Frontend) Stop() {
	h.hostIDHeartbeater.Stop()
	h.SCommon.Stop()
}
func NewFrontendHost(serviceName string, sVice common.SCommon, metadataClient m.TChanMetadataService, config configure.CommonAppConfig) (*Frontend, []thrift.TChanServer) {
	deploymentName := sVice.GetConfig().GetDeploymentName()
	bs := Frontend{
		logger:                      (sVice.GetConfig().GetLogger()).WithFields(bark.Fields{common.TagFrnt: common.FmtFrnt(sVice.GetHostUUID()), common.TagDplName: common.FmtDplName(deploymentName)}),
		SCommon:                     sVice,
		cacheDestinationPathForUUID: make(map[destinationUUID]string),
		cClient:                     nil,
		publishers:                  make(map[string]*publisherInstance),
		consumers:                   make(map[string]*consumerInstance),
		outputClientByUUID:          make(map[string]c.TChanBOut),
		AppConfig:                   config,
	}
	bs.logger.WithFields(bark.Fields{`serviceName`: serviceName}).Info(`New Frontend`)
	bs.m3Client = metrics.NewClient(sVice.GetMetricsReporter(), metrics.Frontend)
	bs.metaClnt = mm.NewMetadataMetricsMgr(metadataClient, bs.m3Client, bs.logger)
	bs.dClient = sVice.GetDConfigClient()
	bs.dynamicConfigManage()
	return &bs, []thrift.TChanServer{c.NewTChanBFrontendServer(&bs)}
}
func (h *Frontend) Start(thriftService []thrift.TChanServer) {
	h.SCommon.Start(thriftService)
	h.hostIDHeartbeater = common.NewHostIDHeartbeater(h.metaClnt, h.GetHostUUID(), h.GetHostPort(), h.GetHostName(), h.logger)
	h.hostIDHeartbeater.Start()
}
func (h *Frontend) readCacheDestinationPathForUUID(dst destinationUUID) (destPath string) {
	h.lk.RLock()
	destPath = h.cacheDestinationPathForUUID[dst]
	h.lk.RUnlock()
	return
}
func (h *Frontend) writeCacheDestinationPathForUUID(dst destinationUUID, destPath string) {
	h.lk.Lock()  
	if len(h.cacheDestinationPathForUUID) > maxSizeCacheDestinationPathForUUID {
		h.logger.WithField(`maxSizeCacheDestinationPathForUUID`, maxSizeCacheDestinationPathForUUID).Error(`Dumped DestinationPathForUUID Cache; more than elements.`)
		h.cacheDestinationPathForUUID = make(map[destinationUUID]string)
	}
	h.cacheDestinationPathForUUID[dst] = destPath
	h.lk.Unlock()
}
func convertDestZoneConfigFromInternal(internalDestZoneCfg *shared.DestinationZoneConfig) *c.DestinationZoneConfig {
	destZoneCfg := c.NewDestinationZoneConfig()
	destZoneCfg.Zone = common.StringPtr(internalDestZoneCfg.GetZone())
	destZoneCfg.AllowPublish = common.BoolPtr(internalDestZoneCfg.GetAllowPublish())
	destZoneCfg.AllowConsume = common.BoolPtr(internalDestZoneCfg.GetAllowConsume())
	destZoneCfg.AlwaysReplicateTo = common.BoolPtr(internalDestZoneCfg.GetAlwaysReplicateTo())
	destZoneCfg.RemoteExtentReplicaNum = common.Int32Ptr(internalDestZoneCfg.GetRemoteExtentReplicaNum())
	return destZoneCfg
}
func convertDestZoneConfigToInternal(destZoneCfg *c.DestinationZoneConfig) *shared.DestinationZoneConfig {
	internalDestZoneCfg := shared.NewDestinationZoneConfig()
	internalDestZoneCfg.Zone = common.StringPtr(destZoneCfg.GetZone())
	internalDestZoneCfg.AllowPublish = common.BoolPtr(destZoneCfg.GetAllowPublish())
	internalDestZoneCfg.AllowConsume = common.BoolPtr(destZoneCfg.GetAllowConsume())
	internalDestZoneCfg.AlwaysReplicateTo = common.BoolPtr(destZoneCfg.GetAlwaysReplicateTo())
	internalDestZoneCfg.RemoteExtentReplicaNum = common.Int32Ptr(destZoneCfg.GetRemoteExtentReplicaNum())
	return internalDestZoneCfg
}
func convertCreateDestRequestToInternal(createRequest *c.CreateDestinationRequest) *shared.CreateDestinationRequest {
	internalCreateRequest := shared.NewCreateDestinationRequest()
	internalCreateRequest.Path = common.StringPtr(createRequest.GetPath())
	internalCreateRequest.Type = common.InternalDestinationTypePtr(shared.DestinationType(createRequest.GetType()))
	internalCreateRequest.ConsumedMessagesRetention = common.Int32Ptr(createRequest.GetConsumedMessagesRetention())
	internalCreateRequest.UnconsumedMessagesRetention = common.Int32Ptr(createRequest.GetUnconsumedMessagesRetention())
	internalCreateRequest.OwnerEmail = common.StringPtr(createRequest.GetOwnerEmail())
	internalCreateRequest.ChecksumOption = common.InternalChecksumOptionPtr(shared.ChecksumOption(createRequest.GetChecksumOption()))
	internalCreateRequest.OwnerEmail = common.StringPtr(createRequest.GetOwnerEmail())
	internalCreateRequest.IsMultiZone = common.BoolPtr(createRequest.GetIsMultiZone())
	internalCreateRequest.KafkaCluster = common.StringPtr(createRequest.GetKafkaCluster())
	internalCreateRequest.KafkaTopics = createRequest.KafkaTopics
	if createRequest.IsSetZoneConfigs() {
		internalCreateRequest.ZoneConfigs = make([]*shared.DestinationZoneConfig, 0, len(createRequest.GetZoneConfigs().GetConfigs()))
		for _, destZoneCfg := range createRequest.GetZoneConfigs().GetConfigs() {
			internalCreateRequest.ZoneConfigs = append(internalCreateRequest.ZoneConfigs, convertDestZoneConfigToInternal(destZoneCfg))
		}
	}
	return internalCreateRequest
}