ramdev 0.1.0
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.
- checksums.yaml +7 -0
- data/bin/ramdev +37 -0
- data/bin/ramdev_sync +14 -0
- data/lib/ramdev.rb +397 -0
- data/lib/ramdev_sync.rb +87 -0
- data/lib/ramdisk.rb +173 -0
- metadata +94 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: d1c089e4b0d2b4a795153868719ac311302c3a92
|
4
|
+
data.tar.gz: e6a958654bbeb09344c16f906219497c750d7b8f
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 0c9f1ca55b4de6dc19b1cdea012b9bb9fb80d41381ccb578202fa3bb6549001f04b19e26b01e7e3c87d39bb7d15dec4caed19f46ffe8249fdb06deadcf18e30b
|
7
|
+
data.tar.gz: e499a8830accb95d90119b1fecfdd360eee8390a0cf3135052198658da96963b09500fd753e97604d16226cbedb65927cf7102d06bea344d773c8d8ee838df86
|
data/bin/ramdev
ADDED
@@ -0,0 +1,37 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'main'
|
4
|
+
require 'ramdev'
|
5
|
+
require 'etc'
|
6
|
+
|
7
|
+
#TODO: Override the rc file from the command line
|
8
|
+
#FIX: This is not windows compatible.
|
9
|
+
|
10
|
+
Main do
|
11
|
+
mode 'up' do
|
12
|
+
def run
|
13
|
+
user = Etc.getlogin
|
14
|
+
rcfile = File.join(Dir.home(user), ".ramdevrc")
|
15
|
+
|
16
|
+
rd = RamDev.new
|
17
|
+
rd.build(rcfile) #10MB
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
mode 'down' do
|
22
|
+
def run
|
23
|
+
user = Etc.getlogin
|
24
|
+
rcfile = File.join(Dir.home(user), ".ramdevrc")
|
25
|
+
|
26
|
+
rd = RamDev.new
|
27
|
+
rd.unbuild(rcfile)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
def run()
|
32
|
+
puts 'Usage: ramdev [up|down]'
|
33
|
+
puts ''
|
34
|
+
puts "\tup\tCreate a ramdisk, move and link working folders."
|
35
|
+
puts "\tdown\tDeallocate ramdisk and restore all file paths."
|
36
|
+
end
|
37
|
+
end
|
data/bin/ramdev_sync
ADDED
data/lib/ramdev.rb
ADDED
@@ -0,0 +1,397 @@
|
|
1
|
+
require 'ramdisk'
|
2
|
+
require 'ramdev_sync'
|
3
|
+
require 'pstore'
|
4
|
+
require 'fileutils'
|
5
|
+
|
6
|
+
class RamDev
|
7
|
+
attr_reader :diskname, :ramdisk, :mountpoint
|
8
|
+
#path to rc file, and 10 mb default size.
|
9
|
+
|
10
|
+
def initialize(sufix = "_ramdev")
|
11
|
+
@backupSuffix = sufix
|
12
|
+
@store = PStore.new("/tmp/ramdev.pstore")
|
13
|
+
end
|
14
|
+
|
15
|
+
def unbuild(rcpath)
|
16
|
+
#TODO force sync
|
17
|
+
load_runcom(rcpath)
|
18
|
+
|
19
|
+
if !restore_folders
|
20
|
+
puts "Ramdisk shutdown was halted because there was a problem restoring folders."
|
21
|
+
puts "Eject the ramdisk manually once you've sorted out any issues."
|
22
|
+
return
|
23
|
+
end
|
24
|
+
ramdisk = Ramdisk.new(mountpoint)
|
25
|
+
|
26
|
+
pid = @store.transaction do |s|
|
27
|
+
s["pid"]
|
28
|
+
end
|
29
|
+
|
30
|
+
Process.kill("QUIT", pid) if pid
|
31
|
+
|
32
|
+
ramdisk.unmount
|
33
|
+
ramdisk.deallocate
|
34
|
+
|
35
|
+
"RAM disk removed at #{mountpoint}"
|
36
|
+
end
|
37
|
+
|
38
|
+
def memory
|
39
|
+
if @memory.nil?
|
40
|
+
r = `/usr/sbin/system_profiler SPHardwareDataType`.split("\n").collect { |s| s == "" ? nil : s.strip }.compact
|
41
|
+
r = r.collect { |s| s.split(":").collect { |ss| ss.strip }}
|
42
|
+
memstring = ""
|
43
|
+
r.each do |i|
|
44
|
+
memstring = i[1] if i[0] == "Memory"
|
45
|
+
end
|
46
|
+
@memory = memstring.match(/([0-9]+) GB/)[1].to_i * 1073741824
|
47
|
+
end
|
48
|
+
@memory
|
49
|
+
end
|
50
|
+
|
51
|
+
def build(rcpath, size = nil)
|
52
|
+
@size = size
|
53
|
+
@size ||= memory / 2
|
54
|
+
load_runcom(rcpath)
|
55
|
+
|
56
|
+
|
57
|
+
ramdisk = Ramdisk.new(mountpoint)
|
58
|
+
|
59
|
+
puts "Allocating ramdisk size: #{@size / 1073741824} GB "
|
60
|
+
if( !ramdisk.allocate(@size) )
|
61
|
+
puts "Allocation failed. Size: #{@size} bytes"
|
62
|
+
exit
|
63
|
+
end
|
64
|
+
if( !ramdisk.format(diskname, :hfs) )
|
65
|
+
puts "Failed to format disk."
|
66
|
+
exit
|
67
|
+
end
|
68
|
+
if( !ramdisk.mount )
|
69
|
+
puts "Failed to mount at #{mountpoint}"
|
70
|
+
ramdisk.deallocate
|
71
|
+
exit
|
72
|
+
end
|
73
|
+
|
74
|
+
|
75
|
+
copy_folders if valid_paths?
|
76
|
+
|
77
|
+
puts "RAM disk mounted at #{mountpoint}"
|
78
|
+
|
79
|
+
#FIX: Not compatible with Windows:
|
80
|
+
|
81
|
+
|
82
|
+
|
83
|
+
|
84
|
+
fork do
|
85
|
+
puts "ramdev_sync pid #{Process.pid}"
|
86
|
+
|
87
|
+
@store.transaction do |s|
|
88
|
+
s["pid"] = Process.pid
|
89
|
+
end
|
90
|
+
|
91
|
+
trap("QUIT") do
|
92
|
+
puts "Interrupted by signal, ramdev_sync will stop now."
|
93
|
+
exit
|
94
|
+
end
|
95
|
+
|
96
|
+
watcher = RamDevSync.new(File.open(rcpath))
|
97
|
+
watcher.listen
|
98
|
+
puts "ramdev_sync listening..."
|
99
|
+
sleep
|
100
|
+
end
|
101
|
+
|
102
|
+
end
|
103
|
+
|
104
|
+
def load_runcom(rcfile)
|
105
|
+
|
106
|
+
return if @loaded == true
|
107
|
+
rc = YAML.load(File.open(rcfile))
|
108
|
+
if rc.nil?
|
109
|
+
@mountpoint = "/ramdev"
|
110
|
+
@diskname = "ramdev"
|
111
|
+
@paths ||= []
|
112
|
+
@paths.push({ source: Dir.pwd, destination: "" })
|
113
|
+
else
|
114
|
+
@mountpoint = rc["ramdisk"]["mountpoint"]
|
115
|
+
@diskname = rc["ramdisk"]["name"]
|
116
|
+
# TODO: Get size of paths and create default ramdisk size based it (2x)
|
117
|
+
@paths = rc["ramdisk"]["paths"]
|
118
|
+
@size ||= rc["ramdisk"]["size"] if rc["ramdisk"]["size"]
|
119
|
+
@loaded = true
|
120
|
+
end
|
121
|
+
|
122
|
+
end
|
123
|
+
|
124
|
+
def valid_paths?
|
125
|
+
@paths.each do |p|
|
126
|
+
src = p["source"].gsub(/\/+$/,"")
|
127
|
+
if File.exist?("#{src}#{@backupSuffix}")
|
128
|
+
puts "A backup already exists for: '#{src}' at: '#{src}#{@backupSuffix}'"
|
129
|
+
return false
|
130
|
+
end
|
131
|
+
end
|
132
|
+
return true
|
133
|
+
end
|
134
|
+
|
135
|
+
def restore_folders
|
136
|
+
@paths.each do |p|
|
137
|
+
src = p["source"].gsub(/\/+$/,"")
|
138
|
+
|
139
|
+
if !File.exists? src+@backupSuffix || !File.symlink?(src)
|
140
|
+
puts "Referenced files don't appear to be linked properly. "
|
141
|
+
return false
|
142
|
+
end
|
143
|
+
end
|
144
|
+
|
145
|
+
@paths.each do |p|
|
146
|
+
src = p["source"].gsub(/\/+$/,"")
|
147
|
+
FileUtils.safe_unlink src
|
148
|
+
FileUtils.move(src+@backupSuffix, src)
|
149
|
+
end
|
150
|
+
true
|
151
|
+
end
|
152
|
+
|
153
|
+
def copy_folders
|
154
|
+
@paths.each do |p|
|
155
|
+
src = p["source"].gsub(/\/+$/,"")
|
156
|
+
next if src.nil? || src.length < 1
|
157
|
+
des = p["destination"].gsub(/\/+$/,"").gsub(/^\/+/,"")
|
158
|
+
name = src.match(/([^\/\\]+)$/)[1]
|
159
|
+
if des.length > 0
|
160
|
+
des = mountpoint+"/#{des}"
|
161
|
+
des = des.gsub(/\/{2,}/,"/")
|
162
|
+
else
|
163
|
+
des = mountpoint
|
164
|
+
end
|
165
|
+
des = File.absolute_path(des)
|
166
|
+
print "Copying #{src}...\n"
|
167
|
+
FileUtils.mkdir_p(des) unless File.exist?(des)
|
168
|
+
IO.popen("rsync --progress -ra #{src} #{des}") do |rsync_io|
|
169
|
+
until rsync_io.eof?
|
170
|
+
line = rsync_io.readline
|
171
|
+
line = line.gsub("\n","")
|
172
|
+
next unless line =~ /to-check/
|
173
|
+
m = line.match(/to-check=([0-9]+)\/([0-9]+)/)
|
174
|
+
scale = (m[1].to_f / m[2].to_f)
|
175
|
+
prog = "#{[9613].pack('U*')}" * ( (1.0 - scale) * 30.0).round
|
176
|
+
|
177
|
+
prog += " " * (scale * 30.0).round
|
178
|
+
print "#{prog}| #{des}/#{name} "
|
179
|
+
print "\r"
|
180
|
+
end
|
181
|
+
end
|
182
|
+
print "\n"
|
183
|
+
|
184
|
+
FileUtils.move(src, src+@backupSuffix)
|
185
|
+
|
186
|
+
puts "Linking: #{name}"
|
187
|
+
|
188
|
+
File.symlink("#{des}/#{name}", src)
|
189
|
+
end
|
190
|
+
end
|
191
|
+
|
192
|
+
end
|
193
|
+
|
194
|
+
|
195
|
+
# require 'etc'
|
196
|
+
# require 'yaml'
|
197
|
+
# require 'fileutils'
|
198
|
+
|
199
|
+
|
200
|
+
#class RamDev
|
201
|
+
#-------
|
202
|
+
# attr_reader :ramDiskSize, :sectors
|
203
|
+
|
204
|
+
# def initialize
|
205
|
+
# @backupSuffix = "_backup_DEV"
|
206
|
+
# @systemInfo = SystemInfo.new
|
207
|
+
# @ramDiskSize = (@systemInfo.memory / 2)
|
208
|
+
# end
|
209
|
+
|
210
|
+
# def build(diskname = "x", mountpoint = "/x", paths = [])
|
211
|
+
# unbuild(diskname, mountpoint, paths)
|
212
|
+
# build = false
|
213
|
+
|
214
|
+
# if @ramDiskSize > 0
|
215
|
+
# @sectors = @ramDiskSize / 512
|
216
|
+
|
217
|
+
# ramdisk = `hdid -nomount ram://#{sectors}`.strip
|
218
|
+
# system "newfs_hfs -v '#{diskname}' #{ramdisk}"
|
219
|
+
# build = system "sudo mount -o noatime -t hfs #{ramdisk} #{mountpoint}"
|
220
|
+
# print "RAM disk mounted at #{mountpoint}\n"
|
221
|
+
|
222
|
+
# if build
|
223
|
+
# paths.each do |p|
|
224
|
+
# print "#{p}\n"
|
225
|
+
# src = p["source"].gsub(/\/+$/,"")
|
226
|
+
# validate(src)
|
227
|
+
# end
|
228
|
+
# paths.each do |p|
|
229
|
+
# src = p["source"].gsub(/\/+$/,"")
|
230
|
+
# next if src.nil? || src.length < 1
|
231
|
+
# des = p["destination"].gsub(/\/+$/,"").gsub(/^\/+/,"")
|
232
|
+
# name = src.match(/([^\/\\]+)$/)[1]
|
233
|
+
# if des.length > 0
|
234
|
+
# des = mountpoint+"/#{des}"
|
235
|
+
# des = des.gsub(/\/{2,}/,"/")
|
236
|
+
# else
|
237
|
+
# des = mountpoint
|
238
|
+
# end
|
239
|
+
# print "Copying #{src}...\n"
|
240
|
+
# FileUtils.mkdir_p(des) if !File.exist?(des)
|
241
|
+
# IO.popen("rsync --progress -ra #{src} #{des}") do |rsync_io|
|
242
|
+
# until rsync_io.eof?
|
243
|
+
# line = rsync_io.readline
|
244
|
+
# line = line.gsub("\n","")
|
245
|
+
# next unless line =~ /to-check/
|
246
|
+
# m = line.match(/to-check=([0-9]+)\/([0-9]+)/)
|
247
|
+
# scale = (m[1].to_f / m[2].to_f)
|
248
|
+
# prog = "#{[9613].pack('U*')}" * ( (1.0 - scale) * 30.0).round
|
249
|
+
|
250
|
+
# prog += " " * (scale * 30.0).round
|
251
|
+
# print "#{prog}| #{des}/#{name} "
|
252
|
+
# print "\r"
|
253
|
+
# end
|
254
|
+
# end
|
255
|
+
# print "\n"
|
256
|
+
|
257
|
+
# FileUtils.move(src, src+@backupSuffix)
|
258
|
+
|
259
|
+
# puts "Linking: #{name}"
|
260
|
+
|
261
|
+
# File.symlink("#{des}/#{name}", src)
|
262
|
+
# end
|
263
|
+
# end
|
264
|
+
# end
|
265
|
+
# end
|
266
|
+
|
267
|
+
# def unbuild(diskname = "x", mountpoint = "/x", paths = [])
|
268
|
+
# paths.each do |p|
|
269
|
+
# print "#{p}\n"
|
270
|
+
# src = p["source"].gsub(/\/+$/,"")
|
271
|
+
# next if src.nil? || src.length < 1
|
272
|
+
# des = p["destination"].gsub(/\/+$/,"").gsub(/^\/+/,"")
|
273
|
+
# name = src.match(/([^\/\\]+)$/)[1]
|
274
|
+
|
275
|
+
# if File.exists? src+@backupSuffix
|
276
|
+
# FileUtils.safe_unlink src if File.symlink?(src)
|
277
|
+
# if File.exist?(src)
|
278
|
+
# print "Conflict between #{src} and #{src+@backupSuffix}"
|
279
|
+
# next
|
280
|
+
# end
|
281
|
+
# FileUtils.move(src+@backupSuffix, src)
|
282
|
+
# end
|
283
|
+
# end
|
284
|
+
|
285
|
+
# unmount = `diskutil unmount force #{mountpoint}`
|
286
|
+
# if unmount =~ /Volume .* on (.*) unmounted/
|
287
|
+
# m = unmount.match(/Volume .* on (.*) unmounted/)
|
288
|
+
# system "hdiutil detach /dev/#{m[1]}"
|
289
|
+
# else
|
290
|
+
# print unmount
|
291
|
+
# end
|
292
|
+
# end
|
293
|
+
|
294
|
+
# private
|
295
|
+
|
296
|
+
# def validate(src)
|
297
|
+
# if File.exist?("#{src}#{@backupSuffix}")
|
298
|
+
# abort "Stopping for safety. A backup already exists for: '#{src}' at: '#{src}#{@backupSuffix}'"
|
299
|
+
# end
|
300
|
+
# end
|
301
|
+
|
302
|
+
#end
|
303
|
+
|
304
|
+
|
305
|
+
# if opts.ram?
|
306
|
+
# print "Building RAM disk"
|
307
|
+
# rd = RamDev.new opts[:ram]
|
308
|
+
# rd.build(rc["ramdisk"]["name"],rc["ramdisk"]["mountpoint"],rc["ramdisk"]["paths"])
|
309
|
+
# elsif opts.fix?
|
310
|
+
# print "fixing links"
|
311
|
+
# rd = RamDev.new opts[:ram]
|
312
|
+
# rd.unbuild(rc["ramdisk"]["name"],rc["ramdisk"]["mountpoint"],rc["ramdisk"]["paths"])
|
313
|
+
# end
|
314
|
+
|
315
|
+
|
316
|
+
# def getrc
|
317
|
+
# si = SystemInfo.new
|
318
|
+
# si.loadOrCreateRC
|
319
|
+
# end
|
320
|
+
|
321
|
+
# def build_ramdisk
|
322
|
+
# rc = getrc
|
323
|
+
# rd = RamDev.new #options?
|
324
|
+
# rd.build(rc["ramdisk"]["name"],rc["ramdisk"]["mountpoint"],rc["ramdisk"]["paths"])
|
325
|
+
# end
|
326
|
+
|
327
|
+
# def teardown_ramdisk
|
328
|
+
# rc = getrc
|
329
|
+
# rd = RamDev.new #options?
|
330
|
+
# rd.unbuild(rc["ramdisk"]["name"],rc["ramdisk"]["mountpoint"],rc["ramdisk"]["paths"])
|
331
|
+
# end
|
332
|
+
|
333
|
+
# -------------------
|
334
|
+
|
335
|
+
#require 'main'
|
336
|
+
|
337
|
+
# Main do
|
338
|
+
# mode 'up' do
|
339
|
+
# def run
|
340
|
+
# puts 'building RAMDISK...'
|
341
|
+
# build_ramdisk
|
342
|
+
# end
|
343
|
+
# end
|
344
|
+
|
345
|
+
# mode 'down' do
|
346
|
+
# def run
|
347
|
+
# puts 'tearing down RAMDISK...'
|
348
|
+
# teardown_ramdisk
|
349
|
+
# end
|
350
|
+
# end
|
351
|
+
|
352
|
+
# mode 'aws' do
|
353
|
+
# def run
|
354
|
+
# puts 'do something with AWS...'
|
355
|
+
# end
|
356
|
+
# end
|
357
|
+
|
358
|
+
# def run()
|
359
|
+
# puts 'doing something different'
|
360
|
+
# end
|
361
|
+
# end
|
362
|
+
# class SystemInfo
|
363
|
+
|
364
|
+
# def memory
|
365
|
+
# if @memory.nil?
|
366
|
+
# r = `/usr/sbin/system_profiler SPHardwareDataType`.split("\n").collect { |s| s == "" ? nil : s.strip }.compact
|
367
|
+
# r = r.collect { |s| s.split(":").collect { |ss| ss.strip }}
|
368
|
+
# memstring = ""
|
369
|
+
# r.each do |i|
|
370
|
+
# memstring = i[1] if i[0] == "Memory"
|
371
|
+
# end
|
372
|
+
# @memory = memstring.match(/([0-9]+) GB/)[1].to_i * 1073741824
|
373
|
+
# end
|
374
|
+
# @memory
|
375
|
+
# end
|
376
|
+
|
377
|
+
# def home
|
378
|
+
# @home ||= Dir.home(user)
|
379
|
+
# end
|
380
|
+
|
381
|
+
# def user
|
382
|
+
# @user ||= Etc.getlogin
|
383
|
+
# end
|
384
|
+
|
385
|
+
# def loadOrCreateRC
|
386
|
+
# rcpath = "#{home}/.devrc"
|
387
|
+
# unless File.exist? rcpath
|
388
|
+
# File.open(rcpath, "w") do |f|
|
389
|
+
# f.puts '# This is a yaml format file with settings for "dev".'
|
390
|
+
# f.puts '# See dev -h for more information.'
|
391
|
+
# end
|
392
|
+
# end
|
393
|
+
# puts "Loading devrc: #{rcpath}"
|
394
|
+
# YAML.load_file rcpath
|
395
|
+
# end
|
396
|
+
|
397
|
+
# end
|
data/lib/ramdev_sync.rb
ADDED
@@ -0,0 +1,87 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'listen'
|
4
|
+
require 'yaml'
|
5
|
+
# require 'pstore'
|
6
|
+
# store = PStore.new("ramdev_sync.pstore")
|
7
|
+
|
8
|
+
class RamDevSync
|
9
|
+
attr_reader :paths, :listener
|
10
|
+
|
11
|
+
def initialize(rcpath, sufix = "_ramdev")
|
12
|
+
@backupSuffix = sufix
|
13
|
+
load_runcom(rcpath)
|
14
|
+
|
15
|
+
# store.transaction do |s|
|
16
|
+
# end
|
17
|
+
end
|
18
|
+
|
19
|
+
#FIX: This is *almost* duplicated from ramdev.rb:
|
20
|
+
def load_runcom(rcpath)
|
21
|
+
|
22
|
+
return if @loaded == true
|
23
|
+
|
24
|
+
rc = YAML.load(rcpath)
|
25
|
+
if rc.nil?
|
26
|
+
@mountpoint = "/ramdev"
|
27
|
+
@diskname = "ramdev"
|
28
|
+
@paths = []
|
29
|
+
|
30
|
+
for pathset in rc["ramdisk"]["paths"] do
|
31
|
+
@paths.push([Dir.pwd, "#{@mountpoint}"])
|
32
|
+
end
|
33
|
+
else
|
34
|
+
@mountpoint = rc["ramdisk"]["mountpoint"]
|
35
|
+
@diskname = rc["ramdisk"]["name"]
|
36
|
+
@paths = []
|
37
|
+
# TODO: Get size of paths and create default ramdisk size (x2)
|
38
|
+
for pathset in rc["ramdisk"]["paths"] do
|
39
|
+
@paths.push([pathset["source"], "#{@mountpoint}/#{pathset['destination']}"])
|
40
|
+
end
|
41
|
+
|
42
|
+
@loaded = true
|
43
|
+
|
44
|
+
end
|
45
|
+
puts "ramdev_sync configured for: #{@mountpoint}"
|
46
|
+
end
|
47
|
+
|
48
|
+
def running?
|
49
|
+
return true if !@listener.nil? && @listener.listen?
|
50
|
+
return false
|
51
|
+
end
|
52
|
+
|
53
|
+
def watchpaths
|
54
|
+
return @paths.collect do |i|
|
55
|
+
# path being watched
|
56
|
+
["#{i[1]}/#{i[0][/([^\/]*)\/*$/,1]}".gsub(/\/{2,}/,"/"),
|
57
|
+
# origin path to sync to
|
58
|
+
"#{i[0][/(.*[^\/]+)\/*$/,1]}#{@backupSuffix}".gsub(/\/{2,}/,"/")]
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
def listen
|
63
|
+
@listener = Listen.to watchpaths.collect { |i| i[0]} do |modified, added, removed|
|
64
|
+
rsync [modified,added,removed]
|
65
|
+
end
|
66
|
+
@listener.start # not blocking
|
67
|
+
end
|
68
|
+
|
69
|
+
def rsync(change_list)
|
70
|
+
list = change_list.flatten
|
71
|
+
for wp in watchpaths
|
72
|
+
list.each do |i|
|
73
|
+
if i.include? wp[0]
|
74
|
+
system("date >> /tmp/ramdev_sync_#{Process.pid}.log")
|
75
|
+
system("rsync -a --delete -v --stats \"#{wp[0]}/\" \"#{wp[1]}/\" >> /tmp/ramdev_sync_#{Process.pid}.log" )
|
76
|
+
break
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
end
|
82
|
+
|
83
|
+
def remove_log
|
84
|
+
File.delete("/tmp/ramdev_sync_#{Process.pid}.log")
|
85
|
+
end
|
86
|
+
|
87
|
+
end
|
data/lib/ramdisk.rb
ADDED
@@ -0,0 +1,173 @@
|
|
1
|
+
require 'plist'
|
2
|
+
|
3
|
+
class SystemInfo
|
4
|
+
|
5
|
+
def self.hdiutil(sectors)
|
6
|
+
`hdiutil attach -nomount ram://#{sectors}`
|
7
|
+
end
|
8
|
+
|
9
|
+
def self.newfs_hfs(diskname, ramdisk)
|
10
|
+
`newfs_hfs -v '#{diskname}' #{ramdisk}`
|
11
|
+
end
|
12
|
+
|
13
|
+
def self.mount(mountpoint, ramdisk)
|
14
|
+
system("mount -o noatime -t hfs #{ramdisk} #{mountpoint}")
|
15
|
+
end
|
16
|
+
|
17
|
+
def self.sudomount(mountpoint, ramdisk)
|
18
|
+
system("sudo mount -o noatime -t hfs #{ramdisk} #{mountpoint}")
|
19
|
+
end
|
20
|
+
|
21
|
+
def self.unmount(mountpoint)
|
22
|
+
system("umount -f #{mountpoint}")
|
23
|
+
end
|
24
|
+
|
25
|
+
def self.sudounmount(mountpoint, ramdisk)
|
26
|
+
system("sudo hdiutil eject -force #{mountpoint}")
|
27
|
+
end
|
28
|
+
|
29
|
+
def self.deallocate(ramdisk)
|
30
|
+
raise "Deallocate called with nil device." if ramdisk.nil?
|
31
|
+
`hdiutil detach #{ramdisk}`
|
32
|
+
device = ramdisk[/\/*([^\/]*)$/,1]
|
33
|
+
return "\"#{device}\" unmounted.\n\"#{device}\" ejected.\n"
|
34
|
+
end
|
35
|
+
|
36
|
+
def self.read_hdutil
|
37
|
+
plist = Plist::parse_xml(`hdiutil info -plist`)
|
38
|
+
|
39
|
+
diskImages = []
|
40
|
+
plist.each do |n|
|
41
|
+
diskImages.concat n[1] if n[0] == "images"
|
42
|
+
end
|
43
|
+
|
44
|
+
response = []
|
45
|
+
diskImages.each do |i|
|
46
|
+
if i["image-path"] =~ /^ram\:\/\//
|
47
|
+
response.push([i["system-entities"][0]["dev-entry"], i["system-entities"][0]["mount-point"]])
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
response
|
52
|
+
end
|
53
|
+
|
54
|
+
|
55
|
+
def self.ramdisks
|
56
|
+
# cannot be ||= because state may have changed.
|
57
|
+
@@ramdisks = read_hdutil
|
58
|
+
end
|
59
|
+
|
60
|
+
end
|
61
|
+
|
62
|
+
|
63
|
+
# class that represents all information associated with a ram disk
|
64
|
+
class Ramdisk
|
65
|
+
|
66
|
+
attr_accessor :system_interface, :mountpoint, :size, :name, :ramdisk
|
67
|
+
|
68
|
+
def initialize(mountpoint, system_interface = SystemInfo)
|
69
|
+
self.mountpoint = mountpoint
|
70
|
+
self.system_interface = system_interface
|
71
|
+
end
|
72
|
+
|
73
|
+
def unmounted=(m)
|
74
|
+
@unmounted = m
|
75
|
+
end
|
76
|
+
|
77
|
+
def unmounted
|
78
|
+
@unmounted ||= []
|
79
|
+
end
|
80
|
+
|
81
|
+
def mounted?
|
82
|
+
list.each do |i|
|
83
|
+
return true if i[1] =~ /#{mountpoint}$/
|
84
|
+
end
|
85
|
+
return false
|
86
|
+
end
|
87
|
+
|
88
|
+
def list
|
89
|
+
# cannot be ||= because state may have changed.
|
90
|
+
@list = system_interface.ramdisks
|
91
|
+
end
|
92
|
+
|
93
|
+
def ramdisk=(device)
|
94
|
+
@ramdisk = device
|
95
|
+
end
|
96
|
+
|
97
|
+
def ramdisk
|
98
|
+
return @ramdisk if !@ramdisk.nil?
|
99
|
+
list.each do |i|
|
100
|
+
if i[1] =~ /#{mountpoint}$/
|
101
|
+
@ramdisk = i[0]
|
102
|
+
break
|
103
|
+
end
|
104
|
+
end
|
105
|
+
@ramdisk
|
106
|
+
end
|
107
|
+
|
108
|
+
def allocate(size)
|
109
|
+
sectors = size / 512
|
110
|
+
self.ramdisk = system_interface.hdiutil(sectors).strip
|
111
|
+
end
|
112
|
+
|
113
|
+
def deallocate
|
114
|
+
unmounted.each do |u|
|
115
|
+
msg = system_interface.deallocate(u)
|
116
|
+
if !msg =~ /.*unmounted\./
|
117
|
+
raise "ramdisk: #{u} failed to deallocate ramdisk with this message: #{msg}"
|
118
|
+
end
|
119
|
+
end
|
120
|
+
unmounted = []
|
121
|
+
return true
|
122
|
+
end
|
123
|
+
|
124
|
+
def format(drivename = "ramdev", fileSystemFormat = :hfs)
|
125
|
+
self.name = drivename
|
126
|
+
case fileSystemFormat
|
127
|
+
when :hfs
|
128
|
+
msg = system_interface.newfs_hfs(name,ramdisk)
|
129
|
+
if msg =~ /Initialized .*#{ramdisk[/\/*([^\/]*)$/,1]} as a/
|
130
|
+
return true
|
131
|
+
else
|
132
|
+
raise "ramdisk failed to format HFS volume #{ramdisk}"
|
133
|
+
end
|
134
|
+
else
|
135
|
+
raise "ramdisk doesn't understand how to build #{fileSystemFormat} file system"
|
136
|
+
end
|
137
|
+
return flase
|
138
|
+
end
|
139
|
+
|
140
|
+
def mount
|
141
|
+
if system_interface.mount(mountpoint, ramdisk)
|
142
|
+
return true
|
143
|
+
else
|
144
|
+
puts "Unable to mount, trying again with 'sudo'"
|
145
|
+
if system_interface.sudomount(mountpoint, ramdisk)
|
146
|
+
return true
|
147
|
+
else
|
148
|
+
puts "ramdisk failed to mount"
|
149
|
+
return false
|
150
|
+
end
|
151
|
+
end
|
152
|
+
end
|
153
|
+
|
154
|
+
def unmount
|
155
|
+
unmounted_device = ramdisk
|
156
|
+
if system_interface.unmount(mountpoint)
|
157
|
+
unmounted.push(unmounted_device)
|
158
|
+
return true
|
159
|
+
else
|
160
|
+
puts "Unable to unmount, trying again with 'sudo'."
|
161
|
+
if system_interface.sudounmount(mountpoint, unmounted_device)
|
162
|
+
return true
|
163
|
+
else
|
164
|
+
puts "ramdisk failed to un-mount."
|
165
|
+
return false
|
166
|
+
end
|
167
|
+
end
|
168
|
+
end
|
169
|
+
|
170
|
+
# def unmount(mountpoint)
|
171
|
+
# end
|
172
|
+
end
|
173
|
+
|
metadata
ADDED
@@ -0,0 +1,94 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: ramdev
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Joshua Kolden
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2013-12-26 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: listen
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ~>
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '2.0'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ~>
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '2.0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: main
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - '>='
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0.0'
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - '>='
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0.0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: plist
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - '>='
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: 3.1.0
|
48
|
+
type: :runtime
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - '>='
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: 3.1.0
|
55
|
+
description: A management tool for creating a ramdrive and syncing folders back to
|
56
|
+
the hard drive automatically while you work.
|
57
|
+
email:
|
58
|
+
- joshua@crackcreative.com
|
59
|
+
executables:
|
60
|
+
- ramdev
|
61
|
+
- ramdev_sync
|
62
|
+
extensions: []
|
63
|
+
extra_rdoc_files: []
|
64
|
+
files:
|
65
|
+
- lib/ramdev.rb
|
66
|
+
- lib/ramdev_sync.rb
|
67
|
+
- lib/ramdisk.rb
|
68
|
+
- bin/ramdev
|
69
|
+
- bin/ramdev_sync
|
70
|
+
homepage: https://github.com/JoshuaKolden/RamDev
|
71
|
+
licenses:
|
72
|
+
- MIT
|
73
|
+
metadata: {}
|
74
|
+
post_install_message:
|
75
|
+
rdoc_options: []
|
76
|
+
require_paths:
|
77
|
+
- lib
|
78
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - '>='
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '0'
|
83
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
84
|
+
requirements:
|
85
|
+
- - '>='
|
86
|
+
- !ruby/object:Gem::Version
|
87
|
+
version: '0'
|
88
|
+
requirements: []
|
89
|
+
rubyforge_project:
|
90
|
+
rubygems_version: 2.1.11
|
91
|
+
signing_key:
|
92
|
+
specification_version: 4
|
93
|
+
summary: Work in ram for ultra high performance.
|
94
|
+
test_files: []
|