From aef2c3629718705975a181a345d3908776b14af5 Mon Sep 17 00:00:00 2001 From: Jeffrey Armstrong Date: Mon, 5 Apr 2021 16:30:15 -0400 Subject: Fixed checkin json to return a name of instructions needed and a job id --- captain/api.f90 | 49 ++++++++++++++++++++++++++--- common/utilities.F90 | 56 +++++++++++++++++++++++++++++++++ player/endpoints.f90 | 73 ++++++++++--------------------------------- player/instructions.f90 | 41 ++++++++++++++++++++++-- player/levitating-player.prj | 74 ++++++++++++++++++++++++++------------------ player/player.F90 | 30 ++++++++++++------ 6 files changed, 221 insertions(+), 102 deletions(-) diff --git a/captain/api.f90 b/captain/api.f90 index 9e92185..4594ba9 100644 --- a/captain/api.f90 +++ b/captain/api.f90 @@ -3,9 +3,31 @@ implicit none character(*), parameter::RESPONSE_JSON_OKAY = '{"status": "okay"}' character(*), parameter::RESPONSE_JSON_IDLE = '{"status": "idle"}' + character(*), parameter::RESPONSE_JSON_WORK_AVAILABLE = & + '{"status": "pending", "job": {job_number}, "instruction": "{instruction_name}"}' contains + function build_job_available_json(job_id) result(json_text) + use captain_db + use utilities, only: replace_field + implicit none + + integer, intent(in)::job_id + character(len=:), pointer::json_text + integer::instruction_id + character(PLAYER_NAME_LENGTH)::instruction_name + + instruction_id = get_job_instruction(job_id) + call get_instruction_name(instruction_id, instruction_name) + + allocate(character(len=(len(RESPONSE_JSON_WORK_AVAILABLE)+len_trim(instruction_name)+32)) :: json_text) + json_text = RESPONSE_JSON_WORK_AVAILABLE + call replace_field(json_text, "job_number", job_id) + call replace_field(json_text, "instruction_name", instruction_name) + + end function build_job_available_json + subroutine handle_task_request(req) use server_response use captain_db @@ -44,8 +66,10 @@ contains type(response)::resp character(8)::job_text - character(PLAYER_NAME_LENGTH)::player + character(PLAYER_NAME_LENGTH)::player, instruction integer::job_i, player_i, instruction_i, ierr + + character(len=:), pointer::checkin_work_json ! Complete - "/api/player/{name}/job/{jobid}/complete" ! Failed - "/api/player/{name}/job/{jobid}/failed" @@ -81,12 +105,29 @@ contains resp%code = GEMINI_CODE_SUCCESS call resp%set_body_contents(RESPONSE_JSON_IDLE) else - resp%code = GEMINI_CODE_SUCCESS - instruction_i = get_job_instruction(job_i) - resp%body_filename => get_instructions_static_filename(instruction_i) + checkin_work_json => build_job_available_json(job_i) + if(associated(checkin_work_json)) then + resp%code = GEMINI_CODE_SUCCESS + call resp%set_body_contents(checkin_work_json, "application/json") + deallocate(checkin_work_json) + else + resp%code = GEMINI_CODE_PERMFAIL + end if + end if + + ! Instruction - /api/instructions/{name} + else if(trim(req%component(2)) == "instruction") then + + call req%path_component(3, instruction) + resp%body_filename => get_special_full_filename("instructions", trim(instruction)//".json") + if(associated(resp%body_filename)) then resp%temporary_file = .false. + resp%code = GEMINI_CODE_SUCCESS resp%body_mimetype = "application/json" + else + resp%code = GEMINI_CODE_PERMFAIL end if + end if end function api_request_gemini diff --git a/common/utilities.F90 b/common/utilities.F90 index 895e604..d4b7b81 100644 --- a/common/utilities.F90 +++ b/common/utilities.F90 @@ -6,6 +6,11 @@ module utilities character, parameter::dir_sep = '/' #endif + interface replace_field + module procedure replace_field_text + module procedure replace_field_int + end interface + contains function is_absolute_path(path) @@ -219,4 +224,55 @@ contains end subroutine delete_file + subroutine replace_field_text(str, field, val) + implicit none + + character(*), intent(inout)::str + character(*), intent(in)::field + character(*), intent(in)::val + + character(len=:), allocatable::holding + integer::length_estimate + integer::field_location, i + + ! This is too big, but close enough + length_estimate = len_trim(str) + len_trim(val) + allocate(character(len=length_estimate) :: holding) + holding = " " + + print *, trim(str) + + ! Find the field + field_location = index(str, "{"//trim(field)//"}") + if(field_location > 0) then + + i = field_location + len_trim(field) + 2 + holding = str(1:field_location-1)//trim(val)//str(i:len_trim(str)) + + ! Put the results back now + str = holding + + end if + + print *, trim(str) + + deallocate(holding) + + end subroutine replace_field_text + + subroutine replace_field_int(str, field, val) + implicit none + + character(*), intent(inout)::str + character(*), intent(in)::field + integer, intent(in)::val + + character(16)::int_text + + write(int_text, *) val + + call replace_field_text(str, field, trim(adjustl(int_text))) + + end subroutine replace_field_int + end module utilities \ No newline at end of file diff --git a/player/endpoints.f90 b/player/endpoints.f90 index 6a2c955..8c655d4 100644 --- a/player/endpoints.f90 +++ b/player/endpoints.f90 @@ -5,6 +5,7 @@ implicit none character(*), parameter::LOCATION_STATUS = "/api/player/{name}/job/{jobid}/task/{step}" character(*), parameter::LOCATION_JOB_COMPLETE = "/api/player/{name}/job/{jobid}/complete" character(*), parameter::LOCATION_JOB_FAILED = "/api/player/{name}/job/{jobid}/failed" + character(*), parameter::LOCATION_INSTRUCTIONS = "/api/instruction/{name}" integer, parameter::STATUS_STARTING=1 integer, parameter::STATUS_COMPLETED=2 @@ -16,11 +17,6 @@ implicit none "failed ", & "inprogress" /) - interface replace_field - module procedure replace_field_text - module procedure replace_field_int - end interface - contains subroutine base_url(server, location, post, res) @@ -39,59 +35,9 @@ contains end subroutine base_url - subroutine replace_field_text(str, field, val) - implicit none - - character(*), intent(inout)::str - character(*), intent(in)::field - character(*), intent(in)::val - - character(len=:), allocatable::holding - integer::length_estimate - integer::field_location, i, j - - ! This is too big, but close enough - length_estimate = len_trim(str) + len_trim(val) - allocate(character(len=length_estimate) :: holding) - holding = " " - - print *, trim(str) - - ! Find the field - field_location = index(str, "{"//trim(field)//"}") - if(field_location > 0) then - - i = field_location + len_trim(field) + 2 - holding = str(1:field_location-1)//trim(val)//str(i:len_trim(str)) - - ! Put the results back now - str = holding - - end if - - print *, trim(str) - - deallocate(holding) - - end subroutine replace_field_text - - subroutine replace_field_int(str, field, val) - implicit none - - character(*), intent(inout)::str - character(*), intent(in)::field - integer, intent(in)::val - - character(16)::int_text - - write(int_text, *) val - - call replace_field_text(str, field, trim(adjustl(int_text))) - - end subroutine replace_field_int - subroutine get_check_in_url(res) use config + use utilities, only: replace_field implicit none character(*), intent(out)::res @@ -103,6 +49,7 @@ contains subroutine get_status_url(job, step, url, posting, status) use config + use utilities, only: replace_field implicit none integer, intent(in)::job @@ -130,6 +77,7 @@ contains subroutine get_job_report_url(job, success, res) use config + use utilities, only: replace_field implicit none integer, intent(in)::job @@ -146,4 +94,17 @@ contains end subroutine get_job_report_url + subroutine get_instruction_url(instruction, url) + use config + use utilities, only: replace_field + implicit none + + character(*), intent(in)::instruction + character(*), intent(out)::url + + call base_url(captain, LOCATION_INSTRUCTIONS, .false., url) + call replace_field(url, "name", instruction) + + end subroutine get_instruction_url + end module player_endpoints diff --git a/player/instructions.f90 b/player/instructions.f90 index 61502da..273c379 100644 --- a/player/instructions.f90 +++ b/player/instructions.f90 @@ -40,6 +40,42 @@ contains end function work_available + subroutine get_instruction_name_from_checkin(j, name) + use json_module + implicit none + + class(json_file)::j + character(*), intent(out)::name + + character(len=:), allocatable::json_string_value + logical::found + + name = " " + call j%get("instruction", json_string_value, found) + if(found) then + name = json_string_value + end if + + end subroutine get_instruction_name_from_checkin + + function get_job_id_from_checkin(j) + use json_module + implicit none + + class(json_file)::j + integer::get_job_id_from_checkin + + character(len=:), allocatable::json_string_value + logical::found + + get_job_id_from_checkin = -1 + call j%get("job", json_string_value, found) + if(found) then + read(json_string_value, *) get_job_id_from_checkin + end if + + end function get_job_id_from_checkin + subroutine get_description(j, description) use json_module implicit none @@ -271,7 +307,7 @@ contains end function perform_task - subroutine perform_tasks(j) + subroutine perform_tasks(j, job_id) use json_module use talking use player_endpoints @@ -279,17 +315,16 @@ contains implicit none class(json_file)::j + integer, intent(in)::job_id integer::task_count integer::i integer::server_status logical::res - integer::job_id character(len=:), pointer::captured_filename character(len=1024)::url task_count = get_task_count(j) - job_id = get_job_id(j) do i = 1, task_count diff --git a/player/levitating-player.prj b/player/levitating-player.prj index bda2479..8bfa9c8 100644 --- a/player/levitating-player.prj +++ b/player/levitating-player.prj @@ -4,51 +4,65 @@ "Folders":[], "Name":"+common", "Files":[{ - "filename":"..\\common\\jessl.f90", + "filename":"../common/jessl.f90", "enabled":"1" },{ - "filename":"..\\common\\network.F90", - "enabled":"1" + "filename":"../common/network.F90", + "enabled":"1", + "panel":1, + "open":"1" },{ - "filename":"..\\common\\protocol.f90", - "enabled":"1" + "filename":"../common/protocol.f90", + "enabled":"1", + "panel":1, + "open":"1" },{ - "filename":"..\\common\\request.f90", + "filename":"../common/request.f90", "enabled":"1" },{ - "filename":".\\common\\utilities.F90", - "enabled":"1" + "filename":"../common/utilities.F90", + "enabled":"1", + "panel":1, + "open":"1" },{ - "filename":"..\\common\\wsa.f90", - "enabled":"1" + "filename":"../common/wsa.f90", + "enabled":"0" }] }], - "Name":"+levitating-player (target.exe)", + "Name":"+levitating-player (levitating-player.exe)", "Files":[{ - "filename":".\\config.f90", + "filename":"config.f90", "enabled":"1" },{ - "filename":".\\endpoints.f90", - "enabled":"1" + "filename":"endpoints.f90", + "enabled":"1", + "panel":1, + "open":"1" },{ - "filename":".\\instructions.f90", - "enabled":"1" + "filename":"instructions.f90", + "enabled":"1", + "panel":1, + "open":"1" },{ - "filename":".\\player.F90", - "enabled":"1" + "filename":"player.F90", + "enabled":"1", + "panel":1, + "open":"1" },{ - "filename":".\\talking.f90", - "enabled":"1" + "filename":"talking.f90", + "enabled":"1", + "panel":1, + "open":"1" },{ - "filename":".\\tasks.f90", + "filename":"tasks.f90", "enabled":"1" }] }, - "Name":"levitating-player (target.exe)", + "Name":"levitating-player (levitating-player.exe)", "Options":{ "Compiler Options":{ "Fortran Flags":"-DGNU", - "Link Flags":"", + "Link Flags":"-ljsonfortran -lssl -lcrypto", "C Flags":"" }, "Architecture":1, @@ -56,12 +70,12 @@ "Revision":2, "Windows GUI":0, "File Options":{ - "Library Directories":["Default Add-On Directory"], + "Library Directories":["Default Add-On Directory","../support/lib"], "Build Directory":"build", "Module Directory":"modules", - "Include Directories":["Default Add-On Include Directory"] + "Include Directories":["Default Add-On Include Directory","../support/include"] }, - "Target":"target.exe", + "Target":"levitating-player.exe", "Fortran Options":{ "Use C Preprocessor":"false", "Runtime Diagnostics":"false", @@ -82,11 +96,11 @@ }, "Build Dependencies":1, "Launch Options":{ - "Working Directory":"", + "Working Directory":"/tmp/example", "Launch Using MPI":"false", "Keep Console":"true", "External Console":"false", - "Command Line Arguments":"", + "Command Line Arguments":"-i windows-1 -l /tmp/player.log -w /tmp/example 127.0.0.1", "Build Before Launch":"true" }, "Build Options":{ @@ -94,9 +108,9 @@ "Auto Makefile":"true" }, "Linker Options":{ - "Static Linking Mode":7, + "Static Linking Mode":3, "Link MPI Library":"false", "Link LAPACK":0 } } -} +} \ No newline at end of file diff --git a/player/player.F90 b/player/player.F90 index 0eb5a72..ddce8cb 100644 --- a/player/player.F90 +++ b/player/player.F90 @@ -12,10 +12,13 @@ use wsa_network, only: windows_network_startup => startup implicit none character(len=1024)::url - type(json_file)::j - logical::work_to_do, json_available + type(json_file)::j_checkin, j_instructions + logical::work_to_do, checkin_json_available, instr_json_available integer::i_task + + integer::job_id + character(128)::instruction_name #ifdef WINDOWS call windows_network_startup() @@ -30,15 +33,24 @@ implicit none ! Check in for work call get_check_in_url(url) - json_available = request_json(url, j) - if(json_available) then - work_to_do = work_available(j) + checkin_json_available = request_json(url, j_checkin) + if(checkin_json_available) then + work_to_do = work_available(j_checkin) end if if(work_to_do) then + job_id = get_job_id_from_checkin(j_checkin) + call get_instruction_name_from_checkin(j_checkin, instruction_name) + + call get_instruction_url(url, instruction_name) + instr_json_available = request_json(url, j_instructions) - ! Task loop - call perform_tasks(j) + if(instr_json_available) then + ! Task loop + call perform_tasks(j_instructions, job_id) + + call destroy_instructions(j_instructions) + end if else @@ -54,8 +66,8 @@ implicit none #endif ! Destroy any existing json - if(json_available) then - call destroy_instructions(j) + if(checkin_json_available) then + call j_checkin%destroy() end if end do -- cgit v1.2.3