summaryrefslogtreecommitdiff
path: root/ace/Filecache.h
blob: c6986bd465d91b6db6aed8c11d4cce9484890249 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
// -*- C++ -*-

//=============================================================================
/**
 *  @file    Filecache.h
 *
 *  $Id$
 *
 *  @author James Hu
 */
//=============================================================================


#ifndef ACE_FILECACHE_H
#define ACE_FILECACHE_H

#include /**/ "ace/pre.h"

#include "ace/Mem_Map.h"

#if !defined (ACE_LACKS_PRAGMA_ONCE)
# pragma once
#endif /* ACE_LACKS_PRAGMA_ONCE */

#include "ace/Hash_Map_Manager_T.h"
#include "ace/Null_Mutex.h"
#include "ace/Synch_Traits.h"
#include "ace/RW_Thread_Mutex.h"
#include "ace/OS_NS_sys_stat.h"

enum ACE_Filecache_Flag
{
  ACE_NOMAP = 0,
  ACE_MAPIT = 1
};

class ACE_Filecache_Object;

/**
 * @class ACE_Filecache_Handle
 *
 * @brief Abstraction over a real file.  This is meant to be the entry
 * point into the Cached Virtual Filesystem.
 *
 * This is a cached filesystem implementation based loosely on the
 * implementation of JAWS_File.  The interfaces will be nearly the
 * same.  The under-the-hood implementation should hopefully be a
 * much faster thing.
 * These will be given their own implementations later. For now, we
 * borrow the implementation provided by JAWS.
 * On creation, the cache is checked, and reference count is
 * incremented.  On destruction, reference count is decremented.  If
 * the reference count is 0, the file is removed from the cache.
 * E.g. 1,
 * {
 * ACE_Filecache_Handle foo("foo.html");
 * this->peer ().send (foo.address (), foo.size ());
 * }
 * E.g. 2,
 * {
 * ACE_Filecache_Handle foo("foo.html");
 * io->transmitfile (foo.handle (), this->peer ().handle ());
 * }
 * E.g. 3,
 * {
 * ACE_Filecache_Handle foo("foo.html", content_length);
 * this->peer ().recv (foo.address (), content_length);
 * }
 * TODO:
 */
class ACE_Export ACE_Filecache_Handle
{
  // (1) Get rid of the useless copying of files when reading.
  // Although it does make sure the file you send isn't being changed,
  // it doesn't make sure the file is in a sensible state before
  // sending it.
  //
  // Alternative: if the file get's trashed while it is being shipped,
  // let the client request the file again.  The cache should have an
  // updated copy by that point.
  //
  // (2) Use hashing for locating files.  This means I need a hastable
  // implementation with buckets.
  //
  // (3) Only lock when absolutely necessary.  JAWS_Virtual_Filesystem was
  // rather conservative, but for some reason it still ran into problems.
  // Since this design should be simpler, problems should be easier to spot.
  //
public:

  /// Query cache for file, and acquire it.  Assumes the file is being
  /// opened for reading.
  ACE_Filecache_Handle (const ACE_TCHAR *filename,
                        ACE_Filecache_Flag mapit = ACE_MAPIT);

  /**
   * Create new entry, and acquire it.  Presence of SIZE assumes the
   * file is being opened for writing.  If SIZE is zero, assumes the
   * file is to be removed from the cache.
   */
  ACE_Filecache_Handle (const ACE_TCHAR *filename,
                        int size,
                        ACE_Filecache_Flag mapit = ACE_MAPIT);

  /// Closes any open handles, release acquired file.
  ~ACE_Filecache_Handle (void);

  /// Base address of memory mapped file.
  void *address (void) const;

  /// A handle (e.g., UNIX file descriptor, or NT file handle).
  ACE_HANDLE handle (void) const;

  /// Any associated error in handle creation and acquisition.
  int error (void) const;

  /// The size of the file.
  off_t size (void) const;

protected:
  /// Default do nothing constructor.  Prevent it from being called.
  ACE_Filecache_Handle (void);

  /// Common initializations for constructors.
  void init (void);

public:
  /// These come from ACE_Filecache_Object, which is an internal class.
  enum
  {
    ACE_SUCCESS = 0,
    ACE_ACCESS_FAILED,
    ACE_OPEN_FAILED,
    ACE_COPY_FAILED,
    ACE_STAT_FAILED,
    ACE_MEMMAP_FAILED,
    ACE_WRITE_FAILED
  };

private:
  /// A reference to the low level instance.
  ACE_Filecache_Object *file_;

  /// A <dup>'d version of the one from <file_>.
  ACE_HANDLE handle_;

  int mapit_;
};

typedef ACE_Hash_Map_Manager_Ex<const ACE_TCHAR *, ACE_Filecache_Object *, ACE_Hash<const ACE_TCHAR *>, ACE_Equal_To<const ACE_TCHAR *>, ACE_Null_Mutex>
        ACE_Filecache_Hash;

typedef ACE_Hash_Map_Entry<const ACE_TCHAR *, ACE_Filecache_Object *> ACE_Filecache_Hash_Entry;

/**
 * @class ACE_Filecache
 *
 * @brief A hash table holding the information about entry point into
 * the Cached Virtual Filesystem. On insertion, the reference
 * count is incremented. On destruction, reference count is
 * decremented.
 */
class ACE_Export ACE_Filecache
{
public:
  /// Singleton pattern.
  static ACE_Filecache *instance (void);

  ~ACE_Filecache (void);

