Skip to content

Commit 31c8447

Browse files
authored
Merge pull request #8 from OpenC3/cmd_delay_and_transaction_retain_seconds
Cmd delay and transaction retain seconds
2 parents 322f08a + 277491b commit 31c8447

File tree

6 files changed

+71
-27
lines changed

6 files changed

+71
-27
lines changed

README.md

+14-12
Original file line numberDiff line numberDiff line change
@@ -109,18 +109,19 @@ Minimum required settings:
109109

110110
### Source Entity Configuration
111111

112-
| Setting Name | Description | Allowed Values | Default Value |
113-
| ------------------------------- | ------------------------------------------------------------------------------------------------- | ------------------------- | ------------------------------- |
114-
| root_path | The path to send/receive files from | Valid directory | N/A - Must be given |
115-
| bucket | The bucket to send/receive files from | Valid bucket Name | nil - Serve from mounted volume |
116-
| source_entity_id | The entity id for this CFDP microservice | Any integer | N/A - Must be given |
117-
| tlm_info | A target_name, packet_name, and item_name to receive PDUs. Multiple tlm_info options can be given | COSMOS packet information | N/A - Must be given |
118-
| eof_sent_indication | Issue EOF-Sent.indication | true or false | true |
119-
| eof_recv_indication | Issue EOF-Recv.indication | true or false | true |
120-
| file_segment_recv_indication | Issue File-Segment-Recv.indication | true or false | true |
121-
| transaction_finished_indication | Issue Transaction-Finished.indication | true or false | true |
122-
| suspended_indication | Issue Suspended.indication | true or false | true |
123-
| resume_indication | Issue Resume.indication | true or false | true |
112+
| Setting Name | Description | Allowed Values | Default Value |
113+
| ------------------------------- | ------------------------------------------------------------------------------------------------- | ----------------------------------- | ------------------------------- |
114+
| root_path | The path to send/receive files from | Valid directory | N/A - Must be given |
115+
| bucket | The bucket to send/receive files from | Valid bucket Name | nil - Serve from mounted volume |
116+
| source_entity_id | The entity id for this CFDP microservice | Any integer | N/A - Must be given |
117+
| tlm_info | A target_name, packet_name, and item_name to receive PDUs. Multiple tlm_info options can be given | COSMOS packet information | N/A - Must be given |
118+
| eof_sent_indication | Issue EOF-Sent.indication | true or false | true |
119+
| eof_recv_indication | Issue EOF-Recv.indication | true or false | true |
120+
| file_segment_recv_indication | Issue File-Segment-Recv.indication | true or false | true |
121+
| transaction_finished_indication | Issue Transaction-Finished.indication | true or false | true |
122+
| suspended_indication | Issue Suspended.indication | true or false | true |
123+
| resume_indication | Issue Resume.indication | true or false | true |
124+
| transaction_retain_seconds | Time to keep completed transactions in seconds. | Floating point value greater than 0 | 86400 |
124125

125126
### Remote Entity Configuration
126127

@@ -150,6 +151,7 @@ Minimum required settings:
150151
| transaction_closure_requested | Default closure requested setting | CLOSURE_REQUESTED or CLOSURE_NOT_REQUESTED | CLOSURE_REQUESTED |
151152
| incomplete_file_disposition | What to do with an incomplete file | DISCARD or RETAIN | DISCARD |
152153
| fault_handler | Fault handler setting | (ACK_LIMIT_REACHED, KEEP_ALIVE_LIMIT_REACHED, INVALID_TRANSMISSION_MODE, FILESTORE_REJECTION, FILE_CHECKSUM_FAILURE, FILE_SIZE_ERROR, NAK_LIMIT_REACHED, INACTIVITY_DETECTED, INVALID_FILE_STRUCTURE, CHECK_LIMIT_REACHED, or UNSUPPORTED_CHECKSUM_TYPE) followed by (ISSUE_NOTICE_OF_CANCELLATION, ISSUE_NOTICE_OF_SUSPENSION, IGNORE_ERROR, or ABANDON_TRANSACTION) | See Code |
154+
| cmd_delay | Delay after sending each PDU in seconds. Defaults to no delay. | Floating point value greater than 0 | nil |
153155

154156
## Known Limitations
155157

microservices/CFDP/app/controllers/cfdp_controller.rb

+1
Original file line numberDiff line numberDiff line change
@@ -216,6 +216,7 @@ def check_authorization
216216
end
217217

