2
* Copyright 2010 Google Inc.
4
* Licensed under the Apache License, Version 2.0 (the "License");
5
* you may not use this file except in compliance with the License.
6
* You may obtain a copy of the License at
8
* http://www.apache.org/licenses/LICENSE-2.0
10
* Unless required by applicable law or agreed to in writing, software
11
* distributed under the License is distributed on an "AS IS" BASIS,
12
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
* See the License for the specific language governing permissions and
14
* limitations under the License.
17
// Author: abliss@google.com (Adam Bliss)
19
#ifndef PAGESPEED_KERNEL_BASE_MEM_FILE_SYSTEM_H_
20
#define PAGESPEED_KERNEL_BASE_MEM_FILE_SYSTEM_H_
24
#include "pagespeed/kernel/base/basictypes.h"
25
#include "pagespeed/kernel/base/callback.h"
26
#include "pagespeed/kernel/base/file_system.h"
27
#include "pagespeed/kernel/base/scoped_ptr.h"
28
#include "pagespeed/kernel/base/string.h"
29
#include "pagespeed/kernel/base/string_util.h"
31
namespace net_instaweb {
39
// An in-memory implementation of the FileSystem interface. This was originally
40
// for use in unit tests; but can also host the lock manager if needed.
41
// Does not fully support directories. Not particularly efficient.
42
// Not threadsafe except for lock methods.
43
// TODO(abliss): add an ability to block writes for arbitrarily long, to
44
// enable testing resilience to concurrency problems with real filesystems.
46
// TODO(jmarantz): make threadsafe.
47
class MemFileSystem : public FileSystem {
49
typedef Callback1<const GoogleString&> FileCallback;
51
explicit MemFileSystem(ThreadSystem* threads, Timer* timer);
52
virtual ~MemFileSystem();
54
virtual InputFile* OpenInputFile(const char* filename,
55
MessageHandler* message_handler);
56
virtual OutputFile* OpenOutputFileHelper(const char* filename,
58
MessageHandler* message_handler);
59
virtual OutputFile* OpenTempFileHelper(const StringPiece& prefix_name,
60
MessageHandler* message_handle);
62
virtual bool ListContents(const StringPiece& dir, StringVector* files,
63
MessageHandler* handler);
64
virtual bool MakeDir(const char* directory_path, MessageHandler* handler);
65
virtual bool RecursivelyMakeDir(const StringPiece& directory_path,
66
MessageHandler* handler);
67
virtual bool RemoveDir(const char* path, MessageHandler* handler);
68
virtual bool RemoveFile(const char* filename, MessageHandler* handler);
69
virtual bool RenameFileHelper(const char* old_file, const char* new_file,
70
MessageHandler* handler);
72
// We offer a "simulated atime" in which the clock ticks forward one
73
// second every time you read or write a file.
74
virtual bool Atime(const StringPiece& path, int64* timestamp_sec,
75
MessageHandler* handler);
76
virtual bool Mtime(const StringPiece& path, int64* timestamp_sec,
77
MessageHandler* handler);
78
virtual bool Size(const StringPiece& path, int64* size,
79
MessageHandler* handler);
80
virtual BoolOrError Exists(const char* path, MessageHandler* handler);
81
virtual BoolOrError IsDir(const char* path, MessageHandler* handler);
83
virtual BoolOrError TryLock(const StringPiece& lock_name,
84
MessageHandler* handler);
85
virtual BoolOrError TryLockWithTimeout(const StringPiece& lock_name,
88
MessageHandler* handler);
89
virtual bool Unlock(const StringPiece& lock_name, MessageHandler* handler);
91
// When atime is disabled, reading a file will not update its atime.
92
void set_atime_enabled(bool enabled) { atime_enabled_ = enabled; }
94
// In order to test file-system 'atime' code, we need to move mock
95
// time forward during tests by an entire second (aka 1000 ms).
96
// However, that's disruptive to other tests that try to use
97
// mock-time to examine millisecond-level timing, so we leave this
98
// behavior off by default.
99
bool advance_time_on_update() { return advance_time_on_update_; }
100
void set_advance_time_on_update(bool x, MockTimer* mock_timer) {
101
advance_time_on_update_ = x;
102
mock_timer_ = mock_timer;
105
// Empties out the entire filesystem. Should not be called while files
109
// Test-specific functionality to disable and re-enable the filesystem.
110
void Disable() { enabled_ = false; }
111
void Enable() { enabled_ = true; }
113
// Access statistics.
115
num_input_file_opens_ = 0;
116
num_input_file_stats_ = 0;
117
num_output_file_opens_ = 0;
118
num_temp_file_opens_ = 0;
120
int num_input_file_opens() const { return num_input_file_opens_; }
122
// returns number of times MTime was called.
123
int num_input_file_stats() const { return num_input_file_stats_; }
124
int num_output_file_opens() const { return num_output_file_opens_; }
125
int num_temp_file_opens() const { return num_temp_file_opens_; }
127
// Adds a callback to be called once after a file-write and then
130
// This is intended primarily for testing, and thus is not on the base
132
void set_write_callback(FileCallback* x) { write_callback_.reset(x); }
134
virtual bool WriteFile(const char* filename,
135
const StringPiece& buffer,
136
MessageHandler* handler);
137
virtual bool WriteTempFile(const StringPiece& prefix_name,
138
const StringPiece& buffer,
139
GoogleString* filename,
140
MessageHandler* handler);
144
// all_else_mutex_ should be held when calling these.
145
inline void UpdateAtime(const StringPiece& path);
146
inline void UpdateMtime(const StringPiece& path);
148
scoped_ptr<AbstractMutex> lock_map_mutex_; // controls access to lock_map_
149
scoped_ptr<AbstractMutex> all_else_mutex_; // controls access to all else.
151
bool enabled_; // When disabled, OpenInputFile returns NULL.
152
// MemFileSystem::RemoveDir depends on string_map_ being sorted by key. If an
153
// unsorted data structure is used (say a hash_map) this implementation will
154
// need to be modified.
155
StringStringMap string_map_;
157
MockTimer* mock_timer_; // used only for auto-advance functionality.
159
// atime_map_ holds times (in s) that files were last opened/modified. Each
160
// time we do such an operation, timer() advances by 1s (so all ATimes are
162
// ctime and mtime are updated only for moves and modifications.
163
std::map<GoogleString, int64> atime_map_;
164
std::map<GoogleString, int64> mtime_map_;
165
int temp_file_index_;
166
// lock_map_ holds times that locks were established (in ms).
167
// locking and unlocking don't advance time.
168
std::map<GoogleString, int64> lock_map_;
171
// Indicates whether MemFileSystem will advance mock time whenever
172
// a file is written.
173
bool advance_time_on_update_;
175
// Access statistics.
176
int num_input_file_opens_;
177
int num_input_file_stats_;
178
int num_output_file_opens_;
179
int num_temp_file_opens_;
181
// Hook to run after a file-write.
182
scoped_ptr<FileCallback> write_callback_;
184
DISALLOW_COPY_AND_ASSIGN(MemFileSystem);
187
} // namespace net_instaweb
189
#endif // PAGESPEED_KERNEL_BASE_MEM_FILE_SYSTEM_H_