forked from MagLev/webtools
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Monty Williams
committed
Apr 7, 2011
0 parents
commit bb4a5a2
Showing
70 changed files
with
6,205 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
## MAC OS | ||
.DS_Store | ||
|
||
## TEXTMATE | ||
*.tmproj | ||
tmtags | ||
|
||
## EMACS | ||
*~ | ||
\#* | ||
.\#* | ||
|
||
## VIM | ||
*.swp | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
# This Gemfile manages gems for the Sinatra examples in this directory. It | ||
# does not manage gems for Sinatra applications in subdirectories. | ||
|
||
source "http://rubygems.org" | ||
|
||
gem 'activemodel', '~> 3.0' | ||
gem 'sinatra', '~> 1.1' | ||
gem 'json_pure', '1.5.1', :require => 'json' |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
GEM | ||
remote: http://rubygems.org/ | ||
specs: | ||
activemodel (3.0.5) | ||
activesupport (= 3.0.5) | ||
builder (~> 2.1.2) | ||
i18n (~> 0.4) | ||
activesupport (3.0.5) | ||
builder (2.1.2) | ||
i18n (0.5.0) | ||
json_pure (1.5.1) | ||
rack (1.2.2) | ||
sinatra (1.2.1) | ||
rack (~> 1.1) | ||
tilt (< 2.0, >= 1.2.2) | ||
tilt (1.2.2) | ||
|
||
PLATFORMS | ||
ruby | ||
|
||
DEPENDENCIES | ||
activemodel (~> 3.0) | ||
json_pure (= 1.5.1) | ||
sinatra (~> 1.1) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
== LICENSE: | ||
|
||
(The MIT License) | ||
|
||
Copyright (c) 2011 VMware, Inc | ||
|
||
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. | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,104 @@ | ||
= WebTools Example | ||
|
||
The WebTools Sinatra application running in MagLev allows you to explore a | ||
MagLev Ruby application's Classes, Modules, Methods, Constants, and Ancestors | ||
in a web browser. | ||
|
||
It will also allow you to explore GemStone/S Smalltalk code, and to examine | ||
detailed statistics about all processes connected to GemStone/S. | ||
|
||
=== Setup | ||
|
||
1. Download and install MagLev using instructions at https://github.com/MagLev/maglev/blob/master/README.rdoc | ||
2. Start the MagLev server | ||
$ maglev start | ||
3. Install necessary gems: | ||
$ bundle install | ||
### Temporary workaround for https://magtrac.gemstone.com/ticket/879 ### | ||
$ maglev-gem pristine rack | ||
|
||
== Viewing Ruby code | ||
|
||
Run the WebTools Sinatra application | ||
|
||
$ rake | ||
|
||
This will start WEBrick in your current window. Hit Ctl-C to stop. | ||
|
||
Browse to http://localhost:9292/, click on a class or module, then | ||
click on a constant or method. Results appear in the bottom pane. | ||
File locations with line numbers appear at the bottom. Time spent on | ||
the server/network/client appear at the top, | ||
|
||
=== Add classes and modules from ActiveModel | ||
|
||
$ rake meta | ||
|
||
Click on "Refresh View" in WebTools. Note that AValidPerson now appears in the | ||
class list, as do a number of classes/modules from ActiveModel and ActiveSupport. | ||
|
||
Click on the class AValidPerson and compare it with the source | ||
(meta_demo.rb). Some things to note: | ||
|
||
1. You get to see all of the methods written by metaprogramming. | ||
2. You can see the file and line number of the code that generated each | ||
method. This makes it simpler to track down which part of ActiveWhatever | ||
is messing with your code. | ||
|
||
=== Modify meta_demo.rb and view updates | ||
|
||
Edit the file meta_demo.rb. Add :age to both validates_presence_of and attr_accessor. | ||
The changed lines should look like | ||
|
||
validates_presence_of :first_name, :last_name, :age | ||
attr_accessor :first_name, :last_name, :age | ||
|
||
Then | ||
|
||
$ rake meta | ||
|
||
Click on "Refresh View" in WebTools. AValidPerson will now include the | ||
new instance methods age and age=. | ||
|
||
=== Add some data | ||
|
||
$ rake demodata | ||
|
||
Click on "Refresh View" in WebTools. Note that AAADemo now appears in the | ||
class list. Click on the class AAADemo and compare it with the source | ||
(demo_data.rb). | ||
|
||
== Viewing GemStone/S code, processes and statistics | ||
|
||
The code for this example was inspired by the Smalltalk example found in | ||
$MAGLEV_HOME/gemstone/examples/www. The smalltalk example code can be | ||
invoked from ruby (a demonstration of how to invoke Smalltalk from Ruby), | ||
via: | ||
|
||
$ rake smalltalk:run | ||
|
||
Then browse to http://localhost:8080/ and explore | ||
|
||
Hit Ctl-C in the terminal window to stop. | ||
|
||
== Known problems | ||
|
||
Network timeouts are not caught. EAGAIN is not handled. If you're running WebTools on | ||
a slow network, this may cause data to not appear in the bottom pane. | ||
|
||
The line number displayed for evals is always 2. This will be fixed at a later date. | ||
|
||
== Contributing | ||
|
||
* Fork the project from https://github.com/MagLev/webtools | ||
* Start a feature or topic branch | ||
* Commit and push until you are happy with your contribution | ||
* Add some tests to ensure we don't break things in a future release | ||
* Make sure to test with the latest MagLev | ||
* Send a pull request | ||
|
||
MagLev Ruby code in this project is MIT licensed. See LICENSE.txt in this directory. | ||
<b>By sending a pull request, you agree your contributed code is also MIT licensed.</b> | ||
|
||
This project includes a copy of CodeMirror, copyrighted by Marijn Haverbeke. | ||
See public/CodeMirror/LICENSE. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
task :default => :run | ||
|
||
MH = ENV['MAGLEV_HOME'] | ||
|
||
desc "Run the WebTools Sinatra App" | ||
task :run do | ||
sh "#{MH}/bin/rackup -Ilib config.ru" | ||
end | ||
|
||
desc "Commit an interesting example class, AValidPerson, to the repository" | ||
task :meta do | ||
sh "maglev-ruby -Mcommit meta_demo.rb" | ||
end | ||
|
||
desc "Run the Smalltalk WebTools code from ruby." | ||
task :smalltalk do | ||
file = "#{MH}/gemstone/examples/www/install.tpz" | ||
raise "Can't find #{file}" unless File.exists? file | ||
cd(MH) { sh "rake maglev:input_file[#{file}]" } | ||
|
||
sh "maglev-ruby -d lib/webtools/smalltalk_tools.rb" | ||
end | ||
|
||
task :test do | ||
FileList['tests/test_*'].each do |file| | ||
sh "maglev-ruby -rubygems -Ilib #{file}" | ||
end | ||
end | ||
|
||
desc "Add some objects to Maglev::PERSISTENT_ROOT" | ||
task :demodata do | ||
sh "maglev-ruby -Mcommit demo_data.rb" | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
require 'webtools_app' | ||
|
||
WebToolsApp.set :root, File.dirname(__FILE__) | ||
|
||
run WebToolsApp |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
#========================================================================= | ||
# | ||
# Name: demo_data.rb | ||
# | ||
# Purpose: Define a persistent class with public, private and protected | ||
# instance methods, a class method, and some data we can explore | ||
# using WebTools. Name it AAADemo so it will appear at the top | ||
# of the Class list. | ||
# | ||
#========================================================================= | ||
|
||
Maglev.persistent do | ||
class AAADemo | ||
# Provide easy access to PERSISTENT_ROOT | ||
PROOT = Maglev::PERSISTENT_ROOT | ||
|
||
def self.foo | ||
"This is a class method" | ||
end | ||
|
||
def initialize | ||
@foo = "foo" | ||
@bar = "bar" | ||
@rand = rand(100) | ||
@a_hash = { :a => rand(51), :b => rand(72) } | ||
end | ||
|
||
protected | ||
def protected_method | ||
"This is a protected method" | ||
end | ||
|
||
private | ||
def private_method | ||
"This is a private method" | ||
end | ||
|
||
# Add a few constants | ||
AN_INSTANCE = AAADemo.new | ||
AN_ARRAY = [] | ||
30.times { |i| AN_ARRAY << i } | ||
end | ||
|
||
# Define a method programmatically | ||
AAADemo.define_method(:metaprogrammed) do | ||
x = :foo | ||
"This method metaprogrammed to return #{x}" | ||
end | ||
|
||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
# Support to emulate the Smalltalk code in $MAGLEV_HOME/gemstone/examples/www | ||
require 'webtools/smalltalk_extensions' | ||
require 'webtools/appmodel' | ||
require 'webtools/code_browser' |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,116 @@ | ||
|
||
require 'webtools/code_browser' | ||
|
||
# This module emulates all of the API from the Smalltalk side of things | ||
module WebTools | ||
|
||
# This is a ViewModel for the WebTools Application. | ||
# | ||
# All of the methods that return "Objects" should return a Hash. Keys | ||
# beginning with '_' are reserved for metadata applied by the GUI. | ||
class AppModel | ||
def initialize | ||
end | ||
|
||
VERSION_HEADERS = [['Attribute', 'The attribute.'], | ||
['Stone', 'The value for the stone process.'], | ||
['WebTools', 'The value for the WebTools vm process (if different than the Stone''s value)']] | ||
|
||
|
||
# Returns a hash of configuration parameters for the stone and the gem. | ||
# The has has three keys: | ||
# + :timestamp => when the report was generated | ||
# + :headers => array of [name, description] pairs for the fields | ||
# + :report => An array of data. Each entry is an array of the field data. | ||
# | ||
def version_report | ||
stone_rpt = stone_version_report | ||
gem_rpt = gem_version_report | ||
data = { } | ||
(stone_rpt.keys + gem_rpt.keys).each do |k| | ||
g = stone_rpt[k] == gem_rpt[k] ? '' : gem_rpt[k] | ||
data[k] = [stone_rpt[k], g] | ||
end | ||
{ :timestamp => Time.now.asctime, | ||
:headers => VERSION_HEADERS, | ||
:report => data } | ||
end | ||
|
||
# An array of [name, description] entries for the fields in the session report. | ||
SESSION_FIELDS = | ||
[['User', 'The UserProfile of the session, or nil if the UserProfile is recently created and not visible from this session''s transactional view, or the session is no longer active.'], | ||
['PID', 'The process ID of the Gem process of the session.'], | ||
['Host', 'The hostname of the machine running the Gem process (a String, limited to 127 bytes).'], | ||
['Prim #', 'Primitive number in which the Gem is executing (if it is executing in a long primitive such as MFC).'], | ||
['View Age', 'Time since the session''s most recent beginTransaction, commitTransaction, or abortTransaction.'], | ||
['State', 'The session state (an enum from SesTaskStatusEType in session.ht).'], | ||
['Trans', 'One of the following: ''none'' if the session is in transactionless mode, ''out'' if it is not in a transaction, and ''in'' if it is in a transaction.'], | ||
['Oldest CR?', 'A Boolean whose value is true if the session is currently referencing the oldest commit record, and false if it is not.'], | ||
['Serial', 'The session''s serial number. A serial number will not be reused until the stone is restarted.'], | ||
['Session', "The session's sessionId."], | ||
['GCI IP', 'A String containing the ip address of host running the GCI process. If the GCI application is linked (using libgcilnk*.so or gcilnk*.dll) this ip address is the address of the machine running the gem process.'], | ||
['Priority', 'The priority of the session where 0 is lowest, 2 is normal, and 4 is highest. Session priority is used by the stone to order requests for service by sessions.'], | ||
['Host ID', 'Unique host ID of the host where the session is running.'], | ||
['Quiet', 'Time since the session''s most recent request to stone.'], | ||
['Age', 'Time since the session logged in.'], | ||
['CRB', 'Commit Record Backlog: number of commits which have occurred since the session obtained its view.']] | ||
|
||
# Returns a hash of configuration parameters for the stone and the gem. | ||
# The has has three keys: | ||
# + :timestamp => when the report was generated | ||
# + :headers => array of [name, description] pairs for the fields | ||
# + :report => An array of data. Each entry is an array of the field data. | ||
# | ||
def session_report | ||
ts = Time.now | ||
now = ts.to_i | ||
session_info = Maglev::System.current_session_ids.map do |id| | ||
sess_desc = Maglev::System.description_of_session id | ||
sess_desc[0] = sess_desc[0].instance_variable_get(:@_st_userId) # UserProfile | ||
sess_desc[3] = '' if sess_desc[3] == 0 # Primitive? | ||
sess_desc[4] = format_secs(now - sess_desc[4]) # View Age | ||
sess_desc[6] = ['none', 'out', 'in'][sess_desc[6] + 1] # Transaction | ||
sess_desc[13] = format_secs(now - sess_desc[13]) # Quiet | ||
sess_desc[14] = format_secs(now - sess_desc[14]) # Age | ||
sess_desc | ||
# sess_cache_slot = Maglev::System.cache_slot_for_sessionid id | ||
end | ||
{ :timestamp => ts.asctime, | ||
:headers => SESSION_FIELDS, | ||
:report => session_info } | ||
end | ||
|
||
|
||
SECS_PER_DAY = 86400 | ||
SECS_PER_HOUR = 3600 | ||
SECS_PER_MIN = 60 | ||
SECS_PER_SEC = 1 | ||
|
||
# Format number of seconds like "3 days 12:07:58" | ||
def format_secs(seconds) | ||
splits = [] | ||
[SECS_PER_DAY, SECS_PER_HOUR, SECS_PER_MIN, SECS_PER_SEC].each do |x| | ||
splits << seconds / x | ||
seconds = seconds % x | ||
end | ||
days = splits.shift | ||
|
||
ts = "%02d:%02d:%02d" % splits | ||
days > 0 ? "#{days} #{days == 1 ? 'day' : 'days'} #{ts}" : ts | ||
end | ||
|
||
def stone_version_report | ||
results = { } | ||
rpt = Maglev::System.stone_version_report | ||
rpt.keys.each { |k| results[k] = rpt.at(k) } | ||
results | ||
end | ||
|
||
def gem_version_report | ||
results = { } | ||
rpt = Maglev::System.gem_version_report | ||
rpt.keys.each { |k| results[k] = rpt.at(k) } | ||
results | ||
end | ||
end | ||
end |
Oops, something went wrong.