og 0.5.0
Sign up to get free protection for your applications and to get access to all the features.
- data/AUTHORS +19 -0
- data/LICENSE +32 -0
- data/README.og +104 -0
- data/RELEASES.og +23 -0
- data/examples/og/README +4 -0
- data/examples/og/run.rb +251 -0
- data/lib/glue.rb +52 -0
- data/lib/glue/array.rb +84 -0
- data/lib/glue/cache.rb +140 -0
- data/lib/glue/hash.rb +143 -0
- data/lib/glue/inflector.rb +91 -0
- data/lib/glue/logger.rb +51 -0
- data/lib/glue/macro.rb +56 -0
- data/lib/glue/mixins.rb +45 -0
- data/lib/glue/number.rb +30 -0
- data/lib/glue/pool.rb +63 -0
- data/lib/glue/property.rb +301 -0
- data/lib/glue/string.rb +224 -0
- data/lib/glue/time.rb +93 -0
- data/lib/og.rb +411 -0
- data/lib/og/backend.rb +258 -0
- data/lib/og/backends/mysql.rb +360 -0
- data/lib/og/backends/psql.rb +359 -0
- data/lib/og/connection.rb +265 -0
- data/lib/og/meta.rb +139 -0
- data/lib/og/version.rb +8 -0
- data/test/tc_og.rb +179 -0
- metadata +71 -0
data/lib/glue/array.rb
ADDED
@@ -0,0 +1,84 @@
|
|
1
|
+
# code:
|
2
|
+
# * George Moschovitis <gm@navel.gr>
|
3
|
+
#
|
4
|
+
# (c) 2002-2003 Navel, all rights reserved.
|
5
|
+
# $Id: array.rb 165 2004-11-18 12:04:04Z gmosx $
|
6
|
+
|
7
|
+
require "sync"
|
8
|
+
|
9
|
+
module G
|
10
|
+
|
11
|
+
# == SafeArray
|
12
|
+
#
|
13
|
+
# A thread-safe array. We use a sync object instead of a mutex,
|
14
|
+
# because it is re-entrant.
|
15
|
+
# An exclusive lock is needed when writing, a shared lock IS NEEDED
|
16
|
+
# when reading
|
17
|
+
#
|
18
|
+
class SafeArray < Array
|
19
|
+
|
20
|
+
attr :sync
|
21
|
+
|
22
|
+
# gmosx: delegator is not used.
|
23
|
+
#
|
24
|
+
def initialize(delegator = nil)
|
25
|
+
@sync = ::Sync.new()
|
26
|
+
end
|
27
|
+
|
28
|
+
def << (value)
|
29
|
+
return @sync.synchronize(::Sync::SH) {
|
30
|
+
super
|
31
|
+
}
|
32
|
+
end
|
33
|
+
|
34
|
+
def delete_if(&block)
|
35
|
+
return @sync.synchronize(::Sync::SH) {
|
36
|
+
super
|
37
|
+
}
|
38
|
+
end
|
39
|
+
|
40
|
+
def [](key)
|
41
|
+
return @sync.synchronize(::Sync::SH) {
|
42
|
+
super
|
43
|
+
}
|
44
|
+
end
|
45
|
+
|
46
|
+
def []=(key, value)
|
47
|
+
return @sync.synchronize(::Sync::EX) {
|
48
|
+
super
|
49
|
+
}
|
50
|
+
end
|
51
|
+
|
52
|
+
def delete(key)
|
53
|
+
return @sync.synchronize(::Sync::EX) {
|
54
|
+
super
|
55
|
+
}
|
56
|
+
end
|
57
|
+
|
58
|
+
def clear
|
59
|
+
@sync.synchronize(::Sync::EX) {
|
60
|
+
super
|
61
|
+
}
|
62
|
+
end
|
63
|
+
|
64
|
+
def size
|
65
|
+
return @sync.synchronize(::Sync::SH) {
|
66
|
+
super
|
67
|
+
}
|
68
|
+
end
|
69
|
+
|
70
|
+
def shift
|
71
|
+
return @sync.synchronize(::Sync::EX) {
|
72
|
+
super
|
73
|
+
}
|
74
|
+
end
|
75
|
+
|
76
|
+
def unshift(el)
|
77
|
+
return @sync.synchronize(::Sync::EX) {
|
78
|
+
super
|
79
|
+
}
|
80
|
+
end
|
81
|
+
|
82
|
+
end
|
83
|
+
|
84
|
+
end # module
|
data/lib/glue/cache.rb
ADDED
@@ -0,0 +1,140 @@
|
|
1
|
+
# code:
|
2
|
+
# * George Moschovitis <gm@navel.gr>
|
3
|
+
# * Anastasios Koutoumanos <ak@navel.gr>
|
4
|
+
#
|
5
|
+
# (c) 2004 Navel, all rights reserved.
|
6
|
+
# $Id: cache.rb 167 2004-11-23 14:03:10Z gmosx $
|
7
|
+
|
8
|
+
module G;
|
9
|
+
|
10
|
+
# = LRUCache
|
11
|
+
#
|
12
|
+
# A cache utilizing a simple LRU (Least Recently Used) policy.
|
13
|
+
# The items managed by this cache must respond to the #key method.
|
14
|
+
# Attempts to optimize reads rather than inserts!
|
15
|
+
#
|
16
|
+
# LRU semantics are enforced by inserting the items in a queue.
|
17
|
+
# The lru item is always at the tail. Two special sentinels
|
18
|
+
# (head, tail) are used to simplify (?) the code.
|
19
|
+
#
|
20
|
+
class LRUCache < Hash
|
21
|
+
|
22
|
+
# Mix this in your class to make LRU-managable.
|
23
|
+
#
|
24
|
+
module Item
|
25
|
+
attr_accessor :lru_key, :lru_prev, :lru_next
|
26
|
+
end
|
27
|
+
|
28
|
+
# head-tail sentinels
|
29
|
+
#
|
30
|
+
class Sentinel; include Item; end
|
31
|
+
|
32
|
+
# the maximum number of items in the cache
|
33
|
+
attr_accessor :max_items
|
34
|
+
|
35
|
+
# the head sentinel
|
36
|
+
attr :head
|
37
|
+
# the tail sentinel, tail.prev points to the lru item.
|
38
|
+
attr :tail
|
39
|
+
|
40
|
+
#
|
41
|
+
#
|
42
|
+
def initialize(max_items)
|
43
|
+
@max_items = max_items
|
44
|
+
lru_clear()
|
45
|
+
end
|
46
|
+
|
47
|
+
# Lookup an item in the cache
|
48
|
+
#
|
49
|
+
def [](key)
|
50
|
+
if item = super
|
51
|
+
return lru_touch(item)
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
# The inserted item is considered mru!
|
56
|
+
#
|
57
|
+
def []=(key, item)
|
58
|
+
item = super
|
59
|
+
item.lru_key = key
|
60
|
+
lru_insert(item)
|
61
|
+
end
|
62
|
+
|
63
|
+
# Delete an item from the cache
|
64
|
+
#
|
65
|
+
def delete(key)
|
66
|
+
if item = super
|
67
|
+
lru_delete(item)
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
# Clear the cache
|
72
|
+
#
|
73
|
+
def clear
|
74
|
+
super
|
75
|
+
lru_clear()
|
76
|
+
end
|
77
|
+
|
78
|
+
# The first (mru) element in the cache
|
79
|
+
#
|
80
|
+
def first
|
81
|
+
@head.lru_next
|
82
|
+
end
|
83
|
+
|
84
|
+
# The last (lru) element in the cache
|
85
|
+
#
|
86
|
+
def last
|
87
|
+
@tail.lru_prev
|
88
|
+
end
|
89
|
+
alias_method :lru, :last
|
90
|
+
|
91
|
+
private
|
92
|
+
|
93
|
+
# Delete an item from the lru list.
|
94
|
+
#
|
95
|
+
def lru_delete(item)
|
96
|
+
lru_join(item.lru_prev, item.lru_next)
|
97
|
+
return item
|
98
|
+
end
|
99
|
+
|
100
|
+
# Join two items in the lru list
|
101
|
+
# Return y to allow for chaining
|
102
|
+
#
|
103
|
+
def lru_join(x, y)
|
104
|
+
x.lru_next = y
|
105
|
+
y.lru_prev = x
|
106
|
+
return y
|
107
|
+
end
|
108
|
+
|
109
|
+
# Append a child item to a parent item in the lru list
|
110
|
+
# (Re)inserts the child in the list.
|
111
|
+
#
|
112
|
+
def lru_append(parent, child)
|
113
|
+
lru_join(child, parent.lru_next)
|
114
|
+
lru_join(parent, child)
|
115
|
+
end
|
116
|
+
|
117
|
+
# Insert an item
|
118
|
+
#
|
119
|
+
def lru_insert(item)
|
120
|
+
delete(last.lru_key) if size() > @max_items
|
121
|
+
lru_append(@head, item)
|
122
|
+
end
|
123
|
+
|
124
|
+
# Touch an item, make mru!
|
125
|
+
# Returns the item
|
126
|
+
#
|
127
|
+
def lru_touch(item)
|
128
|
+
lru_append(@head, lru_delete(item))
|
129
|
+
end
|
130
|
+
|
131
|
+
# Clear the lru
|
132
|
+
#
|
133
|
+
def lru_clear
|
134
|
+
@head = Sentinel.new
|
135
|
+
@tail = Sentinel.new
|
136
|
+
lru_join(@head, @tail)
|
137
|
+
end
|
138
|
+
end
|
139
|
+
|
140
|
+
end # module
|
data/lib/glue/hash.rb
ADDED
@@ -0,0 +1,143 @@
|
|
1
|
+
# code:
|
2
|
+
# * George Moschovitis <gm@navel.gr>
|
3
|
+
#
|
4
|
+
# (c) 2004 Navel, all rights reserved.
|
5
|
+
# $Id: hash.rb 167 2004-11-23 14:03:10Z gmosx $
|
6
|
+
|
7
|
+
require "sync"
|
8
|
+
|
9
|
+
module G;
|
10
|
+
|
11
|
+
# == SafeHash
|
12
|
+
#
|
13
|
+
# A thread-safe hash. We use a sync object instead of a mutex,
|
14
|
+
# because it is re-entrant.
|
15
|
+
# An exclusive lock is needed when writing, a shared lock IS NEEDED
|
16
|
+
# when reading
|
17
|
+
# uses the delegator pattern to allow for multiple
|
18
|
+
# implementations!
|
19
|
+
#
|
20
|
+
class SafeHash < Hash
|
21
|
+
attr :sync
|
22
|
+
|
23
|
+
# gmosx: delegator is not used.
|
24
|
+
#
|
25
|
+
def initialize(delegator = nil)
|
26
|
+
@sync = ::Sync.new
|
27
|
+
end
|
28
|
+
|
29
|
+
def [](key)
|
30
|
+
return @sync.synchronize(::Sync::SH) {
|
31
|
+
super
|
32
|
+
}
|
33
|
+
end
|
34
|
+
|
35
|
+
def []=(key, value)
|
36
|
+
return @sync.synchronize(::Sync::EX) {
|
37
|
+
super
|
38
|
+
}
|
39
|
+
end
|
40
|
+
|
41
|
+
def delete(key)
|
42
|
+
return @sync.synchronize(::Sync::EX) {
|
43
|
+
super
|
44
|
+
}
|
45
|
+
end
|
46
|
+
|
47
|
+
def clear
|
48
|
+
@sync.synchronize(::Sync::EX) {
|
49
|
+
super
|
50
|
+
}
|
51
|
+
end
|
52
|
+
|
53
|
+
def size
|
54
|
+
return @sync.synchronize(::Sync::SH) {
|
55
|
+
super
|
56
|
+
}
|
57
|
+
end
|
58
|
+
|
59
|
+
def values
|
60
|
+
return @sync.synchronize(::Sync::SH) {
|
61
|
+
super
|
62
|
+
}
|
63
|
+
end
|
64
|
+
|
65
|
+
def keys
|
66
|
+
return @sync.synchronize(::Sync::SH) {
|
67
|
+
super
|
68
|
+
}
|
69
|
+
end
|
70
|
+
|
71
|
+
end # SafeHash
|
72
|
+
|
73
|
+
# == SafeHashDelegator
|
74
|
+
#
|
75
|
+
# A thread-safe hash. We use a sync object instead of a mutex,
|
76
|
+
# because it is re-entrant.
|
77
|
+
# An exclusive lock is needed when writing, a shared lock IS NEEDED
|
78
|
+
# when reading
|
79
|
+
#
|
80
|
+
# Design:
|
81
|
+
# This class uses the delegator pattern. However we dont use rubys
|
82
|
+
# delegation facilities, they are more general and powerfull than we
|
83
|
+
# need here (and slower). Instead a custom (but simple) solution is
|
84
|
+
# used.
|
85
|
+
#
|
86
|
+
# Example:
|
87
|
+
#
|
88
|
+
# hash = SafeHashDelegator.new(Hash.new)
|
89
|
+
# hash = SafeHashDelegator.new(Hash.new)
|
90
|
+
|
91
|
+
class SafeHashDelegator < Hash
|
92
|
+
attr :delegate, :sync
|
93
|
+
|
94
|
+
def initialize(delegate)
|
95
|
+
@delegate = delegate
|
96
|
+
@sync = ::Sync.new
|
97
|
+
end
|
98
|
+
|
99
|
+
def [](key)
|
100
|
+
return @sync.synchronize(::Sync::SH) {
|
101
|
+
@delegate[key]
|
102
|
+
}
|
103
|
+
end
|
104
|
+
|
105
|
+
def []=(key, value)
|
106
|
+
return @sync.synchronize(::Sync::EX) {
|
107
|
+
@delegate[key] = value
|
108
|
+
}
|
109
|
+
end
|
110
|
+
|
111
|
+
def delete(key)
|
112
|
+
return @sync.synchronize(::Sync::EX) {
|
113
|
+
@delegate.delete(key)
|
114
|
+
}
|
115
|
+
end
|
116
|
+
|
117
|
+
def clear
|
118
|
+
@sync.synchronize(::Sync::EX) {
|
119
|
+
@delegate.clear
|
120
|
+
}
|
121
|
+
end
|
122
|
+
|
123
|
+
def size
|
124
|
+
return @sync.synchronize(::Sync::SH) {
|
125
|
+
@delegate.size()
|
126
|
+
}
|
127
|
+
end
|
128
|
+
|
129
|
+
def values
|
130
|
+
return @sync.synchronize(::Sync::SH) {
|
131
|
+
@delegate.values()
|
132
|
+
}
|
133
|
+
end
|
134
|
+
|
135
|
+
def keys
|
136
|
+
return @sync.synchronize(::Sync::SH) {
|
137
|
+
@delegate.keys()
|
138
|
+
}
|
139
|
+
end
|
140
|
+
|
141
|
+
end # SafeHashDelegator
|
142
|
+
|
143
|
+
end # module
|
@@ -0,0 +1,91 @@
|
|
1
|
+
# Code from RubyOnRailes (http://www.rubyonrails.com)
|
2
|
+
# Copyright (c) 2004 David Heinemeier Hansson.
|
3
|
+
#
|
4
|
+
|
5
|
+
module G
|
6
|
+
|
7
|
+
# The Inflector transforms words from singular to plural, class names to table names, modulized class names to ones without,
|
8
|
+
# and class names to foreign keys.
|
9
|
+
#
|
10
|
+
module Inflector
|
11
|
+
extend self
|
12
|
+
|
13
|
+
def pluralize(word)
|
14
|
+
result = word.dup
|
15
|
+
plural_rules.each do |(rule, replacement)|
|
16
|
+
break if result.gsub!(rule, replacement)
|
17
|
+
end
|
18
|
+
return result
|
19
|
+
end
|
20
|
+
|
21
|
+
def singularize(word)
|
22
|
+
result = word.dup
|
23
|
+
singular_rules.each do |(rule, replacement)|
|
24
|
+
break if result.gsub!(rule, replacement)
|
25
|
+
end
|
26
|
+
return result
|
27
|
+
end
|
28
|
+
|
29
|
+
def camelize(lower_case_and_underscored_word)
|
30
|
+
lower_case_and_underscored_word.gsub(/(^|_)(.)/){$2.upcase}
|
31
|
+
end
|
32
|
+
|
33
|
+
def underscore(camel_cased_word)
|
34
|
+
camel_cased_word.gsub(/([A-Z]+)([A-Z])/,'\1_\2').gsub(/([a-z])([A-Z])/,'\1_\2').downcase
|
35
|
+
end
|
36
|
+
|
37
|
+
def demodulize(class_name_in_module)
|
38
|
+
class_name_in_module.gsub(/^.*::/, '')
|
39
|
+
end
|
40
|
+
|
41
|
+
def foreign_key(class_name, separate_class_name_and_id_with_underscore = true)
|
42
|
+
Inflector.underscore(Inflector.demodulize(class_name)) +
|
43
|
+
(separate_class_name_and_id_with_underscore ? "_id" : "id")
|
44
|
+
end
|
45
|
+
|
46
|
+
# Convert a class to a name.
|
47
|
+
#
|
48
|
+
def name(klass)
|
49
|
+
Inflector.underscore(Inflector.demodulize(klass.to_s))
|
50
|
+
end
|
51
|
+
|
52
|
+
# Convert a class to a name in plural
|
53
|
+
#
|
54
|
+
def plural_name(klass)
|
55
|
+
Inflector.pluralize(Inflector.underscore(Inflector.demodulize(klass.to_s)))
|
56
|
+
end
|
57
|
+
|
58
|
+
private
|
59
|
+
def plural_rules #:doc:
|
60
|
+
[
|
61
|
+
[/(x|ch|ss)$/, '\1es'], # search, switch, fix, box, process, address
|
62
|
+
[/([^aeiouy]|qu)y$/, '\1ies'], # query, ability, agency
|
63
|
+
[/(?:([^f])fe|([lr])f)$/, '\1\2ves'], # half, safe, wife
|
64
|
+
[/sis$/, 'ses'], # basis, diagnosis
|
65
|
+
[/([ti])um$/, '\1a'], # datum, medium
|
66
|
+
[/person$/, 'people'], # person, salesperson
|
67
|
+
[/man$/, 'men'], # man, woman, spokesman
|
68
|
+
[/child$/, 'children'], # child
|
69
|
+
[/s$/, 's'], # no change (compatibility)
|
70
|
+
[/$/, 's']
|
71
|
+
]
|
72
|
+
end
|
73
|
+
|
74
|
+
def singular_rules #:doc:
|
75
|
+
[
|
76
|
+
[/(x|ch|ss)es$/, '\1'],
|
77
|
+
[/([^aeiouy]|qu)ies$/, '\1y'],
|
78
|
+
[/([lr])ves$/, '\1f'],
|
79
|
+
[/([^f])ves$/, '\1fe'],
|
80
|
+
[/(analy|ba|diagno|parenthe|progno|synop|the)ses$/, '\1sis'],
|
81
|
+
[/([ti])a$/, '\1um'],
|
82
|
+
[/people$/, 'person'],
|
83
|
+
[/men$/, 'man'],
|
84
|
+
[/status$/, 'status'],
|
85
|
+
[/children$/, 'child'],
|
86
|
+
[/s$/, '']
|
87
|
+
]
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
end # module
|