home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 35 Internet / 35-Internet.zip / srev13h.zip / SSICACHE.RXX < prev    next >
Text File  |  1999-06-19  |  18KB  |  571 lines

  1. /* The ssi-caching thread, for SRE-http.
  2. Uses workdata_temp for storage
  3.   call with queue containing:
  4.  transaction ' ' host_nickname ',' newq ',' newsem ','  filename
  5.  
  6.   returns
  7.      status ' ' filename
  8.  
  9. status=0 : no match
  10.       1  : use filename as is 
  11.       2  : read filename, and continue to do ssi's 
  12.       3  : this is a known, non-ssi file
  13. */
  14.  
  15.  
  16.  
  17.  
  18. parse upper arg storage_dir,  usequeue , USESEM, max_semwait,port,cache_size,def_duration,def_trigtype,sport
  19.  
  20. verbose=1
  21.  
  22. storage_dir=strip(storage_dir,'t','\')
  23. cache_list.0=0          ; cache_list.!size=0 ; cache_list.!marked=0
  24. max_marked=8   /* cleanup after this many expirations, etc. */
  25.  
  26.  
  27. signal on error name iserror
  28. signal on syntax name iserror
  29.  
  30. mytid=dostid()
  31. /*
  32. call pmprintf_sref(' SRE-http ssi-cache thread: ssi_cache dir='||storage_dir)
  33. call pmprintf_sref(' SRE-http ssi-cache thread: queue='||usequeue)
  34. call pmprintf_sref(' SRE-http ssi-cache thread: semaphore='||usesem)
  35. call pmprintf_sref(' SRE-http ssi-cache thread: thread id ='||mytid)*/
  36.  
  37. fo=pmprintf_sref(' SRE-http Ssicache: thread, dir, and queue='||mytid', 'storage_dir', 'usequeue,,sport)
  38.  
  39.  
  40. if storage_dir="" | usequeue="" | USESEM="" then do
  41.    call pmprintf('SRE-http Ssicache ERROR: initialization ERROR: '||usequeue)
  42.    exit
  43. end
  44.  
  45. /* clear junk from cache storage directory */
  46. oo=sysfiletree(storage_dir||'\_CS*.'||port,oofs,'FO')
  47. do mm=1 to oofs.0
  48.   foo=sysfiledelete(oofs.mm)
  49. end
  50. foo=pmprintf_sref(' SRE-http Ssicache: Deleted 'oofs.0' old cache files',,sport)
  51. drop oofs.
  52.  
  53. /* Initialization now done == start waiting for requests for ssi-cache */
  54.  
  55. idid=0
  56.  
  57. bakme:
  58.  a=rxqueue('s',usequeue)
  59.  aq=queued()
  60.  if aq=0 then do
  61.     WOW=EVENTSEM_WAIT(USESEM,max_semwait)
  62.     aq=-1
  63.     if wow=640 then do
  64.          signal bakme
  65.     end
  66.     IF WOW<>0 THEN do         /* FATAL ERROR */
  67.         call pmprintf(' SRE-http Ssicache ERROR: fatal semaphore error: 'wow)
  68.         EXIT
  69.     end
  70.  end
  71.  wow=EVENTSEM_RESET(usesem)
  72.  
  73.  if aq=-1 then
  74.    if queued()=0 then signal bakme
  75.  PARSE pull isit0
  76.  
  77.  
  78.  isit0=translate(isit0,' ','000d0a09'x)
  79.  
  80.  if isit0=" " then signal bakme
  81.  
  82. /* die command? */
  83.  if abbrev(isit0,'*DIE*')=1 then
  84.           exit
  85.  
  86. goobs:
  87.  parse var isit0  idnum   ',' newq ',' newsem ','  addto ',' wreply  ',' origfile
  88.  
  89. /* the ssi'ed version, a "wait for reply" flag, the original file */
  90.  
  91.  ADDTO=STRIP(addto) ; origfile=strip(origfile); wreply=strip(wreply)
  92.  
  93.   parse var idnum idnum host_nickname
  94.   host_nickname=strip(upper(host_nickname))
  95.   if newq="" | newsem="" then do
  96.         call pmprintf(' SRE-http Ssicache ERROR: thread: missing queue or semaphore ')
  97.         exit
  98.   end
  99.   newq=upper(strip(newq)); newsem=upper(strip(newsem))
  100.   origfile=upper(strip(origfile))
  101. /* do something ... */
  102.   select
  103.     when abbrev(origfile,'*RESET')=1 then do
  104.           do mm=1 to cache_list.0
  105.              foo=sysfiledelete(cache_list.mm.!dafile)
  106.           end
  107.           foo=cache_list.0
  108.           foo2=cache_list.!size
  109.           drop cache_list.
  110.           cache_list.0=0 ; cache_list.!size=0 ; cache_list.!marked=0
  111.           call lineout addto,' SRE-http Ssicache: cleared ' foo2 ' bytes in ' foo ' files in:' storage_dir
  112.           call lineout addto
  113.           a=rxqueue('s',newq)
  114.           push idnum ','  1
  115.           wow=eventsem_post(newsem)
  116.     end
  117.  
  118.     when abbrev(origfile,'*STATUS')=1 then do
  119.         foo=do_status(origfile)
  120.        a=rxqueue('s',newq)
  121.         push idnum ','  1
  122.         wow=eventsem_post(newsem)
  123.     end
  124.  
  125.     when abbrev(origfile,'*CLEANUP')=1 then do
  126.        foo=shrink_cache(1,addto)
  127.        a=rxqueue('s',newq)
  128.        push idnum ','  1
  129.        wow=eventsem_post(newsem)
  130.     end
  131.  
  132. /* get rid of old entries? */
  133.    when abbrev(origfile,'*REMOVE')=1 then do
  134.       removes=substr(origfile,8)
  135.       removes=translate(removes,' ','+='||'000d0a'x)
  136.       removes=packur(removes); removes=upper(translate(removes,'\','/'))
  137.  
  138.       do mm=1 to words(removes)
  139.           arem=strip(word(removes,mm))
  140.           call lineout addto,' Attempting to remove from SSI-cache: ' arem
  141.           do meow=1 to cache_list.0
  142.             if cache_list.meow=arem & cache_list.meow.!host=host_nickname then do
  143.                 wass=cache_list.meow.!size
  144.                 foo=cache_del(meow)
  145.                 call lineout addto,'    ....  removed ' arem '( ' wass ' bytes) from SSI-cache '
  146.             end
  147.           end
  148.           call lineout addto
  149.           a=rxqueue('s',newq)
  150.           push idnum ','  1
  151.           wow=eventsem_post(newsem)
  152.       end
  153.  
  154.     end
  155.  
  156.     otherwise do                      /* look up a cache entry!!!!!!! */
  157.       a=rxqueue('s',newq)
  158.       dog1=get_from_ssi_cache(origfile,addto)
  159.       if addto<>'' & wreply<>1 & dog1<>0  then do
  160.         nop
  161.       end
  162.       else do
  163.           push idnum ',' dog1
  164.           wow=eventsem_post(newsem)
  165.       end               /* if ADD, no return expected */
  166.     end                 /* otherwiase */
  167.  
  168.   end          /* select */
  169. signal bakme
  170.  
  171.  
  172. iserror:
  173. signal off error ; signal off syntax
  174. foo=condition('d')
  175. call pmprintf(' SRE-http Ssicache ERROR: error in ssi-cache thread at line ' sigl ' rc= ' rc)
  176.  
  177. n1=queued()
  178. a=rxqueue('d',usequeue)
  179. a=rxqueue('c',usequeue)
  180. foo=eventsem_reset(usesem)
  181. a=eventsem_close(usesem)
  182. a=eventsem_create(usesem)
  183. a=rxqueue('s',newq)
  184. push idnum ', 0 '
  185. wow=eventsem_post(newsem)
  186. call pmprintf('SRE-http Ssicache: done resetting ssi-cache thread ')
  187. signal on error name iserror
  188. signal on syntax name iserror
  189. signal bakme
  190.  
  191. exit
  192.  
  193. /***********/
  194. /* origfile = file to be looked for (the original file)
  195.    dafile = a "temporary" file used that should be stored in the cache
  196.  
  197. fields of cache_list.
  198.    .0 = # entries
  199.    .!size= Running totals: kbytes
  200.    .!marked= Marked for deletion
  201.    .m = name of file "to be cached" (origfile) -- or =0 if marked for deletion
  202.    .m.!type = type of file (1=use as is, 2=process further, 3 -- no ssis)
  203.    .m.!time = time file was created
  204.    .m.!host= host nickname for this entry
  205.    .m.!recent = most recent access
  206.    .m.!size = size of Cached-file (the _CS*.80 file)
  207.    .m.!duration = lifespan of this file
  208.    .m.!ntriggers   = # of trigger files (usually =1 : own file name )
  209.    .m.!trigger.n = A trigger file stamp: date size attribs fully_qualified_name
  210.    .m.!trigtype  = Type of trigger (DATE TIME TIMEDATE DATETIME SIZE ALL)
  211.    .m.!dafile = The "cached" (_CS*.80) file
  212. */
  213.  
  214. get_from_ssi_cache:procedure expose cache_list. storage_dir def_duration cache_size def_trigtype ,
  215.                 host_nickname max_marked verbose
  216.  
  217. parse upper arg origfile,todo
  218.  
  219. inc=cache_list.0
  220. nowtime=date('b')+(time('m')/(24*60))
  221.  
  222.  
  223. /* ========  Here to add a file to the cache */
  224. if todo<>' ' then do
  225.    itype=2         /* assume changes will be necessary */
  226.    parse var todo dafile al
  227.    if pos('=',dafile)>0 then parse var dafile stype '=' dafile
  228.    if translate(stype)='STEM' then itype=2.2
  229.  
  230.    dafile=strip(dafile)
  231.    triggers=origfile 
  232.    duration=def_duration ; trigtype=def_trigtype
  233.    do until al=""
  234.         parse var al val ';' al
  235.         val=upper(strip(val)) 
  236.         val1=strip(word(val,1))
  237.         if val="ASIS" then do   /* asis must be explicitly invoked by CACHE ASIS */
  238.                 itype=1
  239.         end
  240.         if val="NOCHANGE" then itype=1  /* no change occurs if all static ssis */
  241.         if val1="TRIGGER" then  triggers=triggers||' '||subword(val,2)
  242.         if val1="TRIGGER_TYPE" then  trigtype=strip(word(val,2))
  243.         if val1="DURATION" | val1="DAYS" then  duration=strip(word(val,2))
  244.         if val1="HOURS" then  do
  245.             duration=word(val,2)
  246.             if datatype(duration)="NUM" then duration=duration/24 ;
  247.          end
  248.    end
  249. /* convert .01, 3H, 180M, 1200S to fractoins of day */
  250.    duration=convert_duratioN(duration)
  251.  
  252. /* done with file specific options */
  253.    if datatype(duration)<>'NUM' then duration=def_duration
  254.  
  255. /* NOte:itype=1 : return as is  2: partial cache
  256.         2.2 : partial cache as stem file  3: this is non-ssi file */
  257.    if dafile<>'NOSSI' then do
  258.      dafilesize=stream(dafile,'c','query size')
  259.      if dafilesize=0 then return 0  /* no such entry */
  260.      if dafilesize>(cache_size*500) then do
  261.      if verbose>0 then call pmprintf_sref('SSI-Cache warning: too big for cache 'dafilesize ' 'origfile)
  262.        foo=sysfiledelete(dafile)
  263.        return ' '  /* too big */
  264.      end
  265.    end
  266.    else do
  267.       itype=3
  268.    end
  269.  
  270. /* size is not a problem,save results */
  271.    inc=inc+1
  272.    cache_list.inc=origfile
  273.    cache_list.inc.!host=host_nickname
  274.    cache_list.inc.!type=itype                       /* 1= use as is */
  275.    cache_list.inc.!ntriggers=0
  276.    cache_list.inc.!duration=duration
  277.    cache_list.inc.!time=nowtime          /*the creation time stamp */
  278.    cache_list.inc.!recent=nowtime        /* the most recent hit time stamp */
  279.    cache_list.inc.!trigtype=trigtype   /* type of trigger */
  280.   do until triggers=""                  /* add triggers (possibly just self */
  281.         parse upper var triggers atrig triggers ; atrig=strip(atrig)
  282.         foo=sysfiletree(atrig,stamp,'FT')
  283.         if stamp.0>0 then do
  284.            lk=cache_list.inc.!ntriggers+1
  285.            cache_list.inc.!trigger.lk=space(stamp.1)
  286.            cache_list.inc.!ntriggers=lk
  287.         end
  288.    end
  289.    if dafile<>'NOSSI' then do
  290.      cache_list.inc.!dafile=dafile
  291.      cache_list.inc.!size=dafilesize
  292.      cache_list.!size=cache_list.!size+dafilesize
  293.      cache_list.0=inc
  294.    end
  295.    else do
  296.        cache_list.inc.!dafile=''
  297.        cache_list.0=inc
  298.        cache_list.inc.!size=0
  299.    end
  300.  
  301. /* get rid of old entries? */
  302.   do meow=1 to inc-1
  303.         if cache_list.meow=origfile & cache_list.meow.!host=host_nickname then do
  304.             foo=cache_del(meow)
  305.             leave
  306.         end
  307.   end
  308. /* now check size of cache, and delete files if necessary */
  309.    if cache_list.!size>(cache_size*1000) then do
  310.      if verbose>0 then
  311.        call pmprintf_sref('SSI-cache warning: shrinking cache 'cache_list.!size ',' cache_size)
  312.      foo=shrink_cache(0)
  313.    end
  314.    return ' '           /* no return info expected */
  315. end
  316.  
  317.  
  318. /*  ========== here to check for a file in the cache */
  319. do mm=1 to inc
  320.    if cache_list.mm=0 then iterate
  321.    if cache_list.mm=origfile  & cache_list.mm.!host=host_nickname then do    /* got a match -- check it's time and triggers */
  322.         cache_list.inc.!recent=nowtime
  323.         fexpire=cache_list.mm.!time+cache_list.mm.!duration
  324.         if fexpire<nowtime then do           /* expired -- so no matdh */
  325.            foo=cache_del(mm)
  326.            return 0
  327.         end
  328.         do it0=1 to cache_list.mm.!ntriggers  /* check all trigger files */
  329.              atrig=cache_list.mm.!trigger.it0
  330.              atrig=strip(word(atrig,4))
  331.              foo=sysfiletree(atrig,nowstamp,'FT')
  332.              oldstamp=cache_list.mm.!trigger.it0
  333.              if nowstamp.0=0  then do
  334.                  Call pmprintf_sref(" ERROR: ssi-cache trigger missing : " atrig)
  335.                  foo=cache_del(mm);  return 0
  336.              end
  337.              if CHECK_STAMP(nowstamp.1,oldstamp,cache_list.mm.!TRIGTYPE)=0 then do
  338.                  foo=cache_del(mm);  return 0
  339.              end
  340.         end 
  341.  
  342. /* not expired, triggers okay; so use it */
  343.  
  344. /* last check -- make sure size is correct */
  345.         if cache_list.mm.!dafile<>'' then do
  346.           tst1=stream(cache_list.mm.!dafile,'c','query size')
  347.           if tst1<>cache_list.mm.!size then do
  348.             call pmprintf_sref(' SSI-cache error: ('origfile 'mismatch in cache sizes 'tst1 ',' cache_list.mm.!size', 'cache_list.mm.!dafile)
  349.             foo=cache_del(mm)  /* delete this entry */
  350.             return 0
  351.           end
  352.         end
  353.         itype=cache_list.mm.!type
  354.         return itype' 'cache_list.mm.!duration||','||cache_list.mm.!dafile
  355.    end
  356. end
  357. return 0                /* don't got */
  358.  
  359. /*********/
  360. check_stamp:procedure
  361. parse upper arg stmp1,stmp2,atype
  362.  
  363. select
  364.   when atype='SIZE' then do
  365.     stmp1=strip(word(stmp1,2))
  366.     stmp2=strip(word(stmp2,2))
  367.   end
  368.   when atype='TIMEDATE' | atype='DATETIME' then do
  369.     stmp1=strip(word(stmp1,1))
  370.     stmp2=strip(word(stmp2,1))
  371.  
  372.   end
  373.   when atype="ALL" then do
  374.     stmp1=strip(space(stmp1))
  375.     stmp2=strip(space(stmp2))
  376.   end
  377.   when atype='TIME' then do
  378.     stmp1=substr(strip(stmp1),10,5)
  379.     stmp2=substr(strip(stmp2),10,5)
  380.   end
  381.   when atype='DATE' then do
  382.     stmp1=substr(strip(stmp1),1,8)
  383.     stmp2=substr(strip(stmp2),1,8)
  384.   end
  385.   otherwise do
  386.      call pmprintf_sref(' bad trigtype: 'atype)
  387.      return 0           /* should never happen */
  388.   end
  389. end
  390.  
  391. if stmp1=stmp2 then return 1   /* 1 means "okay", 0 means "out of sync */
  392. return 0
  393.  
  394.  
  395.  
  396.  
  397. /*********/
  398. /* remove a cache entry */
  399. cache_del:procedure expose cache_list. cache_size max_marked
  400. parse arg nn
  401.   i1=cache_list.0
  402.   if cache_list.nn.!dafile<>'' then do
  403.     foo=sysfiledelete(strip(cache_list.nn.!dafile))
  404.     gsize=cache_list.nn.!size
  405.     cache_list.!size=cache_list.!size-gsize
  406.   end
  407.   cache_list.nn=0
  408.  
  409. /* deleted entry  # nn */
  410.   cache_list.!marked=cache_list.!marked+1
  411.  
  412.   if cache_list.!marked > max_marked then foo=shrink_cache(0)
  413.  
  414.   return foo
  415.  
  416. /*******/
  417. do_status:procedure expose cache_list.  addto host_nickname /* display current state */
  418. parse arg iss0
  419. iss=translate(iss0,' ','*+=?')
  420.  
  421.  select 
  422.     when strip(upper(word(iss,2)))='SHORT' then do
  423.         call lineout addto,"  "
  424.         call lineout addto," Current status of SSI-Cache "
  425.         call lineout addto,' # entries ' cache_list.0 ', bytes stored = ' cache_list.!size
  426.         if cache_list.0>0 then do
  427.           call lineout addto,' Host-nickname : File    Cache-file , status, size ,  #trigger_files  most_recent_hit '
  428.           do mm=1 to cache_list.0
  429.             if cache_list.mm=0 then
  430.                 call lineout addto,' Entry ' mm ' marked for deletion '
  431.             else
  432.                 call lineout addto,cache_list.mm.!host ' : ' cache_list.mm ' ' ,
  433.                  filespec('n',cache_list.mm.!dafile) ', 'cache_list.mm.!type ', ' cache_list.mm.!size ' ' cache_list.mm.!ntriggers '  ' cache_list.mm.!time
  434.          end
  435.        end              /* clist>0 */
  436.     end
  437.     when words(iss)>1 then do
  438.       removes=substr(iss0,8)
  439.       removes=translate(removes,' ','+='||'000d0a'x)
  440.       removes=packur(removes); removes=upper(translate(removes,'\','/'))
  441.       removes=strip(word(removes,1))
  442.       call lineout addto,' '
  443.       call lineout addto,' Status info for cache entry: ' removes
  444.       do mm = 1 to cache_list.0
  445.         if cache_list.mm=removes & cache_list.mm.!Host=host_nickname then do
  446.            booger=cvtails(cache_list.mm.,stuff)
  447.            foo=arraysort(stuff)
  448.            do mm2=1 to stuff.0
  449.               aa=stuff.mm2
  450.               wow=cache_list.mm.aa
  451.               call lineout addto,'   ' aa ' = 'wow
  452.            end
  453.            leave
  454.         end             /* if */
  455.      end  /* do loop */
  456.  
  457.     end    /* when words iss */
  458.  
  459.     otherwise do                        /* show all the status stuff */
  460.        booger=cvtails(cache_list,stuff)
  461.        foo=arraysort(stuff)
  462.        do mm=1 to stuff.0
  463.             aa=stuff.mm
  464.             wow=cache_list.aa
  465.             call lineout addto,'   ' aa ' = 'wow
  466.        end
  467.    end
  468.  
  469. end
  470. call lineout addto
  471. return 0
  472.  
  473. /*********/
  474. /* shrink the cache 
  475.   get rid of "marked for deletions". ALso, cut size of cache to 85% of max */
  476.  
  477. shrink_cache:procedure expose cache_list. cache_size
  478. parse arg iwrite,tempfile
  479.  
  480. signal on error name aprob
  481. signal on syntax name prob
  482.  
  483. ntmp=0
  484.  
  485. if cache_list.0=0 then do
  486.    call lineout tempfile,' '
  487.    call lineout tempfile,' SSI-Cache cleanup: No entries in cache list '
  488.    call lineout tempfile
  489.    return 1
  490. end
  491.  
  492. wassize=cache_list.!size
  493. wasentries=cache_list.0
  494. nolds=0
  495. ncleaned=0
  496. /* This section is used to cut cache down to size */
  497. if cache_list.!size>(cache_size*1000) then do
  498.       iwas=cache_list.!size
  499.       iww=0
  500.       do iw=1 to cache_list.0           /* make a sortable list */
  501.           if cache_list.iw<>0 then do
  502.              iww=iww+1
  503.              sht.iww=left(cache_list.iw.!recent,15)||' '||iw||' '||cache_list.iw.!size||' '||cache_list.iw
  504.           end
  505.       end
  506.       sht.0=iww
  507.       foo=arraysort(sht,1,,1,15,'A','N')
  508. /* cut size of cache (by marking oldest for deletion, and deleting the cache file */
  509.       do iat=1 to sht.0
  510.             if cache_list.!size<(cache_size*850) then leave  /*clean out some extra */
  511.             parse var sht.iat tt nth asize aname ; nth=strip(nth) ;asize=strip(asize)
  512.             cache_list.!size=cache_list.!size-asize
  513.             dafile=strip(dafile); foo=sysfiledelete(cache_list.nth.!dafile)
  514.             cache_list.nth=0   /* mark for deletion, along with prior marked items */
  515.       end
  516.       ntmp=0
  517. end
  518. /* now shrink cache_list array  (remove marked for dletion enetries */
  519.  do iu=1 to cache_list.0
  520.          if cache_list.iu=0 then iterate 
  521.          ntmp=ntmp+1
  522.          tmps.ntmp=cache_list.iu
  523.          foo=cvcopy(cache_list.iu.,tmps.ntmp.)
  524.  end
  525.  tmps.0=ntmp
  526.  tmps.!size=cache_list.!size
  527.  tmps.!marked=0
  528.  drop cache_list.
  529.  foo=cvcopy(tmps,cache_list)
  530.  drop tmps.; drop sht.
  531.  if iwrite=1 then do
  532.    call lineout tempfile,' '
  533.    call lineout tempfile,' SSI-Cache cleanup: Starting size (entries,bytes): 'wasentries ',' wassize
  534.    call lineout tempfile,'                      ending size (entries,bytes): 'cache_list.0 ',' cache_list.!size
  535.    call lineout tempfile
  536.  end
  537.  
  538.  return 1
  539.  
  540. aprob:
  541. signal off syntax
  542. signal off error
  543. call pmprintf_sref(' Some kind of error in SSICACHE:cleanup procedure')
  544. return 0
  545.  
  546. /**********/
  547. /* convert durationSMDH to fractions of day */
  548. convert_duration:procedure
  549. parse arg tt
  550. fact=1
  551. select
  552.   when right(tt,1)='H' then do
  553.        fact=24
  554.        tt=strip(tt,,'H')
  555.   end
  556.   when right(tt,1)='M' then do
  557.      fact=1440
  558.      tt=strip(tt,,'M')
  559.   end
  560.   when right(tt,1)='S' then do
  561.       fact=86400
  562.       tt=strip(tt,,'S')
  563.   end
  564.   when right(tt,1)='D' then do
  565.       tt=strip(tt,,'D')
  566.   end
  567.   otherwise nop
  568. end
  569. if datatype(tt)='NUM' then return tt/fact
  570. return tt
  571.