arrow 1.0.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (198) hide show
  1. data/ChangeLog +1590 -0
  2. data/LICENSE +28 -0
  3. data/README +75 -0
  4. data/Rakefile +366 -0
  5. data/Rakefile.local +63 -0
  6. data/data/arrow/applets/TEMPLATE.rb.tpl +53 -0
  7. data/data/arrow/applets/args.rb +50 -0
  8. data/data/arrow/applets/config.rb +55 -0
  9. data/data/arrow/applets/error.rb +63 -0
  10. data/data/arrow/applets/files.rb +46 -0
  11. data/data/arrow/applets/inspect.rb +46 -0
  12. data/data/arrow/applets/nosuchapplet.rb +31 -0
  13. data/data/arrow/applets/status.rb +92 -0
  14. data/data/arrow/applets/test.rb +133 -0
  15. data/data/arrow/applets/tutorial/counter.rb +96 -0
  16. data/data/arrow/applets/tutorial/dingus.rb +67 -0
  17. data/data/arrow/applets/tutorial/hello.rb +34 -0
  18. data/data/arrow/applets/tutorial/hello2.rb +73 -0
  19. data/data/arrow/applets/tutorial/imgtext.rb +90 -0
  20. data/data/arrow/applets/tutorial/imgtext2.rb +286 -0
  21. data/data/arrow/applets/tutorial/index.rb +36 -0
  22. data/data/arrow/applets/tutorial/logo.rb +98 -0
  23. data/data/arrow/applets/tutorial/memcache.rb +61 -0
  24. data/data/arrow/applets/tutorial/missing.rb +37 -0
  25. data/data/arrow/applets/tutorial/protected.rb +100 -0
  26. data/data/arrow/applets/tutorial/redirector.rb +52 -0
  27. data/data/arrow/applets/tutorial/rndimages.rb +159 -0
  28. data/data/arrow/applets/tutorial/sharenotes.rb +83 -0
  29. data/data/arrow/applets/tutorial/subclassed-hello.rb +32 -0
  30. data/data/arrow/applets/tutorial/superhello.rb +72 -0
  31. data/data/arrow/applets/tutorial/timeclock.rb +78 -0
  32. data/data/arrow/applets/view-applet.rb +123 -0
  33. data/data/arrow/applets/view-template.rb +85 -0
  34. data/data/arrow/applets/wiki.rb +274 -0
  35. data/data/arrow/templates/TEMPLATE.tmpl.tpl +36 -0
  36. data/data/arrow/templates/applet-status.tmpl +153 -0
  37. data/data/arrow/templates/args-display.tmpl +120 -0
  38. data/data/arrow/templates/config/display-table.tmpl +36 -0
  39. data/data/arrow/templates/config/display.tmpl +36 -0
  40. data/data/arrow/templates/counter-deleted.tmpl +33 -0
  41. data/data/arrow/templates/counter.tmpl +59 -0
  42. data/data/arrow/templates/dingus.tmpl +55 -0
  43. data/data/arrow/templates/enumtable.tmpl +8 -0
  44. data/data/arrow/templates/error-display.tmpl +92 -0
  45. data/data/arrow/templates/filemap.tmpl +89 -0
  46. data/data/arrow/templates/hello-world-src.tmpl +34 -0
  47. data/data/arrow/templates/hello-world.tmpl +60 -0
  48. data/data/arrow/templates/imgtext/fontlist.tmpl +46 -0
  49. data/data/arrow/templates/imgtext/form.tmpl +70 -0
  50. data/data/arrow/templates/imgtext/reload-error.tmpl +40 -0
  51. data/data/arrow/templates/imgtext/reload.tmpl +55 -0
  52. data/data/arrow/templates/inspect/display.tmpl +80 -0
  53. data/data/arrow/templates/loginform.tmpl +64 -0
  54. data/data/arrow/templates/logout.tmpl +32 -0
  55. data/data/arrow/templates/memcache/display.tmpl +41 -0
  56. data/data/arrow/templates/navbar.incl +27 -0
  57. data/data/arrow/templates/nosuchapplet.tmpl +32 -0
  58. data/data/arrow/templates/printsource.tmpl +35 -0
  59. data/data/arrow/templates/protected.tmpl +36 -0
  60. data/data/arrow/templates/rndimages.tmpl +38 -0
  61. data/data/arrow/templates/service-response.tmpl +13 -0
  62. data/data/arrow/templates/sharenotes/display.tmpl +38 -0
  63. data/data/arrow/templates/status.tmpl +120 -0
  64. data/data/arrow/templates/templateviewer.tmpl +43 -0
  65. data/data/arrow/templates/test/harness.tmpl +57 -0
  66. data/data/arrow/templates/test/list.tmpl +48 -0
  67. data/data/arrow/templates/test/problem.tmpl +42 -0
  68. data/data/arrow/templates/tutorial/index.tmpl +37 -0
  69. data/data/arrow/templates/tutorial/missingapplet.tmpl +29 -0
  70. data/data/arrow/templates/view-applet-nosuch.tmpl +32 -0
  71. data/data/arrow/templates/view-applet.tmpl +40 -0
  72. data/data/arrow/templates/view-template.tmpl +83 -0
  73. data/data/arrow/templates/wiki/formerror.tmpl +47 -0
  74. data/data/arrow/templates/wiki/markup_help.incl +6 -0
  75. data/data/arrow/templates/wiki/new.tmpl +56 -0
  76. data/data/arrow/templates/wiki/new_system.tmpl +122 -0
  77. data/data/arrow/templates/wiki/sectionlist.tmpl +43 -0
  78. data/data/arrow/templates/wiki/show.tmpl +34 -0
  79. data/docs/manual/layouts/default.page +43 -0
  80. data/docs/manual/lib/api-filter.rb +81 -0
  81. data/docs/manual/lib/editorial-filter.rb +64 -0
  82. data/docs/manual/lib/examples-filter.rb +244 -0
  83. data/docs/manual/lib/links-filter.rb +117 -0
  84. data/lib/apache/fakerequest.rb +448 -0
  85. data/lib/apache/logger.rb +33 -0
  86. data/lib/arrow.rb +51 -0
  87. data/lib/arrow/acceptparam.rb +207 -0
  88. data/lib/arrow/applet.rb +725 -0
  89. data/lib/arrow/appletmixins.rb +218 -0
  90. data/lib/arrow/appletregistry.rb +590 -0
  91. data/lib/arrow/applettestcase.rb +503 -0
  92. data/lib/arrow/broker.rb +255 -0
  93. data/lib/arrow/cache.rb +176 -0
  94. data/lib/arrow/config-loaders/yaml.rb +75 -0
  95. data/lib/arrow/config.rb +615 -0
  96. data/lib/arrow/constants.rb +24 -0
  97. data/lib/arrow/cookie.rb +359 -0
  98. data/lib/arrow/cookieset.rb +108 -0
  99. data/lib/arrow/dispatcher.rb +368 -0
  100. data/lib/arrow/dispatcherloader.rb +50 -0
  101. data/lib/arrow/exceptions.rb +61 -0
  102. data/lib/arrow/fallbackhandler.rb +48 -0
  103. data/lib/arrow/formvalidator.rb +631 -0
  104. data/lib/arrow/htmltokenizer.rb +343 -0
  105. data/lib/arrow/logger.rb +488 -0
  106. data/lib/arrow/logger/apacheoutputter.rb +69 -0
  107. data/lib/arrow/logger/arrayoutputter.rb +63 -0
  108. data/lib/arrow/logger/coloroutputter.rb +111 -0
  109. data/lib/arrow/logger/fileoutputter.rb +96 -0
  110. data/lib/arrow/logger/htmloutputter.rb +54 -0
  111. data/lib/arrow/logger/outputter.rb +123 -0
  112. data/lib/arrow/mixins.rb +425 -0
  113. data/lib/arrow/monkeypatches.rb +94 -0
  114. data/lib/arrow/object.rb +117 -0
  115. data/lib/arrow/path.rb +196 -0
  116. data/lib/arrow/service.rb +447 -0
  117. data/lib/arrow/session.rb +289 -0
  118. data/lib/arrow/session/dbstore.rb +100 -0
  119. data/lib/arrow/session/filelock.rb +160 -0
  120. data/lib/arrow/session/filestore.rb +132 -0
  121. data/lib/arrow/session/id.rb +98 -0
  122. data/lib/arrow/session/lock.rb +253 -0
  123. data/lib/arrow/session/md5id.rb +42 -0
  124. data/lib/arrow/session/nulllock.rb +42 -0
  125. data/lib/arrow/session/posixlock.rb +166 -0
  126. data/lib/arrow/session/sha1id.rb +54 -0
  127. data/lib/arrow/session/store.rb +366 -0
  128. data/lib/arrow/session/usertrackid.rb +52 -0
  129. data/lib/arrow/spechelpers.rb +73 -0
  130. data/lib/arrow/template.rb +713 -0
  131. data/lib/arrow/template/attr.rb +31 -0
  132. data/lib/arrow/template/call.rb +31 -0
  133. data/lib/arrow/template/comment.rb +33 -0
  134. data/lib/arrow/template/container.rb +118 -0
  135. data/lib/arrow/template/else.rb +41 -0
  136. data/lib/arrow/template/elsif.rb +44 -0
  137. data/lib/arrow/template/escape.rb +53 -0
  138. data/lib/arrow/template/export.rb +87 -0
  139. data/lib/arrow/template/for.rb +145 -0
  140. data/lib/arrow/template/if.rb +78 -0
  141. data/lib/arrow/template/import.rb +119 -0
  142. data/lib/arrow/template/include.rb +206 -0
  143. data/lib/arrow/template/iterator.rb +208 -0
  144. data/lib/arrow/template/nodes.rb +734 -0
  145. data/lib/arrow/template/parser.rb +571 -0
  146. data/lib/arrow/template/prettyprint.rb +53 -0
  147. data/lib/arrow/template/render.rb +191 -0
  148. data/lib/arrow/template/selectlist.rb +94 -0
  149. data/lib/arrow/template/set.rb +87 -0
  150. data/lib/arrow/template/timedelta.rb +81 -0
  151. data/lib/arrow/template/unless.rb +78 -0
  152. data/lib/arrow/template/urlencode.rb +51 -0
  153. data/lib/arrow/template/yield.rb +139 -0
  154. data/lib/arrow/templatefactory.rb +125 -0
  155. data/lib/arrow/testcase.rb +567 -0
  156. data/lib/arrow/transaction.rb +608 -0
  157. data/rake/191_compat.rb +26 -0
  158. data/rake/dependencies.rb +76 -0
  159. data/rake/documentation.rb +114 -0
  160. data/rake/helpers.rb +502 -0
  161. data/rake/hg.rb +282 -0
  162. data/rake/manual.rb +787 -0
  163. data/rake/packaging.rb +129 -0
  164. data/rake/publishing.rb +278 -0
  165. data/rake/style.rb +62 -0
  166. data/rake/svn.rb +668 -0
  167. data/rake/testing.rb +187 -0
  168. data/rake/verifytask.rb +64 -0
  169. data/spec/arrow/acceptparam_spec.rb +157 -0
  170. data/spec/arrow/applet_spec.rb +575 -0
  171. data/spec/arrow/appletmixins_spec.rb +409 -0
  172. data/spec/arrow/appletregistry_spec.rb +294 -0
  173. data/spec/arrow/broker_spec.rb +153 -0
  174. data/spec/arrow/config_spec.rb +224 -0
  175. data/spec/arrow/cookieset_spec.rb +164 -0
  176. data/spec/arrow/dispatcher_spec.rb +137 -0
  177. data/spec/arrow/dispatcherloader_spec.rb +65 -0
  178. data/spec/arrow/formvalidator_spec.rb +781 -0
  179. data/spec/arrow/logger_spec.rb +346 -0
  180. data/spec/arrow/mixins_spec.rb +120 -0
  181. data/spec/arrow/service_spec.rb +645 -0
  182. data/spec/arrow/session_spec.rb +121 -0
  183. data/spec/arrow/template/iterator_spec.rb +222 -0
  184. data/spec/arrow/templatefactory_spec.rb +185 -0
  185. data/spec/arrow/transaction_spec.rb +319 -0
  186. data/spec/arrow_spec.rb +37 -0
  187. data/spec/lib/appletmatchers.rb +281 -0
  188. data/spec/lib/constants.rb +77 -0
  189. data/spec/lib/helpers.rb +41 -0
  190. data/spec/lib/matchers.rb +44 -0
  191. data/tests/cookie.tests.rb +310 -0
  192. data/tests/path.tests.rb +157 -0
  193. data/tests/session.tests.rb +111 -0
  194. data/tests/session_id.tests.rb +82 -0
  195. data/tests/session_lock.tests.rb +191 -0
  196. data/tests/session_store.tests.rb +53 -0
  197. data/tests/template.tests.rb +1360 -0
  198. metadata +339 -0
