)
type Handler struct {
- handlerName string
- libPath string
- devicesScore map[string]float64
- intervalMs int
- resourceCount int
- scoreValue chan float64
- symbolPtr unsafe.Pointer
+ handlerName string
+ libPath string
+ functionName string
+ devicesScore map[string]float64
+ intervalMs int
+ resourceCount int
- scoreValue int
++ scoreValue float64
+ statusSignal chan int
+ endSignal chan bool
+ parents *Handlers
+
+ //for dynamic loading
+ symbol uintptr
+ dl uintptr
+
}
type Handlers struct {
- table map[string]*Handler
+ table map[string]*Handler
- Ch chan interface{}
- IloadScoringLibrary func(string, int, chan float64)
+ Ch chan interface{}
-
++
+ IRunningScore func (uintptr) ()
- IGetScore func (string, string) float64
++ IGetScore func (string, string, chan float64) float64
}
+ var (
+ handlers *Handlers
+ )
- func Init() (handlers *Handlers){
+ const (
+ // ConstLocalTarget is for knowing local environments
+ ConstLocalTarget = "localhost"
- handlers = new(Handlers)
- handlers.table = make(map[string]*Handler)
+ // ConstPrefixHTTP is "http://"
+ ConstPrefixHTTP = "http://"
- return
+ // ConstWellknownPort is wellknonw port
+ ConstWellknownPort = 56001
+ )
+
+ func Init() *Handlers {
+
+ handlers = new(Handlers)
+ handlers.table = make(map[string]*Handler)
+
+ return handlers
}
//TODO : async notify lib loading
- func PushLibPath(libPath string, doc *confdescription.Doc, handlersCh chan<- interface{}) (err error){
+ func PushLibPath(libPath string, doc *confdescription.Doc, handlersCh chan<- interface{}) (err error) {
+ ILog.Printf("input PushLibPath : %s", libPath)
+ handlersCh <- pair{libPath, doc}
+ return nil
+ }
- handlersCh <- pair{libPath, doc}
- return nil
+ // GetScore is getting score of device
+ func GetScore(target string, name string) (scoreValue float64, err error) {
+ if strings.Compare(target, getOutboundIP()) == 0 || strings.Compare(target, ConstLocalTarget) == 0 {
+ scoreValue, err = getScoreLocalEnv(name)
+ } else {
+ scoreValue, err = getScoreRemoteEnv(target, name)
+ }
+
+ DLog.Println("scoreValue", scoreValue)
+
+ return
}
+ // Listening function
func (handlers *Handlers) Listening() {
- go func(){
+ go func() {
- ILog.Println("listening started")
- for {
+ ILog.Println("listening started")
+ for {
+
+ select {
+ case obj := <- handlers.Ch :
+ ILog.Printf("input handlers.Ch from configuremgr")
+ handlers.makeHandler(obj.(pair)).runScoring()
- }
- select {
- case obj := <-handlers.Ch:
++ } //select end
++ } // for end
- }
- handlerObj := handlers.makeHandler(obj.(pair))
- handlers.runScoring(handlerObj)
- }
- }
++ }() //function call
- }()
- }()
+ }
+
+ func (handlers *Handlers) runScoring(handlerObj *Handler) {
+ go handlers.IloadScoringLibrary(handlerObj.libPath, handlerObj.intervalMs, handlerObj.scoreValue)
+ return
}
+func (handlers *Handlers) RemoveLib(libName string) {
+ handler := handlers.table[libName]
+
+ //for producer
+ handler.endSignal <- LIB_STATUS_DONE
+
+ //for consumer
+ handler.endSignal <- LIB_STATUS_DONE
+
+ //Close dynamic loader
+ defer C.dlclose(unsafe.Pointer(handler.dl))
+
+ ILog.Println("RemoveLib end")
+}
+
func (handlers *Handlers) makeHandler(pairObj pair) (handlerObj *Handler) {
- handlerObj = new(Handler)
- handlerObj.handlerName = getLibName(pairObj.libPath)
- handlerObj.libPath = pairObj.libPath
- handlerObj.intervalMs = pairObj.doc.ResourceType.IntervalTimeMs
- handlerObj.devicesScore = make(map[string]float64)
+
- handlers.table[handlerObj.handlerName] = handlerObj
+ handlerObj = new(Handler)
- handlerObj.handlerName = pairObj.libPath
++ handlerObj.handlerName = getLibName(pairObj.libPath)
+ handlerObj.libPath = pairObj.libPath
+ handlerObj.intervalMs = pairObj.doc.ResourceType.IntervalTimeMs
+ handlerObj.functionName = pairObj.doc.ScoringMethod.FunctionName
+ handlerObj.devicesScore = make(map[string]float64)
+ handlerObj.statusSignal = make(chan int, 1024)
+ handlerObj.endSignal = make(chan bool, 1024)
+ handlerObj.parents = handlers
- handlers.table[pairObj.libPath] = handlerObj
+ handlerObj.scoreValue = make(chan float64, 1)
- return
++ handlers.table[handlerObj.handlerName] = handlerObj
++
+ return
}
- handler.parents.IRunningScore(handler.symbol)
- }
+func (handler *Handler) runScoring() {
+
+ ILog.Println("Run scoring")
+
+ go func(){
+
+ for {
+ select {
+ case status := <- handler.statusSignal :
+ handler.process(status)
+ case <- handler.endSignal :
+ ILog.Println("consumer signal go routine die")
+ return
+ }
+ }
+ }()
+
+ go func() {
+
+ handler.statusSignal <- LIB_STATUS_INIT
+
+ for {
+
+ select {
+ case <- handler.endSignal :
+ ILog.Println("producer signal go routine die")
+ return
+ default:
+ handler.statusSignal <- LIB_STATUS_RUN
+ time.Sleep(time.Duration(1000) * time.Millisecond)
+ ILog.Printf("status run sleep time : %d\n", handler.intervalMs)
+ }
+
+ }
+
+ }()
+
+ return
+}
+
+func (handler *Handler) process(status int) {
+
+ switch(status){
+ case LIB_STATUS_INIT:
+ ILog.Printf("init\n")
+ handler.init()
+ break
+ case LIB_STATUS_RUN:
+ ILog.Printf("run\n")
+ handler.running()
+ break
+ }
+
+}
+
+
+func (handler *Handler) init() {
+
+ sym := C.CString(handler.functionName)
+ defer C.free(unsafe.Pointer(sym))
+
+ lib := C.CString(handler.libPath)
+ defer C.free(unsafe.Pointer(lib))
+
+ dl, err := C.dlopen(lib , C.RTLD_LAZY)
+ handler.dl = uintptr(dl)
+
+ if err != nil {
+ ELog.Fatal("dlopen error occured")
+ }
+
+ symbolPtr, symbolErr := C.dlsym(dl, sym)
+ if symbolErr != nil {
+ ELog.Fatal("symbol error occured")
+ }
+
+ handler.symbol = uintptr(symbolPtr)
+
+ ILog.Printf("functionName : %s\n", handler.functionName)
+ ILog.Printf("libPath : %s\n", handler.libPath)
+ ILog.Printf("symbol : %#08X\n", handler.symbol)
+
+
+ return
+}
+
+func (handler *Handler) running() {
-func getChan(name string) (score chan float64, err error) {
- handlerObj := handlers.table[name]
++ handler.scoreValue = handler.parents.IRunningScore(handler.symbol)
++}
++
+ func getLibName(libPath string) string {
+ name := strings.Split(libPath, "/")
+ lastIdx := len(name)
+
+ libName := strings.Split(name[lastIdx-1], ".")
+ return strings.TrimPrefix(libName[0], "lib")
+ }
+
- if handlerObj == nil {
- err = errors.New("Invalid Service Name")
- return
- }
++// func getScore(name string) (score float64, err error) {
++// handlerObj := handlers.table[name]
+
- score = handlerObj.scoreValue
++// if handlerObj == nil {
++// err = errors.New("Invalid Service Name")
++// return
++// }
+
- return
-}
++// score = handlerObj.scoreValue
+
- scoreChan, err := getChan(name)
- if err != nil {
- return
- }
++// return
++// }
+
+ func getScoreLocalEnv(name string) (scoreValue float64, err error) {
- select {
- case scoreValue = <-scoreChan:
- DLog.Println(scoreValue)
++ // scoreChan, err := getScore(name)
++ // if err != nil {
++ // return
++ // }
++
++ // select {
++ // case scoreValue = <-scoreChan:
++ // DLog.Println(scoreValue)
++ // }
++ // return
+
- return
++ handlerObj := handlers.table[name]
++
++ if handlerObj == nil {
++ err = errors.New("Invalid Service Name")
++ return
+ }
+
++ scoreValue = handlerObj.scoreValue
++
++ return
+ }
+
+ func getScoreRemoteEnv(target string, name string) (scoreValue float64, err error) {
+ targetURL := ConstPrefixHTTP + target + ":" + strconv.Itoa(ConstWellknownPort) + "/" + name
+
+ respBytes, err := doGet(targetURL)
+ if checkError(err) == true {
+ return scoreValue, err
+ }
+
+ var responseMsg map[string]interface{}
+ err = json.Unmarshal(respBytes, &responseMsg)
+
+ if err == nil {
+ scoreValue = responseMsg["ScoreValue"].(float64)
+ }
+
+ return
+ }
+
+ func getOutboundIP() string {
+ conn, err := net.Dial("udp", "8.8.8.8:80")
+ if err != nil {
+ log.Fatal(err)
+ }
+ defer conn.Close()
+
+ localAddr := conn.LocalAddr().(*net.UDPAddr)
+
+ return localAddr.IP.String()
+ }
+
+ func checkError(err error) bool {
+ if err != nil {
+ log.Println(err.Error())
+ return true
+ }
+ return false
+ }