HDK
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
FS_IndexFile.h
Go to the documentation of this file.
1 /*
2  * PROPRIETARY INFORMATION. This software is proprietary to
3  * Side Effects Software Inc., and is not to be reproduced,
4  * transmitted, or disclosed in any way without written permission.
5  *
6  * NAME: FS_IndexFile.h ( FS Library, C++)
7  *
8  * COMMENTS:
9  *
10  */
11 
12 #ifndef __FS_IndexFile__
13 #define __FS_IndexFile__
14 
15 #include "FS_API.h"
16 
17 #include <UT/UT_ArrayStringMap.h>
18 #include <UT/UT_Defines.h>
19 #include <UT/UT_Lock.h>
20 #include <UT/UT_SharedPtr.h>
21 #include <UT/UT_StringHolder.h>
22 #include <UT/UT_ValArray.h>
23 #include <UT/UT_VectorTypes.h>
24 #include <SYS/SYS_Types.h>
25 #include <iosfwd>
26 #include <time.h>
27 
28 class FS_IndexFileHandle;
30 class FS_Reader;
31 class FS_ReaderStream;
32 class FS_Section;
34 class UT_Options;
35 class UT_String;
36 class UT_WorkBuffer;
37 
38 #define FS_SECTION_SEPARATOR UT_SECTION_SEPARATOR_CHAR
39 #define FS_SECTION_SEPARATOR_STRING UT_SECTION_SEPARATOR_STRING
40 #define FS_SECTIONFILE "Sections.list"
41 
42 // Result of checking whether an index file's section sizes fit the on-disk
43 // format. The 32-bit fields cap a single section at 2GB; the cumulative offset
44 // may use the unsigned range (up to 4GB), which older Houdini cannot read.
46 {
47  FS_INDEX_SIZE_OK, // fits signed offsets; readable everywhere
48  FS_INDEX_SIZE_OVERFLOW, // needs unsigned offsets (>2GB total); warn
49  FS_INDEX_SIZE_SECTION_OVERFLOW,// a single section exceeds 2GB
50  FS_INDEX_SIZE_TOTAL_OVERFLOW // cumulative offset exceeds 4GB
51 };
52 
53 // Check an index's ordered section sizes. bad_index = first section over 2GB;
54 // max_offset = largest cumulative offset (sum of all but the last).
56 FSindexOverflowCheck(const exint *section_sizes, int num_sections,
57  int &bad_index, exint &max_offset);
58 
59 // This class implements a file that contains several sections that can be found
60 // at certain offsets of a main file.
62 {
63 public:
64  /// Default constructor.
65  FS_IndexFile();
66 
67  /// This constructor takes a path of some sort (e.g. a file path, an oplib:
68  /// path, an opdef: path, an http:// path, etc) to the index file.
69  FS_IndexFile(const char *source);
70 
71  /// This constructor takes a reader that will be used to retrieve section
72  /// data. The index file takes ownership and will delete the reader in the
73  /// destructor. (If null is passed in, this object creates its own default
74  /// FS_Reader, but unless a source is given nothing can be read from such
75  /// an index file.)
76  ///
77  /// If no source is given, closing the index file and reopening it again
78  /// will have no effect on the underlying reader. The reader will only be
79  /// closed and deleted when the index file object is deleted. If a source
80  /// is passed in, though, the reader will be deleted when the index file is
81  /// closed and subsequent openings will use the source path to construct a
82  /// new reader.
83  FS_IndexFile(FS_Reader *reader, const char *source=nullptr);
84 
85  virtual ~FS_IndexFile();
86 
87  // Some basic operations on sections (add, remove, modify).
88  // These functions don't affect the source file. The changes
89  // are only evident when we call writeFile.
90  // Reading is NOT currently threadsafe.
91  inline bool hasSection(const UT_StringRef &section) const
92  { return mySectionTable.contains(section) ||
93  myTempSectionTable.contains(section); }
94  inline bool hasTempSection(const UT_StringRef &section) const
95  { return myTempSectionTable.contains(section); }
96  inline bool hasRegularSection(const UT_StringRef &section) const
97  { return mySectionTable.contains(section); }
98  time_t getSectionModTime(const UT_StringRef &section) const;
99  int getSectionDataSize(const UT_StringRef &section) const;
100  bool readSection(const UT_StringRef &section,
101  char *buffer) const;
102  bool readSection(const UT_StringRef &section,
103  UT_WorkBuffer &buffer) const;
104  bool readOptionsSection(const UT_StringRef &section,
105  UT_Options &options) const;
106  void addSection(const UT_StringRef &section,
107  const char *filename);
108  void addSection(const UT_StringRef &section,
109  const UT_WorkBuffer &buf,
110  time_t modtime = time_t(-1));
111  void addSection(const UT_StringRef &section,
112  const char *buffer,
113  int len, time_t modtime = time_t(-1));
114  void addSection(const UT_StringRef &section,
115  const FS_IndexFile &file);
116  void modifySection(const UT_StringRef &section,
117  const char *buffer,
118  int len, time_t modtime = time_t(-1));
119  void modifySection(const UT_StringRef &section,
120  const UT_WorkBuffer &buf,
121  time_t modtime = time_t(-1));
122  void removeSection(const UT_StringRef &section);
123  void mergeIndexFile(const FS_IndexFile &file, bool overwrite);
124 
125  // Change the ordering of some sections. This is basically a book-keeping
126  // change, and only affects things when this index file is then saved.
127  void moveSections(int first, int last, int offset);
128 
129  // Get the modification time for the index file as a whole.
130  time_t getModTime() const;
131 
132  // Get the size of the whole index file
133  int64 getFileDataSize() const;
134 
135  // Sets the stream filters used for processing the data when it is read
136  // in or written out.
137  void setFilters(FS_WriteFilterFactory *encrypt_factory,
138  FS_IStreamFilterFactory *decrypt_factory);
139 
140  // Gets the decryption and encryption filter factories.
141  FS_WriteFilterFactory *getEncryptionFilter() const;
142  FS_IStreamFilterFactory *getDecryptionFilter() const;
143 
144  // Get an opaque pointer to a section.
145  FS_Section *getSection(const UT_StringRef &section) const;
146 
147  // Get an FS_Reader for reading a section of the index.
148  FS_Reader *getSectionReader(const UT_StringRef &section) const;
149 
150  // These utility functions should only be used by FS_ReaderHelpers
151  FS_ReaderStream *getSectionStream(const UT_StringRef &section) const;
152  FS_ReaderStream *getStreamCopy() const;
153 
154  // Given an opaque section pointer get an FS_IndexFile it represents.
155  FS_IndexFileHandle getIndexFileFromSection(const UT_StringRef &section,
156  const char *source = nullptr) const;
157 
158  // Simple access functions to find out about our sections.
159  int getNumSections() const;
160  const UT_StringHolder &getSectionName(int index) const;
161 
162  // Access our source file name (which may be empty).
163  const UT_StringHolder &getSourceFile() const { return mySourceFile; }
164 
165  // Access functions for our description string.
166  const UT_StringHolder &getDescription() const;
167  void setDescription(const UT_StringHolder &description);
168 
169 
170  // If we are going to be written to a strstream, this function returns
171  // a sensible guess about the buffer size that should be allocated.
172  exint guessStreamSize() const;
173 
174  // Pre-flight before saving: returns false (and logs) if a section exceeds
175  // 2GB or the cumulative data exceeds 4GB -- callers MUST abort the save
176  // before touching the destination so the existing asset is not lost. Also
177  // logs a warning (but returns true) when the file needs unsigned offsets
178  // (>2GB), which older Houdini cannot read.
179  bool checkWriteSizeLimits() const;
180 
181  // Write us out to a stream (with all modifications).
182  // Note: Don't write out an index file to the same file it was loaded
183  // from, since writing implicitly reads the file. Instead, write it to a
184  // separate file and then copy it over. This will also require this index
185  // file to be reloaded.
186  virtual void writeFile(std::ostream &os) const;
187 
188  // This functions are for expanding and collapsing an index file,
189  // much like hexpand and hcollapse do for cpio archives.
190  virtual bool expandToDirectory(const char *destdir);
191  virtual bool collapseFromDirectory(const char *srcdir);
192 
193  // Get the current time, used to set the section modification time.
194  static time_t getCurrentTime()
195  {
196  time_t currtime;
197  return ::time(&currtime);
198  }
199 
200  /// Tests if the index file is copy-protected.
201  bool isCopyProtected() const;
202 
203  /// Tests if the index file is black boxed.
204  bool isBlackBoxed() const;
205 
206  /// Tests if the index file is stored as expanded.
207  bool isExpanded() const
208  { return myIsExpanded; }
209 
210  static bool canWriteFile(const char *filename);
211 
212  bool getSectionFileName(const char *section,
214 
215  static void clearStartupCache();
216 
217  // -----------------------------------------------------------------------
218  // Section data conversion to/from text
219 
220  typedef bool(*ConvertFunc)(const UT_StringHolder &src_path,
221  const UT_WorkBuffer &in_data,
222  UT_WorkBuffer &out_data);
223 
225  {
226  ConversionFuncs(const char *bin_file_pattern = "",
227  const char *text_file_pattern = "",
228  ConvertFunc to_text = nullptr,
229  ConvertFunc from_text = nullptr)
230  : myToText(to_text),
231  myFromText(from_text),
232  myBinFilePattern(bin_file_pattern),
233  myTextFilePattern(text_file_pattern)
234  {}
235 
236  void clear()
237  {
238  myToText = nullptr;
239  myFromText = nullptr;
240  myBinFilePattern.clear();
241  myTextFilePattern.clear();
242  }
243 
244  bool isClear() const
245  {
246  // sufficient to just text first data member
247  return myToText == nullptr;
248  }
249 
250  ConvertFunc myToText;
251  ConvertFunc myFromText;
254  };
256 
257 
258  static bool registerConversionFuncs(const char *bin_file_pattern,
259  const char *text_file_pattern,
260  ConvertFunc to_text,
261  ConvertFunc from_text);
262 
263  static const ConversionList &getConversionsToText();
264  static const ConversionList &getConversionsFromText();
265 
266 
267 protected:
268  void setModified() { myModified = true; }
269 
270  exint writeHeader(std::ostream &os,
271  const UT_Int32Array &section_sizes) const;
272 
273  // Check this index's section sizes (shared by writeFile and
274  // checkWriteSizeLimits) via FSindexOverflowCheck.
276  exint &max_offset) const;
277 
278  static ConversionList &_getConversionsToText();
279  static ConversionList &_getConversionsFromText();
280 
281  mutable UT_Lock myLock;
282 
283 private:
285 
286  // Functions for opening and closing our stream.
287  void openStream(const UT_Options *options = nullptr) const;
288  void closeStream() const;
289 
290  // Helper functions for reading and writing ourselves to a directory.
291  static void makeValidFileName(UT_String &filename);
292  bool writeSectionListFile(const char *sectionfile);
293 
294  // Writes out a section to the output stream. If the filter factory
295  // has been set, the filter will be applied to the section data before
296  // it is written out.
297  void writeSection(FS_Section *section,
298  std::ostream &os,
299  bool as_text) const;
300 
301  // Get an FS_Reader for reading a section of the index.
302  FS_Reader *getSectionReader(FS_Section *section) const;
303 
304  // These utility functions should only be used by FS_ReaderHelpers
305  FS_ReaderStream *getSectionStream(FS_Section *section) const;
306 
307  // Read in our index and use it to create our section data structures.
308  void readIndex();
309  void readDirectoryIndex(
310  const UT_String &source_file_path,
311  const UT_String &sections_file_path);
312  void readStreamIndex();
313 
314  // Obtains a size of the i-th section after it has been filtered (if at all)
315  int getWriteFilteredSectionSize( int index ) const;
316 
317  // Recalculates the data sizes of our sections when the read filter is set.
318  void recalculateFilteredSectionSizes();
319 
321 
322  // Data:
323  mutable FS_Reader *myReader;
324  FS_SectionArray mySections;
325  SectionMap mySectionTable;
326  FS_SectionArray myTempSections;
327  SectionMap myTempSectionTable;
328  UT_StringHolder myDescription;
329  UT_StringHolder mySourceFile;
330  FS_WriteFilterFactory *myWriteFilter;
331  FS_IStreamFilterFactory *myReadFilter;
332  time_t myModTime;
333  int64 mySize;
334  int myStreamStart;
335  bool myModified;
336  bool myIsExpanded;
337  bool myHadOversizedSection = false;
338 
339  friend class FS_Section;
340  friend class FS_EmbeddedSection;
341  friend class FS_DiskSection;
342  friend class FS_IndexFileHandle;
343 };
344 
345 class FS_API FS_IndexFileHandle : public UT_SharedPtr<FS_IndexFile>
346 {
347 public:
350  virtual ~FS_IndexFileHandle();
351 
352  // FIXME:TODO:XXX: This is highly suspicious because we have a non-trivial
353  // destructor. But making this explicit for now for rule of three without
354  // any behaviour changes.
355  FS_IndexFileHandle(const FS_IndexFileHandle &src) = default;
356  FS_IndexFileHandle &operator=(const FS_IndexFileHandle &src) = default;
357 
358 private:
359 
360  friend class FS_Section;
361  friend class FS_EmbeddedSection;
362  friend class FS_DiskSection;
363  friend class FS_IndexFile;
364 };
365 
366 // For UT::ArraySet.
367 namespace UT
368 {
369 template <typename T>
370 struct DefaultClearer;
371 
372 template <>
373 struct DefaultClearer<FS_IndexFile::ConversionFuncs>
374 {
376  static void clear(ValueT &v) { v.clear(); }
377  static bool isClear(const ValueT &v) { return v.isClear(); }
378  static void clearConstruct(ValueT *p)
379  {
380  new ((void *)p) ValueT();
381  }
382  static const bool clearNeedsDestruction = false;
383 };
384 } // namespace UT
385 
386 #endif
387 
GLint first
Definition: glcorearb.h:405
Class for reading files.
Definition: FS_Reader.h:33
GLenum GLuint GLenum GLsizei const GLchar * buf
Definition: glcorearb.h:2540
PXL_API const char * getDescription(const ColorSpace *space)
Return the description of the color space.
GT_API const UT_StringHolder filename
UT_StringHolder myTextFilePattern
Definition: FS_IndexFile.h:253
UT_Lock myLock
Definition: FS_IndexFile.h:281
GT_API const UT_StringHolder time
const GLdouble * v
Definition: glcorearb.h:837
ConversionFuncs(const char *bin_file_pattern="", const char *text_file_pattern="", ConvertFunc to_text=nullptr, ConvertFunc from_text=nullptr)
Definition: FS_IndexFile.h:226
int64 exint
Definition: SYS_Types.h:125
bool hasRegularSection(const UT_StringRef &section) const
Definition: FS_IndexFile.h:96
static time_t getCurrentTime()
Definition: FS_IndexFile.h:194
GLuint buffer
Definition: glcorearb.h:660
OutGridT const XformOp bool bool
bool isExpanded() const
Tests if the index file is stored as expanded.
Definition: FS_IndexFile.h:207
UT_ArrayStringMap< ConversionFuncs > ConversionList
Definition: FS_IndexFile.h:255
void setModified()
Definition: FS_IndexFile.h:268
GLintptr offset
Definition: glcorearb.h:665
std::shared_ptr< T > UT_SharedPtr
Wrapper around std::shared_ptr.
Definition: UT_SharedPtr.h:36
bool hasTempSection(const UT_StringRef &section) const
Definition: FS_IndexFile.h:94
GLsizei GLsizei GLchar * source
Definition: glcorearb.h:803
long long int64
Definition: SYS_Types.h:116
FS_IndexSizeOverflowCheck
Definition: FS_IndexFile.h:45
virtual bool writeFile(const GA_Detail &g, const char *filename, const GA_SaveOptions *opts, UT_StringArray *errors) const
__hostdev__ uint64_t last(uint32_t i) const
Definition: NanoVDB.h:5976
bool hasSection(const UT_StringRef &section) const
Definition: FS_IndexFile.h:91
A map of string to various well defined value types.
Definition: UT_Options.h:87
const UT_StringHolder & getSourceFile() const
Definition: FS_IndexFile.h:163
LeafData & operator=(const LeafData &)=delete
GLuint index
Definition: glcorearb.h:786
FS_API FS_IndexSizeOverflowCheck FSindexOverflowCheck(const exint *section_sizes, int num_sections, int &bad_index, exint &max_offset)
std::enable_if< std::is_signed< T >::value, T >::type overflowCheck(const T &a, const T &b)
Do a check for overflow on signed numbers.
Definition: CLI11.h:3212
#define FS_API
Definition: FS_API.h:10
UT_StringHolder myBinFilePattern
Definition: FS_IndexFile.h:252
GLenum src
Definition: glcorearb.h:1793