aboutsummaryrefslogtreecommitdiff
path: root/captain
diff options
context:
space:
mode:
Diffstat (limited to 'captain')
-rw-r--r--captain/api.f9045
-rw-r--r--captain/config.f905
-rw-r--r--captain/db.f9028
-rw-r--r--captain/external.f9011
-rw-r--r--captain/gemini.f9015
-rw-r--r--captain/levitating-captain.prj44
-rw-r--r--captain/response.f9020
7 files changed, 114 insertions, 54 deletions
diff --git a/captain/api.f90 b/captain/api.f90
index 4594ba9..003a601 100644
--- a/captain/api.f90
+++ b/captain/api.f90
@@ -1,10 +1,11 @@
module api_handling
+use iso_c_binding
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}"}'
+ '{"status": "pending",'//c_new_line//' "job": {job_number},'//c_new_line//' "instruction": "{instruction_name}"}'
contains
@@ -46,6 +47,7 @@ contains
if(ierr == 0) then
if(req%query_string == "starting" .or. req%query_string == "inprogress") then
call update_task_status(job_i, task_i, JOB_STATUS_WORKING)
+ call update_job_status(job_i, JOB_STATUS_WORKING)
else if(req%query_string == "complete") then
call update_task_status(job_i, task_i, JOB_STATUS_SUCCESS)
else if(req%query_string == "failed") then
@@ -60,6 +62,7 @@ contains
use server_response
use captain_db
use special_filenames
+ use logging
implicit none
type(request), intent(in)::req
@@ -92,7 +95,7 @@ contains
resp%code = GEMINI_CODE_SUCCESS
call resp%set_body_contents(RESPONSE_JSON_OKAY)
- resp%body_mimetype = "application/json"
+ resp%body_mimetype = "text/plain"
! Checkin - /api/player/{name}/checkin.json
else if(trim(req%component(2)) == "player" .and. trim(req%component(4)) == "checkin.json") then
@@ -100,6 +103,10 @@ contains
call req%path_component(3, player)
player_i = get_player_id(player)
+ ! If we have a checkin, but the worker should have a job in progress, mark
+ ! the jobs as failed.
+ call mark_working_jobs_as_failed(player_i)
+
job_i = get_pending_job_for_player(player_i)
if(job_i < 0) then
resp%code = GEMINI_CODE_SUCCESS
@@ -108,7 +115,8 @@ contains
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")
+ call write_log("Sending: "//trim(checkin_work_json))
+ call resp%set_body_contents(trim(checkin_work_json), "text/gemini")
deallocate(checkin_work_json)
else
resp%code = GEMINI_CODE_PERMFAIL
@@ -123,7 +131,7 @@ contains
if(associated(resp%body_filename)) then
resp%temporary_file = .false.
resp%code = GEMINI_CODE_SUCCESS
- resp%body_mimetype = "application/json"
+ resp%body_mimetype = "text/plain"
else
resp%code = GEMINI_CODE_PERMFAIL
end if
@@ -135,6 +143,7 @@ contains
function api_request_titan(req) result(resp)
use server_response
use special_filenames
+ use logging
implicit none
type(titan_request), intent(in)::req
@@ -144,27 +153,25 @@ contains
character(12)::job_text, task_text
integer::job_id, task_num, ierr
+ character(64)::msg
+
fullpath => null()
+ call write_log("Titan request encountered")
+
! Task - "/api/player/{name}/job/{jobid}/task/{task num}"
if(trim(req%component(2)) == "player" .and. &
trim(req%component(4)) == "job" .and. &
trim(req%component(6)) == "task") then
- call req%path_component(5, job_text)
- read(job_text, *, iostat=ierr) job_id
- if(ierr /= 0) then
- resp%code = GEMINI_CODE_PERMFAIL
- return
- end if
-
- call req%path_component(5, task_text)
- read(task_text, *, iostat=ierr) task_num
- if(ierr /= 0) then
- resp%code = GEMINI_CODE_PERMFAIL
- return
- end if
+ job_id = req%path_component_int(5)
+
+ task_num = req%path_component_int(7)
+
+ write(job_text, '(I6)') job_id
+ write(task_text, '(I6)') task_num
+ call write_log("Handling a task update for job "//trim(job_text)//" task "//trim(task_text))
call handle_task_request(req)
fullpath => get_task_result_static_filename(job_id, task_num)
@@ -174,11 +181,13 @@ contains
if(associated(fullpath)) then
! Write the file
+ call write_log("Storing titan file to "//trim(fullpath))
+
call req%write_to(fullpath)
resp%code = GEMINI_CODE_SUCCESS
call resp%set_body_contents(RESPONSE_JSON_OKAY)
- resp%body_mimetype = "application/json"
+ resp%body_mimetype = "text/plain"
else
diff --git a/captain/config.f90 b/captain/config.f90
index 3d23011..6c622b4 100644
--- a/captain/config.f90
+++ b/captain/config.f90
@@ -144,10 +144,7 @@ contains
call get_variable(line, cvariable)
call get_value(line, cvalue)
-
- ! Debugging
- ! Print *, trim(cvariable)//" => "//trim(cvalue)
-
+
call assign_config(trim(cvariable), trim(cvalue))
end if
diff --git a/captain/db.f90 b/captain/db.f90
index fa53774..a661fd4 100644
--- a/captain/db.f90
+++ b/captain/db.f90
@@ -589,12 +589,15 @@ contains
implicit none
integer, intent(in)::job_id
- character(8)::update_date
- character(10)::update_time
+ character(10)::update_date
+ character(8)::update_time
+ integer, dimension(8)::values
type(sqlite3_stmt)::stmt
- call date_and_time(date=update_date, time=update_time)
+ call date_and_time(values=values)
+ write(update_date, '(I4,A1,I0.2,A1,I0.2)') values(1), "-", values(2), "-", values(3)
+ write(update_time, '(I2,A1,I0.2,A1,I0.2)') values(5), ":", values(6), ":", values(7)
if(stmt%prepare(db, "UPDATE jobs SET time=? WHERE id=?") == SQLITE_OK) then
if(stmt%bind_text(1, update_date//" "//update_time) == SQLITE_OK .and. &
stmt%bind_int(2, job_id) == SQLITE_OK) then
@@ -697,6 +700,25 @@ contains
end function get_pending_job_for_player
+ subroutine mark_working_jobs_as_failed(player)
+ implicit none
+
+ integer, intent(in)::player
+ type(sqlite3_stmt)::stmt
+
+ if(stmt%prepare(db, "UPDATE jobs SET status=? WHERE player=? AND status=? LIMIT 1") == SQLITE_OK) then
+ if(stmt%bind_int(1, JOB_STATUS_FAILURE) == SQLITE_OK .and. &
+ stmt%bind_int(2, player) == SQLITE_OK .and. &
+ stmt%bind_int(3, JOB_STATUS_WORKING) == SQLITE_OK) then
+
+ call stmt%step_now()
+
+ end if
+ end if
+ call stmt%finalize()
+
+ end subroutine mark_working_jobs_as_failed
+
subroutine scan_instructions_for_db()
use config
use utilities
diff --git a/captain/external.f90 b/captain/external.f90
index 97fa69c..db34a11 100644
--- a/captain/external.f90
+++ b/captain/external.f90
@@ -81,7 +81,16 @@ contains
res = trim(res)//nl//nl//link
- res = trim(res)//nl//"Running on "//trim(player)// &
+ select case(jobs(i)%status)
+ case(JOB_STATUS_SUCCESS, JOB_STATUS_FAILURE)
+ res = trim(res)//nl//"Completed on"
+ case(JOB_STATUS_PENDING)
+ res = trim(res)//nl//"Waiting to run on"
+ case(JOB_STATUS_WORKING)
+ res = trim(res)//nl//"Running on"
+ end select
+
+ res = trim(res)//" "//trim(player)// &
" - Last Update: "//trim(jobs(i)%time)
end do
diff --git a/captain/gemini.f90 b/captain/gemini.f90
index 8453db9..db0ac17 100644
--- a/captain/gemini.f90
+++ b/captain/gemini.f90
@@ -58,7 +58,7 @@ contains
ierr = 0
i = 0
- do while(ierr == 0 .and. i < len(buffer))
+ do while(ierr == 0 .and. i < 64)
i = i + 1
read(unit_number, iostat=ierr) buffer(i)
end do
@@ -86,9 +86,9 @@ contains
write(int_text, '(I8)') code
line = trim(adjustl(int_text))//" "//trim(meta)
- call write_log("Status line: "//trim(line))
+ call write_log("Status line: '"//trim(line)//"'")
- call write_string(ssl, trim(adjustl(int_text))//" "//trim(meta)//c_carriage_return//c_new_line)
+ call write_string(ssl, trim(line)//c_carriage_return//c_new_line)
end subroutine write_status
@@ -106,7 +106,7 @@ contains
integer::buflen, written
call write_status(ssl, GEMINI_CODE_SUCCESS, mimetype)
-
+
buflen = read_into_buffer(unit_number, buf)
do while(buflen > 0)
written = ssl_write(ssl, buf(1:buflen))
@@ -267,8 +267,10 @@ contains
if(trim(first) == 'api') then
if(req%protocol == "gemini") then
resp = api_request_gemini(req)
+ call write_log("resp filename is: '"//trim(resp%body_filename)//"'")
else if(req%protocol == "titan") then
call treq%init_from_request(req, ssl)
+ resp = api_request_titan(treq)
end if
else
resp = external_request_gemini(req)
@@ -292,15 +294,16 @@ contains
form="unformatted", iostat=ioerror, access="stream")
call write_file(ssl, rendered_unit, resp%body_mimetype)
call write_log("File written")
-
close(rendered_unit)
end select
+ call write_log("Cleanup")
+
call req%destroy()
call resp%destroy()
-
+ call write_log("shutdown")
res = ssl_shutdown(ssl)
res = ssl_free(ssl)
res = ctx_free(ctx)
diff --git a/captain/levitating-captain.prj b/captain/levitating-captain.prj
index 6e48fb2..7202344 100644
--- a/captain/levitating-captain.prj
+++ b/captain/levitating-captain.prj
@@ -4,85 +4,85 @@
"Folders":[],
"Name":"+common",
"Files":[{
- "filename":"..\\common\\jessl.f90",
+ "filename":"../common/jessl.f90",
"enabled":"1"
},{
- "filename":"..\\common\\network.F90",
+ "filename":"../common/network.F90",
"enabled":"1"
},{
- "filename":"..\\common\\protocol.f90",
+ "filename":"../common/protocol.f90",
"enabled":"1"
},{
- "filename":"..\\common\\request.f90",
+ "filename":"../common/request.f90",
"enabled":"1"
},{
- "filename":"..\\common\\utilities.F90",
+ "filename":"../common/utilities.F90",
"enabled":"1"
},{
- "filename":"..\\common\\wsa.f90",
+ "filename":"../common/wsa.f90",
"enabled":"0"
}]
},{
"Folders":[],
"Name":"+example",
"Files":[{
- "filename":".\\example\\levitating.conf",
+ "filename":"example/levitating.conf",
"enabled":"1"
}]
},{
"Folders":[],
"Name":"+sql",
"Files":[{
- "filename":".\\sql\\create.sql",
+ "filename":"sql/create.sql",
"enabled":"1"
},{
- "filename":".\\sql\\scan_instructions.sh",
+ "filename":"sql/scan_instructions.sh",
"enabled":"1"
}]
},{
"Folders":[],
"Name":"+templates",
"Files":[{
- "filename":".\\templates\\index.gmi",
+ "filename":"templates/index.gmi",
"enabled":"1"
}]
}],
"Name":"+levitating-captain (levitating-captain)",
"Files":[{
- "filename":".\\api.f90",
+ "filename":"api.f90",
"enabled":"1"
},{
- "filename":".\\captian.f90",
+ "filename":"captian.f90",
"enabled":"1"
},{
- "filename":".\\config.f90",
+ "filename":"config.f90",
"enabled":"1"
},{
- "filename":".\\db.f90",
+ "filename":"db.f90",
"enabled":"1"
},{
- "filename":".\\external.f90",
+ "filename":"external.f90",
"enabled":"1"
},{
- "filename":".\\gemini.f90",
+ "filename":"gemini.f90",
"enabled":"1"
},{
- "filename":".\\launch.f90",
+ "filename":"launch.f90",
"enabled":"1"
},{
- "filename":".\\log.f90",
+ "filename":"log.f90",
"enabled":"1"
},{
- "filename":".\\response.f90",
+ "filename":"response.f90",
"enabled":"1"
},{
- "filename":".\\special.f90",
+ "filename":"special.f90",
"enabled":"1"
},{
- "filename":".\\sqlite.f90",
+ "filename":"sqlite.f90",
"enabled":"1"
},{
- "filename":".\\template.f90",
+ "filename":"template.f90",
"enabled":"1"
}]
},
diff --git a/captain/response.f90 b/captain/response.f90
index 3526766..1c7a0b5 100644
--- a/captain/response.f90
+++ b/captain/response.f90
@@ -45,6 +45,7 @@ implicit none
procedure :: destroy => request_destroy
procedure :: last_component => request_last_component
procedure :: path_component => request_component
+ procedure :: path_component_int => request_component_int
procedure :: component => request_component_func
end type request
@@ -158,6 +159,25 @@ contains
end subroutine request_component
+
+ function request_component_int(self, i) result(res)
+ implicit none
+
+ class(request) :: self
+ integer, intent(in)::i
+ integer :: res
+
+ character(24)::restext
+
+ restext = " "
+
+ call self%path_component(i, restext)
+
+ read(restext, '(I16)') res
+
+ end function request_component_int
+
+
function request_component_func(self, i) result(res)
implicit none