]> wimlib.net Git - wimlib/blobdiff - include/wimlib/lookup_table.h
Heuristic sorting of streams for solid compression
[wimlib] / include / wimlib / lookup_table.h
index a169e3934985f995b80ae34a908def3fe35ab3ee..4158f1578f1a9f79289d26eccb311803b3356c7d 100644 (file)
@@ -22,14 +22,12 @@ enum resource_location {
        /* The stream is located in a resource in a WIM file identified by the
         * `struct wim_resource_spec' pointed to by @rspec.  @offset_in_res
         * identifies the offset at which this particular stream begins in the
-        * uncompressed data of the resource; this is normally 0, but in general
-        * a WIM resource may be "packed" and potentially contain multiple
-        * streams.  */
+        * uncompressed data of the resource; this is normally 0, but a WIM
+        * resource can be "solid" and contain multiple streams.  */
        RESOURCE_IN_WIM,
 
        /* The stream is located in the external file named by @file_on_disk.
-        * On Windows, @file_on_disk may actually specify a named data stream
-        * (file path, then colon, then name of the stream).  */
+        */
        RESOURCE_IN_FILE_ON_DISK,
 
        /* The stream is directly attached in the in-memory buffer pointed to by
@@ -52,6 +50,11 @@ enum resource_location {
 #endif
 
 #ifdef __WIN32__
+       /* Windows only: the stream is located in the external file named by
+        * @file_on_disk, which is in the Windows NT namespace and may specify a
+        * named data stream.  */
+       RESOURCE_IN_WINNT_FILE_ON_DISK,
+
        /* Windows only: the stream is located in the external file named by
         * @file_on_disk, but the file is encrypted and must be read using the
         * appropriate Windows API.  */
@@ -59,6 +62,11 @@ enum resource_location {
 #endif
 };
 
+struct stream_owner {
+       struct wim_inode *inode;
+       const utf16lechar *stream_name;
+};
+
 /* Specification for a stream, which may be the contents of a file (unnamed data
  * stream), a named data stream, reparse point data, or a WIM metadata resource.
  *
@@ -97,6 +105,11 @@ struct wim_lookup_table_entry {
         * need this.)  */
        u32 dont_check_metadata_hash : 1;
 
+       u32 may_send_done_with_file : 1;
+
+       /* Only used by wimlib_export_image() */
+       u32 was_exported : 1;
+
        union {
                /* (On-disk field) SHA1 message digest of the stream referenced
                 * by this lookup table entry.  */
@@ -123,17 +136,17 @@ struct wim_lookup_table_entry {
 
        /* Number of times this lookup table entry is referenced by dentries in
         * the WIM.  When a WIM's lookup table is read, this field is
-        * initialized from a corresponding entry; while it should be correct,
-        * in general it may not be.  wim_recalculate_refcnts() recalculates the
-        * reference counts for all streams and is run before doing any
-        * deletions.  */
+        * initialized from a corresponding entry.
+        *
+        * However, see lte_decrement_refcnt() for information about the
+        * limitations of this field.  */
        u32 refcnt;
 
        /* When a WIM file is written, this is set to the number of references
         * (by dentries) to this stream in the output WIM file.
         *
-        * During extraction, this is set to the number of times the stream must
-        * be extracted.
+        * During extraction, this is the number of slots in stream_owners (or
+        * inline_stream_owners) that have been filled.
         *
         * During image export, this is set to the number of references of this
         * stream that originated from the source WIM.
@@ -157,10 +170,16 @@ struct wim_lookup_table_entry {
                        struct wim_resource_spec *rspec;
                        u64 offset_in_res;
                };
-               tchar *file_on_disk;
+               struct {
+                       tchar *file_on_disk;
+                       struct wim_inode *file_inode;
+               };
                void *attached_buffer;
        #ifdef WITH_FUSE
-               tchar *staging_file_name;
+               struct {
+                       char *staging_file_name;
+                       int staging_dir_fd;
+               };
        #endif
        #ifdef WITH_NTFS_3G
                struct ntfs_location *ntfs_loc;
@@ -172,12 +191,6 @@ struct wim_lookup_table_entry {
         */
        struct list_head rspec_node;
 
-       /* This field is used during the hardlink and symlink image extraction
-        * modes.   In these modes, all identical files are linked together, and
-        * @extracted_file will be set to the filename of the first extracted
-        * file containing this stream.  */
-       tchar *extracted_file;
-
        /* Temporary fields  */
        union {
                /* Fields used temporarily during WIM file writing.  */
@@ -186,38 +199,47 @@ struct wim_lookup_table_entry {
                                /* List node used for stream size table.  */
                                struct hlist_node hash_list_2;
 
-                               /* Metadata for the underlying packed resource
-                                * in the WIM being written (only valid if
-                                * WIM_RESHDR_FLAG_PACKED_STREAMS set in
+                               /* Metadata for the underlying solid resource in
+                                * the WIM being written (only valid if
+                                * WIM_RESHDR_FLAG_SOLID set in
                                 * out_reshdr.flags).  */
                                struct {
                                        u64 out_res_offset_in_wim;
                                        u64 out_res_size_in_wim;
+                                       u64 out_res_uncompressed_size;
                                };
                        };
 
                        /* Links streams being written to the WIM.  */
                        struct list_head write_streams_list;
 
-                       /* Metadata for this stream in the WIM being written.
-                        */
-                       struct wim_reshdr out_reshdr;
+                       union {
+                               /* Metadata for this stream in the WIM being
+                                * written.  */
+                               struct wim_reshdr out_reshdr;
+
+                               struct {
+                                       /* Name under which this stream is being
+                                        * sorted; used only when sorting
+                                        * streams for solid compression.  */
+                                       utf16lechar *solid_sort_name;
+                                       size_t solid_sort_name_nbytes;
+                               };
+                       };
                };
 
-               /* Used temporarily during extraction  */
+               /* Used temporarily during extraction.  This is an array of
+                * pointers to the inodes being extracted that use this stream.
+                */
                union {
-                       /* Dentries to extract that reference this stream.
+                       /* Inodes to extract that reference this stream.
                         * out_refcnt tracks the number of slots filled.  */
-                       struct wim_dentry *inline_lte_dentries[7];
+                       struct stream_owner inline_stream_owners[3];
                        struct {
-                               struct wim_dentry **lte_dentries;
-                               size_t alloc_lte_dentries;
+                               struct stream_owner *stream_owners;
+                               u32 alloc_stream_owners;
                        };
                };
-
-               /* Actual reference count to this stream (only used while
-                * verifying an image).  */
-               u32 real_refcnt;
        };
 
        /* Temporary list fields.  */
@@ -327,16 +349,13 @@ extern int
 sort_stream_list_by_sequential_order(struct list_head *stream_list,
                                     size_t list_head_offset);
 
-/* Utility functions  */
-
 extern int
-lte_zero_out_refcnt(struct wim_lookup_table_entry *lte, void *ignore);
+cmp_streams_by_sequential_order(const void *p1, const void *p2);
 
-extern int
-lte_zero_real_refcnt(struct wim_lookup_table_entry *lte, void *ignore);
+/* Utility functions  */
 
 extern int
-lte_free_extracted_file(struct wim_lookup_table_entry *lte, void *ignore);
+lte_zero_out_refcnt(struct wim_lookup_table_entry *lte, void *ignore);
 
 static inline bool
 lte_is_partial(const struct wim_lookup_table_entry * lte)
@@ -345,17 +364,13 @@ lte_is_partial(const struct wim_lookup_table_entry * lte)
               lte->size != lte->rspec->uncompressed_size;
 }
 
-static inline bool
-lte_filename_valid(const struct wim_lookup_table_entry *lte)
+static inline const struct stream_owner *
+stream_owners(struct wim_lookup_table_entry *stream)
 {
-       return     lte->resource_location == RESOURCE_IN_FILE_ON_DISK
-       #ifdef __WIN32__
-               || lte->resource_location == RESOURCE_WIN32_ENCRYPTED
-       #endif
-       #ifdef WITH_FUSE
-               || lte->resource_location == RESOURCE_IN_STAGING_FILE
-       #endif
-               ;
+       if (stream->out_refcnt <= ARRAY_LEN(stream->inline_stream_owners))
+               return stream->inline_stream_owners;
+       else
+               return stream->stream_owners;
 }
 
 static inline void