cache_tree 0.0.0

Sign up to get free protection for your applications and to get access to all the features.
data/.document ADDED
@@ -0,0 +1,5 @@
1
+ lib/**/*.rb
2
+ bin/*
3
+ -
4
+ features/**/*.feature
5
+ LICENSE.txt
data/Gemfile ADDED
@@ -0,0 +1,17 @@
1
+ source "http://rubygems.org"
2
+ # Add dependencies required to use your gem here.
3
+ # Example:
4
+ # gem "activesupport", ">= 2.3.5"
5
+
6
+ # Add dependencies to develop your gem here.
7
+ # Include everything needed to run rake, tests, features, etc.
8
+ group :development do
9
+ gem "shoulda", ">= 0"
10
+ gem "rdoc", "~> 3.12"
11
+ gem "bundler", "~> 1.0.0"
12
+ gem "jeweler", "~> 1.8.3"
13
+ gem "rcov", ">= 0"
14
+ end
15
+
16
+ gem 'isna'
17
+ gem 'tree_node'
data/LICENSE.txt ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2012 kazuyoshi tlacaelel
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.rdoc ADDED
@@ -0,0 +1,28 @@
1
+ = cache_tree
2
+
3
+ Btree based cache
4
+
5
+ == Contributing to cache_tree
6
+
7
+ require 'rubygems'
8
+ require 'cache_tree'
9
+
10
+ class Record
11
+ def id
12
+ 1
13
+ end
14
+ end
15
+
16
+ CacheTree::Node.directory = 'cache_tree'
17
+ record = CacheTree::Node.new(Record.new)
18
+ CacheTree::Manager.instance.use(record)
19
+ unless CacheTree::Manager.instance.exists?
20
+ CacheTree::Manager.instance.save('data')
21
+ end
22
+ puts CacheTree::Manager.instance.read
23
+
24
+ == Copyright
25
+
26
+ Copyright (c) 2012 kazuyoshi tlacaelel. See LICENSE.txt for
27
+ further details.
28
+
data/Rakefile ADDED
@@ -0,0 +1,53 @@
1
+ # encoding: utf-8
2
+
3
+ require 'rubygems'
4
+ require 'bundler'
5
+ begin
6
+ Bundler.setup(:default, :development)
7
+ rescue Bundler::BundlerError => e
8
+ $stderr.puts e.message
9
+ $stderr.puts "Run `bundle install` to install missing gems"
10
+ exit e.status_code
11
+ end
12
+ require 'rake'
13
+
14
+ require 'jeweler'
15
+ Jeweler::Tasks.new do |gem|
16
+ # gem is a Gem::Specification... see http://docs.rubygems.org/read/chapter/20 for more options
17
+ gem.name = "cache_tree"
18
+ gem.homepage = "http://github.com/ktlacaelel/cache_tree"
19
+ gem.license = "MIT"
20
+ gem.summary = %Q{Simple cache tree}
21
+ gem.description = %Q{Cache based on btrees, for large ammounts of cache.}
22
+ gem.email = "kazu.dev@gmail.com"
23
+ gem.authors = ["kazuyoshi tlacaelel"]
24
+ # dependencies defined in Gemfile
25
+ end
26
+ Jeweler::RubygemsDotOrgTasks.new
27
+
28
+ require 'rake/testtask'
29
+ Rake::TestTask.new(:test) do |test|
30
+ test.libs << 'lib' << 'test'
31
+ test.pattern = 'test/**/test_*.rb'
32
+ test.verbose = true
33
+ end
34
+
35
+ require 'rcov/rcovtask'
36
+ Rcov::RcovTask.new do |test|
37
+ test.libs << 'test'
38
+ test.pattern = 'test/**/test_*.rb'
39
+ test.verbose = true
40
+ test.rcov_opts << '--exclude "gems/*"'
41
+ end
42
+
43
+ task :default => :test
44
+
45
+ require 'rdoc/task'
46
+ Rake::RDocTask.new do |rdoc|
47
+ version = File.exist?('VERSION') ? File.read('VERSION') : ""
48
+
49
+ rdoc.rdoc_dir = 'rdoc'
50
+ rdoc.title = "cache_tree #{version}"
51
+ rdoc.rdoc_files.include('README*')
52
+ rdoc.rdoc_files.include('lib/**/*.rb')
53
+ end
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.0.0
data/lib/cache_tree.rb ADDED
@@ -0,0 +1,155 @@
1
+ require 'md5'
2
+ require 'singleton'
3
+ require 'fileutils'
4
+ require 'isna'
5
+ require 'tree_node'
6
+
7
+ module CacheTree
8
+
9
+ class Manager
10
+
11
+ include Singleton
12
+
13
+ def initialize
14
+ @current_link = nil
15
+ @configuration = { :perform_caching => true }
16
+ end
17
+
18
+ def configure(options)
19
+ @configuration.merge(options)
20
+ end
21
+
22
+ def use(cache_link)
23
+ @current_link = cache_link
24
+ end
25
+
26
+ def exists?
27
+ return false unless @configuration[:perform_caching]
28
+ btree_key_files = @current_link.map(:up) { |node| node.btree_key }
29
+ return false unless btree_key_files.all? { |btree_key| File.exists?(btree_key) }
30
+ @current_link.map(:up) { |node| node.load_btree_key }
31
+ File.exists?(@current_link.cache_file)
32
+ end
33
+
34
+ def expire!
35
+ @current_link.expire
36
+ end
37
+
38
+ def read
39
+ @current_link.map(:up) { |node| node.load_btree_key }
40
+ File.read(@current_link.cache_file)
41
+ end
42
+
43
+ def save(data)
44
+ @current_link.map(:up) { |node| node.save }
45
+ FileUtils.mkdir_p(File.dirname(@current_link.cache_file))
46
+ File.open(@current_link.cache_file, 'w+') { |file| file.write data }
47
+ end
48
+
49
+ end
50
+
51
+ class Node
52
+
53
+ class << self
54
+ attr_accessor :directory
55
+ end
56
+
57
+ SEPARATOR = '/'
58
+
59
+ attr_accessor :name, :value, :stamp
60
+
61
+ include Tree::Node
62
+
63
+ def initialize(target)
64
+ @name = target.class.name.gsub(/([A-Z])/) { "_#{$1}" }.gsub(/^./, '').downcase
65
+ @value = target.id
66
+ @stamp = generate_stamp
67
+ end
68
+
69
+ def directory
70
+ self.class.directory
71
+ end
72
+
73
+ def generate_stamp
74
+ (Time.now.to_f * 1.0).to_s + '-' + Kernel.rand(1000000).to_s
75
+ end
76
+
77
+ # Path of the cache node
78
+ def path
79
+ "#{name}#{SEPARATOR}#{value}#{SEPARATOR}"
80
+ end
81
+
82
+ # Resolves final name for btree_key file.
83
+ def btree_key
84
+ directory + SEPARATOR + (map(:up) { |node| node.path } * '') + 'btree.key'
85
+ end
86
+
87
+ # Updates current node stamp from btree_key
88
+ def load_btree_key
89
+ @stamp = eval(File.read(btree_key))
90
+ end
91
+
92
+ # Sums up all stamps and generates a checksum.
93
+ def checksum
94
+ MD5.hexdigest(map(:up) { |node| node.stamp } * '')
95
+ end
96
+
97
+ # Resolves final name for cache file.
98
+ def cache_file
99
+ directory + SEPARATOR + (map(:up) { |node| node.path } * '') + checksum + '.cache'
100
+ end
101
+
102
+ # Writes node stamp from to btree_key file
103
+ def save
104
+ FileUtils.mkdir_p File.dirname(btree_key)
105
+ File.open(btree_key, 'w+') { |file| file.write stamp.inspect }
106
+ end
107
+
108
+ # Quickly expire a whole cache-tree or a single node.
109
+ # Expiring a node in the middle will automatically expire all
110
+ # children nodes. no need to expire each one individually.
111
+ def expire
112
+ @stamp = generate_stamp
113
+ save
114
+ end
115
+
116
+ # Cleans up expired cache files for a specific node.
117
+ #
118
+ # You need to be specific the engine will not walk down the tree
119
+ # for you to prevent iterating through large trees.
120
+ #
121
+ # @return [Array] of items that were deleted.
122
+ def clean
123
+ diagnose[:dead].each { |file| FileUtils.rm file }
124
+ end
125
+
126
+ # Runs an analysis on a given node and returns its status.
127
+ #
128
+ # @return [Hash] with detailed diagnosis of curret status for that
129
+ # node's cache
130
+ def diagnose
131
+ file_alive = cache_file
132
+ base = File.basename(file_alive)
133
+ dir = File.dirname(file_alive)
134
+ diagnostic = {}
135
+ diagnostic[:btree_key] = btree_key
136
+ diagnostic[:alive] = file_alive
137
+ diagnostic[:dead] = []
138
+ Dir["#{dir}/*.cache"].each do |cached_file|
139
+ next if File.basename(cached_file) == base
140
+ diagnostic[:dead] << cached_file
141
+ end
142
+ diagnostic
143
+ end
144
+
145
+ # Prints out active cache in green, and expired files in red.
146
+ def debug
147
+ puts cache_file.to_ansi.green
148
+ diagnose[:dead].each { |file| puts file.to_ansi.red }
149
+ nil
150
+ end
151
+
152
+ end
153
+
154
+ end
155
+
data/test/helper.rb ADDED
@@ -0,0 +1,18 @@
1
+ require 'rubygems'
2
+ require 'bundler'
3
+ begin
4
+ Bundler.setup(:default, :development)
5
+ rescue Bundler::BundlerError => e
6
+ $stderr.puts e.message
7
+ $stderr.puts "Run `bundle install` to install missing gems"
8
+ exit e.status_code
9
+ end
10
+ require 'test/unit'
11
+ require 'shoulda'
12
+
13
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
14
+ $LOAD_PATH.unshift(File.dirname(__FILE__))
15
+ require 'cache_tree'
16
+
17
+ class Test::Unit::TestCase
18
+ end
@@ -0,0 +1,7 @@
1
+ require 'helper'
2
+
3
+ class TestCacheTree < Test::Unit::TestCase
4
+ should "probably rename this file and start testing for real" do
5
+ flunk "hey buddy, you should probably rename this file and start testing for real"
6
+ end
7
+ end
metadata ADDED
@@ -0,0 +1,178 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: cache_tree
3
+ version: !ruby/object:Gem::Version
4
+ hash: 31
5
+ prerelease: false
6
+ segments:
7
+ - 0
8
+ - 0
9
+ - 0
10
+ version: 0.0.0
11
+ platform: ruby
12
+ authors:
13
+ - kazuyoshi tlacaelel
14
+ autorequire:
15
+ bindir: bin
16
+ cert_chain: []
17
+
18
+ date: 2012-11-01 00:00:00 -06:00
19
+ default_executable:
20
+ dependencies:
21
+ - !ruby/object:Gem::Dependency
22
+ type: :runtime
23
+ prerelease: false
24
+ name: isna
25
+ version_requirements: &id001 !ruby/object:Gem::Requirement
26
+ none: false
27
+ requirements:
28
+ - - ">="
29
+ - !ruby/object:Gem::Version
30
+ hash: 3
31
+ segments:
32
+ - 0
33
+ version: "0"
34
+ requirement: *id001
35
+ - !ruby/object:Gem::Dependency
36
+ type: :runtime
37
+ prerelease: false
38
+ name: tree_node
39
+ version_requirements: &id002 !ruby/object:Gem::Requirement
40
+ none: false
41
+ requirements:
42
+ - - ">="
43
+ - !ruby/object:Gem::Version
44
+ hash: 3
45
+ segments:
46
+ - 0
47
+ version: "0"
48
+ requirement: *id002
49
+ - !ruby/object:Gem::Dependency
50
+ type: :development
51
+ prerelease: false
52
+ name: shoulda
53
+ version_requirements: &id003 !ruby/object:Gem::Requirement
54
+ none: false
55
+ requirements:
56
+ - - ">="
57
+ - !ruby/object:Gem::Version
58
+ hash: 3
59
+ segments:
60
+ - 0
61
+ version: "0"
62
+ requirement: *id003
63
+ - !ruby/object:Gem::Dependency
64
+ type: :development
65
+ prerelease: false
66
+ name: rdoc
67
+ version_requirements: &id004 !ruby/object:Gem::Requirement
68
+ none: false
69
+ requirements:
70
+ - - ~>
71
+ - !ruby/object:Gem::Version
72
+ hash: 31
73
+ segments:
74
+ - 3
75
+ - 12
76
+ version: "3.12"
77
+ requirement: *id004
78
+ - !ruby/object:Gem::Dependency
79
+ type: :development
80
+ prerelease: false
81
+ name: bundler
82
+ version_requirements: &id005 !ruby/object:Gem::Requirement
83
+ none: false
84
+ requirements:
85
+ - - ~>
86
+ - !ruby/object:Gem::Version
87
+ hash: 23
88
+ segments:
89
+ - 1
90
+ - 0
91
+ - 0
92
+ version: 1.0.0
93
+ requirement: *id005
94
+ - !ruby/object:Gem::Dependency
95
+ type: :development
96
+ prerelease: false
97
+ name: jeweler
98
+ version_requirements: &id006 !ruby/object:Gem::Requirement
99
+ none: false
100
+ requirements:
101
+ - - ~>
102
+ - !ruby/object:Gem::Version
103
+ hash: 49
104
+ segments:
105
+ - 1
106
+ - 8
107
+ - 3
108
+ version: 1.8.3
109
+ requirement: *id006
110
+ - !ruby/object:Gem::Dependency
111
+ type: :development
112
+ prerelease: false
113
+ name: rcov
114
+ version_requirements: &id007 !ruby/object:Gem::Requirement
115
+ none: false
116
+ requirements:
117
+ - - ">="
118
+ - !ruby/object:Gem::Version
119
+ hash: 3
120
+ segments:
121
+ - 0
122
+ version: "0"
123
+ requirement: *id007
124
+ description: Cache based on btrees, for large ammounts of cache.
125
+ email: kazu.dev@gmail.com
126
+ executables: []
127
+
128
+ extensions: []
129
+
130
+ extra_rdoc_files:
131
+ - LICENSE.txt
132
+ - README.rdoc
133
+ files:
134
+ - .document
135
+ - Gemfile
136
+ - LICENSE.txt
137
+ - README.rdoc
138
+ - Rakefile
139
+ - VERSION
140
+ - lib/cache_tree.rb
141
+ - test/helper.rb
142
+ - test/test_cache_tree.rb
143
+ has_rdoc: true
144
+ homepage: http://github.com/ktlacaelel/cache_tree
145
+ licenses:
146
+ - MIT
147
+ post_install_message:
148
+ rdoc_options: []
149
+
150
+ require_paths:
151
+ - lib
152
+ required_ruby_version: !ruby/object:Gem::Requirement
153
+ none: false
154
+ requirements:
155
+ - - ">="
156
+ - !ruby/object:Gem::Version
157
+ hash: 3
158
+ segments:
159
+ - 0
160
+ version: "0"
161
+ required_rubygems_version: !ruby/object:Gem::Requirement
162
+ none: false
163
+ requirements:
164
+ - - ">="
165
+ - !ruby/object:Gem::Version
166
+ hash: 3
167
+ segments:
168
+ - 0
169
+ version: "0"
170
+ requirements: []
171
+
172
+ rubyforge_project:
173
+ rubygems_version: 1.3.7
174
+ signing_key:
175
+ specification_version: 3
176
+ summary: Simple cache tree
177
+ test_files: []
178
+