DIRECTORY Basics, BasicTime, IO, Process, RedBlackTree, Rope, STP, STPConnectionCache, UserCredentials; STPConnectionCacheImpl: CEDAR MONITOR IMPORTS BasicTime, IO, Process, RedBlackTree, Rope, STP, UserCredentials EXPORTS STPConnectionCache = {OPEN STPConnectionCache; Time: TYPE = BasicTime.GMT; PrivateStuff: TYPE = REF PrivateStuffRec; PrivateStuffRec: TYPE = RECORD [ client: ROPE _ NIL, change: CONDITION, dieAfter: Time _ BasicTime.earliestGMT]; cache: RedBlackTree.Table _ RedBlackTree.Create[GetCacheKey, CacheCompare]; Get: PUBLIC ENTRY PROC [host, client: ROPE] RETURNS [h: Handle] = { ENABLE UNWIND => NULL; p: PrivateStuff; h _ NARROW[cache.Lookup[host]]; IF client = NIL THEN { self: CARDINAL _ LOOPHOLE[Process.GetCurrent[]]; client _ IO.PutFR["Process %g", IO.card[self]]; }; IF h = NIL THEN { h _ NEW [HandleRec _ [ host: host, stpHandle: STP.Create[], private: p _ NEW [PrivateStuffRec _ []] ]]; TRUSTED { Process.InitializeCondition[@p.change, Process.SecondsToTicks[5]]; Process.EnableAborts[@p.change]; Process.Detach[FORK CloseIt[h, p]]; }; RedBlackTree.Insert[cache, h, host]; } ELSE p _ NARROW[h.private]; IF NOT h.stpHandle.IsOpen[] THEN { name, password: ROPE; [name, password] _ UserCredentials.Get[]; [] _ h.stpHandle.Open[host]; h.stpHandle.Login[name, password]; }; WHILE p.client # NIL DO WAIT p.change ENDLOOP; p.client _ client; BROADCAST p.change; }; Release: PUBLIC ENTRY PROC [h: Handle, timeout: INT--seconds--] = { ENABLE UNWIND => NULL; p: PrivateStuff _ NARROW[h.private]; expire: Time _ BasicTime.Update[BasicTime.Now[], timeout]; p.client _ NIL; IF BasicTime.Period[from: p.dieAfter, to: expire] > 0 THEN p.dieAfter _ expire; BROADCAST p.change; }; CloseIt: ENTRY PROC [h: Handle, p: PrivateStuff] = { ENABLE UNWIND => NULL; DO now: Time; delta: INT; WAIT p.change; now _ BasicTime.Now[]; delta _ BasicTime.Period[from: now, to: p.dieAfter]; IF delta <= 0 THEN {--time to be closed-- IF p.client = NIL THEN { IF h.stpHandle.IsOpen[] THEN h.stpHandle.Close[]; TRUSTED { Process.SetTimeout[@p.change, maxDelay]; }; } ELSE TRUSTED { Process.SetTimeout[@p.change, minDelay]; }; } ELSE { TRUSTED { Process.SetTimeout[@p.change, Process.SecondsToTicks[MIN[delta, 60]+1]]; }; }; ENDLOOP; }; minDelay: Process.Ticks _ Process.SecondsToTicks[6]; maxDelay: Process.Ticks _ Process.SecondsToTicks[600]; GetCacheKey: PROC [data: REF ANY] RETURNS [key: ROPE] --RedBlackTree.GetKey-- = { h: Handle _ NARROW[data]; key _ h.host}; CacheCompare: PROC [k, data: REF ANY] RETURNS [Basics.Comparison] --RedBlackTree.Compare-- = { k1: ROPE _ NARROW[k]; k2: ROPE _ GetCacheKey[data]; RETURN [k1.Compare[k2, FALSE]]; }; }. JSTPConnectionCacheImpl.Mesa Spreitzer, July 29, 1985 6:48:17 pm PDT Κ– "cedar" style˜code™K™'—K˜KšΟk œœœ&˜gK˜šΠbxœœ˜%Kšœ œœ˜HKšœ˜K˜Kšœœ˜K˜Kšœœ œ˜K˜Kšœœœ˜)šœœœ˜ Kšœœœ˜Kšœ œ˜Kšœ(˜(—K˜KšœK˜KK˜š Οnœœœœœœ˜CKšœœœ˜K˜Kšœœ˜šœ œœ˜Kšœœœ˜0Kšœ œœ ˜/K˜—šœœœ˜šœœ˜K˜ Kšœ œ ˜Kšœ œ˜'K˜—šœ˜ KšœB˜BKšœ ˜ Kšœœ˜#Kšœ˜—Kšœ$˜$K˜—Kšœœ ˜šœœœ˜"Kšœœ˜K˜)Kšœ˜Kšœ"˜"K˜—Kš œ œœœ œ˜.K˜Kš œ ˜K˜—K˜š ŸœœœœΟc œ˜CKšœœœ˜Kšœœ ˜$Kšœ:˜:Kšœ œ˜Kšœ4œ˜OKš œ ˜K˜—K˜šŸœœœ!˜4Kšœœœ˜š˜K˜ Kšœœ˜ Kšœ ˜K˜Kšœ4˜4šœ œ ˜)šœ œœ˜Kšœœ˜1šœ˜ Kšœ(˜(K˜—Kšœ˜—šœœ˜Kšœ(˜(K˜—K˜—šœ˜šœ˜ Kšœ5œ˜HK˜—K˜—Kšœ˜—K˜—K˜Kšœ4˜4Kšœ6˜6K˜šŸ œœœœœœ œ˜QKšœ œ˜K˜—K˜š Ÿ œœ œœœ œ˜^Kšœœœ˜Kšœœ˜Kšœœ˜K˜—K˜K˜——…— b»