[macruby-changes] [4885] ControlTower/trunk

source_changes at macosforge.org source_changes at macosforge.org
Fri Nov 5 03:10:08 PDT 2010


Revision: 4885
          http://trac.macosforge.org/projects/ruby/changeset/4885
Author:   joshua.ballanco at apple.com
Date:     2010-11-05 03:10:04 -0700 (Fri, 05 Nov 2010)
Log Message:
-----------
Added GCD timer source based session store.

Modified Paths:
--------------
    ControlTower/trunk/Rakefile

Added Paths:
-----------
    ControlTower/trunk/lib/rack/session/
    ControlTower/trunk/lib/rack/session/gcd.rb

Modified: ControlTower/trunk/Rakefile
===================================================================
--- ControlTower/trunk/Rakefile	2010-11-05 04:09:54 UTC (rev 4884)
+++ ControlTower/trunk/Rakefile	2010-11-05 10:10:04 UTC (rev 4885)
@@ -20,6 +20,7 @@
                    lib/control_tower/rack_socket.rb
                    lib/control_tower/server.rb
                    lib/rack/handler/control_tower.rb
+                   lib/rack/session/gcd.rb
                    bin/control_tower
                    ext/CTParser/http11_parser.h
                    ext/CTParser/http11_parser.c

Added: ControlTower/trunk/lib/rack/session/gcd.rb
===================================================================
--- ControlTower/trunk/lib/rack/session/gcd.rb	                        (rev 0)
+++ ControlTower/trunk/lib/rack/session/gcd.rb	2010-11-05 10:10:04 UTC (rev 4885)
@@ -0,0 +1,110 @@
+#
+# Copyright © 2010 Apple Inc. All rights reserved.
+#
+# IMPORTANT NOTE:  This file is licensed only for use on Apple-branded computers
+# and is subject to the terms and conditions of the Apple Software License Agreement
+# accompanying the package this file is a part of.  You may not port this file to
+# another platform without Apple's written consent.
+#
+
+require 'rack/session/abstract/id'
+
+module Rack
+  module Session
+    class GCDSession
+      attr_reader :session_id
+
+      def initialize(sid, store)
+        @session_id = sid
+        @session_store = store
+        @session_values = {}
+        @session_timer = nil
+        @session_expires_at = nil
+        @session_access_queue = Dispatch::Queue.new("session-#{sid}-access")
+
+        # Sessions are self expiring. This is the block that handles expiry. The first task is to cancel the timer so that it only
+        # fires once
+        @timer_block = lambda do |src|
+          @session_timer.cancel! unless @session_timer.nil?
+          time_remaining = @session_expires_at - Time.now
+          if time_remaining < 0
+            @session_store.delete(@session_id)
+          else
+            @session_timer = Dispatch::Source.timer(time_remaining, 500, 0.5, @session_access_queue, &@timer_block)
+          end
+        end
+      end
+
+      def set_timer(seconds)
+        # If this is the first time we're setting the timer, then we need to create the timer source as well
+        @session_timer ||= Dispatch::Source.timer(seconds, 500, 0.5, @session_access_queue, &@timer_block)
+        @session_access_queue.sync { @session_expires_at = Time.now + seconds }
+      end
+
+      def [](key)
+        @session_values[key]
+      end
+      alias :fetch :[]
+
+      def []=(key, value)
+        @session_access_queue.sync do
+          @session_values[key] = value
+        end
+        value
+      end
+      alias :store :[]=
+
+      def delete(key)
+        @session_access_queue.sync do
+          @session_values.delete(key)
+        end
+      end
+
+      def clear
+        @session_access_queue.sync do
+          @session_values.clear
+        end
+      end
+    end
+
+    class GCD < Abstract::ID
+      def initialize(app, options={})
+        super
+        @sessions = {}
+      end
+
+      # Use UUIDs for session keys and save time on uniqueness checks
+      def generate_sid
+        uuid = CFUUIDCreate(nil)
+        CFMakeCollectable(uuid)
+        uuid_string = CFUUIDCreateString(nil, uuid)
+        CFMakeCollectable(uuid_string)
+        uuid_string
+      end
+
+      def get_session(env, sid)
+        session = @sessions[sid] if sid
+        unless sid and session
+          env['rack.errors'].puts("Session '#{sid.inspect}' not found, initializing...") if $VERBOSE and not sid.nil?
+          sid = generate_sid
+          session = GCDSession.new(sid, @sessions)
+          @sessions[sid] = session
+        end
+        return sid, session
+      end
+
+      def set_session(env, sid, session, options)
+        session = @sessions[sid]
+        if options[:renew] or options[:drop]
+          @sessions.delete(sid)
+          return false if options[:drop]
+          session_id = generate_sid
+          @sessions[session_id] = 0
+        end
+        session ||= GCDSession.new(generate_sid, @sessions)
+        session.set_timer(options[:expire_after]) unless options[:expire_after].nil?
+        session.session_id
+      end
+    end
+  end
+end
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.macosforge.org/pipermail/macruby-changes/attachments/20101105/b176b3f3/attachment-0001.html>


More information about the macruby-changes mailing list