Skip to content

Commit

Permalink
Initial commit
Browse files Browse the repository at this point in the history
  • Loading branch information
wycats committed Feb 12, 2009
0 parents commit 3cbb15d
Show file tree
Hide file tree
Showing 15 changed files with 692 additions and 0 deletions.
20 changes: 20 additions & 0 deletions LICENSE
@@ -0,0 +1,20 @@
Copyright (c) 2009 Yehuda Katz

Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:

The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
4 changes: 4 additions & 0 deletions README
@@ -0,0 +1,4 @@
moneta
======

A gem that provides...
60 changes: 60 additions & 0 deletions Rakefile
@@ -0,0 +1,60 @@
require 'rubygems'
require 'rake/gempackagetask'
require 'rubygems/specification'
require 'spec/rake/spectask'
require 'date'

GEM = "moneta"
GEM_VERSION = "0.5.0"
AUTHOR = "Yehuda Katz"
EMAIL = "wycats@gmail.com"
HOMEPAGE = "http://www.yehudakatz.com"
SUMMARY = "A unified interface to key/value stores"

spec = Gem::Specification.new do |s|
s.name = GEM
s.version = GEM_VERSION
s.platform = Gem::Platform::RUBY
s.has_rdoc = true
s.extra_rdoc_files = ["README", "LICENSE", 'TODO']
s.summary = SUMMARY
s.description = s.summary
s.author = AUTHOR
s.email = EMAIL
s.homepage = HOMEPAGE

# Uncomment this to add a dependency
# s.add_dependency "foo"

s.require_path = 'lib'
s.autorequire = GEM
s.files = %w(LICENSE README Rakefile TODO) + Dir.glob("{lib,specs}/**/*")
end

Rake::GemPackageTask.new(spec) do |pkg|
pkg.gem_spec = spec
end

desc "install the gem locally"
task :install => [:package] do
sh %{sudo gem install pkg/#{GEM}-#{GEM_VERSION}}
end

desc "create a gemspec file"
task :make_spec do
File.open("#{GEM}.gemspec", "w") do |file|
file.puts spec.to_ruby
end
end

desc "Run all examples (or a specific spec with TASK=xxxx)"
Spec::Rake::SpecTask.new('spec') do |t|
t.spec_opts = ["-cfs"]
t.spec_files = begin
if ENV["TASK"]
ENV["TASK"].split(',').map { |task| "spec/**/#{task}_spec.rb" }
else
FileList['spec/**/*_spec.rb']
end
end
end
4 changes: 4 additions & 0 deletions TODO
@@ -0,0 +1,4 @@
TODO:
Fix LICENSE with your name
Fix Rakefile with your name and contact info
Add your code to lib/<%= name %>.rb
50 changes: 50 additions & 0 deletions lib/moneta.rb
@@ -0,0 +1,50 @@
module Moneta
module Expires
def check_expired(key)
if @expiration[key] && Time.now > @expiration[key]
@expiration.delete(key)
self.delete(key)
end
end

def has_key?(key)
check_expired(key)
super
end

def key?(key)
has_key?(key)
end

def [](key)
check_expired(key)
super
end

def fetch(key, default)
check_expired(key)
super
end

def delete(key)
check_expired(key)
super
end

def update_key(key, options)
update_options(key, options)
end

def store(key, value, options = {})
super(key, value)
update_options(key, options)
end

private
def update_options(key, options)
if options[:expires_in]
@expiration[key] = (Time.now + options[:expires_in])
end
end
end
end
107 changes: 107 additions & 0 deletions lib/moneta/datamapper.rb
@@ -0,0 +1,107 @@
begin
gem "dm-core", "0.9.10"
require "dm-core"
rescue LoadError
puts "You need the dm-core gem in order to use the DataMapper moneta store"
exit
end

class MonetaHash
include DataMapper::Resource

def self.default_repository_name
:moneta
end

property :the_key, String, :key => true
property :value, Object, :lazy => false
property :expires, Time

def self.value(key)
obj = self.get(key)
obj && obj.value
end
end

module Moneta
class DataMapper
class Expiration
def initialize(klass)
@klass = klass
end

def [](key)
if obj = get(key)
obj.expires
end
end

def []=(key, value)
obj = get(key)
obj.expires = value
obj.save
end

def delete(key)
obj = get(key)
obj.expires = nil
obj.save
end

private
def get(key)
@klass.get(key)
end
end

def initialize(options = {})
::DataMapper.setup(:moneta, options[:setup])
MonetaHash.auto_upgrade!
@hash = MonetaHash
@expiration = Expiration.new(MonetaHash)
end

module Implementation
def key?(key)
!!@hash.get(key)
end

def has_key?(key)
!!@hash.get(key)
end

def [](key)
@hash.value(key)
end

def []=(key, value)
obj = @hash.get(key)
if obj
obj.update(key, value)
else
@hash.create(:the_key => key, :value => value)
end
end

def fetch(key, default)
self[key] || default
end

def delete(key)
value = self[key]
@hash.all(:the_key => key).destroy!
value
end

def store(key, value, options = {})
self[key] = value
end

def clear
@hash.all.destroy!
end
end
include Implementation
include Expires
end
end
100 changes: 100 additions & 0 deletions lib/moneta/file.rb
@@ -0,0 +1,100 @@
begin
require "fileutils"
require "xattr"
rescue LoadError
puts "You need the xattr gem to use the File moneta store"
exit
end

module Moneta
class File
class Expiration
def initialize(directory)
@directory = directory
end

def [](key)
attrs = xattr(key)
ret = Marshal.load(attrs.get("moneta_expires"))
rescue Errno::ENOENT, SystemCallError
end

def []=(key, value)
attrs = xattr(key)
attrs.set("moneta_expires", Marshal.dump(value))
end

def delete(key)
attrs = xattr(key)
attrs.remove("moneta_expires")
end

private
def xattr(key)
::Xattr.new(::File.join(@directory, key))
end
end

def initialize(options = {})
@directory = options[:path]
if ::File.file?(@directory)
raise StandardError, "The path you supplied #{@directory} is a file"
elsif !::File.exists?(@directory)
FileUtils.mkdir(@directory)
end

@expiration = Expiration.new(@directory)
end

module Implementation
def key?(key)
::File.exist?(path(key))
end

def has_key?(key)
::File.exist?(path(key))
end

def [](key)
if ::File.exist?(path(key))
Marshal.load(::File.read(path(key)))
end
end

def []=(key, value)
::File.open(path(key), "w") do |file|
contents = Marshal.dump(value)
file.puts(contents)
end
end

def fetch(key, default)
self[key] || default
end

def delete(key)
value = self[key]
FileUtils.rm(path(key))
value
rescue Errno::ENOENT
end

def store(key, value, options = {})
self[key] = value
end

def clear
FileUtils.rm_rf(@directory)
FileUtils.mkdir(@directory)
end

private
def path(key)
::File.join(@directory, key)
end
end
include Implementation
include Expires

end
end

0 comments on commit 3cbb15d

Please sign in to comment.