218218
# Authorized
219+
CfdpMib.cleanup_old_transactions()
219220
return true
220221
end
221222

microservices/CFDP/app/models/cfdp_mib.rb

+26-1
Original file line numberDiff line numberDiff line change
@@ -101,14 +101,16 @@ class CfdpMib
101101
'enable_keep_alive',
102102
'enable_finished',
103103
'enable_eof_nak',
104+
'cmd_delay',
104105
'tlm_info',
105106
'eof_sent_indication',
106107
'eof_recv_indication',
107108
'file_segment_recv_indication',
108109
'transaction_finished_indication',
109110
'suspended_indication',
110111
'resume_indication',
111-
'fault_handler'
112+
'fault_handler',
113+
'transaction_retain_seconds'
112114
]
113115

114116
@@source_entity_id = 0
@@ -184,6 +186,7 @@ def self.define_entity(entity_id)
184186
entity['enable_keep_alive'] = true
185187
entity['enable_finished'] = true
186188
entity['enable_eof_nak'] = false
189+
entity['cmd_delay'] = nil
187190

188191
# Local Entity Settings
189192
entity['tlm_info'] = []
@@ -205,6 +208,7 @@ def self.define_entity(entity_id)
205208
entity['fault_handler']["INVALID_FILE_STRUCTURE"] = "IGNORE_ERROR"
206209
entity['fault_handler']["CHECK_LIMIT_REACHED"] = "IGNORE_ERROR"
207210
entity['fault_handler']["UNSUPPORTED_CHECKSUM_TYPE"] = "IGNORE_ERROR"
211+
entity['transaction_retain_seconds'] = 86400.0
208212

209213
# TODO: Use interface connected? to limit opportunities?
210214
@@entities[entity_id] = entity
@@ -499,6 +503,13 @@ def self.setup
499503
else
500504
raise "Value for MIB setting #{field_name} must be a three part array of target_name, packet_name, item_name"
501505
end
506+
when 'cmd_delay', 'transaction_retain_seconds'
507+
value = Float(value)
508+
if value >= 0
509+
CfdpMib.set_entity_value(current_entity_id, field_name, value)
510+
else
511+
raise "Value for MIB setting #{field_name} must be greater than or equal to zero"
512+
end
502513
when 'immediate_nak_mode', 'crcs_required', 'eof_sent_indication', 'eof_recv_indication', 'file_segment_recv_indication', 'transaction_finished_indication', 'suspended_indication', 'resume_indication',
503514
'enable_acks', 'enable_keep_alive', 'enable_finished', 'enable_eof_nak'
504515
value = OpenC3::ConfigParser.handle_true_false(value)
@@ -610,4 +621,18 @@ def self.clear
610621
@@root_path = "/"
611622
@@transactions = {}
612623
end
624+
625+
def self.cleanup_old_transactions
626+
to_remove = []
627+
current_time = Time.now.utc
628+
transaction_retain_seconds = @@entities[@@source_entity_id]['transaction_retain_seconds']
629+
@@transactions.each do |id, transaction|
630+
if transaction.complete_time and (current_time - transaction.complete_time) > transaction_retain_seconds
631+
to_remove << id
632+
end
633+
end
634+
to_remove.each do |id|
635+
@@transactions.delete(id)
636+
end
637+
end
613638
end

microservices/CFDP/app/models/cfdp_receive_transaction.rb

+6-5
Original file line numberDiff line numberDiff line change
@@ -174,7 +174,7 @@ def notice_of_completion
174174
fault_location_entity_id: nil)
175175
cmd_params = {}
176176
cmd_params[item_name] = @finished_pdu
177-
cmd(target_name, packet_name, cmd_params, scope: ENV['OPENC3_SCOPE'])
177+
cfdp_cmd(source_entity, target_name, packet_name, cmd_params, scope: ENV['OPENC3_SCOPE'])
178178
rescue => err
179179
abandon() if @state == "CANCELED"
180180
raise err
@@ -184,6 +184,7 @@ def notice_of_completion
184184

185185
@state = "FINISHED" unless @state == "CANCELED" or @state == "ABANDONED"
186186
@transaction_status = "TERMINATED"
187+
@complete_time = Time.now.utc
187188
OpenC3::Logger.info("CFDP Finished Receive Transaction #{@id}, #{@condition_code}", scope: ENV['OPENC3_SCOPE'])
188189