@@ -0,0 +1,132 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'arrow/exceptions'
4
+ require 'arrow/session/store'
5
+
6
+ # The Arrow::Session::FileStore class, a derivative of Arrow::Session::Store.
7
+ # Instances of this class store a session object as a marshalled hash on disk.
8
+ #
9
+ # == Authors
10
+ #
11
+ # * Michael Granger <ged@FaerieMUD.org>
12
+ #
13
+ # Please see the file LICENSE in the top-level directory for licensing details.
14
+ #
15
+ class Arrow::Session::FileStore < Arrow::Session::Store
16
+
17
+ # The default flags to use when opening the backing store file
18
+ DefaultIoFlags = File::RDWR|File::CREAT
19
+
20
+
21
+
22
+ #################################################################
23
+ ### I N S T A N C E M E T H O D S
24
+ #################################################################
25
+
26
+ ### Create a new Arrow::Session::FileStore object.
27
+ def initialize( uri, idobj )
28
+ path = (uri.path || uri.opaque).dup
29
+ path.untaint
30
+
31
+ @dir = File.expand_path( path )
32
+ @io = nil
33
+
34
+ super
35
+ end
36
+
37
+
38
+ ######
39
+ public
40
+ ######
41
+
42
+ # The fully-qualified directory in which session files will be written.
43
+ attr_reader :dir
44
+
45
+
46
+ ### Return the fully-qualified path to the session file for this
47
+ ### store.
48
+ def session_file
49
+ return File.join( @dir, @id.to_s )
50
+ end
51
+
52
+
53
+ ### Close the file after saving to make sure it's synched.
54
+ def save
55
+ super
56
+ @io = nil
57
+ end
58
+
59
+
60
+ ### Get the output filehandle for the session backing store
61
+ ### file. Open it with the specified +ioflags+ if it's not
62
+ ### already open.
63
+ def open( ioflags=DefaultIoFlags )
64
+ if @io.nil? || @io.closed?
65
+ file = self.session_file
66
+ self.log.debug "Opening session file %s" % file
67
+ @io = File.open( file, File::RDWR|File::CREAT )
68
+ @io.sync = true
69
+ end
70
+
71
+ return @io
72
+ end
73
+
74
+
75
+ ### Close the output filehandle if it is opened.
76
+ def close
77
+ @io.close unless @io.nil? || @io.closed?
78
+ end
79
+
80
+
81
+ ### Insert the specified +data+ hash into whatever permanent storage the
82
+ ### Store object is acting as an interface to.
83
+ def insert
84
+ super {|data|
85
+ self.log.debug "Inserting data into session file"
86
+ self.open( DefaultIoFlags|File::EXCL ).print( data )
87
+ }
88
+ end
89
+
90
+
91
+ ### Update the current data hash stored in permanent storage with the
92
+ ### values contained in +data+.
93
+ def update
94
+ super {|data|
95
+ self.log.debug "Updating data in session file"
96
+ ofh = self.open
97
+ ofh.seek( 0, File::SEEK_SET )
98
+ ofh.print( data )
99
+ }
100
+ end
101
+
102
+
103
+ ### Retrieve the data hash stored in permanent storage associated with
104
+ ### the id the object was created with.
105
+ def retrieve
106
+ super {
107
+ self.log.debug "Reading data in session file"
108
+ ofh = self.open( File::RDWR )
109
+ ofh.seek( 0, File::SEEK_SET )
110
+ ofh.read
111
+ }
112
+ end
113
+
114
+
115
+ ### Permanently remove the data hash associated with the id used in the
116
+ ### receiver's creation from permanent storage.
117
+ def remove
118
+ super
119
+ self.close
120
+ file = self.session_file
121
+ if File.exists?( file )
122
+ File.delete( file )
123
+ else
124
+ raise Arrow::SessionError,
125
+ "Session file #{file} does not exist in the data store"
126
+ end
127
+ end
128
+
129
+
130
+ end # class Arrow::Session::FileStore
131
+
132
+
@@ -0,0 +1,98 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'pluginfactory'
4
+
5
+ require 'arrow/object'
6
+ require 'arrow/mixins'
7
+ require 'arrow/session'
8
+
9
+ # The Arrow::Session::Id class, a derivative of Arrow::Object. Instances of
10
+ # concrete derivatives of this class are used as session IDs in Arrow::Session
11
+ # objects.
12
+ #
13
+ # == Authors
14
+ #
15
+ # * Michael Granger <ged@FaerieMUD.org>
16
+ #
17
+ # Please see the file LICENSE in the top-level directory for licensing details.
18
+ #
19
+ class Arrow::Session::Id < Arrow::Object
20
+ include PluginFactory
21
+
22
+
23
+ #############################################################
24
+ ### C L A S S M E T H O D S
25
+ #############################################################
26
+
27
+ ### Returns the Array of directories to search for derivatives; part of
28
+ ### the PluginFactory interface.
29
+ def self::derivativeDirs
30
+ [ 'arrow/session', 'arrow/session/id' ]
31
+ end
32
+
33
+
34
+ ### Create a new Arrow::Session::Id object for the given +request+ (an
35
+ ### Apache::Request) of the type specified by +uri+.
36
+ def self::create( uri, request, idstring=nil )
37
+ uri = Arrow::Session.parse_uri( uri ) if uri.is_a?( String )
38
+ super( uri.scheme.dup, uri, request, idstring )
39
+ end
40
+
41
+
42
+ ### Generate a new id string for the given +request+.
43
+ def self::generate( uri, request )
44
+ raise NotImplementedError, "%s does not implement #generate" %
45
+ self.name
46
+ end
47
+
48
+
49
+ ### Validate the given +idstring+, returning an untainted copy of it if
50
+ ### it's valid, or +nil+ if it's not.
51
+ def self::validate( uri, idstring )
52
+ raise NotImplementedError, "%s does not implement #validate" %
53
+ self.name
54
+ end
55
+
56
+
57
+
58
+ #############################################################
59
+ ### I N S T A N C E M E T H O D S
60
+ #############################################################
61
+
62
+ ### Create a new Arrow::Session::Id object. If the +idstring+ is given, it
63
+ ### will be used as the unique key for this session. If it is not
64
+ ### specified, a new one will be generated.
65
+ def initialize( uri, request, idstring=nil )
66
+ @new = true
67
+
68
+ if idstring
69
+ self.log.debug "Validating id %p" % [ idstring ]
70
+ @str = self.class.validate( uri, idstring )
71
+ self.log.debug " validation %s" % [ @str ? "succeeded" : "failed" ]
72
+ @new = false
73
+ end
74
+
75
+ @str ||= self.class.generate( uri, request )
76
+ super()
77
+ end
78
+
79
+
80
+ ######
81
+ public
82
+ ######
83
+
84
+
85
+ ### Return the id as a String.
86
+ def to_s
87
+ return @str
88
+ end
89
+
90
+
91
+ ### Returns +true+ if the id was generated for this request as opposed
92
+ ### to being fetched from a cookie or the URL.
93
+ def new?
94
+ @new ? true : false
95
+ end
96
+
97
+ end # class Arrow::Session::Id
98
+
@@ -0,0 +1,253 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'uri'
4
+ require 'pluginfactory'
5
+
6
+ require 'arrow/object'
7
+ require 'arrow/exceptions'
8
+ require 'arrow/mixins'
9
+ require 'arrow/session'
10
+
11
+
12
+ # The Arrow::Session::Lock class, which is the abstract
13
+ # superclass for session lock object classes. Locks are objects which fulfill
14
+ # the locking interface of Arrow::Session, providing a way of serializing
15
+ # access to session data.
16
+ #
17
+ # To derive your own lock manager classes from this class, you'll need to
18
+ # follow the following interface:
19
+ #
20
+ # === Derivative Interface ===
21
+ #
22
+ # Locking is achieved via four methods: #acquire_read_lock, #acquire_write_lock,
23
+ # #release_read_lock, and #release_write_lock. These methods provide the
24
+ # #concurrency for sessions shared between multiple servers. You will probably
25
+ # #also want to provide your own initializer to capture the session's ID.
26
+ #
27
+ # #initialize( uri=string, id=Arrow::Session::Id )
28
+ #
29
+ # #acquire_read_lock::
30
+ # Acquire a shared lock on the session data.
31
+ #
32
+ # #acquire_write_lock::
33
+ # Acquire an exclusive lock on the session data.
34
+ #
35
+ # #release_read_lock
36
+ # Release a shared lock on the session data.
37
+ #
38
+ # #release_write_lock::
39
+ # Release an exclusive lock on the session data.
40
+ #
41
+ # == Authors
42
+ #
43
+ # * Michael Granger <ged@FaerieMUD.org>
44
+ #
45
+ # Please see the file LICENSE in the top-level directory for licensing details.
46
+ #
47
+ class Arrow::Session::Lock < Arrow::Object
48
+ include PluginFactory
49
+
50
+ # Lock status flags
51
+ UNLOCKED = 0b00
52
+ READ = 0b01
53
+ WRITE = 0b10
54
+
55
+
56
+ #############################################################
57
+ ### C L A S S M E T H O D S
58
+ #############################################################
59
+
60
+ ### Returns the Array of directories to search for derivatives; part of
61
+ ### the PluginFactory interface.
62
+ def self::derivativeDirs
63
+ [ 'arrow/session', 'arrow/session/lock' ]
64
+ end
65
+
66
+
67
+ ### Create a new Arrow::Session::Lock object for the given +id+ of the
68
+ ### type specified by +uri+.
69
+ def self::create( uri, id )
70
+ uri = Arrow::Session.parse_uri( uri ) if
71
+ uri.is_a?( String )
72
+ super( uri.scheme.dup, uri, id )
73
+ end
74
+
75
+
76
+
77
+ #############################################################
78
+ ### I N S T A N C E M E T H O D S
79
+ #############################################################
80
+
81
+ ### Create a new Arrow::Session::Lock object.
82
+ def initialize( uri, id )
83
+ super()
84
+ @status = UNLOCKED
85
+ end
86
+
87
+
88
+ ######
89
+ public
90
+ ######
91
+
92
+ ### Acquire a read (shared) lock. If +blocking+ is false, will return
93
+ ### +false+ if the lock was not able to be acquired.
94
+ def read_lock( blocking=true )
95
+ return true if self.read_locked?
96
+ self.log.debug "Acquiring read lock"
97
+ self.acquire_read_lock( blocking ) or return false
98
+ @status |= READ
99
+ self.log.debug "Got read lock"
100
+ return true
101
+ end
102
+
103
+
104
+ ### Acquire a write (exclusive) lock. If +blocking+ is false, will
105
+ ### return +false+ if the lock was not able to be acquired.
106
+ def write_lock( blocking=true )
107
+ return true if self.write_locked?
108
+ self.log.debug "Acquiring write lock"
109
+ self.acquire_write_lock( blocking ) or return false
110
+ @status |= WRITE
111
+ self.log.debug "Got write lock"
112
+ return true
113
+ end
114
+
115
+
116
+ ### Execute the given block after obtaining a read lock, and give up the
117
+ ### lock when the block returns. If +blocking+ is false, will raise an
118
+ ### Errno::EAGAIN error without calling the block if the lock cannot be
119
+ ### immediately established.
120
+ def with_read_lock( blocking=true )
121
+ begin
122
+ self.read_lock( blocking ) or raise Errno::EAGAIN
123
+ yield
124
+ ensure
125
+ self.release_read_lock
126
+ end
127
+ end
128
+
129
+
130
+ ### Execute the given block after obtaining a write lock, and give up
131
+ ### the lock when the block returns. If +blocking+ is false, will raise
132
+ ### an Errno::EAGAIN error without calling the block if the lock cannot
133
+ ### be immediately established.
134
+ def with_write_lock( blocking=true )
135
+ begin
136
+ self.write_lock( blocking ) or raise Errno::EAGAIN
137
+ yield
138
+ ensure
139
+ self.release_write_lock
140
+ end
141
+ end
142
+
143
+
144
+ ### Returns +true+ if the lock object currently holds either a read or
145
+ ### write lock.
146
+ def locked?
147
+ (@status & (READ|WRITE)).nonzero?
148
+ end
149
+
150
+
151
+ ### Returns +true+ if the lock object has acquired a read lock.
152
+ def read_locked?
153
+ (@status & READ).nonzero?
154
+ end
155
+
156
+
157
+ ### Returns +true+ if the lock object has acquired a write lock.
158
+ def write_locked?
159
+ (@status & WRITE).nonzero?
160
+ end
161
+
162
+
163
+ ### Give up a read (shared) lock. Raises an exception if no read lock
164
+ ### has been acquired.
165
+ def read_unlock
166
+ raise Arrow::LockingError, "No read lock to release" unless
167
+ self.read_locked?
168
+ self.log.debug "Releasing read lock"
169
+ self.release_read_lock
170
+ @status &= ( @status ^ READ )
171
+ end
172
+
173
+
174
+ ### Release a write (exclusive) lock. Raises an exception if no write
175
+ ### lock has been acquired.
176
+ def write_unlock
177
+ raise Arrow::LockingError, "No write lock to release" unless
178
+ self.write_locked?
179
+ self.log.debug "Releasing write lock"
180
+ self.release_write_lock
181
+ @status &= ( @status ^ WRITE )
182
+ end
183
+
184
+
185
+ ### Release any locks acquired by this lock object.
186
+ def release_all_locks
187
+ return false unless self.locked?
188
+ self.write_unlock if self.write_locked?
189
+ self.read_unlock if self.read_locked?
190
+ end
191
+
192
+
193
+ ### Indicate to the lock that the caller will no longer be using it, and
194
+ ### it may free any resources it had been using.
195
+ def finish
196
+ self.release_all_locks
197
+ end
198
+
199
+
200
+ #########
201
+ protected
202
+ #########
203
+
204
+ ### Interface method for concrete derivatives: acquire a read lock
205
+ ### through whatever mechanism is being implemented. If +blocking+ is
206
+ ### +true+, the method should only return if the lock was successfully
207
+ ### acquired. If +blocking+ is +false+, this method should attempt the
208
+ ### lock and return +false+ immediately if the lock was not able to the
209
+ ### acquired. Concrete implementations should *not* call +super+ for
210
+ ### this method.
211
+ def acquire_read_lock( blocking )
212
+ raise UnimplementedError,
213
+ "%s does not provide an implementation of #acquire_read_lock." %
214
+ self.class.name
215
+ end
216
+
217
+
218
+ ### Interface method for concrete derivatives: acquire a write lock
219
+ ### through whatever mechanism is being implemented. If +blocking+ is
220
+ ### +true+, the method should only return if the lock was successfully
221
+ ### acquired. If +blocking+ is +false+, this method should attempt the
222
+ ### lock and return +false+ immediately if the lock was not able to the
223
+ ### acquired. Concrete implementations should *not* call +super+ for
224
+ ### this method.
225
+ def acquire_write_lock( blocking )
226
+ raise UnimplementedError,
227
+ "%s does not provide an implementation of #acquire_write_lock." %
228
+ self.class.name
229
+ end
230
+
231
+
232
+ ### Interface method for concrete derivatives: release a read lock
233
+ ### through whatever mechanism is being implemented. Concrete
234
+ ### implementations should *not* call +super+ for this method.
235
+ def release_read_lock
236
+ raise UnimplementedError,
237
+ "%s does not provide an implementation of #release_read_lock." %
238
+ self.class.name
239
+ end
240
+
241
+
242
+ ### Interface method for concrete derivatives: release a write lock
243
+ ### through whatever mechanism is being implemented. Concrete
244
+ ### implementations should *not* call +super+ for this method.
245
+ def release_write_lock
246
+ raise UnimplementedError,
247
+ "%s does not provide an implementation of #release_write_lock." %
248
+ self.class.name
249
+ end
250
+
251
+ end # class Arrow::Session::Lock
252
+
253
+