in internal/oraclediscovery/oraclediscovery.go [464:555]
func populateInstanceHandlers(ctx context.Context, r io.Reader, listener *odpb.Discovery_Listener) error {
var (
currentService *odpb.Discovery_Listener_Service
currentInstance *odpb.Discovery_Listener_Service_DatabaseInstance
currentHandler *odpb.Discovery_Listener_Service_DatabaseInstance_Handler
currentDispatcher *odpb.Discovery_Listener_Service_DatabaseInstance_Handler_Dispatcher
)
scanner := bufio.NewScanner(r)
reService := regexp.MustCompile(`Service\s+"([^"]+)"\s+has\s+\d+\s+instance\(s\)`)
reInstance := regexp.MustCompile(`Instance\s+"([^"]+)",\s+status\s+(\w+)`)
reHandler := regexp.MustCompile(`"([^"]+)"\s+established:(\d+)\s+refused:(\d+)(\s+current:(\d+))?(\s+max:(\d+))?\s+state:(\w+)`)
reDispatcher := regexp.MustCompile(`DISPATCHER\s+<machine:\s+([^,]+),\s+pid:\s+(\d+)>`)
reAddress := regexp.MustCompile(`\(ADDRESS=\(PROTOCOL=(ipc|tcp|tcps|nmp)\)(\(HOST=([^)]+)\))?(\(PORT=(\d+)\))?(\(SERVER=([^)]+)\))?(\(PIPE=([^)]+)\))?(\(KEY=([^)]+)\))?\)`)
findServiceByName := func(name string) *odpb.Discovery_Listener_Service {
for _, service := range listener.Services {
if service.Name == name {
return service
}
}
return nil
}
findInstanceByName := func(service *odpb.Discovery_Listener_Service, name string) *odpb.Discovery_Listener_Service_DatabaseInstance {
for _, instance := range service.Instances {
if instance.Name == name {
return instance
}
}
return nil
}
for scanner.Scan() {
line := strings.TrimSpace(scanner.Text())
switch {
case reService.MatchString(line):
serviceName := reService.FindStringSubmatch(line)[1]
currentService = findServiceByName(serviceName)
case reInstance.MatchString(line) && currentService != nil:
instanceName := reInstance.FindStringSubmatch(line)[1]
currentInstance = findInstanceByName(currentService, instanceName)
case reHandler.MatchString(line) && currentInstance != nil:
matches := reHandler.FindStringSubmatch(line)
name := matches[1]
state := matches[8]
currentHandler = &odpb.Discovery_Listener_Service_DatabaseInstance_Handler{
Name: name,
State: parseHandlerState(state), // TODO: Integrate this into the metrics collection pipeline
}
if name == "DEDICATED" {
currentHandler.Type = &odpb.Discovery_Listener_Service_DatabaseInstance_Handler_DedicatedServer_{
DedicatedServer: &odpb.Discovery_Listener_Service_DatabaseInstance_Handler_DedicatedServer{},
}
}
currentInstance.Handlers = append(currentInstance.Handlers, currentHandler)
case reDispatcher.MatchString(line) && currentHandler != nil:
matches := reDispatcher.FindStringSubmatch(line)
machineName := matches[1]
pid, err := strconv.Atoi(matches[2])
if err != nil {
log.CtxLogger(ctx).Warnw("Failed to parse PID", "error", err, "pid_string", matches[2])
}
currentDispatcher = &odpb.Discovery_Listener_Service_DatabaseInstance_Handler_Dispatcher{
MachineName: machineName,
Pid: uint32(pid),
}
currentHandler.Type = &odpb.Discovery_Listener_Service_DatabaseInstance_Handler_Dispatcher_{
Dispatcher: currentDispatcher,
}
case reAddress.MatchString(line) && currentDispatcher != nil:
matches := reAddress.FindStringSubmatch(line)
port, err := strconv.Atoi(matches[5])
if err != nil {
log.CtxLogger(ctx).Warnw("Failed to parse port", "error", err, "port_string", matches[5])
}
currentDispatcher.Address = &odpb.Discovery_Listener_Service_DatabaseInstance_Handler_Dispatcher_Address{
Protocol: matches[1],
Host: matches[3],
Port: uint32(port),
}
}
}
if err := scanner.Err(); err != nil {
return err
}
return nil
}