189190
if CfdpMib.source_entity['transaction_finished_indication']
@@ -297,7 +298,7 @@ def update
297298
raise "cmd_info not defined for source entity: #{@metadata_pdu_hash['SOURCE_ENTITY_ID']}" unless target_name and packet_name and item_name
298299
cmd_params = {}
299300
cmd_params[item_name] = @finished_pdu
300-
cmd(target_name, packet_name, cmd_params, scope: ENV['OPENC3_SCOPE'])
301+
cfdp_cmd(source_entity, target_name, packet_name, cmd_params, scope: ENV['OPENC3_SCOPE'])
301302
@finished_count += 1
302303
if @finished_count > CfdpMib.entity(@source_entity_id)['ack_timer_expiration_limit']
303304
# Positive ACK Limit Reached Fault
@@ -328,7 +329,7 @@ def send_keep_alive
328329
progress: @progress)
329330
cmd_params = {}
330331
cmd_params[item_name] = keep_alive_pdu
331-
cmd(target_name, packet_name, cmd_params, scope: ENV['OPENC3_SCOPE'])
332+
cfdp_cmd(source_entity, target_name, packet_name, cmd_params, scope: ENV['OPENC3_SCOPE'])
332333
end
333334

334335
def send_naks(force = false)
@@ -421,7 +422,7 @@ def send_naks(force = false)
421422
start_of_scope = end_of_scope
422423
cmd_params = {}
423424
cmd_params[item_name] = nak_pdu
424-
cmd(target_name, packet_name, cmd_params, scope: ENV['OPENC3_SCOPE'])
425+
cfdp_cmd(source_entity, target_name, packet_name, cmd_params, scope: ENV['OPENC3_SCOPE'])
425426
end
426427
break if segment_requests.length <= 0
427428
end
@@ -520,7 +521,7 @@ def handle_pdu(pdu_hash)
520521
transaction_status: "ACTIVE")
521522
cmd_params = {}
522523
cmd_params[item_name] = ack_pdu
523-
cmd(target_name, packet_name, cmd_params, scope: ENV['OPENC3_SCOPE'])
524+
cfdp_cmd(source_entity, target_name, packet_name, cmd_params, scope: ENV['OPENC3_SCOPE'])
524525
end
525526

526527
# Note: This also handles canceled

microservices/CFDP/app/models/cfdp_source_transaction.rb

+8-7
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,7 @@ def update
9696
# Resend eof pdu
9797
cmd_params = {}
9898
cmd_params[@item_name] = @eof_pdu
99-
cmd(@target_name, @packet_name, cmd_params, scope: ENV['OPENC3_SCOPE'])
99+
cfdp_cmd(@destination_entity, @target_name, @packet_name, cmd_params, scope: ENV['OPENC3_SCOPE'])
100100
@eof_count += 1
101101
if @eof_count > @destination_entity['ack_timer_expiration_limit']
102102
# Positive ACK Limit Reached Fault
@@ -206,7 +206,7 @@ def copy_file(
206206
transmission_mode: @transmission_mode)
207207
cmd_params = {}
208208
cmd_params[@item_name] = @metadata_pdu
209-
cmd(@target_name, @packet_name, cmd_params, scope: ENV['OPENC3_SCOPE'])
209+
cfdp_cmd(@destination_entity, @target_name, @packet_name, cmd_params, scope: ENV['OPENC3_SCOPE'])
210210

211211
if source_file
212212
checksum = get_checksum(@destination_entity['default_checksum_type'])
@@ -236,7 +236,7 @@ def copy_file(
236236
transmission_mode: @transmission_mode)
237237
cmd_params = {}
238238
cmd_params[@item_name] = file_data_pdu
239-
cmd(@target_name, @packet_name, cmd_params, scope: ENV['OPENC3_SCOPE'])
239+
cfdp_cmd(@destination_entity, @target_name, @packet_name, cmd_params, scope: ENV['OPENC3_SCOPE'])
240240
checksum.add(offset, file_data)
241241
offset += file_data.length
242242
@progress = offset
@@ -271,7 +271,7 @@ def copy_file(
271271
canceling_entity_id: @canceling_entity_id)
272272
cmd_params = {}
273273
cmd_params[@item_name] = @eof_pdu
274-
cmd(@target_name, @packet_name, cmd_params, scope: ENV['OPENC3_SCOPE'])
274+
cfdp_cmd(@destination_entity, @target_name, @packet_name, cmd_params, scope: ENV['OPENC3_SCOPE'])
275275
rescue => err
276276
abandon() if @canceling_entity_id
277277
raise err
@@ -327,6 +327,7 @@ def notice_of_completion
327327
end
328328
@state = "FINISHED" unless @state == "CANCELED" or @state == "ABANDONED"
329329
@transaction_status = "TERMINATED"
330+
@complete_time = Time.now.utc
330331
OpenC3::Logger.info("CFDP Finished Source Transaction #{@id}, #{@condition_code}", scope: ENV['OPENC3_SCOPE'])
331332

