Skip to content

Commit

Permalink
Support cmd_delay and transaction_retain_seconds
Browse files Browse the repository at this point in the history
  • Loading branch information
ryanmelt committed Nov 25, 2023
1 parent c6ea835 commit d37d98f
Show file tree
Hide file tree
Showing 6 changed files with 71 additions and 27 deletions.
26 changes: 14 additions & 12 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -109,18 +109,19 @@ Minimum required settings:

### Source Entity Configuration

| Setting Name | Description | Allowed Values | Default Value |
| ------------------------------- | ------------------------------------------------------------------------------------------------- | ------------------------- | ------------------------------- |
| root_path | The path to send/receive files from | Valid directory | N/A - Must be given |
| bucket | The bucket to send/receive files from | Valid bucket Name | nil - Serve from mounted volume |
| source_entity_id | The entity id for this CFDP microservice | Any integer | N/A - Must be given |
| 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 |
| eof_sent_indication | Issue EOF-Sent.indication | true or false | true |
| eof_recv_indication | Issue EOF-Recv.indication | true or false | true |
| file_segment_recv_indication | Issue File-Segment-Recv.indication | true or false | true |
| transaction_finished_indication | Issue Transaction-Finished.indication | true or false | true |
| suspended_indication | Issue Suspended.indication | true or false | true |
| resume_indication | Issue Resume.indication | true or false | true |
| Setting Name | Description | Allowed Values | Default Value |
| ------------------------------- | ------------------------------------------------------------------------------------------------- | ----------------------------------- | ------------------------------- |
| root_path | The path to send/receive files from | Valid directory | N/A - Must be given |
| bucket | The bucket to send/receive files from | Valid bucket Name | nil - Serve from mounted volume |
| source_entity_id | The entity id for this CFDP microservice | Any integer | N/A - Must be given |
| 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 |
| eof_sent_indication | Issue EOF-Sent.indication | true or false | true |
| eof_recv_indication | Issue EOF-Recv.indication | true or false | true |
| file_segment_recv_indication | Issue File-Segment-Recv.indication | true or false | true |
| transaction_finished_indication | Issue Transaction-Finished.indication | true or false | true |
| suspended_indication | Issue Suspended.indication | true or false | true |
| resume_indication | Issue Resume.indication | true or false | true |
| transaction_retain_seconds | Time to keep completed transactions in seconds. | Floating point value greater than 0 | 86400 |

### Remote Entity Configuration

Expand Down Expand Up @@ -150,6 +151,7 @@ Minimum required settings:
| transaction_closure_requested | Default closure requested setting | CLOSURE_REQUESTED or CLOSURE_NOT_REQUESTED | CLOSURE_REQUESTED |
| incomplete_file_disposition | What to do with an incomplete file | DISCARD or RETAIN | DISCARD |
| 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 |
| cmd_delay | Delay after sending each PDU in seconds. Defaults to no delay. | Floating point value greater than 0 | nil |

## Known Limitations

Expand Down
1 change: 1 addition & 0 deletions microservices/CFDP/app/controllers/cfdp_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -216,6 +216,7 @@ def check_authorization
end

# Authorized
CfdpMib.cleanup_old_transactions()
return true
end

Expand Down
27 changes: 26 additions & 1 deletion microservices/CFDP/app/models/cfdp_mib.rb
Original file line number Diff line number Diff line change
Expand Up @@ -101,14 +101,16 @@ class CfdpMib
'enable_keep_alive',
'enable_finished',
'enable_eof_nak',
'cmd_delay',
'tlm_info',
'eof_sent_indication',
'eof_recv_indication',
'file_segment_recv_indication',
'transaction_finished_indication',
'suspended_indication',
'resume_indication',
'fault_handler'
'fault_handler',
'transaction_retain_seconds'
]

@@source_entity_id = 0
Expand Down Expand Up @@ -184,6 +186,7 @@ def self.define_entity(entity_id)
entity['enable_keep_alive'] = true
entity['enable_finished'] = true
entity['enable_eof_nak'] = false
entity['cmd_delay'] = nil

# Local Entity Settings
entity['tlm_info'] = []
Expand All @@ -205,6 +208,7 @@ def self.define_entity(entity_id)
entity['fault_handler']["INVALID_FILE_STRUCTURE"] = "IGNORE_ERROR"
entity['fault_handler']["CHECK_LIMIT_REACHED"] = "IGNORE_ERROR"
entity['fault_handler']["UNSUPPORTED_CHECKSUM_TYPE"] = "IGNORE_ERROR"
entity['transaction_retain_seconds'] = 86400.0

