s3fsr 1.7 → 1.8

Sign up to get free protection for your applications and to get access to all the features.
data/bin/s3fsr CHANGED
@@ -16,7 +16,8 @@ if ENV['AWS_ACCESS_KEY_ID'] == nil or ENV['AWS_SECRET_ACCESS_KEY'] == nil
16
16
  end
17
17
 
18
18
  root = BUCKET != nil ? SBucketDir.new(nil, BUCKET) : SBucketsDir.new
19
- s3fsr = MethodLogger.new(S3fsr.new(root))
19
+ s3fsr = S3fsr.new(root)
20
+ # s3fsr = MethodLogger.new(s3fsr)
20
21
  FuseFS.set_root s3fsr
21
22
  FuseFS.mount_under MOUNT #, "allow_other"
22
23
  begin
@@ -303,6 +303,10 @@ module AWS
303
303
  when :deleted then object_cache.delete(object)
304
304
  end
305
305
  end
306
+
307
+ def truncated?
308
+ attributes['is_truncated']
309
+ end
306
310
 
307
311
  private
308
312
  def build_contents!
data/lib/s3fsr.rb CHANGED
@@ -9,13 +9,25 @@ S3SYNC_DIR_ETAG = 'd66759af42f282e1ba19144df2d405d0'
9
9
  S3SYNC_DIR_LENGTH = 38
10
10
  AWS::S3::Base.establish_connection!(:access_key_id => ENV['AWS_ACCESS_KEY_ID'], :secret_access_key => ENV['AWS_SECRET_ACCESS_KEY'])
11
11
 
12
+ # old key split name perf sucked, so optimize with a cached rindex/slice
13
+ def last_part(key)
14
+ last_slash = key.rindex('/', -2)
15
+ drop = key.end_with?('/') ? 1 : 0
16
+ if last_slash then
17
+ key.slice(last_slash + 1, key.length - last_slash - 1 - drop)
18
+ else
19
+ key.slice(0, key.length - drop)
20
+ end
21
+ end
22
+
12
23
  class SFile
13
24
  def initialize(parent, s3obj)
14
25
  @parent = parent
15
26
  @s3obj = s3obj
27
+ @name = last_part(@s3obj.key)
16
28
  end
17
29
  def name
18
- @s3obj.key.split('/')[-1]
30
+ @name
19
31
  end
20
32
  def is_directory?
21
33
  false
@@ -51,25 +63,27 @@ class SBaseDir
51
63
  true
52
64
  end
53
65
  def content_deleted name
54
- get_contents.delete_if { |i| i.name == name }
66
+ get_contents.delete name
55
67
  end
56
68
  def create_file child_key, content
57
69
  AWS::S3::S3Object.store(child_key, content, bucket)
58
- get_contents << SFile.new(self, AWS::S3::S3Object.find(child_key, bucket))
70
+ f = SFile.new(self, AWS::S3::S3Object.find(child_key, bucket))
71
+ get_contents[f.name] = f
59
72
  end
60
73
  def create_dir child_key
61
74
  AWS::S3::S3Object.store(child_key + '/', '', bucket)
62
- get_contents << SPrefixDir.new(self, child_key + '/')
75
+ d = SPrefixDir.new(self, child_key + '/')
76
+ get_contents[d.name] = d
63
77
  end
64
78
  def delete
65
79
  AWS::S3::S3Object.delete @key, bucket
66
80
  @parent.content_deleted name
67
81
  end
68
82
  def contents
69
- get_contents.collect { |i| i.name }
83
+ get_contents.keys
70
84
  end
71
85
  def get(name)
72
- get_contents.find { |i| i.name == name }
86
+ get_contents[name]
73
87
  end
74
88
  def size
75
89
  0
@@ -81,29 +95,41 @@ class SBaseDir
81
95
  def get_contents
82
96
  return @data if @data != nil
83
97
  puts "Loading '#{name}' from #{bucket}..."
84
- @data = []
98
+ @data = {}
85
99
  marker = ''
86
100
  loop do
87
101
  s3_bucket = AWS::S3::Bucket.find(bucket, :prefix => prefix, :delimiter => '/', :marker => marker, :max_keys => 1000)
88
- s3_bucket.object_cache.each do |s3_obj|
102
+
103
+ oc = s3_bucket.object_cache
104
+ cpc = s3_bucket.common_prefix_cache
105
+
106
+ cpc.reject { |p| p == '/' }.each do |prefix|
107
+ d = SPrefixDir.new(self, prefix)
108
+ @data[d.name] = d
109
+ end
110
+
111
+ oc.each do |s3_obj|
89
112
  # Technically we should use S3SYNC_DIR_LENGTH but aws-s3 decides it
