Relay-Version: version B 2.10 5/3/83; site utzoo.UUCP Path: utzoo!mnetor!seismo!lll-crg!mordor!sri-spam!nike!ucbcad!ucbvax!rtpark.RTP.GE.COM!rlb From: rlb@rtpark.RTP.GE.COM Newsgroups: mod.computers.vax Subject: (none) Message-ID: <8609060338.AA01717@ge-rtp.GE.COM> Date: Fri, 5-Sep-86 23:38:23 EDT Article-I.D.: ge-rtp.8609060338.AA01717 Posted: Fri Sep 5 23:38:23 1986 Date-Received: Sat, 6-Sep-86 22:02:06 EDT Sender: daemon@ucbvax.BERKELEY.EDU Organization: The ARPA Internet Lines: 180 Approved: info-vax@sri-kl.arpa From: mcnc!rtpark.rtp.ge.com!rlb@seismo.CSS.GOV (Bob Boyd,8*274-3627) To: "info-vax@sri-kl.arpa"@ge-rtp.ge.com Subject: Re: Cluster Time Synchronization $! timeset.com -- used to update time setting in a cluster/network environment $! author: R.L. Boyd, GE Semiconductor $! date: 3-Sep-1986 $! location: Res. Tri. Pk., NC $! Permission is granted to copy/modify as long as this notice remains $! prerequisites: DECnet $! System: VMS V4.0 $ set noon $ set control=y $ on control_y then $ goto EXIT $ vfl = f$ver(0) $ null = "" $ yes = "Y" $! make sure we have all the necessary privileges $ priv_list = "LOG_IO,OPER,ALTPRI" $ interactive = f$mode().eqs."INTERACTIVE" $ @UTL:checkpriv "''priv_list'" $ if .not.$status then goto ERR_EXIT $! make sure we're executing at priority 7 $ save_prib = f$getjpi(null,"PRIB") $ set proc/prior=7 $ @utl:getnode my_node $! reference node name supplied here $ other_node = "RTPVN1" $ if f$type(cvttime).eqs.null then $ cvttime = "$util_root:[fermilab]time" $ sh sym my_node $ sh sym other_node $GET_TIME: $ if my_node.nes.other_node then $ goto GET_FROM_OTHER $ if .not.interactive then $ goto EXIT ! if this is the reference node $! get the correct time from the privileged user $ if p1.eqs.null then inquire p1 "What time is it (DD-MMM-YYYY HH:MM:SS)" $ my_time = f$time() $ time_rec = p1 $ goto START_FIGURE $ERR_EXIT: $ write sys$Output - "SYSTEM-F-NOPRIV, operation requires privileges: ",priv_list $EXIT: $ @UTL:checkpriv $ set proc/prior='save_prib' $ exit !'f$ver(vfl)' $GET_FROM_OTHER: $! the assumption here is that the time will be correctly set on the one $! system and copied from that system to the others $! the following code accomplishes the copy operation $TMP_SKIP: $ open/read/err=ERR_ACCESSING_NODE time 'other_node'::"task=timecheck" $ err_stat = $status $ read/err=ERR_ACCESSING_NODE/end=ERR_ACCESSING_NODE time time_rec $ if .not.err_stat then $ goto PUT_OTHER $ my_time = f$time() $ close time $ if vfl then $ show sym time_rec $ goto START_FIGURE $WORK_BACK: $! determine how many seconds we're ahead $ cvttime/sym=s_diff 'time_rec'(-)'my_time'(/)0-0:0:1 $ sign = "-" $ goto END_FIGURE $START_FIGURE: ! figure out if we're behind or ahead and how much $ if vfl then $ show sym my_time $ comp_time = f$cvtime(my_time).gts.f$cvtime(time_rec) $ err_stat = $status $ if comp_time then $ goto WORK_BACK $ if err_stat then $ goto COMP_DELTA $ p1 = null $ if interactive then $ goto GET_TIME $ goto EXIT $COMP_DELTA: $! determine how many seconds we're behind $ cvttime/sym=s_diff 'my_time'(-)'time_rec'(/)0-0:0:1 $ err_stat = $status $ if vfl then $ show sym s_diff $ if err_stat then $ goto SIGN_PUT $! if there's an error then reset and ask again if interactive $ p1 = null $ if interactive then $ goto GET_TIME $ goto EXIT $SIGN_PUT: $ sign = "+" $END_FIGURE: $! if the delta is less than 10 seconds don't bother -- DECnet $! could give that much slop easily $ if s_diff.lt.10 then $ goto EXIT $! what follows is to prevent giant leaps in time forward or $! backward. This will also help to reduce the likelyhood of $! negative connect time in accounting records. $ delta_small = 1 $ if s_diff.le.60 .or. sign.nes."-" then $ goto DELTA_COMPUTE $ delta_small = 0 $ delta_master = s_diff $ delta_min = 15 $ delta_wait = 2*delta_min $ goto DELTA_LOOP $DELTA_WAIT: $ wait 0:0:'delta_wait' $DELTA_LOOP: $ if delta_master.gt.delta_min then $ goto DELTA_BIG $ s_diff = delta_master $ delta_small = 1 $ goto DELTA_COMPUTE $DELTA_BIG: $ s_diff = delta_min $ delta_master = delta_master-delta_min $ sh sym delta_master $ if delta_master.lt.0 then $ goto EXIT $DELTA_COMPUTE: $ delta_h = s_diff/3600 $ s_diff2 = s_diff-3600*delta_h $ delta_m = s_diff2/60 $ delta_s = s_diff2-60*delta_m $ delta_t = sign+f$fao("0 !2ZL:!2ZL:!2ZL",delta_h,delta_m,delta_s) $ sh sym delta_t $ ans = yes $ if interactive then $ - read sys$command ans- /prompt="Go ahead ?(cr=Y) "/timeout=30/end=set_it $ if f$type(ans).eqs.null then $ ans = yes $ if ans.eqs.null then $ ans = yes $ if f$ver() then $ sh sym ans $SET_IT: $ if ans then $ set time="''delta_t'" $ if .not.delta_small then $ goto DELTA_WAIT $SKIP_SET: $ delete time.tmp;*/nolog $! purge 'tmp_file'/keep=1/nolog $ goto EXIT $PUT_OTHER: $! create the file on the other node if it doesn't exist $ tmp_file = other_node+"::timecheck.com" $! see if the tmp file already exists -- if so, don't create it again $ ctx1 = 1563 $ if f$search(tmp_file+";*",ctx1).eqs.null then $ goto TMP_CREATE $TMP_LOOP: if f$search(tmp_file+";*",ctx1).nes.null then $ goto TMP_LOOP $ goto TMP_SKIP $TMP_CREATE: $ open/write tmp 'tmp_file' $ write tmp "$ open/write tmp sys$net" $ write tmp "$ write sys$net f$time()" $ write tmp "$ close tmp" $ close tmp $ goto TMP_SKIP $ERR_ACCESSING_NODE: $ write sys$output "Error accessing master clock node -- try again later" $ GOTO EXIT $! the MASTER node should be carefully chosen by observing which node $! keeps the best time over some fairly long interval -- several days $! to 2 or 3 weeks if you can wait that long. Use the US Naval Observatory $! or WWV or similar source accurate to the second. $! $! this procedure may require doing the following for additional speed $! to achieve better synchronicity: $! $! on the MASTER node only: $! NCP DEFINE OBJECT TIMECHECK NUMBER 0 FILE SYS$MANAGER:TIMECHECK.COM $! this will speed up the startup of the object $! $! the basic mechanism is to decide if this procedure is on the $! MASTER node (set at the beginning). If so, & interactive then $! prompt the user for the current time. The user should then enter $! a time (to the second) that is approaching. Then sit with finger $! poised over the key and press it JUST as that second occurs. $! the procedure will then compute the delta between the time the user $! supplied and what the system currently is running with. $! $! if not on the master node, the reference time is obtained by $! using a DECnet task to retrieve it from the MASTER node. $! $! once the reference is obtained the delta is computed, the time is $! is adjusted in increments so as not to make a scene for the accounting $! at one time the accounting utility was not amenable to negative $! connect time, so this attempts to prevent it. $! $! requires FERMILAB TIME utility -- we can supply a corrected copy $! of it. It can also be had from the DECUS tapes.