Index: openacs-4/packages/acs-authentication/tcl/apm-callback-procs.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/acs-authentication/tcl/apm-callback-procs.tcl,v diff -u -r1.4 -r1.5 --- openacs-4/packages/acs-authentication/tcl/apm-callback-procs.tcl 9 Sep 2003 11:15:56 -0000 1.4 +++ openacs-4/packages/acs-authentication/tcl/apm-callback-procs.tcl 9 Sep 2003 12:31:59 -0000 1.5 @@ -26,13 +26,19 @@ # Register local authentication implementations and update the local authority auth::local::install + + # Register HTTP method for GetDocument + auth::sync::get_doc::http::register_impl } } ad_proc -private auth::package_uninstall {} {} { db_transaction { + # Unregister HTTP method for GetDocument + auth::sync::get_doc::http::unregister_impl + # Unregister local authentication implementations and update the local authority auth::local::uninstall @@ -368,7 +374,7 @@ input { job_id:integer document:string - paraemters:string,multiple + parameters:string,multiple } } GetParameters { Index: openacs-4/packages/acs-authentication/tcl/authority-procs.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/acs-authentication/tcl/authority-procs.tcl,v diff -u -r1.8 -r1.9 --- openacs-4/packages/acs-authentication/tcl/authority-procs.tcl 9 Sep 2003 12:09:50 -0000 1.8 +++ openacs-4/packages/acs-authentication/tcl/authority-procs.tcl 9 Sep 2003 12:31:59 -0000 1.9 @@ -245,6 +245,87 @@ +ad_proc -public auth::authority::batch_sync { + -authority_id:required + -snapshot:boolean +} { + Execute batch synchronization for this authority now. + + @param authority_id + @param snapshot If set, we will delete all authority's users + not touched by the process document proc. + + @return job_id +} { + set job_id [auth::sync::job::start \ + -authority_id $authority_id \ + -snapshot=$snapshot_p] + + get -authority_id $authority_id -array authority + + set message {} + + # Verify that we have implementations + if { [empty_string_p $authority(get_doc_impl_id)] } { + set message "No Get Document implementation" + } elseif { [empty_string_p $authority(process_doc_impl_id)] } { + set message "No Process Document implementation" + } else { + auth::sync::job::start_get_document -job_id $job_id + + array set doc_result { + doc_status failed_to_connect + doc_message {} + document {} + } + with_catch errmsg { + array set doc_result [auth::sync::GetDocument -authority_id $authority_id] + } { + global errorInfo + ns_log Error "Error getting sync document:\n$errorInfo" + } + + auth::sync::end_get_document \ + -job_id $job_id \ + -doc_status $doc_result(doc_status) \ + -doc_message $doc_result(doc_message) \ + -document $doc_result(document) + + if { [string equal $doc_status "ok"] && ![empty_string_p $doc_result(document)] } { + with_catch errmsg { + auth::sync::ProcessDocument \ + -authority_id $authority_id \ + -job_id $job_id \ + -document $doc_result(document) + } { + global errorInfo + ns_log Error "Error processing sync document:\n$errorInfo" + set message "Error processing sync document: $errmsg" + } + } + + if { $snapshot_p } { + # If this is a snapshot, we need to delete all the users belonging to this authority + # that weren't included in the snapshot. + auth::sync::job::snapshot_delete_remaining \ + -job_id $job_id \ + -authority_id $authority_id + } + } + + auth::sync::job::end \ + -job_id $job_id \ + -message $message + + return $job_id +} + + + + + + + ##### # # Private Index: openacs-4/packages/acs-authentication/tcl/sync-init.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/acs-authentication/tcl/sync-init.tcl,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/acs-authentication/tcl/sync-init.tcl 9 Sep 2003 12:31:59 -0000 1.1 @@ -0,0 +1,23 @@ +ad_library { + + Set up scheduled procs for running nightly batch sync, and for purging old logs. + + @cvs-id $Id: sync-init.tcl,v 1.1 2003/09/09 12:31:59 lars Exp $ + @author Lars Pind (lars@collaboraid.biz) + @creation-date 2003-09-09 + +} + +# Schedule old job log purge +ad_schedule_proc \ + -thread t \ + -schedule_proc ns_schedule_daily \ + [list 0 30] \ + auth::sync::purge_jobs + +# Schedule batch sync sweeper +ad_schedule_proc \ + -thread t \ + -schedule_proc ns_schedule_daily \ + [list 1 0] \ + auth::sync::sweeper Index: openacs-4/packages/acs-authentication/tcl/sync-procs-oracle.xql =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/acs-authentication/tcl/sync-procs-oracle.xql,v diff -u -r1.2 -r1.3 --- openacs-4/packages/acs-authentication/tcl/sync-procs-oracle.xql 9 Sep 2003 08:38:23 -0000 1.2 +++ openacs-4/packages/acs-authentication/tcl/sync-procs-oracle.xql 9 Sep 2003 12:31:59 -0000 1.3 @@ -9,12 +9,15 @@ job_start_time, job_end_time, interactive_p, + snapshot_p, + authority_id, + message, creation_user, doc_start_time, doc_end_time, doc_status, doc_message, - document_id, + document, (j.job_end_time - j.job_start_time) * 24*60*60 as run_time_seconds, (select count(e1.entry_id) from auth_batch_job_entries e1 @@ -42,8 +45,9 @@ set doc_end_time = sysdate doc_status = :doc_status, doc_message = :doc_message, - document_id = :document_id + document = empty_clob() where job_id = :job_id + returning document into :1 Index: openacs-4/packages/acs-authentication/tcl/sync-procs-postgresql.xql =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/acs-authentication/tcl/sync-procs-postgresql.xql,v diff -u -r1.2 -r1.3 --- openacs-4/packages/acs-authentication/tcl/sync-procs-postgresql.xql 9 Sep 2003 08:38:23 -0000 1.2 +++ openacs-4/packages/acs-authentication/tcl/sync-procs-postgresql.xql 9 Sep 2003 12:31:59 -0000 1.3 @@ -9,12 +9,16 @@ job_start_time, job_end_time, interactive_p, + snapshot_p, + authority_id, + (select aa.pretty_name from auth_authorities aa where aa.authority_id = j.authority_id) as authority_pretty_name, + message, creation_user, doc_start_time, doc_end_time, doc_status, doc_message, - document_id, + document, trunc(extract(epoch from (j.job_end_time - j.job_start_time))) as run_time_seconds, (select count(e1.entry_id) from auth_batch_job_entries e1 @@ -42,7 +46,7 @@ set doc_end_time = current_timestamp, doc_status = :doc_status, doc_message = :doc_message, - document_id = :document_id + document = :document where job_id = :job_id Index: openacs-4/packages/acs-authentication/tcl/sync-procs.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/acs-authentication/tcl/sync-procs.tcl,v diff -u -r1.4 -r1.5 --- openacs-4/packages/acs-authentication/tcl/sync-procs.tcl 9 Sep 2003 08:38:23 -0000 1.4 +++ openacs-4/packages/acs-authentication/tcl/sync-procs.tcl 9 Sep 2003 12:31:59 -0000 1.5 @@ -9,6 +9,8 @@ namespace eval auth {} namespace eval auth::sync {} namespace eval auth::sync::job {} +namespace eval auth::sync::get_doc {} +namespace eval auth::sync::get_doc::http {} ##### @@ -20,17 +22,13 @@ ad_proc -public auth::sync::job::get { {-job_id:required} {-array:required} - {-include_document:boolean} } { Get information about a batch job in an array. @param job_id The ID of the batch job you're ending. @param array Name of an array into which you want the information. - @param include_document - Set this switch if you also want the document returned in the array. - @author Lars Pind (lars@collaboraid.biz) } { upvar 1 $array row @@ -39,17 +37,13 @@ # TODO: This is temporary, make sure this is where the UI ends up set row(log_url) [export_vars -base "[ad_url]/acs-admin/package/acs-authentication/sync-log" { job_id }] - - if { $include_document_p } { - # TODO: Return the document once we know how we'll store it - set job(document) "Not implemented" - } } ad_proc -public auth::sync::job::start { {-job_id ""} {-authority_id:required} {-interactive:boolean} + {-snapshot:boolean} {-creation_user ""} } { Record the beginning of a job. @@ -58,6 +52,8 @@ @param interactive Set this if this is an interactive job, i.e. it's initiated by a user. + @param snapshot Set this if this is a snapshot job, as opposed to an incremental ('event driven') job. + @return job_id An ID for the new batch job. Used when calling other procs in this API. @author Lars Pind (lars@collaboraid.biz) @@ -73,9 +69,9 @@ db_dml job_insert { insert into auth_batch_jobs - (job_id, interactive_p, creation_user) + (job_id, interactive_p, snapshot_p, creation_user, authority_id) values - (:job_id, :interactive_p, :creation_user) + (:job_id, :interactive_p, :snapshot_p, :creation_user, :authority_id) } } @@ -84,6 +80,7 @@ ad_proc -public auth::sync::job::end { {-job_id:required} + {-message ""} } { Record the end of a batch job. Closes out the transaction log and sends out notifications. @@ -98,7 +95,8 @@ } { db_dml set_end_time { update auth_batch_jobs - set job_end_time = current_timestamp + set job_end_time = current_timestamp, + message = :message where job_id = :job_id } @@ -112,8 +110,16 @@ ns_sendmail \ [ad_system_owner] \ [ad_system_owner] \ - "Batch sync completed" \ - "Batch user synchronization is complete.\n\nRunning time: $job(run_time_seconds) seconds\nNumber of actions: $job(num_actions)\nNumber of problems: $job(num_problems)\n\nTo view the log, please visit\n$job(log_url)" + "Batch user synchronization for $job(authority_pretty_name) complete" \ + "Batch user synchronization for $job(authority_pretty_name) is complete. + +Authority : $job(authority_pretty_name) +Running time : $job(run_time_seconds) seconds +Number of actions : $job(num_actions) +Number of problems: $job(num_problems) +Job message : $job(message) + +To view the complete log, please visit\n$job(log_url)" } { # We don't fail hard here, just log an error global errorInfo @@ -144,10 +150,7 @@ @param job_id The ID of the batch job you're ending. } { - # TODO: Create cr_item containing document. Talk to Jun Kyamog about a CR API - set document_id {} - - db_dml update_doc_end {} + db_dml update_doc_end {} -clobs [list $document] } ad_proc -public auth::sync::job::create_entry { @@ -354,7 +357,7 @@ auth::sync::job::action \ -job_id $job_id \ -operation "delete" \ - -authority_id [auth::authority::local] \ + -authority_id $authority_id \ -username $username } } @@ -378,9 +381,133 @@ validate_integer num_days $num_days if { $num_days > 0 } { - # TODO: Don't forget to also delete the cr_item referenced by the auth_batch_jobs.document column. - db_dml purge_jobs {} } } +ad_proc -private auth::sync::sweeper {} { + db_foreach select_authorities { + select authority_id, + snapshot_p + from auth_authorities + where enabled_p = 't' + and batch_sync_enabled_p = 't' + } { + auth::authority::batch_sync \ + -authority_id $authority_id \ + -snapshot=[template::util::is_true $snapshot_p] + } +} + +ad_proc -private auth::sync::GetDocument { + {-authority_id:required} +} { + Wrapper for the GetDocument operation of the GetDocument service contract. +} { + set impl_id [auth::authority::get_element -authority_id $authority_id -element "get_doc_impl_id"] + + if { [empty_string_p $impl_id] } { + # No implementation of GetDocument + set authority_pretty_name [auth::authority::get_element -authority_id $authority_id -element "pretty_name"] + error "The authority '$authority_pretty_name' doesn't support GetDocument" + } + + set parameters [auth::driver::get_parameter_values \ + -authority_id $authority_id \ + -impl_id $impl_id] + + return [acs_sc::invoke \ + -error \ + -impl_id $impl_id \ + -operation GetDocument \ + -call_args [list $parameters]] +} + +ad_proc -private auth::sync::ProcessDocument { + {-authority_id:required} + {-job_id:required} + {-document:required} +} { + Wrapper for the ProcessDocument operation of the auth_sync_process service contract. +} { + set impl_id [auth::authority::get_element -authority_id $authority_id -element "process_doc_impl_id"] + + if { [empty_string_p $impl_id] } { + # No implementation of auth_sync_process + set authority_pretty_name [auth::authority::get_element -authority_id $authority_id -element "pretty_name"] + error "The authority '$authority_pretty_name' doesn't support auth_sync_process" + } + + set parameters [auth::driver::get_parameter_values \ + -authority_id $authority_id \ + -impl_id $impl_id] + + return [acs_sc::invoke \ + -error \ + -impl_id $impl_id \ + -operation ProcessDocument \ + -call_args [list $job_id $document $parameters]] +} + + + + + +##### +# +# auth::sync::get_doc::http namespace +# +##### + +ad_proc -private auth::sync::get_doc::http::register_impl {} { + Register this implementation +} { + set spec { + contract_name "GetDocument" + owner "acs-authentication" + name "HTTPGet" + aliases { + GetDocument auth::sync::get_doc::http::GetDocument + GetParameters auth::sync::get_doc::http::GetParameters + } + } + + return [acs_sc::impl::new_from_spec -spec $spec] + +} + +ad_proc -private auth::sync::get_doc::http::unregister_impl {} { + Unregister this implementation +} { + acs_sc::impl::delete -contract_name "GetDocument" -impl_name "HTTPGet" +} + +ad_proc -private auth::sync::get_doc::http::GetParameters {} { + Parameters for HTTP GetDocument implementation. +} { + return { + URL {The URL from which to retrieve the document} + } +} + +ad_proc -private auth::sync::get_doc::http::GetDocument { + parameters +} { + Retrieve the document by HTTP +} { + array set result { + doc_status failed_to_conntect + doc_message {} + document {} + } + + array set param $parameters + + set result(document) [util_httpget $param(URL)] + + set result(doc_status) "ok" + + retun [array get result] +} + + Index: openacs-4/packages/acs-authentication/tcl/test/sync-test-procs.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/acs-authentication/tcl/test/sync-test-procs.tcl,v diff -u -r1.4 -r1.5 --- openacs-4/packages/acs-authentication/tcl/test/sync-test-procs.tcl 9 Sep 2003 08:38:23 -0000 1.4 +++ openacs-4/packages/acs-authentication/tcl/test/sync-test-procs.tcl 9 Sep 2003 12:31:59 -0000 1.5 @@ -450,3 +450,20 @@ } } + + +aa_register_case job_batch_for_local { + Test a batch job for the local authority +} { + aa_run_with_teardown \ + -rollback \ + -test_code { + + set job_id [auth::authority::batch_sync -authority_id [auth::authority::local]] + + auth::sync::job::get -job_id $job_id -array job + + aa_log "job.message = '$job(message)'" + + } +}