====== Rti_resolve_select_callback ======
==== Description ====
A system routine which displays progress messages during selects and reports. It is called from within RLIST, RESOLVE_SELECT, EXTERNAL.SORT, RTI_RLISTX_PRODUCE.
You can register on or more of your own routines as a listener. Registered listeners will receive notification of progress and completion. A registered listener can cancel a long running select.
==== Syntax ====
**rti_resolve_Select_callback**(//method//, //cursor//, //p1//,//p2//,//p3//,//p4//)
==== Parameters ====
**rti_resolve_Select_callback** has the following parameters.
^Parameter^Description^^
|//method//|The name of the table that contains the row or rows to be copied.||
|//cursor//|The select cursor number (0-8). See Select by . Defaults to 0 |
|//p1...p4//| depends on the method, see method decriptions below ||
==== Methods ====
**rti_resolve_Select_callback** has the following methods.
^Parameter^Description^^
|rtirsc_start$ | called at the beginning of a process |
|rtirsc_progress$| called periodically ( every couple of seconds ) while a select running|
|rtirsc_complete$| called when the select completes|
|rtirsc_cancel$| called if the select is cancelled |
|rtirsc_error$| called when there is an error|
|rtirsc_register_listener$| add a name to the list of registered listeners|
|rtirsc_unregister_listener$| remove a name from the list of registered listeners|
|rtirsc_getContinue$| get the value of the continue flag|
|rtirsc_SetContinue$| set the continue flag. pass false in P1 to stop the current select|
|rtirsc_IncrementCount$| increment the progress counter |
|rtirsc_setDisplayHandler$| provide the name of a routine to display progress|
|rtirsc_getDisplayHandler$| get the name of a routine which displays progress|
|rtirsc_EnableGui$| Turn on gui progress messages|
|rtirsc_DisableGui$|Turn off gui progress messages |
|rtirsc_getGuiEnabled$| return true if gui is enabled |
==== See Also ====
[[rlist|Rlist]]
==== Example ====
A sample of a custom callback routine
/*
** Example of adding a select callback listener
*/
#pragma format_indent_comments
Declare Function retStack,IsEventContext
$Insert logical
$Insert rti_resolve_Select_callback_equates
$Insert RTI_SEND_INFO_PROGRESS_EQUATES
$Insert rti_resolve_Select_callback_Common
Equ ancestor_Proc$ To "RTI_RESOLVE_SELECT_CALLBACK"
common /test_Select_callback_com/callCount@
* Count how many times called
callCount@ += 1
* The name of the program which called rti_resolve_select_callback
caller = retstack()<3>
If Assigned(method) Else method = ""
retval = null$
atProc = retstack()<1>
* I only care about progress and completion for this example
supported_methods = rtirsc_progress$ : @fm : rtirsc_complete$
Locate method In supported_methods Using @fm Setting pos then
On pos Gosub onProgress,onComplete
End
Return retval
///////////////////////////
onProgress:
progress_Count = If Assigned(p4) Then p4 Else null$
* Pass somthing around?
If Assigned(p4) Else p4 = null$
myCustominfo = p4
* For this example, count how many times called.
* For this example, just write to a log
Call rti_logit('', 'Progress', 'Called ' :callCount@ : ' times ' : myCustomInfo : ' Caller ' : caller)
Return
///////////////////////////
onComplete:
progress_Count = If Assigned(p4) Then p4 Else null$
If Assigned(p4) Else p4 = null$
myCustominfo = p4
Call rti_logit('', 'Completed', 'Called ' :callCount@ : ' times ' : myCustomInfo: ' Caller ' : caller)
If isEventContext() then
Call Msg(@Window, 'Called ' : callCount@ : ' times')
End
callCount@ = 0
Return
///////////////////////////
A BASIC+ Program which calls the above custom routine
Subroutine test_select_callback_harness(void)
/*
* An example of using a custom callback routine for RTI_RESOLVE_SELECT_CALLBACK
*/
#pragma format_indent_Comments
Declare Function get.reccount
$Insert logical
$Insert rlist_equates
$insert select.constants
$insert fserrors_hdr
$Insert fserrors_100
$Insert msg_equates
* See this equate for the rti_resolve_Select_callback methods
$Insert rti_resolve_Select_callback_equates
* Register my custom routine with rti_Resolve_select_callback
* Note that it accepts a cursor number to support use of different cursors for sub selects ( see SELECT BY / READNEXT BY )
cursor = 0
myRoutine = "TEST_SELECT_CALLBACK"
unused = rti_resolve_select_Callback(rtirsc_register_listener$, cursor, myRoutine)
*
* Initialize the progress info for this process
*
continue = rti_resolve_Select_callback(rtirsc_start$, cursor,0, '','','')
* Turn system progress dialog on or off as you desire.
* By default they are off
* If your routine has its own gui then turn off system progress dialogs here so that the selects will show MY progress, if desired
* unused = rti_resolve_select_Callback(rtirsc_disableGui$, cursor)
* In my case, I want to use the system gui
cursor = 0
unused = rti_resolve_select_Callback(rtirsc_enableGui$, cursor)
table = 'PERSON'
statement = 'SELECT PERSON WITH CITY STARTING "NEW"'
* For this example I want to open the table
* So I can process the records
Open Table To f_table Else return
Open 'DICT.':table To @dict Else return
* Could call rlist or REDUCE, SELECT BY
Call Rlist(statement , target_activelist$)
* To estimate the pct complete, use @reccount, or assume entire table
expected_count = 0
If @list.active == EXTRN.Select$ Then
expected_Count = @reccount
End Else
stat = null$
expected_Count = Get.RecCount(f_table, stat, 0)
end
* I can pass custom information to my callback routine.
* I think you can roundtrip this, if you want the callback to send information back
myCustomInfo = "Hello World " :Time()
*---
* Process the records
*---
* I this example I load some data into a buffer named 'sb'
sb = null$;sballoc_Size = 0x7FFF;sbPos = 1
rnDone = false$
readcount = 0
Loop
until rnDone Or Not(continue)
readnext @id using cursor by AT Then
Read @record From f_table, @id then
readcount += 1
line = @id:@vm:{CITY}:@vm:{LNAME}:@vm:{FNAME}:@fm
* Does it fit?
If getbytesize(line) + sbpos gt Blen(sb) Then
sb := str(\00\,sballoc_size)
End
* Add it to buffer
putbinaryValue( sb, sbpos,CHAR, line)
sbpos += getbytesize(line)
* Yield every couple seconds, show some progress
* The custom callback routine can cancel the operation if desired
If Mod(readcount, 100) Eq 1 Then
myCustomInfo = 'Currently processing ' : @id
* Update progress, test for continue
continue = rti_resolve_select_callback(rtirsc_progress$, cursor,readcount,'', '', myCustomInfo)
If Not(continue) Then
* Discard results, end the loop
sb = ''; sbpos = 1
rndone = true$
End
End
end
End Else
* Readnext error
* normally this is readnext_done$, not a problem )
rnDone = TRUE$
if @file_error == FS_READNEXT_DONE$ Then
* We may not have displayed progress for the last chunk of records
* To make user happy, show 100%
myCustomInfo = '100% progress'
unused = rti_resolve_select_callback(rtirsc_progress$, cursor,expected_Count,'', '', myCustomInfo)
End Else
* Some kind of error
ClearSelect cursor
sb = ''; sbpos = 1
End
End
Repeat
* Call the complete method to take down any gui display
myCustomInfo = 'Read count = ' : readcount
unused = rti_resolve_Select_callback(rtirsc_complete$, cursor ,'', '', '', myCustomInfo)
* Turn off system progress dialogs here, or subsequent select will display the gui
cursor = 0
unused = rti_resolve_select_Callback(rtirsc_disableGui$, cursor)
* Unregister my progress callback or susequent selects will call it
unused = rti_resolve_select_Callback(rtirsc_unregister_listener$, cursor, myRoutine)
* For this example, extract result from the buffer and return it
If sbpos gt 1 Then
sbpos -= 1 ; * kill trailing @fm
result = getBinaryValue(sb,1,CHAR,sbpos-1)
End Else
result = null$
End
Return result
//////////////////