# TODO: Use interface connected? to limit opportunities?
@@entities[entity_id] = entity
Expand Down Expand Up @@ -499,6 +503,13 @@ def self.setup
else
raise "Value for MIB setting #{field_name} must be a three part array of target_name, packet_name, item_name"
end
when 'cmd_delay', 'transaction_retain_seconds'
value = Float(value)
if value >= 0
CfdpMib.set_entity_value(current_entity_id, field_name, value)
else
raise "Value for MIB setting #{field_name} must be greater than or equal to zero"
end
when 'immediate_nak_mode', 'crcs_required', 'eof_sent_indication', 'eof_recv_indication', 'file_segment_recv_indication', 'transaction_finished_indication', 'suspended_indication', 'resume_indication',
'enable_acks', 'enable_keep_alive', 'enable_finished', 'enable_eof_nak'
value = OpenC3::ConfigParser.handle_true_false(value)
Expand Down Expand Up @@ -610,4 +621,18 @@ def self.clear
@@root_path = "/"
@@transactions = {}
end

def self.cleanup_old_transactions
to_remove = []
current_time = Time.now.utc
transaction_retain_seconds = @@entities[@@source_entity_id]['transaction_retain_seconds']
@@transactions.each do |id, transaction|
if transaction.complete_time and (current_time - transaction.complete_time) > transaction_retain_seconds
to_remove << id
end
end
to_remove.each do |id|
@@transactions.delete(id)
end
end
end
11 changes: 6 additions & 5 deletions microservices/CFDP/app/models/cfdp_receive_transaction.rb
Original file line number Diff line number Diff line change
Expand Up @@ -174,7 +174,7 @@ def notice_of_completion
fault_location_entity_id: nil)
cmd_params = {}
cmd_params[item_name] = @finished_pdu
cmd(target_name, packet_name, cmd_params, scope: ENV['OPENC3_SCOPE'])
cfdp_cmd(source_entity, target_name, packet_name, cmd_params, scope: ENV['OPENC3_SCOPE'])
rescue => err
abandon() if @state == "CANCELED"
raise err
Expand All @@ -184,6 +184,7 @@ def notice_of_completion

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

if CfdpMib.source_entity['transaction_finished_indication']
Expand Down Expand Up @@ -297,7 +298,7 @@ def update
raise "cmd_info not defined for source entity: #{@metadata_pdu_hash['SOURCE_ENTITY_ID']}" unless target_name and packet_name and item_name
cmd_params = {}
cmd_params[item_name] = @finished_pdu
cmd(target_name, packet_name, cmd_params, scope: ENV['OPENC3_SCOPE'])
cfdp_cmd(source_entity, target_name, packet_name, cmd_params, scope: ENV['OPENC3_SCOPE'])
@finished_count += 1
if @finished_count > CfdpMib.entity(@source_entity_id)['ack_timer_expiration_limit']
# Positive ACK Limit Reached Fault
Expand Down Expand Up @@ -328,7 +329,7 @@ def send_keep_alive
progress: @progress)
cmd_params = {}
cmd_params[item_name] = keep_alive_pdu
cmd(target_name, packet_name, cmd_params, scope: ENV['OPENC3_SCOPE'])
cfdp_cmd(source_entity, target_name, packet_name, cmd_params, scope: ENV['OPENC3_SCOPE'])
end

def send_naks(force = false)
Expand Down Expand Up @@ -421,7 +422,7 @@ def send_naks(force = false)
start_of_scope = end_of_scope
cmd_params = {}
cmd_params[item_name] = nak_pdu
cmd(target_name, packet_name, cmd_params, scope: ENV['OPENC3_SCOPE'])
cfdp_cmd(source_entity, target_name, packet_name, cmd_params, scope: ENV['OPENC3_SCOPE'])
end
break if segment_requests.length <= 0
end
Expand Down Expand Up @@ -520,7 +521,7 @@ def handle_pdu(pdu_hash)
transaction_status: "ACTIVE")
cmd_params = {}
cmd_params[item_name] = ack_pdu
cmd(target_name, packet_name, cmd_params, scope: ENV['OPENC3_SCOPE'])
cfdp_cmd(source_entity, target_name, packet_name, cmd_params, scope: ENV['OPENC3_SCOPE'])
end

# Note: This also handles canceled
Expand Down
15 changes: 8 additions & 7 deletions microservices/CFDP/app/models/cfdp_source_transaction.rb
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ def update
# Resend eof pdu
cmd_params = {}
cmd_params[@item_name] = @eof_pdu
cmd(@target_name, @packet_name, cmd_params, scope: ENV['OPENC3_SCOPE'])
cfdp_cmd(@destination_entity, @target_name, @packet_name, cmd_params, scope: ENV['OPENC3_SCOPE'])
@eof_count += 1
if @eof_count > @destination_entity['ack_timer_expiration_limit']
# Positive ACK Limit Reached Fault
Expand Down Expand Up @@ -206,7 +206,7 @@ def copy_file(
transmission_mode: @transmission_mode)
cmd_params = {}
cmd_params[@item_name] = @metadata_pdu
cmd(@target_name, @packet_name, cmd_params, scope: ENV['OPENC3_SCOPE'])
cfdp_cmd(@destination_entity, @target_name, @packet_name, cmd_params, scope: ENV['OPENC3_SCOPE'])

