Add concurrent map data structure & service discovery
authorjw_wonny.cha <jw_wonny.cha@samsung.com>
Thu, 14 Mar 2019 05:29:20 +0000 (14:29 +0900)
committerjw_wonny.cha <jw_wonny.cha@samsung.com>
Thu, 14 Mar 2019 05:29:20 +0000 (14:29 +0900)
src/servicemgr/concurrent_map.go [new file with mode: 0644]
src/servicemgr/service_discovery.go [new file with mode: 0644]

diff --git a/src/servicemgr/concurrent_map.go b/src/servicemgr/concurrent_map.go
new file mode 100644 (file)
index 0000000..56af2d1
--- /dev/null
@@ -0,0 +1,113 @@
+package servicemgr
+
+import (
+       "os/exec"
+       "sync"
+       "sync/atomic"
+)
+
+// ConcurrentMap type
+type ConcurrentMap struct {
+       sync.RWMutex
+       items map[uint64]interface{}
+}
+
+// ConcurrentMapItem type
+type ConcurrentMapItem struct {
+       Key   uint64
+       Value interface{}
+}
+
+// Set is for setting map item
+func (cm *ConcurrentMap) Set(key uint64, value interface{}) {
+       cm.Lock()
+       defer cm.Unlock()
+
+       cm.items[key] = value
+}
+
+// Get is for getting map item
+func (cm *ConcurrentMap) Get(key uint64) (interface{}, bool) {
+       cm.Lock()
+       defer cm.Unlock()
+
+       value, ok := cm.items[key]
+
+       return value, ok
+}
+
+// Remove is for removing map item
+func (cm *ConcurrentMap) Remove(key uint64) {
+       cm.Lock()
+       defer cm.Unlock()
+
+       delete(cm.items, key)
+}
+
+// Iter is for iterating map item
+func (cm *ConcurrentMap) Iter() <-chan ConcurrentMapItem {
+       c := make(chan ConcurrentMapItem)
+
+       f := func() {
+               cm.Lock()
+               defer cm.Unlock()
+
+               for k, v := range cm.items {
+                       c <- ConcurrentMapItem{k, v}
+               }
+               close(c)
+       }
+       go f()
+
+       return c
+}
+
+// CreateServiceMap function
+func CreateServiceMap(cmd *exec.Cmd, serviceName string, appName string) uint64 {
+       serviceID := getServiceIdx()
+       msgChan := make(chan string, 10)
+
+       ServiceCmdMap.Set(serviceID, cmd)
+       ServiceMsgMap.Set(serviceID, msgChan)
+       ServiceNameMap.Set(serviceID, serviceName)
+       ServiceAppNameMap.Set(serviceID, appName)
+
+       return serviceID
+}
+
+// InitServiceMap function
+func InitServiceMap() {
+       ServiceCmdMap = ConcurrentMap{items: make(map[uint64]interface{})}
+       ServiceMsgMap = ConcurrentMap{items: make(map[uint64]interface{})}
+       ServiceNameMap = ConcurrentMap{items: make(map[uint64]interface{})}
+       ServiceAppNameMap = ConcurrentMap{items: make(map[uint64]interface{})}
+}
+
+// DeleteServiceMap function
+func DeleteServiceMap(serviceID uint64) {
+       ServiceCmdMap.Remove(serviceID)
+       ServiceMsgMap.Remove(serviceID)
+       ServiceNameMap.Remove(serviceID)
+       ServiceAppNameMap.Remove(serviceID)
+}
+
+// getServiceIdx() is for getting global serviceID
+func getServiceIdx() uint64 {
+       atomic.AddUint64(&ServiceIdx, 1)
+       return atomic.LoadUint64(&ServiceIdx)
+}
+
+// ServiceCmdMap is that map has service information (KEY : ServiceID / Value : *exec.Cmd)
+var ServiceCmdMap ConcurrentMap
+
+// ServiceMsgMap is that map has service information (KEY : ServiceID / Value : chan string)
+var ServiceMsgMap ConcurrentMap
+
+// ServiceNameMap is that map has service information (KEY : ServiceID / Value : string)
+var ServiceNameMap ConcurrentMap
+
+// ServiceAppNameMap is that map has service information (KEY : ServiceID / Value : string)
+var ServiceAppNameMap ConcurrentMap
+
+// ServiceIdx is for unique service ID
+var ServiceIdx uint64
diff --git a/src/servicemgr/service_discovery.go b/src/servicemgr/service_discovery.go
new file mode 100644 (file)
index 0000000..1d25051
--- /dev/null
@@ -0,0 +1,68 @@
+package servicemgr
+
+import (
+       "fmt"
+
+       "github.com/grandcat/zeroconf"
+)
+
+const (
+       //pass & fail public enum
+       Fail = 0
+       Pass = 1
+)
+
+var exits map[string]chan int = make(map[string]chan int)
+
+func RegisterService(name string, domain string, port int, ret chan int) (int, error) {
+       if name == "" {
+               ret <- Fail
+               return Fail, fmt.Errorf("Missing service name")
+       }
+
+       if domain == "" {
+               domain = "local"
+       }
+
+       if port == 0 {
+               ret <- Fail
+               return Fail, fmt.Errorf("Missing service port")
+       }
+
+       var service string = "_" + name + "._tcp"
+
+       server, err := zeroconf.Register(name, service, domain, port, []string{""}, nil)
+       if err != nil {
+               return Fail, err
+       }
+       defer server.Shutdown()
+
+       exits[name] = make(chan int)
+       ret <- Pass
+
+       select {
+       case <-exits[name]:
+               server.Shutdown()
+       }
+
+       return Pass, nil
+}
+
+func RemoveService(name string) (int, error) {
+       done := make(chan int)
+
+       if exits[name] == nil {
+               return Fail, fmt.Errorf("Service name is invalid")
+       }
+
+       go func() {
+               exits[name] <- Pass
+               done <- Pass
+       }()
+
+       select {
+       case <-done:
+               delete(exits, name)
+       }
+       return Pass, nil
+}