celluloid-essentials-0.20.5/0000755000004100000410000000000012620347010015745 5ustar www-datawww-datacelluloid-essentials-0.20.5/.env-ci0000644000004100000410000000020312620347010017122 0ustar www-datawww-dataCELLULOID_SPECS_LOG_STRATEGY=stderr CELLULOID_SPECS_LOG_LEVEL=3 CELLULOID_SPECS_LOG_FILE=log/ci.log CELLULOID_SPECS_LOG_SYNC=false celluloid-essentials-0.20.5/Rakefile0000644000004100000410000000031512620347010017411 0ustar www-datawww-datarequire "bundler/gem_tasks" Dir["tasks/**/*.rake"].each { |task| load task } default_tasks = ["spec"] default_tasks << "rubocop" unless ENV["CI"] task default: default_tasks task ci: %w(spec benchmark) celluloid-essentials-0.20.5/Gemfile0000644000004100000410000000012512620347010017236 0ustar www-datawww-datarequire File.expand_path("../culture/sync", __FILE__) Celluloid::Sync::Gemfile[self] celluloid-essentials-0.20.5/celluloid-essentials.gemspec0000644000004100000410000000151712620347010023442 0ustar www-datawww-data# -*- encoding: utf-8 -*- require File.expand_path("../culture/sync", __FILE__) Gem::Specification.new do |gem| gem.name = "celluloid-essentials" gem.version = "0.20.5" gem.platform = Gem::Platform::RUBY gem.summary = "Internally used tools, and superstructural dependencies of Celluloid" gem.description = "Notifications, Internals, Logging, Probe, and essential Celluloid pieces demanding Supervision" gem.licenses = ["MIT"] gem.authors = ["Tony Arcieri", "Donovan Keme"] gem.email = ["tony.arcieri@gmail.com", "code@extremist.digital"] gem.homepage = "https://github.com/celluloid/celluloid-essentials" gem.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|examples|spec|features)/}) } gem.require_path = "lib" Celluloid::Sync::Gemspec[gem] end celluloid-essentials-0.20.5/.rspec0000644000004100000410000000011712620347010017061 0ustar www-datawww-data--color --format documentation --order random --warnings --require spec_helper celluloid-essentials-0.20.5/LICENSE.txt0000644000004100000410000000206512620347010017573 0ustar www-datawww-dataThe MIT License (MIT) Copyright (c) 2015 Celluloid Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. celluloid-essentials-0.20.5/.travis.yml0000644000004100000410000000173012620347010020057 0ustar www-datawww-datascript: rake ci language: ruby rvm: - rbx-2 - jruby - 2.2.2 - 2.2.0 - 2.1.4 - 2.0.0 - 1.9.3 - ruby-head - jruby-head matrix: fast_finish: true allow_failures: - rvm: 1.9.3 - rvm: ruby-head - rvm: jruby-head - env: CELLULOID_BACKPORTED=true - env: CELLULOID_BACKPORTED=false CELLULOID_TASK_CLASS=Threaded - env: CELLULOID_BACKPORTED=true CELLULOID_TASK_CLASS=Threaded env: global: - NUMBER_OF_PROCESSORS=4 CELLULOID_CONFIG_FILE=.env-ci matrix: - CELLULOID_BACKPORTED=true - CELLULOID_BACKPORTED=false - CELLULOID_BACKPORTED=false CELLULOID_TASK_CLASS=Threaded - CELLULOID_BACKPORTED=true CELLULOID_TASK_CLASS=Threaded notifications: irc: "irc.freenode.org#celluloid" before_install: # Only use 1 job until Travis fixes the rbx --jobs issue. - if [ "$TRAVIS_RUBY_VERSION" == "rbx-2" ] ; then export BUNDLE_JOBS=1 ; else export BUNDLE_JOBS=4; fi sudo: false install: bundle install --without=development celluloid-essentials-0.20.5/lib/0000755000004100000410000000000012620347010016513 5ustar www-datawww-datacelluloid-essentials-0.20.5/lib/celluloid/0000755000004100000410000000000012620347010020467 5ustar www-datawww-datacelluloid-essentials-0.20.5/lib/celluloid/essentials.rb0000644000004100000410000000222512620347010023167 0ustar www-datawww-datamodule Celluloid::Internals; end require "celluloid/internals/call_chain" require "celluloid/internals/cpu_counter" require "celluloid/internals/links" require "celluloid/internals/logger" require "celluloid/internals/method" require "celluloid/internals/properties" require "celluloid/internals/handlers" require "celluloid/internals/receivers" require "celluloid/internals/registry" require "celluloid/internals/responses" require "celluloid/internals/signals" require "celluloid/internals/task_set" require "celluloid/internals/thread_handle" require "celluloid/internals/uuid" require "celluloid/internals/stack" require "celluloid/notifications" require "celluloid/logging" if $CELLULOID_BACKPORTED module Celluloid UUID = Internals::UUID Links = Internals::Links Logger = Internals::Logger Registry = Internals::Registry CPUCounter = Internals::CPUCounter StackDump = Internals::Stack::Dump Properties = Internals::Properties ThreadHandle = Internals::ThreadHandle end end require "celluloid/supervision" # TODO: Remove unneeded gem requirements once the gems are well known. require "celluloid/pool" require "celluloid/fsm" celluloid-essentials-0.20.5/lib/celluloid/logger.rb0000644000004100000410000000006112620347010022270 0ustar www-datawww-data# DEPRECATE require "celluloid/internals/logger" celluloid-essentials-0.20.5/lib/celluloid/notifications.rb0000644000004100000410000000444512620347010023674 0ustar www-datawww-datamodule Celluloid module Notifications def self.notifier Actor[:notifications_fanout] || fail(DeadActorError, "notifications fanout actor not running") end def publish(pattern, *args) Celluloid::Notifications.notifier.publish(pattern, *args) rescue DeadActorError # Bad shutdown logic. Oh well.... # TODO: needs a tests end module_function :publish def subscribe(pattern, method) Celluloid::Notifications.notifier.subscribe(Actor.current, pattern, method) end def unsubscribe(*args) Celluloid::Notifications.notifier.unsubscribe(*args) end class Fanout include Celluloid trap_exit :prune def initialize @subscribers = [] @listeners_for = {} end def subscribe(actor, pattern, method) subscriber = Subscriber.new(actor, pattern, method).tap do |s| @subscribers << s end link actor @listeners_for.clear subscriber end def unsubscribe(subscriber) @subscribers.reject! { |s| s.matches?(subscriber) } @listeners_for.clear end def publish(pattern, *args) listeners_for(pattern).each { |s| s.publish(pattern, *args) } end def listeners_for(pattern) @listeners_for[pattern] ||= @subscribers.select { |s| s.subscribed_to?(pattern) } end def listening?(pattern) listeners_for(pattern).any? end def prune(actor, _reason=nil) @subscribers.reject! { |s| s.actor == actor } @listeners_for.clear end end class Subscriber attr_accessor :actor, :pattern, :method def initialize(actor, pattern, method) @actor = actor @pattern = pattern @method = method end def publish(pattern, *args) actor.async method, pattern, *args rescue DeadActorError # TODO: needs a tests # Bad shutdown logic. Oh well.... end def subscribed_to?(pattern) !pattern || @pattern === pattern.to_s || @pattern === pattern end def matches?(subscriber_or_pattern) self === subscriber_or_pattern || @pattern && @pattern === subscriber_or_pattern end end end def self.publish(*args) Notifications.publish(*args) end end celluloid-essentials-0.20.5/lib/celluloid/internals/0000755000004100000410000000000012620347010022466 5ustar www-datawww-datacelluloid-essentials-0.20.5/lib/celluloid/internals/stack/0000755000004100000410000000000012620347010023573 5ustar www-datawww-datacelluloid-essentials-0.20.5/lib/celluloid/internals/stack/states.rb0000644000004100000410000000411212620347010025421 0ustar www-datawww-datamodule Celluloid module Internals class Stack module DisplayBacktrace def display_backtrace(backtrace, output, indent = nil) backtrace ||= ["EMPTY BACKTRACE"] backtrace.each do |line| output << indent if indent output << "\t" << line << "\n" end output << "\n\n" end end class TaskState < Struct.new(:task_class, :type, :meta, :status, :backtrace); end class CellState < Struct.new(:subject_id, :subject_class) def dump "Celluloid::Cell 0x#{subject_id.to_s(16)}: #{subject_class}" end end class ThreadState < Struct.new(:thread_id, :backtrace, :role) include DisplayBacktrace def dump string = "" string << "Thread 0x#{thread_id.to_s(16)} (#{role}):\n" display_backtrace backtrace, string if backtrace string end end class ActorState include DisplayBacktrace attr_accessor :name, :id, :cell attr_accessor :status, :tasks attr_accessor :backtrace def dump string = "" string << "Celluloid::Actor 0x#{id.to_s(16)}" string << " [#{name}]" if name string << "\n" if cell string << cell.dump string << "\n" end if status == :idle string << "State: Idle (waiting for messages)\n" display_backtrace backtrace, string if backtrace else string << "State: Running (executing tasks)\n" display_backtrace backtrace, string if backtrace string << "\tTasks:\n" tasks.each_with_index do |task, i| string << "\t #{i + 1}) #{task.task_class}[#{task.type}]: #{task.status}\n" if task.backtrace string << "\t #{task.meta.inspect}\n" display_backtrace task.backtrace, string, "\t" end end end string << "\n" unless backtrace string end end end end end celluloid-essentials-0.20.5/lib/celluloid/internals/stack/dump.rb0000644000004100000410000000030712620347010025065 0ustar www-datawww-datamodule Celluloid module Internals class Stack class Dump < Stack def initialize(threads) super(threads) snapshot(true) end end end end end celluloid-essentials-0.20.5/lib/celluloid/internals/stack/summary.rb0000644000004100000410000000030412620347010025612 0ustar www-datawww-datamodule Celluloid module Internals class Stack class Summary < Stack def initialize(threads) super(threads) snapshot end end end end end celluloid-essentials-0.20.5/lib/celluloid/internals/uuid.rb0000644000004100000410000000224712620347010023766 0ustar www-datawww-datarequire "securerandom" module Celluloid module Internals # Clearly Ruby doesn't have enough UUID libraries # This one aims to be fast and simple with good support for multiple threads # If there's a better UUID library I can use with similar multithreaded # performance, I certainly wouldn't mind using a gem for this! module UUID values = SecureRandom.hex(9).match(/(.{8})(.{4})(.{3})(.{3})/) PREFIX = "#{values[1]}-#{values[2]}-4#{values[3]}-8#{values[4]}".freeze BLOCK_SIZE = 0x10000 @counter = 0 @counter_mutex = Mutex.new def self.generate thread = Thread.current unless thread.uuid_limit @counter_mutex.synchronize do block_base = @counter @counter += BLOCK_SIZE thread.uuid_counter = block_base thread.uuid_limit = @counter - 1 end end counter = thread.uuid_counter if thread.uuid_counter >= thread.uuid_limit thread.uuid_counter = thread.uuid_limit = nil else thread.uuid_counter += 1 end "#{PREFIX}-#{sprintf('%012x', counter)}".freeze end end end end celluloid-essentials-0.20.5/lib/celluloid/internals/call_chain.rb0000644000004100000410000000052012620347010025065 0ustar www-datawww-datamodule Celluloid module Internals class CallChain def self.current_id=(value) Thread.current[:celluloid_chain_id] = value task = Thread.current[:celluloid_task] task.chain_id = value if task end def self.current_id Thread.current[:celluloid_chain_id] end end end end celluloid-essentials-0.20.5/lib/celluloid/internals/stack.rb0000644000004100000410000000364012620347010024123 0ustar www-datawww-datamodule Celluloid module Internals class Stack attr_accessor :actors, :threads def initialize(threads) @group = threads @actors = [] @threads = [] end def snapshot(backtrace=nil) @group.each do |thread| if thread.role == :actor @actors << snapshot_actor(thread.actor, backtrace) if thread.actor else @threads << snapshot_thread(thread, backtrace) end end end def snapshot_actor(actor, backtrace=nil) state = ActorState.new state.id = actor.object_id # TODO: delegate to the behavior state.cell = snapshot_cell(actor.behavior) if actor.behavior.is_a?(Cell) tasks = actor.tasks if tasks.empty? state.status = :idle else state.status = :running state.tasks = tasks.to_a.map { |t| TaskState.new(t.class, t.type, t.meta, t.status, t.backtrace) } end state.backtrace = actor.thread.backtrace if backtrace && actor.thread state end def snapshot_cell(behavior) state = CellState.new state.subject_id = behavior.subject.object_id state.subject_class = behavior.subject.class state end def snapshot_thread(thread, backtrace=nil) backtrace = begin thread.backtrace rescue NoMethodError # for Rubinius < 2.5.2.c145 [] end if backtrace ThreadState.new(thread.object_id, backtrace, thread.role) end def print(output = STDERR) @actors.each do |actor| output.print actor.dump end @threads.each do |thread| output.print thread.dump end end end end end require "celluloid/internals/stack/states" require "celluloid/internals/stack/dump" require "celluloid/internals/stack/summary" celluloid-essentials-0.20.5/lib/celluloid/internals/handlers.rb0000644000004100000410000000153212620347010024614 0ustar www-datawww-datarequire "set" module Celluloid module Internals class Handlers def initialize @handlers = Set.new end def handle(*patterns, &block) patterns.each do |pattern| handler = Handler.new pattern, block @handlers << handler end end # Handle incoming messages def handle_message(message) handler = @handlers.find { |h| h.match(message) } handler.call message if handler handler end end # Methods blocking on a call to receive class Handler def initialize(pattern, block) @pattern = pattern @block = block end # Match a message with this receiver's block def match(message) @pattern === message end def call(message) @block.call message end end end end celluloid-essentials-0.20.5/lib/celluloid/internals/links.rb0000644000004100000410000000145312620347010024136 0ustar www-datawww-datamodule Celluloid module Internals # Linked actors send each other system events class Links include Enumerable def initialize @links = {} end # Add an actor to the current links def <<(actor) @links[actor.mailbox.address] = actor end # Do links include the given actor? def include?(actor) @links.key? actor.mailbox.address end # Remove an actor from the links def delete(actor) @links.delete actor.mailbox.address end # Iterate through all links def each @links.each { |_, actor| yield(actor) } end # Generate a string representation def inspect links = map(&:inspect).join(",") "#<#{self.class}[#{links}]>" end end end end celluloid-essentials-0.20.5/lib/celluloid/internals/thread_handle.rb0000644000004100000410000000270012620347010025574 0ustar www-datawww-datamodule Celluloid module Internals # An abstraction around threads from the InternalPool which ensures we don't # accidentally do things to threads which have been returned to the pool, # such as, say, killing them class ThreadHandle def initialize(actor_system, role = nil) @mutex = Mutex.new @join = ConditionVariable.new @thread = actor_system.get_thread do Thread.current.role = role begin yield ensure @mutex.synchronize do @thread = nil @join.broadcast end end end end # Is the thread running? def alive? @mutex.synchronize { @thread.alive? if @thread } end # Forcibly kill the thread def kill !!@mutex.synchronize { @thread.kill if @thread } self end # Join to a running thread, blocking until it terminates def join(limit = nil) fail ThreadError, "Target thread must not be current thread" if @thread == Thread.current @mutex.synchronize { @join.wait(@mutex, limit) if @thread } self end # Obtain the backtrace for this thread def backtrace @thread.backtrace rescue NoMethodError # undefined method `backtrace' for nil:NilClass # Swallow this in case this ThreadHandle was terminated and @thread was # set to nil end end end end celluloid-essentials-0.20.5/lib/celluloid/internals/properties.rb0000644000004100000410000000166312620347010025215 0ustar www-datawww-datamodule Celluloid module Internals # Properties define inheritable attributes of classes, somewhat similar to # Rails cattr_*/mattr_* or class_attribute module Properties def property(name, opts = {}) default = opts.fetch(:default, nil) multi = opts.fetch(:multi, false) ivar_name = "@#{name}".to_sym singleton = class << ancestors.first; self; end singleton.send(:remove_method, name) rescue nil singleton.send(:define_method, name) do |value = nil, *extra| if value value = value ? [value, *send(name), *extra].uniq : [] if multi instance_variable_set(ivar_name, value) elsif instance_variables.include?(ivar_name) instance_variable_get(ivar_name) elsif superclass.respond_to? name superclass.send(name) else default end end end end end end celluloid-essentials-0.20.5/lib/celluloid/internals/logger.rb0000644000004100000410000000452112620347010024274 0ustar www-datawww-datamodule Celluloid module Internals module Logger class WithBacktrace def initialize(backtrace) @backtrace = backtrace end def debug(string) Celluloid.logger.debug(decorate(string)) if $CELLULOID_DEBUG end def info(string) Celluloid.logger.info(decorate(string)) end def warn(string) Celluloid.logger.warn(decorate(string)) end def error(string) Celluloid.logger.error(decorate(string)) end def decorate(string) [string, @backtrace].join("\n\t") end end @exception_handlers = [] module_function def with_backtrace(backtrace) yield WithBacktrace.new(backtrace) if Celluloid.logger end # Send a debug message def debug(string) Celluloid.logger.debug(string) if Celluloid.logger && $CELLULOID_DEBUG end # Send a info message def info(string) Celluloid.logger.info(string) if Celluloid.logger end # Send a warning message def warn(string) Celluloid.logger.warn(string) if Celluloid.logger end # Send an error message def error(string) Celluloid.logger.error(string) if Celluloid.logger end # Handle a crash def crash(string, exception) if Celluloid.log_actor_crashes string << "\n" << format_exception(exception) error string end @exception_handlers.each do |handler| begin handler.call(exception) rescue => ex error "EXCEPTION HANDLER CRASHED:\n" << format_exception(ex) end end end # Note a deprecation def deprecate(message) trace = caller.join("\n\t") warn "DEPRECATION WARNING: #{message}\n\t#{trace}" end # Define an exception handler # NOTE: These should be defined at application start time def exception_handler(&block) @exception_handlers << block nil end # Format an exception message def format_exception(exception) str = "#{exception.class}: #{exception}\n\t" if exception.backtrace str << exception.backtrace.join("\n\t") else str << "EMPTY BACKTRACE\n\t" end end end end end celluloid-essentials-0.20.5/lib/celluloid/internals/task_set.rb0000644000004100000410000000216512620347010024634 0ustar www-datawww-datarequire "set" require "forwardable" module Celluloid module Internals if RUBY_PLATFORM == "java" require "jruby/synchronized" class TaskSet extend Forwardable include JRuby::Synchronized def_delegators :@tasks, :<<, :delete, :first, :empty?, :to_a def initialize @tasks = Set.new end end elsif RUBY_ENGINE == "rbx" class TaskSet def initialize @tasks = Set.new end def <<(task) Rubinius.synchronize(self) { @tasks << task } end def delete(task) Rubinius.synchronize(self) { @tasks.delete task } end def first Rubinius.synchronize(self) { @tasks.first } end def empty? Rubinius.synchronize(self) { @tasks.empty? } end def to_a Rubinius.synchronize(self) { @tasks.to_a } end end else # Assume we're on MRI, where we have the GIL. But what about IronRuby? # Or MacRuby. Do people care? This will break Celluloid::Internals::StackDumps TaskSet = Set end end end celluloid-essentials-0.20.5/lib/celluloid/internals/registry.rb0000644000004100000410000000517312620347010024671 0ustar www-datawww-datarequire "thread" module Celluloid module Internals # The Registry allows us to refer to specific actors by human-meaningful names class Registry def initialize @root = nil # keep root out of the standard list of registered names @actors = {} # hash of name => actor @index = {} # hash of name => branch @branches = {} # hash of branch => [ actors ] @registry = Mutex.new end # Register an Actor def []=(name, actor) if name == :root @registry.synchronize do @root = actor end else actor_singleton = class << actor; self; end unless actor_singleton.ancestors.include? Proxy::Abstract fail TypeError, "not an actor" end # if actor.class.ancestors.include? Supervision::Container # puts "Supervisor: #{actor.links.inspect}" # end @registry.synchronize do @actors[name.to_sym] = actor end actor.mailbox << NamingRequest.new(name.to_sym) end end def add(name, actor, branch=:services) set(name, actor) @registry.synchronize do unless @branches.key? branch @branches[branch] = [] self.class.instance_eval do remove_method(branch) rescue nil define_method(branch) { @branches[branch] } end @branches[branch] << name end @index[name.to_sym] = branch end end # Retrieve an actor by name def [](name) return @root if name == :root @registry.synchronize do @actors[name.to_sym] end end def branch(name) @registry.synchronize do @index.select { |a, b| b == name } end end alias_method :get, :[] alias_method :set, :[]= def delete(name) @registry.synchronize do @index.delete name.to_sym @actors.delete name.to_sym end end def include?(name) names.include? name end # List all registered actors by name def names @registry.synchronize { @actors.keys } end def index @registry.synchronize { @index } end # removes and returns all registered actors as a hash of `name => actor` # can be used in testing to clear the registry def clear hash = nil @registry.synchronize do hash = @actors.dup @actors.clear @index.clear end hash end end end end celluloid-essentials-0.20.5/lib/celluloid/internals/method.rb0000644000004100000410000000135212620347010024274 0ustar www-datawww-datamodule Celluloid module Internals # Method handles that route through an actor proxy class Method def initialize(proxy, name) fail NoMethodError, "undefined method `#{name}'" unless proxy.respond_to? name @proxy, @name = proxy, name @klass = @proxy.class end def arity @proxy.method_missing(:method, @name).arity end def name @proxy.method_missing(:method, @name).name end def parameters @proxy.method_missing(:method, @name).parameters end def call(*args, &block) @proxy.__send__(@name, *args, &block) end def inspect "#" end end end end celluloid-essentials-0.20.5/lib/celluloid/internals/signals.rb0000644000004100000410000000121212620347010024447 0ustar www-datawww-datamodule Celluloid module Internals # Event signaling between methods of the same object class Signals def initialize @conditions = {} end # Wait for the given signal and return the associated value def wait(name) fail "cannot wait for signals while exclusive" if Celluloid.exclusive? @conditions[name] ||= Condition.new @conditions[name].wait end # Send a signal to all method calls waiting for the given name def broadcast(name, value = nil) condition = @conditions.delete(name) condition.broadcast(value) if condition end end end end celluloid-essentials-0.20.5/lib/celluloid/internals/receivers.rb0000644000004100000410000000267512620347010025014 0ustar www-datawww-datarequire "set" require "timers" module Celluloid module Internals # Allow methods to directly interact with the actor protocol class Receivers def initialize(timers) @receivers = Set.new @timers = timers end # Receive an asynchronous message def receive(timeout = nil, &block) if Celluloid.exclusive? Celluloid.mailbox.receive(timeout, &block) else receiver = Receiver.new block if timeout receiver.timer = @timers.after(timeout) do @receivers.delete receiver receiver.resume end end @receivers << receiver Task.suspend :receiving end end # Handle incoming messages def handle_message(message) receiver = @receivers.find { |r| r.match(message) } return unless receiver @receivers.delete receiver receiver.timer.cancel if receiver.timer receiver.resume message message end end # Methods blocking on a call to receive class Receiver attr_accessor :timer def initialize(block) @block = block @task = Task.current @timer = nil end # Match a message with this receiver's block def match(message) @block ? @block.call(message) : true end def resume(message = nil) @task.resume message end end end end celluloid-essentials-0.20.5/lib/celluloid/internals/cpu_counter.rb0000644000004100000410000000310512620347010025340 0ustar www-datawww-datamodule Celluloid module Internals module CPUCounter class << self def cores @cores ||= count_cores end private unless $CELLULOID_TEST def count_cores from_result(from_env || from_sysdev || from_java || from_proc || from_win32ole || from_sysctl) || 1 end def from_env result = ENV["NUMBER_OF_PROCESSORS"] result if result && !result.empty? rescue end def from_sysdev ::IO.read("/sys/devices/system/cpu/present").split("-").last.to_i + 1 rescue Errno::ENOENT begin result = Dir["/sys/devices/system/cpu/cpu*"].count { |n| n =~ /cpu\d+/ } result unless result.zero? rescue end rescue end def from_java Java::Java.lang.Runtime.getRuntime.availableProcessors if defined? Java::Java rescue end def from_proc File.read("/proc/cpuinfo").scan(/^processor\s*:/).size if File.exist?("/proc/cpuinfo") rescue end def from_win32ole require "win32ole" WIN32OLE.connect("winmgmts://").ExecQuery("select * from Win32_ComputerSystem").NumberOfProcessors rescue LoadError rescue end def from_sysctl Integer `sysctl -n hw.ncpu 2>/dev/null` rescue end def from_result(result) if result i = Integer(result.to_s[/\d+/], 10) return i if i > 0 end rescue end end end end end celluloid-essentials-0.20.5/lib/celluloid/internals/responses.rb0000644000004100000410000000161512620347010025037 0ustar www-datawww-datamodule Celluloid module Internals # Responses to calls class Response attr_reader :call, :value def initialize(call, value) @call, @value = call, value end def dispatch @call.task.resume self end # Call completed successfully class Success < Response; end # Call was aborted due to sender error class Error < Response def value ex = super ex = ex.cause if ex.is_a? Celluloid::AbortError if ex.backtrace ex.backtrace << "(celluloid):0:in `remote procedure call'" ex.backtrace.concat(caller) end fail ex end end class Block def initialize(call, result) @call = call @result = result end def dispatch @call.task.resume(@result) end end end end end celluloid-essentials-0.20.5/lib/celluloid/logging/0000755000004100000410000000000012620347010022115 5ustar www-datawww-datacelluloid-essentials-0.20.5/lib/celluloid/logging/ring_buffer.rb0000644000004100000410000000204612620347010024734 0ustar www-datawww-datamodule Celluloid class RingBuffer def initialize(size) @size = size @start = 0 @count = 0 @buffer = Array.new(size) @mutex = Mutex.new end def full? @count == @size end def empty? @count == 0 end def push(value) @mutex.synchronize do stop = (@start + @count) % @size @buffer[stop] = value if full? @start = (@start + 1) % @size else @count += 1 end value end end alias_method :<<, :push def shift @mutex.synchronize do remove_element end end def flush values = [] @mutex.synchronize do values << remove_element until empty? end values end def clear @buffer = Array.new(@size) @start = 0 @count = 0 end private def remove_element return nil if empty? value, @buffer[@start] = @buffer[@start], nil @start = (@start + 1) % @size @count -= 1 value end end end celluloid-essentials-0.20.5/lib/celluloid/logging/incident_reporter.rb0000644000004100000410000000214012620347010026156 0ustar www-datawww-datarequire "logger" module Celluloid # Subscribes to log incident topics to report on them. class IncidentReporter include Celluloid include Celluloid::Notifications # get the time from the event class Formatter < ::Logger::Formatter def call(severity, _time, progname, msg) super(severity, msg.time, progname, msg.message) end end def initialize(*args) subscribe(/log\.incident/, :report) @logger = ::Logger.new(*args) @logger.formatter = Formatter.new @silenced = false end def report(_topic, incident) return if @silenced header = "INCIDENT" header << " AT #{incident.triggering_event.time}" if incident.triggering_event @logger << header @logger << "\n" @logger << "====================\n" incident.events.each do |event| @logger.add(event.severity, event, event.progname) end @logger << "====================\n" end def silence @silenced = true end def unsilence @silenced = false end def silenced? @silenced end end end celluloid-essentials-0.20.5/lib/celluloid/logging/log_event.rb0000644000004100000410000000111512620347010024422 0ustar www-datawww-datamodule Celluloid # Wraps a single log event. class LogEvent attr_accessor :id, :severity, :message, :progname, :time def initialize(severity, message, progname, time=Time.now, &_block) # This id should be ordered. For now relies on Celluloid::UUID to be ordered. # May want to use a generation/counter strategy for independence of uuid. @id = Internals::UUID.generate @severity = severity @message = block_given? ? yield : message @progname = progname @time = time end def <=>(other) @id <=> other.id end end end celluloid-essentials-0.20.5/lib/celluloid/logging/incident_logger.rb0000644000004100000410000000731412620347010025603 0ustar www-datawww-datarequire "logger" module Celluloid # A logger that holds all messages in circular buffers, then flushes the buffers # when an event occurs at a configurable severity threshold. # # Unlike ruby's Logger, this class only supports a single progname. class IncidentLogger module Severity include ::Logger::Severity TRACE = -1 def severity_to_string(severity) case severity when TRACE then "TRACE" when DEBUG then "DEBUG" when INFO then "INFO" when WARN then "WARN" when ERROR then "ERROR" when FATAL then "FATAL" when UNKNOWN then "UNKNOWN" end end end include Severity # The progname (facility) for this instance. attr_accessor :progname # The logging level. Messages below this severity will not be logged at all. attr_accessor :level # The incident threshold. Messages at or above this severity will generate an # incident and be published to incident reporters. attr_accessor :threshold # The buffer size limit. Each log level will retain this number of messages # at maximum. attr_accessor :sizelimit attr_accessor :buffers # Create a new IncidentLogger. def initialize(progname=nil, options={}) @progname = progname || "default" @level = options[:level] || DEBUG @threshold = options[:threshold] || ERROR @sizelimit = options[:sizelimit] || 100 @buffer_mutex = Mutex.new @buffers = Hash.new do |progname_hash, _progname| @buffer_mutex.synchronize do progname_hash[_progname] = Hash.new do |severity_hash, severity| severity_hash[severity] = RingBuffer.new(@sizelimit) end end end # When the IncidentLogger itself encounters an error, it falls back to logging to stderr @fallback_logger = ::Logger.new(STDERR) @fallback_logger.progname = "FALLBACK" end # add an event. def add(severity, message=nil, progname=nil, &block) progname ||= @progname severity ||= UNKNOWN return event.id if severity < @level if message.nil? && !block_given? message = progname progname = @progname end event = LogEvent.new(severity, message, progname, &block) @buffers[progname][severity] << event if severity >= @threshold begin Celluloid::Notifications.notifier.async.publish(incident_topic, create_incident(event)) rescue => ex @fallback_logger.error(ex) end end event.id end alias_method :log, :add # See docs for Logger#info def trace(progname=nil, &block) add(TRACE, nil, progname, &block) end def debug(progname=nil, &block) add(DEBUG, nil, progname, &block) end def info(progname=nil, &block) add(INFO, nil, progname, &block) end def warn(progname=nil, &block) add(WARN, nil, progname, &block) end def error(progname=nil, &block) add(ERROR, nil, progname, &block) end def fatal(progname=nil, &block) add(FATAL, nil, progname, &block) end def unknown(progname=nil, &block) add(UNKNOWN, nil, progname, &block) end def flush messages = [] @buffer_mutex.synchronize do @buffers.each do |progname, severities| severities.each do |severity, buffer| messages += buffer.flush end end end messages.sort end def clear @buffer_mutex.synchronize do @buffers.each(&:clear) end end def create_incident(event=nil) Incident.new(flush, event) end def incident_topic "log.incident.#{@progname}" end end end celluloid-essentials-0.20.5/lib/celluloid/logging/incident.rb0000644000004100000410000000117612620347010024244 0ustar www-datawww-datamodule Celluloid # Wraps all events and context for a single incident. class Incident attr_accessor :pid attr_accessor :events, :triggering_event def initialize(events, triggering_event=nil) @events = events @triggering_event = triggering_event @pid = $PROCESS_ID end # Merge two incidents together. This may be useful if two incidents occur at the same time. def merge(*other_incidents) merged_events = other_incidents.flatten.inject(events) do |events, incident| events += incident.events end Incident.new(merged_events.sort, triggering_event) end end end celluloid-essentials-0.20.5/lib/celluloid/probe.rb0000644000004100000410000000311412620347010022122 0ustar www-datawww-datarequire "celluloid" $CELLULOID_MONITORING = true module Celluloid class Probe include Celluloid include Celluloid::Notifications NOTIFICATIONS_TOPIC_BASE = "celluloid.events.%s" EVENTS_BUFFER = Queue.new class << self def run # spawn the actor if not found supervise_as(:probe_actor) unless Actor[:probe_actor] && Actor[:probe_actor].alive? end def run_without_supervision Actor[:probe_actor] = Celluloid::Probe.new end def actor_created(actor) trigger_event(:actor_created, actor) end def actor_named(actor) trigger_event(:actor_named, actor) end def actor_died(actor) trigger_event(:actor_died, actor) end def actors_linked(a, b) a = find_actor(a) b = find_actor(b) trigger_event(:actors_linked, a, b) end private def trigger_event(name, *args) return unless $CELLULOID_MONITORING EVENTS_BUFFER << [name, args] probe_actor = Actor[:probe_actor] probe_actor.async.process_queue if probe_actor end def find_actor(obj) if obj.__send__(:class) == Actor obj elsif owner = obj.instance_variable_get(OWNER_IVAR) owner end end end def initialize async.process_queue end def process_queue until EVENTS_BUFFER.empty? event = EVENTS_BUFFER.pop dispatch_event(*event) end end def dispatch_event(cmd, args) publish(NOTIFICATIONS_TOPIC_BASE % cmd, args) end end end celluloid-essentials-0.20.5/.rubocop.yml0000644000004100000410000000005512620347010020217 0ustar www-datawww-datainherit_from: - culture/rubocop/rubocop.ymlcelluloid-essentials-0.20.5/metadata.yml0000644000004100000410000002125012620347010020250 0ustar www-datawww-data--- !ruby/object:Gem::Specification name: celluloid-essentials version: !ruby/object:Gem::Version version: 0.20.5 platform: ruby authors: - Tony Arcieri - Donovan Keme autorequire: bindir: bin cert_chain: [] date: 2015-09-30 00:00:00.000000000 Z dependencies: - !ruby/object:Gem::Dependency name: bundler version_requirements: !ruby/object:Gem::Requirement requirements: - - ">=" - !ruby/object:Gem::Version version: '0' type: :development prerelease: false requirement: !ruby/object:Gem::Requirement requirements: - - ">=" - !ruby/object:Gem::Version version: '0' - !ruby/object:Gem::Dependency name: nenv version_requirements: !ruby/object:Gem::Requirement requirements: - - ">=" - !ruby/object:Gem::Version version: '0' type: :development prerelease: false requirement: !ruby/object:Gem::Requirement requirements: - - ">=" - !ruby/object:Gem::Version version: '0' - !ruby/object:Gem::Dependency name: dotenv version_requirements: !ruby/object:Gem::Requirement requirements: - - ">=" - !ruby/object:Gem::Version version: '0' type: :development prerelease: false requirement: !ruby/object:Gem::Requirement requirements: - - ">=" - !ruby/object:Gem::Version version: '0' - !ruby/object:Gem::Dependency name: benchmark_suite version_requirements: !ruby/object:Gem::Requirement requirements: - - ">=" - !ruby/object:Gem::Version version: '0' type: :development prerelease: false requirement: !ruby/object:Gem::Requirement requirements: - - ">=" - !ruby/object:Gem::Version version: '0' - !ruby/object:Gem::Dependency name: rubocop version_requirements: !ruby/object:Gem::Requirement requirements: - - ">=" - !ruby/object:Gem::Version version: '0' type: :development prerelease: false requirement: !ruby/object:Gem::Requirement requirements: - - ">=" - !ruby/object:Gem::Version version: '0' - !ruby/object:Gem::Dependency name: transpec version_requirements: !ruby/object:Gem::Requirement requirements: - - ">=" - !ruby/object:Gem::Version version: '0' type: :development prerelease: false requirement: !ruby/object:Gem::Requirement requirements: - - ">=" - !ruby/object:Gem::Version version: '0' - !ruby/object:Gem::Dependency name: pry version_requirements: !ruby/object:Gem::Requirement requirements: - - ">=" - !ruby/object:Gem::Version version: '0' type: :development prerelease: false requirement: !ruby/object:Gem::Requirement requirements: - - ">=" - !ruby/object:Gem::Version version: '0' - !ruby/object:Gem::Dependency name: rake version_requirements: !ruby/object:Gem::Requirement requirements: - - ">=" - !ruby/object:Gem::Version version: '0' type: :development prerelease: false requirement: !ruby/object:Gem::Requirement requirements: - - ">=" - !ruby/object:Gem::Version version: '0' - !ruby/object:Gem::Dependency name: rspec version_requirements: !ruby/object:Gem::Requirement requirements: - - ">=" - !ruby/object:Gem::Version version: '0' type: :development prerelease: false requirement: !ruby/object:Gem::Requirement requirements: - - ">=" - !ruby/object:Gem::Version version: '0' - !ruby/object:Gem::Dependency name: guard-rspec version_requirements: !ruby/object:Gem::Requirement requirements: - - ">=" - !ruby/object:Gem::Version version: '0' type: :development prerelease: false requirement: !ruby/object:Gem::Requirement requirements: - - ">=" - !ruby/object:Gem::Version version: '0' - !ruby/object:Gem::Dependency name: rspec-retry version_requirements: !ruby/object:Gem::Requirement requirements: - - ">=" - !ruby/object:Gem::Version version: '0' type: :development prerelease: false requirement: !ruby/object:Gem::Requirement requirements: - - ">=" - !ruby/object:Gem::Version version: '0' - !ruby/object:Gem::Dependency name: coveralls version_requirements: !ruby/object:Gem::Requirement requirements: - - ">=" - !ruby/object:Gem::Version version: '0' type: :development prerelease: false requirement: !ruby/object:Gem::Requirement requirements: - - ">=" - !ruby/object:Gem::Version version: '0' - !ruby/object:Gem::Dependency name: celluloid version_requirements: !ruby/object:Gem::Requirement requirements: - - ">=" - !ruby/object:Gem::Version version: 0.17.2 type: :development prerelease: false requirement: !ruby/object:Gem::Requirement requirements: - - ">=" - !ruby/object:Gem::Version version: 0.17.2 - !ruby/object:Gem::Dependency name: celluloid-supervision version_requirements: !ruby/object:Gem::Requirement requirements: - - ">=" - !ruby/object:Gem::Version version: '0' type: :development prerelease: false requirement: !ruby/object:Gem::Requirement requirements: - - ">=" - !ruby/object:Gem::Version version: '0' - !ruby/object:Gem::Dependency name: celluloid-pool version_requirements: !ruby/object:Gem::Requirement requirements: - - ">=" - !ruby/object:Gem::Version version: '0' type: :development prerelease: false requirement: !ruby/object:Gem::Requirement requirements: - - ">=" - !ruby/object:Gem::Version version: '0' - !ruby/object:Gem::Dependency name: celluloid-fsm version_requirements: !ruby/object:Gem::Requirement requirements: - - ">=" - !ruby/object:Gem::Version version: '0' type: :development prerelease: false requirement: !ruby/object:Gem::Requirement requirements: - - ">=" - !ruby/object:Gem::Version version: '0' - !ruby/object:Gem::Dependency name: celluloid-extras version_requirements: !ruby/object:Gem::Requirement requirements: - - ">=" - !ruby/object:Gem::Version version: '0' type: :development prerelease: false requirement: !ruby/object:Gem::Requirement requirements: - - ">=" - !ruby/object:Gem::Version version: '0' - !ruby/object:Gem::Dependency name: timers version_requirements: !ruby/object:Gem::Requirement requirements: - - ">=" - !ruby/object:Gem::Version version: 4.1.1 type: :runtime prerelease: false requirement: !ruby/object:Gem::Requirement requirements: - - ">=" - !ruby/object:Gem::Version version: 4.1.1 description: Notifications, Internals, Logging, Probe, and essential Celluloid pieces demanding Supervision email: - tony.arcieri@gmail.com - code@extremist.digital executables: [] extensions: [] extra_rdoc_files: [] files: - ".env-ci" - ".env-dev" - ".gitignore" - ".gitmodules" - ".rspec" - ".rubocop.yml" - ".travis.yml" - CHANGES.md - Gemfile - LICENSE.txt - README.md - Rakefile - celluloid-essentials.gemspec - lib/celluloid/essentials.rb - lib/celluloid/internals/call_chain.rb - lib/celluloid/internals/cpu_counter.rb - lib/celluloid/internals/handlers.rb - lib/celluloid/internals/links.rb - lib/celluloid/internals/logger.rb - lib/celluloid/internals/method.rb - lib/celluloid/internals/properties.rb - lib/celluloid/internals/receivers.rb - lib/celluloid/internals/registry.rb - lib/celluloid/internals/responses.rb - lib/celluloid/internals/signals.rb - lib/celluloid/internals/stack.rb - lib/celluloid/internals/stack/dump.rb - lib/celluloid/internals/stack/states.rb - lib/celluloid/internals/stack/summary.rb - lib/celluloid/internals/task_set.rb - lib/celluloid/internals/thread_handle.rb - lib/celluloid/internals/uuid.rb - lib/celluloid/logger.rb - lib/celluloid/logging/incident.rb - lib/celluloid/logging/incident_logger.rb - lib/celluloid/logging/incident_reporter.rb - lib/celluloid/logging/log_event.rb - lib/celluloid/logging/ring_buffer.rb - lib/celluloid/notifications.rb - lib/celluloid/probe.rb - tasks/benchmarks.rake - tasks/rspec.rake - tasks/rubocop.rake homepage: https://github.com/celluloid/celluloid-essentials licenses: - MIT metadata: {} post_install_message: rdoc_options: [] require_paths: - lib required_ruby_version: !ruby/object:Gem::Requirement requirements: - - ">=" - !ruby/object:Gem::Version version: '0' required_rubygems_version: !ruby/object:Gem::Requirement requirements: - - ">=" - !ruby/object:Gem::Version version: '0' requirements: [] rubyforge_project: rubygems_version: 2.4.8 signing_key: specification_version: 4 summary: Internally used tools, and superstructural dependencies of Celluloid test_files: [] celluloid-essentials-0.20.5/.gitignore0000644000004100000410000000011112620347010017726 0ustar www-datawww-datacoverage/ rdoc/ doc/ pkg/ tmp/ .yardoc .bundle Gemfile.lock log .DS_Storecelluloid-essentials-0.20.5/tasks/0000755000004100000410000000000012620347010017072 5ustar www-datawww-datacelluloid-essentials-0.20.5/tasks/rubocop.rake0000644000004100000410000000011312620347010021402 0ustar www-datawww-dataunless ENV["CI"] require "rubocop/rake_task" RuboCop::RakeTask.new end celluloid-essentials-0.20.5/tasks/benchmarks.rake0000644000004100000410000000071212620347010022053 0ustar www-datawww-datarequire "timeout" desc "Run Celluloid benchmarks" task :benchmark do begin Timeout.timeout(120) do glob = File.expand_path("../../benchmarks/*.rb", __FILE__) Dir[glob].each { |benchmark| load benchmark } end rescue Exception, Timeout::Error => ex puts "ERROR: Couldn't complete benchmark: #{ex.class}: #{ex}" puts " #{ex.backtrace.join("\n ")}" exit 1 unless ENV["CI"] # Hax for running benchmarks on Travis end end celluloid-essentials-0.20.5/tasks/rspec.rake0000644000004100000410000000017512620347010021055 0ustar www-datawww-datarequire "rspec/core/rake_task" RSpec::Core::RakeTask.new RSpec::Core::RakeTask.new(:rcov) do |task| task.rcov = true end celluloid-essentials-0.20.5/CHANGES.md0000644000004100000410000000107012620347010017335 0ustar www-datawww-data0.20.5 (2015-09-30) ----- * Revamped test suite, using shared RSpec configuration layer provided by Celluloid itself. * Updated gem dependencies provided by Celluloid::Sync... extraneous gems removed, or marked as development dependencies. 0.20.2 (2015-08-07) ----- * `ActorSystem` moved to `Actor::System` in Celluloid; that is reflected here. * Only show `:debug` level of output if `$CEULLULOID_DEBUG` set to `true`. 0.20.1 (2015-07-15) ----- * Refactored `Celluloid::Internals::CPUCounter` 0.20.0 ----- * Original release of new gem, extracted from `Celluloid` celluloid-essentials-0.20.5/.env-dev0000644000004100000410000000020412620347010017306 0ustar www-datawww-dataCELLULOID_SPECS_LOG_STRATEGY=single CELLULOID_SPECS_LOG_FILE=log/test.log CELLULOID_SPECS_LOG_LEVEL=0 CELLULOID_SPECS_LOG_SYNC=true celluloid-essentials-0.20.5/README.md0000644000004100000410000000261512620347010017230 0ustar www-datawww-data# Celluloid Essentials [![Gem Version](https://badge.fury.io/rb/celluloid-essentials.svg)](http://rubygems.org/gems/celluloid-essentials) [![Build Status](https://secure.travis-ci.org/celluloid/celluloid-essentials.svg?branch=master)](http://travis-ci.org/celluloid/celluloid-essentials) [![Code Climate](https://codeclimate.com/github/celluloid/celluloid-essentials.svg)](https://codeclimate.com/github/celluloid/celluloid-essentials) [![Coverage Status](https://coveralls.io/repos/celluloid/celluloid-essentials/badge.svg?branch=master)](https://coveralls.io/r/celluloid/celluloid-essentials) This gem houses fundamental supporting pieces of `Celluloid` which are not *quite* `Celluloid` itself. ## Classes: * `Celluloid::Probe` * `Celluloid::Notifications` * `Celluloid::Internals` * `CallChain` * `CPUCounter` * `Handlers` * `Links` * `Logger` * `Method` * `Properties` * `Receivers` * `Registry` * `Responses` * `Signals` * `Stack` * `TaskSet` * `ThreadHandle` * `UUID` ## Contributing * Fork this repository on github * Make your changes and send us a pull request * If we like them we'll merge them * If we've accepted a patch, feel free to ask for commit access ## License Copyright (c) 2011-2015 Tony Arcieri, Donovan Keme. Distributed under the MIT License. See [LICENSE.txt](https://github.com/celluloid/celluloid-essentials/blob/master/LICENSE.txt) for further details. celluloid-essentials-0.20.5/.gitmodules0000644000004100000410000000012512620347010020120 0ustar www-datawww-data[submodule "culture"] path = culture url = http://github.com/celluloid/culture.git