332333
if CfdpMib.source_entity['transaction_finished_indication']
@@ -369,7 +370,7 @@ def handle_pdu(pdu_hash)
369370
transaction_status: @transaction_status)
370371
cmd_params = {}
371372
cmd_params[@item_name] = ack_pdu
372-
cmd(@target_name, @packet_name, cmd_params, scope: ENV['OPENC3_SCOPE'])
373+
cfdp_cmd(@destination_entity, @target_name, @packet_name, cmd_params, scope: ENV['OPENC3_SCOPE'])
373374
end
374375

375376
when "ACK"
@@ -412,7 +413,7 @@ def handle_nak(pdu_hash)
412413
# Send Metadata PDU
413414
cmd_params = {}
414415
cmd_params[@item_name] = @metadata_pdu
415-
cmd(@target_name, @packet_name, cmd_params, scope: ENV['OPENC3_SCOPE'])
416+
cfdp_cmd(@destination_entity, @target_name, @packet_name, cmd_params, scope: ENV['OPENC3_SCOPE'])
416417
else
417418
# Send File Data PDU(s)
418419
offset = start_offset
@@ -438,7 +439,7 @@ def handle_nak(pdu_hash)
438439
transmission_mode: @transmission_mode)
439440
cmd_params = {}
440441
cmd_params[@item_name] = file_data_pdu
441-
cmd(@target_name, @packet_name, cmd_params, scope: ENV['OPENC3_SCOPE'])
442+
cfdp_cmd(@destination_entity, @target_name, @packet_name, cmd_params, scope: ENV['OPENC3_SCOPE'])
442443
offset += file_data.length
443444
end
444445
end

microservices/CFDP/app/models/cfdp_transaction.rb

+16-2
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,8 @@ class CfdpTransaction
3737
attr_reader :file_status
3838
attr_reader :metadata_pdu_hash
3939
attr_reader :metadata_pdu_count
40+
attr_reader :create_time
41+
attr_reader :complete_time
4042
attr_accessor :proxy_response_info
4143
attr_accessor :proxy_response_needed
4244

@@ -59,19 +61,24 @@ def initialize
5961
@proxy_response_needed = false
6062
@source_file_name = nil
6163
@destination_file_name = nil
64+
@create_time = Time.now.utc
65+
@complete_time = nil
6266
end
6367

6468
def as_json(*args)
65-
return {
69+
result = {
6670
"id" => @id,
6771
"frozen" => @frozen,
6872
"state" => @state,
6973
"transaction_status" => @transaction_status,
7074
"progress" => @progress,
7175
"condition_code" => @condition_code,
7276
"source_file_name" => @source_file_name,
73-
"destination_file_name" => @destination_file_name
77+
"destination_file_name" => @destination_file_name,
78+
"create_time" => @create_time.iso8601(6)
7479
}
80+
result["complete_time"] = @complete_time.iso8601(6) if @complete_time
81+
return result
7582
end
7683

7784
def suspend
@@ -104,6 +111,7 @@ def cancel(canceling_entity_id = nil)
104111
end
105112
@state = "CANCELED"
106113
@transaction_status = "TERMINATED"
114+
@complete_time = Time.now.utc
107115
end
108116
end
109117

@@ -113,6 +121,7 @@ def abandon
113121
@state = "ABANDONED"
114122
@transaction_status = "TERMINATED"
115123
CfdpTopic.write_indication("Abandoned", transaction_id: @id, condition_code: @condition_code, progress: @progress)
124+
@complete_time = Time.now.utc
116125
end
117126
end
118127

@@ -185,4 +194,9 @@ def get_checksum(checksum_type)
185194
return nil
186195
end
187196
end
197+
198+
def cfdp_cmd(entity, target_name, packet_name, cmd_params, scope: ENV['OPENC3_SCOPE'])
199+
cmd(target_name, packet_name, cmd_params, scope: ENV['OPENC3_SCOPE'])
200+
sleep(entity['cmd_delay']) if entity['cmd_delay']
201+
end
188202
end

0 commit comments

Comments
 (0)