21200: copied branch from arvados-workbench2 Arvados-DCO-1.1-Signed-off-by: Lisa...
[arvados.git] / sdk / ruby-google-api-client / lib / google / api_client / service / simple_file_store.rb
1 # Copyright 2013 Google Inc.
2 #
3 # Licensed under the Apache License, Version 2.0 (the "License");
4 # you may not use this file except in compliance with the License.
5 # You may obtain a copy of the License at
6 #
7 #      http://www.apache.org/licenses/LICENSE-2.0
8 #
9 # Unless required by applicable law or agreed to in writing, software
10 # distributed under the License is distributed on an "AS IS" BASIS,
11 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 # See the License for the specific language governing permissions and
13 # limitations under the License.
14
15 module Google
16   class APIClient
17     class Service
18
19       # Simple file store to be used in the event no ActiveSupport cache store
20       # is provided. This is not thread-safe, and does not support a number of
21       # features (such as expiration), but it's useful for the simple purpose of
22       # caching discovery documents to disk.
23       # Implements the basic cache methods of ActiveSupport::Cache::Store in a
24       # limited fashion.
25       class SimpleFileStore
26
27         # Creates a new SimpleFileStore.
28         #
29         # @param [String] file_path
30         #   The path to the cache file on disk.
31         # @param [Object] options
32         #   The options to be used with this SimpleFileStore. Not implemented.
33         def initialize(file_path, options = nil)
34           @file_path = file_path.to_s
35         end
36
37         # Returns true if a key exists in the cache.
38         #
39         # @param [String] name
40         #   The name of the key. Will always be converted to a string.
41         # @param [Object] options
42         #   The options to be used with this query. Not implemented.
43         def exist?(name, options = nil)
44           read_file
45           @cache.nil? ? nil : @cache.include?(name.to_s)
46         end
47
48         # Fetches data from the cache and returns it, using the given key.
49         # If the key is missing and no block is passed, returns nil.
50         # If the key is missing and a block is passed, executes the block, sets
51         # the key to its value, and returns it.
52         #
53         # @param [String] name
54         #   The name of the key. Will always be converted to a string.
55         # @param [Object] options
56         #   The options to be used with this query. Not implemented.
57         # @yield [String]
58         #   optional block with the default value if the key is missing
59         def fetch(name, options = nil)
60           read_file
61           if block_given?
62             entry = read(name.to_s, options)
63             if entry.nil?
64               value = yield name.to_s
65               write(name.to_s, value)
66               return value
67             else
68               return entry
69             end
70           else
71             return read(name.to_s, options)
72           end
73         end
74
75         # Fetches data from the cache, using the given key.
76         # Returns nil if the key is missing.
77         #
78         # @param [String] name
79         #   The name of the key. Will always be converted to a string.
80         # @param [Object] options
81         #   The options to be used with this query. Not implemented.
82         def read(name, options = nil)
83           read_file
84           @cache.nil? ? nil : @cache[name.to_s]
85         end
86
87         # Writes the value to the cache, with the key.
88         #
89         # @param [String] name
90         #   The name of the key. Will always be converted to a string.
91         # @param [Object] value
92         #   The value to be written.
93         # @param [Object] options
94         #   The options to be used with this query. Not implemented.
95         def write(name, value, options = nil)
96           read_file
97           @cache = {} if @cache.nil?
98           @cache[name.to_s] = value
99           write_file
100           return nil
101         end
102
103         # Deletes an entry in the cache.
104         # Returns true if an entry is deleted.
105         #
106         # @param [String] name
107         #   The name of the key. Will always be converted to a string.
108         # @param [Object] options
109         #   The options to be used with this query. Not implemented.
110         def delete(name, options = nil)
111           read_file
112           return nil if @cache.nil?
113           if @cache.include? name.to_s
114             @cache.delete name.to_s
115             write_file
116             return true
117           else
118             return nil
119           end
120         end
121
122         protected
123
124         # Read the entire cache file from disk.
125         # Will avoid reading if there have been no changes.
126         def read_file
127           if !File.exist? @file_path
128             @cache = nil
129           else
130             # Check for changes after our last read or write.
131             if @last_change.nil? || File.mtime(@file_path) > @last_change
132               File.open(@file_path) do |file|
133                 @cache = Marshal.load(file)
134                 @last_change = file.mtime
135               end
136             end
137           end
138           return @cache
139         end
140
141         # Write the entire cache contents to disk.
142         def write_file
143           File.open(@file_path, 'w') do |file|
144             Marshal.dump(@cache, file)
145           end
146           @last_change = File.mtime(@file_path)
147         end
148       end
149     end
150   end
151 end