  /// Returns 0 if the file associated with ``filename'' is in the cache,
  /// or -1 if not.
  int find (const ACE_TCHAR *filename);

  /// Return the file associated with ``filename'' if it is in the cache,
  /// or create if not.
  ACE_Filecache_Object *fetch (const ACE_TCHAR *filename, int mapit = 1);

  /// Remove the file associated with ``filename'' from the cache.
  ACE_Filecache_Object *remove (const ACE_TCHAR *filename);

  /// Create a new Filecache_Object, returns it.
  ACE_Filecache_Object *create (const ACE_TCHAR *filename, int size);

  /// Release an acquired Filecache_Object, returns it again or NULL if it
  /// was deleted.
  ACE_Filecache_Object *finish (ACE_Filecache_Object *&new_file);

protected:
  ACE_Filecache_Object *insert_i (const ACE_TCHAR *filename,
                                  ACE_SYNCH_RW_MUTEX &filelock,
                                  int mapit);
  ACE_Filecache_Object *remove_i (const ACE_TCHAR *filename);
  ACE_Filecache_Object *update_i (const ACE_TCHAR *filename,
                                  ACE_SYNCH_RW_MUTEX &filelock,
                                  int mapit);

public:

  enum
  {
    /// For this stupid implementation, use an array.  Someday, use a
    /// balanced search tree, or real hash table.
    ACE_DEFAULT_VIRTUAL_FILESYSTEM_TABLE_SIZE = 512,

    /// This determines the highwater mark in megabytes for the cache.
    /// This will be ignored for now.
    ACE_DEFAULT_VIRTUAL_FILESYSTEM_CACHE_SIZE = 20
  };

protected:
  /// Prevent it from being called.
  ACE_Filecache (void);

private:
  int size_;

  /// The hash table
  ACE_Filecache_Hash hash_;

  /// The reference to the instance
  static ACE_Filecache *cvf_;

  // = Synchronization variables.
  ACE_SYNCH_RW_MUTEX hash_lock_[ACE_DEFAULT_VIRTUAL_FILESYSTEM_TABLE_SIZE];
  ACE_SYNCH_RW_MUTEX file_lock_[ACE_DEFAULT_VIRTUAL_FILESYSTEM_TABLE_SIZE];
};

/**
 * @class ACE_Filecache_Object
 *
 * @brief Abstraction over a real file.  This is what the Virtual
 * Filesystem contains.  This class is not intended for general
 * consumption.  Please consult a physician before attempting to
 * use this class.
 */
class ACE_Export ACE_Filecache_Object
{
public:
  friend class ACE_Filecache;

  /// Creates a file for reading.
  ACE_Filecache_Object (const ACE_TCHAR *filename,
                        ACE_SYNCH_RW_MUTEX &lock,
                        LPSECURITY_ATTRIBUTES sa = 0,
                        int mapit = 1);

  /// Creates a file for writing.
  ACE_Filecache_Object (const ACE_TCHAR *filename,
                        off_t size,
                        ACE_SYNCH_RW_MUTEX &lock,
                        LPSECURITY_ATTRIBUTES sa = 0);

  /// Only if reference count is zero should this be called.
  ~ACE_Filecache_Object (void);

  /// Increment the reference_count_.
  int acquire (void);

  /// Decrement the reference_count_.
  int release (void);

  // = error_ accessors
  int error (void) const;
  int error (int error_value,
             const ACE_TCHAR *s = ACE_LIB_TEXT ("ACE_Filecache_Object"));

  /// filename_ accessor
  const ACE_TCHAR *filename (void) const;

  /// handle_ accessor.
  ACE_HANDLE handle (void) const;

  /// Base memory address for memory mapped file.
  void *address (void) const;

  /// size_ accessor.
  off_t size (void) const;

  /// True if file on disk is newer than cached file.
  int update (void) const;

protected:
  /// Prevent from being called.
  ACE_Filecache_Object (void);

  /// Common initialization code,
  void init (void);

private:
  /// Internal error logging method, no locking.
  int error_i (int error_value,
               const ACE_TCHAR *s = ACE_LIB_TEXT ("ACE_Filecache_Object"));

public:

  enum Creation_States
  {
    ACE_READING = 1,
    ACE_WRITING = 2
  };

  enum Error_Conditions
  {
    ACE_SUCCESS = 0,
    ACE_ACCESS_FAILED,
    ACE_OPEN_FAILED,
    ACE_COPY_FAILED,
    ACE_STAT_FAILED,
    ACE_MEMMAP_FAILED,
    ACE_WRITE_FAILED
  };

private:
  /// The temporary file name and the real file name.  The real file is
  /// copied into the temporary file for safety reasons.
  ACE_TCHAR *tempname_;
  ACE_TCHAR filename_[MAXPATHLEN + 1];

  /// Holds the memory mapped version of the temporary file.
  ACE_Mem_Map mmap_;

  /// The descriptor to the temporary file.
  ACE_HANDLE handle_;

  /// Used to compare against the real file to test if an update is needed.
  ACE_stat stat_;
  off_t size_;

  /// Status indicators.
  int action_;
  int error_;

  /// If set to 1, means the object is flagged for removal.
  int stale_;

  /// Security attribute object.
  LPSECURITY_ATTRIBUTES sa_;

  /// The default initializer
  ACE_SYNCH_RW_MUTEX junklock_;

  /// Provides a bookkeeping mechanism for users of this object.
  ACE_SYNCH_RW_MUTEX &lock_;
};


#include /**/ "ace/post.h"

#endif /* ACE_FILECACHE_H */