if source_file
checksum = get_checksum(@destination_entity['default_checksum_type'])
Expand Down Expand Up @@ -236,7 +236,7 @@ def copy_file(
transmission_mode: @transmission_mode)
cmd_params = {}
cmd_params[@item_name] = file_data_pdu
cmd(@target_name, @packet_name, cmd_params, scope: ENV['OPENC3_SCOPE'])
cfdp_cmd(@destination_entity, @target_name, @packet_name, cmd_params, scope: ENV['OPENC3_SCOPE'])
checksum.add(offset, file_data)
offset += file_data.length
@progress = offset
Expand Down Expand Up @@ -271,7 +271,7 @@ def copy_file(
canceling_entity_id: @canceling_entity_id)
cmd_params = {}
cmd_params[@item_name] = @eof_pdu
cmd(@target_name, @packet_name, cmd_params, scope: ENV['OPENC3_SCOPE'])
cfdp_cmd(@destination_entity, @target_name, @packet_name, cmd_params, scope: ENV['OPENC3_SCOPE'])
rescue => err
abandon() if @canceling_entity_id
raise err
Expand Down Expand Up @@ -327,6 +327,7 @@ def notice_of_completion
end
@state = "FINISHED" unless @state == "CANCELED" or @state == "ABANDONED"
@transaction_status = "TERMINATED"
@complete_time = Time.now.utc
OpenC3::Logger.info("CFDP Finished Source Transaction #{@id}, #{@condition_code}", scope: ENV['OPENC3_SCOPE'])

if CfdpMib.source_entity['transaction_finished_indication']
Expand Down Expand Up @@ -369,7 +370,7 @@ def handle_pdu(pdu_hash)
transaction_status: @transaction_status)
cmd_params = {}
cmd_params[@item_name] = ack_pdu
cmd(@target_name, @packet_name, cmd_params, scope: ENV['OPENC3_SCOPE'])
cfdp_cmd(@destination_entity, @target_name, @packet_name, cmd_params, scope: ENV['OPENC3_SCOPE'])
end

when "ACK"
Expand Down Expand Up @@ -412,7 +413,7 @@ def handle_nak(pdu_hash)
# Send Metadata PDU
cmd_params = {}
cmd_params[@item_name] = @metadata_pdu
cmd(@target_name, @packet_name, cmd_params, scope: ENV['OPENC3_SCOPE'])
cfdp_cmd(@destination_entity, @target_name, @packet_name, cmd_params, scope: ENV['OPENC3_SCOPE'])
else
# Send File Data PDU(s)
offset = start_offset
Expand All @@ -438,7 +439,7 @@ def handle_nak(pdu_hash)
transmission_mode: @transmission_mode)
cmd_params = {}
cmd_params[@item_name] = file_data_pdu
cmd(@target_name, @packet_name, cmd_params, scope: ENV['OPENC3_SCOPE'])
cfdp_cmd(@destination_entity, @target_name, @packet_name, cmd_params, scope: ENV['OPENC3_SCOPE'])
offset += file_data.length
end
end
Expand Down
18 changes: 16 additions & 2 deletions microservices/CFDP/app/models/cfdp_transaction.rb
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,8 @@ class CfdpTransaction
attr_reader :file_status
attr_reader :metadata_pdu_hash
attr_reader :metadata_pdu_count
attr_reader :create_time
attr_reader :complete_time
attr_accessor :proxy_response_info
attr_accessor :proxy_response_needed

Expand All @@ -59,19 +61,24 @@ def initialize
@proxy_response_needed = false
@source_file_name = nil
@destination_file_name = nil
@create_time = Time.now.utc
@complete_time = nil
end

def as_json(*args)
return {
result = {
"id" => @id,
"frozen" => @frozen,
"state" => @state,
"transaction_status" => @transaction_status,
"progress" => @progress,
"condition_code" => @condition_code,
"source_file_name" => @source_file_name,
"destination_file_name" => @destination_file_name
"destination_file_name" => @destination_file_name,
"create_time" => @create_time.iso8601(6)
}
result["complete_time"] = @complete_time.iso8601(6) if @complete_time
return result
end

def suspend
Expand Down Expand Up @@ -104,6 +111,7 @@ def cancel(canceling_entity_id = nil)
end
@state = "CANCELED"
@transaction_status = "TERMINATED"
@complete_time = Time.now.utc
end
end

Expand All @@ -113,6 +121,7 @@ def abandon
@state = "ABANDONED"
@transaction_status = "TERMINATED"
CfdpTopic.write_indication("Abandoned", transaction_id: @id, condition_code: @condition_code, progress: @progress)
@complete_time = Time.now.utc
end
end

Expand Down Expand Up @@ -185,4 +194,9 @@ def get_checksum(checksum_type)
return nil
end
end

def cfdp_cmd(entity, target_name, packet_name, cmd_params, scope: ENV['OPENC3_SCOPE'])
cmd(target_name, packet_name, cmd_params, scope: ENV['OPENC3_SCOPE'])
sleep(entity['cmd_delay']) if entity['cmd_delay']
end
end

0 comments on commit d37d98f

Please sign in to comment.