Class: Og::Database

Inherits:
Object show all
Includes:
Enchant
Defined in:
lib/og/database.rb

Overview

Encapsulates an Og Database.

Defined Under Namespace

Classes: ManagedClassMeta

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Methods included from Enchant

#enchant

Constructor Details

#initialize(config) ⇒ Database

Initialize the database interface.



57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
# File 'lib/og/database.rb', line 57

def initialize(config)
	@config = config

	# populate with default options if needed.
	@config[:connection_count] ||= 1
	
	Logger.info "Connecting to database '#{@config[:database]}' using the '#{@config[:adapter]}' adapter."

	@adapter =  Adapter.for_name(@config[:adapter])

	@connection_pool = N::Pool.new
	@managed_classes = N::SafeHash.new
	
	@config[:connection_count].times do
		# @connection_pool << Og::Connection.new(self)
		@connection_pool << @adapter.new_connection(self)
	end

	# gmosx, FIXME: this automanage code is not elegant and slow
	# should probably recode this, along with glue/property.rb
	
	if Og.auto_manage_classes
		# automatically manage classes with properties and metadata.
		# gmosx: Any idea how to optimize this?

		classes_to_manage = []

		ObjectSpace.each_object(Class) do |c|
			if c.respond_to?(:__props) and c.__props
				classes_to_manage << c
			end
		end
		
		Logger.info "Og auto manages the following classes:"
		Logger.info "#{classes_to_manage.inspect}"
		
		manage_classes(*classes_to_manage)
	end

	# use the newly created database.
	Og.use(self)
end

Instance Attribute Details

#adapterObject

The adapter that comunicates with the backend datastore.



45
46
47
# File 'lib/og/database.rb', line 45

def adapter
  @adapter
end

#configObject

hash of configuration options.



40
41
42
# File 'lib/og/database.rb', line 40

def config
  @config
end

#connection_poolObject

Pool of connections.



49
50
51
# File 'lib/og/database.rb', line 49

def connection_pool
  @connection_pool
end

#managed_classesObject

Managed classes.



53
54
55
# File 'lib/og/database.rb', line 53

def managed_classes
  @managed_classes
end

Class Method Details

.create_db!(config) ⇒ Object Also known as: create!



254
255
256
257
# File 'lib/og/database.rb', line 254

def create_db!(config)
	adapter = Adapter.for_name(config[:adapter])
	adapter.create_db(config[:database], config[:user], config[:password])
end

.drop_db!(config) ⇒ Object Also known as: drop!



260
261
262
263
# File 'lib/og/database.rb', line 260

def drop_db!(config)
	adapter = Adapter.for_name(config[:adapter])
	adapter.drop_db(config[:database], config[:user], config[:password])
end

.wrap_method(method, args) ⇒ Object

Automatically wrap connection methods.



217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
# File 'lib/og/database.rb', line 217

def self.wrap_method(method, args)
	args = args.split(/,/)
	class_eval %{
		def #{method}(#{args.join(", ")})
			thread = Thread.current
			
			unless conn = thread[:og_conn]
				conn = @connection_pool.pop()
				thread[:og_conn] = conn
			end
		
			return conn.#{method}(#{args.collect {|a| a.split(/=/)[0]}.join(", ")})
		end
	}
end

Instance Method Details

#connect(&block) ⇒ Object Also known as: open

Utility method, automatically restores a connection to the pool.



137
138
139
140
141
142
143
144
145
146
147
148
# File 'lib/og/database.rb', line 137

def connect(&block)
	result = nil
	
	begin
		conn = get_connection
		result = yield(conn)
	ensure
		put_connection
	end

	return result
end

#convert(klass) ⇒ Object

Add standard og functionality to the class



188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
# File 'lib/og/database.rb', line 188

def convert(klass)
	# gmosx: this check is needed to allow the developer to customize
	# the sql generated for oid

	@adapter.eval_og_oid(klass) unless klass.instance_methods.include?(:oid)
	
	klass.class_eval %{
		DBTABLE = "#{Adapter.table(klass)}"
		DBSEQ = "#{Adapter.table(klass)}_oid_seq" 
		
		def to_i()
			@oid
		end			
	}

	# Create the schema for this class if not available.
	@adapter.create_table(klass, self)				

	# Precompile some code that gets executed all the time.
	# Deletion code is not precompiled, because it is not used
	# as frequently.

	@adapter.eval_og_insert(klass, self)
	@adapter.eval_og_update(klass, self)
	@adapter.eval_og_read(klass, self)
end

#get_connectionObject Also known as: connection

Get a connection from the pool to access the database. Stores the connection in a thread-local variable.



112
113
114
115
116
117
118
119
120
121
# File 'lib/og/database.rb', line 112

def get_connection
	thread = Thread.current
	
	unless conn = thread[:og_conn]
		conn = @connection_pool.pop()
		thread[:og_conn] = conn
	end
	
	return conn
end

#manage(klass) ⇒ Object

Register a standard Ruby class as managed.



154
155
156
157
158
159
160
161
162
163
164
# File 'lib/og/database.rb', line 154

def manage(klass)
	return if managed?(klass) or klass.ancestors.include?(Og::Unmanageable)
	
	@managed_classes[klass] = ManagedClassMeta.new(klass)
	
	# Add standard og methods to the class.
	convert(klass)
	
	# Add helper methods to the class.
	enchant(klass) if Og.enchant_managed_classes 
end

#manage_classes(*klasses) ⇒ Object

Helper method to set multiple managed classes.



168
169
170
171
172
# File 'lib/og/database.rb', line 168

def manage_classes(*klasses)
	for klass in klasses
		manage(klass)
	end
end

#managed?(klass) ⇒ Boolean

Is this class managed?

Returns:

  • (Boolean)


182
183
184
# File 'lib/og/database.rb', line 182

def managed?(klass)
	return @managed_classes.include?(klass)
end

#put_connectionObject

Restore an unused connection to the pool.



126
127
128
129
130
131
132
133
# File 'lib/og/database.rb', line 126

def put_connection
	thread = Thread.current
	
	if conn = thread[:og_conn]
		thread[:og_conn] = nil
		return @connection_pool.push(conn)
	end
end

#shutdownObject Also known as: close

Shutdown the database interface.



102
103
104
105
106
# File 'lib/og/database.rb', line 102

def shutdown
	for con in @connection_pool
		con.close()
	end
end

#unmanage(klass) ⇒ Object

Stop managing a Ruby class



176
177
178
# File 'lib/og/database.rb', line 176

def unmanage(klass)
	@managed_classes.delete(klass)
end