master
go 196 lines 5.7 KB
Raw
1 // SPDX-License-Identifier: GPL-3.0-or-later
2
3 //go:build cgo && ibm_mq
4
5 package pcf
6
7 import (
8 "fmt"
9 "strings"
10 "time"
11
12 "github.com/ibm-messaging/mq-golang/v5/ibmmq"
13 )
14
15 // InquireSubscription queries subscription information from the queue manager
16 func (c *Client) InquireSubscription(subName string) ([]SubscriptionMetrics, error) {
17 c.protocol.Debugf("Inquiring subscriptions, filter: '%s'", subName)
18
19 // Build parameters
20 params := []pcfParameter{}
21
22 // Add subscription name filter if provided
23 if subName != "" {
24 params = append(params, newStringParameter(ibmmq.MQCACF_SUB_NAME, subName))
25 } else {
26 // Use wildcard to get all subscriptions
27 params = append(params, newStringParameter(ibmmq.MQCACF_SUB_NAME, "*"))
28 }
29
30 // Send PCF command
31 response, err := c.sendPCFCommand(ibmmq.MQCMD_INQUIRE_SUBSCRIPTION, params)
32 if err != nil {
33 c.protocol.Errorf("Failed to inquire subscriptions: %v", err)
34 return nil, err
35 }
36
37 // Parse the response using new parameters-based method
38 result := c.parseSubscriptionListResponseFromParams(response)
39
40 if result.InternalErrors > 0 {
41 c.protocol.Warningf("Encountered %d internal errors while parsing subscription list",
42 result.InternalErrors)
43 }
44
45 c.protocol.Debugf("Found %d subscriptions", len(result.Subscriptions))
46 return result.Subscriptions, nil
47 }
48
49 // InquireSubscriptionStatus queries subscription status information
50 func (c *Client) InquireSubscriptionStatus(subName string) (*SubscriptionMetrics, error) {
51 c.protocol.Debugf("Inquiring subscription status for: '%s'", subName)
52
53 // Build parameters - subscription name is required
54 params := []pcfParameter{
55 newStringParameter(ibmmq.MQCACF_SUB_NAME, subName),
56 }
57
58 // Send PCF command
59 response, err := c.sendPCFCommand(ibmmq.MQCMD_INQUIRE_SUB_STATUS, params)
60 if err != nil {
61 c.protocol.Errorf("Failed to inquire subscription status for '%s': %v", subName, err)
62 return nil, err
63 }
64
65 // Parse the response using new parameters-based method
66 result := c.parseSubscriptionStatusResponseFromParams(response)
67
68 if result.InternalErrors > 0 {
69 c.protocol.Warningf("Encountered %d internal errors while parsing subscription status",
70 result.InternalErrors)
71 }
72
73 if len(result.Subscriptions) == 0 {
74 return nil, fmt.Errorf("no status found for subscription: %s", subName)
75 }
76
77 // Return the first (and should be only) subscription
78 sub := result.Subscriptions[0]
79 sub.Name = subName // Ensure name is set
80
81 return &sub, nil
82 }
83
84 // GetSubscriptionAge calculates the age of the last message in seconds
85 func (s *SubscriptionMetrics) GetSubscriptionAge() (int64, error) {
86 if s.LastMessageDate == "" || s.LastMessageTime == "" {
87 return 0, fmt.Errorf("no last message timestamp available")
88 }
89
90 // IBM MQ date format: YYYY-MM-DD
91 // IBM MQ time format: HH.MM.SS
92 dateTimeStr := s.LastMessageDate + " " + strings.Replace(s.LastMessageTime, ".", ":", -1)
93
94 lastMsgTime, err := time.Parse("2006-01-02 15:04:05", dateTimeStr)
95 if err != nil {
96 return 0, fmt.Errorf("failed to parse timestamp: %w", err)
97 }
98
99 age := time.Since(lastMsgTime).Seconds()
100 return int64(age), nil
101 }
102
103 // SubscriptionParseResult contains subscription parsing results
104 type SubscriptionParseResult struct {
105 Subscriptions []SubscriptionMetrics
106 InternalErrors int
107 ErrorCounts map[int32]int
108 }
109
110 // parseSubscriptionListResponseFromParams parses PCF parameters into SubscriptionParseResult
111 func (c *Client) parseSubscriptionListResponseFromParams(params []*ibmmq.PCFParameter) *SubscriptionParseResult {
112 result := &SubscriptionParseResult{
113 Subscriptions: make([]SubscriptionMetrics, 0),
114 ErrorCounts: make(map[int32]int),
115 InternalErrors: 0,
116 }
117
118 // Convert IBM PCFParameter array to attrs format for existing logic
119 attrs := convertPCFParametersToAttrs(params)
120
121 // Create a subscription metrics object from the parameters
122 sub := SubscriptionMetrics{
123 Type: NotCollected,
124 MessageCount: NotCollected,
125 }
126
127 // Get subscription name
128 if name, ok := attrs[ibmmq.MQCACF_SUB_NAME]; ok {
129 if nameStr, ok := name.(string); ok && nameStr != "" {
130 sub.Name = strings.TrimSpace(nameStr)
131 }
132 }
133
134 if sub.Name != "" {
135 result.Subscriptions = append(result.Subscriptions, sub)
136 }
137
138 return result
139 }
140
141 // parseSubscriptionStatusResponseFromParams parses PCF parameters into subscription status
142 func (c *Client) parseSubscriptionStatusResponseFromParams(params []*ibmmq.PCFParameter) *SubscriptionParseResult {
143 result := &SubscriptionParseResult{
144 Subscriptions: make([]SubscriptionMetrics, 0),
145 ErrorCounts: make(map[int32]int),
146 InternalErrors: 0,
147 }
148
149 // Convert IBM PCFParameter array to attrs format for existing logic
150 attrs := convertPCFParametersToAttrs(params)
151
152 // Create a subscription metrics object from the parameters
153 sub := SubscriptionMetrics{
154 Type: NotCollected,
155 MessageCount: NotCollected,
156 }
157
158 // Get subscription name
159 if name, ok := attrs[ibmmq.MQCACF_SUB_NAME]; ok {
160 if nameStr, ok := name.(string); ok && nameStr != "" {
161 sub.Name = strings.TrimSpace(nameStr)
162 }
163 }
164
165 // Get subscription type if available
166 if subType, ok := attrs[ibmmq.MQIACF_SUB_TYPE]; ok {
167 if typeVal, ok := subType.(int32); ok {
168 sub.Type = AttributeValue(typeVal)
169 }
170 }
171
172 // Get message count if available
173 if count, ok := attrs[ibmmq.MQIACF_MESSAGE_COUNT]; ok {
174 if countVal, ok := count.(int32); ok {
175 sub.MessageCount = AttributeValue(countVal)
176 }
177 }
178
179 // Get last message date/time
180 if dateStr, ok := attrs[ibmmq.MQCACF_LAST_MSG_DATE]; ok {
181 if dateVal, ok := dateStr.(string); ok {
182 sub.LastMessageDate = strings.TrimSpace(dateVal)
183 }
184 }
185 if timeStr, ok := attrs[ibmmq.MQCACF_LAST_MSG_TIME]; ok {
186 if timeVal, ok := timeStr.(string); ok {
187 sub.LastMessageTime = strings.TrimSpace(timeVal)
188 }
189 }
190
191 if sub.Name != "" {
192 result.Subscriptions = append(result.Subscriptions, sub)
193 }
194
195 return result
196 }