90
113
  # needs to issue an HEAD request for every dir for that.
91
114
  if s3_obj.etag == S3SYNC_DIR_ETAG or s3_obj.key.end_with? S3ORGANIZER_DIR_SUFFIX
92
- @data << SFakeDir.new(self, s3_obj.key)
115
+ d = SFakeDir.new(self, s3_obj.key)
116
+ @data[d.name] = d
93
117
  elsif s3_obj.key.end_with? '/'
94
118
  # We passed 'prefix/', delimiter='/', if we get any keys that
95
119
  # end with /, it's just a marker object for our current directory
96
120
  # so ignore it.
97
121
  else
98
- @data << SFile.new(self, s3_obj)
122
+ f = SFile.new(self, s3_obj)
123
+ @data[f.name] = f
99
124
  end
100
125
  end
101
- s3_bucket.common_prefix_cache.reject { |p| p == '/' }.each do |prefix|
102
- hidden = SPrefixDir.new(self, prefix)
103
- @data << hidden unless @data.find { |i| i.name == hidden.name }
104
- end
105
- break unless s3_bucket.object_cache.length > 0 && s3_bucket.object_cache.length % 1000 == 0
106
- marker = s3_bucket.object_cache.last.key
126
+
127
+ break unless s3_bucket.truncated?
128
+
129
+ # find which of the object/prefix keys is alphabetically last
130
+ last_object_key = oc.size == 0 ? '' : oc.last.key
131
+ last_prefix_key = cpc.size == 0 ? '' : cpc.last
132
+ marker = last_object_key < last_prefix_key ? last_prefix_key : last_object_key
107
133
  end
108
134
  puts "done"
109
135
  @data
@@ -116,9 +142,10 @@ class SPrefixDir < SBaseDir
116
142
  @parent = parent
117
143
  @key = key
118
144
  @data = nil
145
+ @name = last_part(@key)
119
146
  end
120
147
  def name
121
- @key.split('/')[-1]
148
+ @name
122
149
  end
123
150
  def bucket
124
151
  @parent.bucket
@@ -135,9 +162,10 @@ class SFakeDir < SBaseDir
135
162
  @parent = parent
136
163
  @key = key
137
164
  @data = nil
165
+ @name = strip_dir_suffix(last_part(@key))
138
166
  end
139
167
  def name
140
- strip_dir_suffix @key.split('/')[-1]
168
+ @name
141
169
  end
142
170
  def bucket
143
171
  @parent.bucket
@@ -188,7 +216,8 @@ class SBucketsDir < SBaseDir
188
216
  end
189
217
  def create_dir child_key
190
218
  AWS::S3::Bucket.create(child_key)
191
- get_contents << SBucketDir.new(self, child_key)
219
+ d = SBucketDir.new(self, child_key)
220
+ get_contents[d.name] = d
192
221
  end
193
222
  def delete
194
223
  raise 'cannot delete the buckets dir'
@@ -205,9 +234,10 @@ class SBucketsDir < SBaseDir
205
234
  def get_contents
206
235
  return @data if @data != nil
207
236
  puts "Loading buckets..."
208
- @data = []
237
+ @data = {}
209
238
  AWS::S3::Bucket.list(true).each do |s3_bucket|
210
- @data << SBucketDir.new(self, s3_bucket.name)
239
+ d = SBucketDir.new(self, s3_bucket.name)
240
+ @data[d.name] = d
211
241
  end
212
242
  puts "done"
213
243
  @data
metadata CHANGED
@@ -1,12 +1,12 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: s3fsr
3
3
  version: !ruby/object:Gem::Version
4
- hash: 1
4
+ hash: 31
5
5
  prerelease: false
6
6
  segments:
7
7
  - 1
8
- - 7
9
- version: "1.7"
8
+ - 8
9
+ version: "1.8"
10
10
  platform: ruby
11
11
  authors:
12
12
  - Stephen Haberman
@@ -14,7 +14,7 @@ autorequire:
14
14
  bindir: bin
15
15
  cert_chain: []
16
16
 
17
- date: 2010-11-13 00:00:00 -06:00
17
+ date: 2011-01-25 00:00:00 -06:00
18
18
  default_executable:
19
19
  dependencies:
20
20
  - !ruby/object:Gem::Dependency