omnizip 0.4.7-arm-linux
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.rspec +3 -0
- data/.rubocop.yml +32 -0
- data/.rubocop_todo.yml +293 -0
- data/CHANGELOG.md +1647 -0
- data/CONTEXT.md +68 -0
- data/COPYING +502 -0
- data/Gemfile +19 -0
- data/LICENSE +12 -0
- data/README.adoc +1327 -0
- data/Rakefile +15 -0
- data/TODO.refactor/00-overview.md +67 -0
- data/TODO.refactor/01-registry-base-class.md +81 -0
- data/TODO.refactor/02-error-hierarchy.md +57 -0
- data/TODO.refactor/03-autoload-entry-point.md +69 -0
- data/TODO.refactor/04-filter-base-consolidation.md +49 -0
- data/TODO.refactor/05-send-private-methods.md +64 -0
- data/TODO.refactor/06-instance-variable-access.md +69 -0
- data/TODO.refactor/07-respond-to-replacement.md +237 -0
- data/TODO.refactor/08-spec-doubles.md +27 -0
- data/TODO.refactor/09-cli-shared-module.md +35 -0
- data/TODO.refactor/10-format-detector-ocp.md +34 -0
- data/TODO.refactor/11-convenience-decoupling.md +38 -0
- data/TODO.refactor/12-thread-safety.md +8 -0
- data/TODO.refactor/13-lutaml-model-migration.md +158 -0
- data/TODO.refactor/14-add-missing-specs.md +25 -0
- data/benchmark/README.md +260 -0
- data/benchmark/benchmark_suite.rb +125 -0
- data/benchmark/compression_bench.rb +181 -0
- data/benchmark/filter_bench.rb +180 -0
- data/benchmark/models/benchmark_result.rb +59 -0
- data/benchmark/models/comparison_result.rb +69 -0
- data/benchmark/profile_suite.rb +167 -0
- data/benchmark/reporter.rb +150 -0
- data/benchmark/run_benchmarks.rb +66 -0
- data/benchmark/test_data.rb +137 -0
- data/config/formats/rar3_spec.yml +92 -0
- data/config/formats/rar5_spec.yml +102 -0
- data/docs/.github/workflows/docs.yml +142 -0
- data/docs/.gitignore +21 -0
- data/docs/.lychee.toml +67 -0
- data/docs/Gemfile +13 -0
- data/docs/RAR_WRITE_SUPPORT.md +26 -0
- data/docs/README.md +101 -0
- data/docs/_config.yml +112 -0
- data/docs/assets/logo.svg +1 -0
- data/docs/assets/omnizip-logo.pdf +1540 -11
- data/docs/comparison/feature-matrix.adoc +694 -0
- data/docs/comparison/index.adoc +113 -0
- data/docs/comparison/vs-7zip.adoc +309 -0
- data/docs/comparison/vs-peazip.adoc +77 -0
- data/docs/comparison/vs-rubyzip.adoc +342 -0
- data/docs/comparison/vs-winrar.adoc +100 -0
- data/docs/compatibility.adoc +579 -0
- data/docs/concepts/index.adoc +129 -0
- data/docs/developer/architecture.adoc +256 -0
- data/docs/developer/contributing.adoc +158 -0
- data/docs/developer/index.adoc +25 -0
- data/docs/developer/testing.adoc +212 -0
- data/docs/getting-started/basic-usage.adoc +263 -0
- data/docs/getting-started/index.adoc +42 -0
- data/docs/getting-started/installation.adoc +138 -0
- data/docs/getting-started/quick-start.adoc +183 -0
- data/docs/getting-started/your-first-archive.adoc +219 -0
- data/docs/guides/advanced-features/encryption.adoc +277 -0
- data/docs/guides/advanced-features/index.adoc +59 -0
- data/docs/guides/advanced-features/parallel-processing.adoc +144 -0
- data/docs/guides/advanced-features/progress-tracking.adoc +124 -0
- data/docs/guides/advanced-features/streaming.adoc +142 -0
- data/docs/guides/archive-formats/gzip-format.adoc +105 -0
- data/docs/guides/archive-formats/index.adoc +160 -0
- data/docs/guides/archive-formats/ole-format.adoc +151 -0
- data/docs/guides/archive-formats/rar-format.adoc +104 -0
- data/docs/guides/archive-formats/rar5.adoc +521 -0
- data/docs/guides/archive-formats/rpm-format.adoc +108 -0
- data/docs/guides/archive-formats/seven-zip-format.adoc +35 -0
- data/docs/guides/archive-formats/tar-format.adoc +106 -0
- data/docs/guides/archive-formats/xz-format.adoc +118 -0
- data/docs/guides/archive-formats/zip-format.adoc +35 -0
- data/docs/guides/compression-algorithms/bzip2.adoc +114 -0
- data/docs/guides/compression-algorithms/deflate.adoc +313 -0
- data/docs/guides/compression-algorithms/index.adoc +190 -0
- data/docs/guides/compression-algorithms/lzma.adoc +394 -0
- data/docs/guides/compression-algorithms/lzma2.adoc +244 -0
- data/docs/guides/compression-algorithms/ppmd.adoc +313 -0
- data/docs/guides/compression-algorithms/zstandard.adoc +296 -0
- data/docs/guides/creating-archives.adoc +348 -0
- data/docs/guides/extracting-archives.adoc +53 -0
- data/docs/guides/format-conversion.adoc +64 -0
- data/docs/guides/index.adoc +49 -0
- data/docs/guides/migration-rubyzip.adoc +217 -0
- data/docs/guides/parity-archives.adoc +605 -0
- data/docs/guides/performance-tuning.adoc +88 -0
- data/docs/index.adoc +228 -0
- data/docs/lychee.toml +67 -0
- data/docs/reference/api/overview.adoc +187 -0
- data/docs/reference/cli/compress-command.adoc +114 -0
- data/docs/reference/cli/overview.adoc +140 -0
- data/docs/reference/index.adoc +26 -0
- data/docs/resources/faq.adoc +185 -0
- data/docs/resources/quick-reference.adoc +222 -0
- data/docs/rust-backend.md +0 -0
- data/docs/troubleshooting/index.adoc +207 -0
- data/docs/xar_format.md +216 -0
- data/examples/api_comparison.rb +205 -0
- data/examples/deflate64_example.rb +96 -0
- data/examples/par2_demo.rb +121 -0
- data/examples/quick_start_native.rb +150 -0
- data/examples/quick_start_rubyzip.rb +115 -0
- data/examples/rubyzip_compatibility_demo.rb +194 -0
- data/exe/omnizip +27 -0
- data/lib/omnizip/algorithm.rb +176 -0
- data/lib/omnizip/algorithm_registry.rb +65 -0
- data/lib/omnizip/algorithms/.keep +0 -0
- data/lib/omnizip/algorithms/bzip2/bwt.rb +236 -0
- data/lib/omnizip/algorithms/bzip2/bz2.rb +687 -0
- data/lib/omnizip/algorithms/bzip2/rle.rb +146 -0
- data/lib/omnizip/algorithms/bzip2.rb +108 -0
- data/lib/omnizip/algorithms/deflate/constants.rb +28 -0
- data/lib/omnizip/algorithms/deflate/decoder.rb +37 -0
- data/lib/omnizip/algorithms/deflate/encoder.rb +45 -0
- data/lib/omnizip/algorithms/deflate.rb +135 -0
- data/lib/omnizip/algorithms/deflate64/constants.rb +45 -0
- data/lib/omnizip/algorithms/deflate64/decoder.rb +151 -0
- data/lib/omnizip/algorithms/deflate64/encoder.rb +95 -0
- data/lib/omnizip/algorithms/deflate64/huffman_coder.rb +352 -0
- data/lib/omnizip/algorithms/deflate64/lz77_encoder.rb +140 -0
- data/lib/omnizip/algorithms/deflate64.rb +118 -0
- data/lib/omnizip/algorithms/lzma/bit_model.rb +120 -0
- data/lib/omnizip/algorithms/lzma/constants.rb +112 -0
- data/lib/omnizip/algorithms/lzma/decoder.rb +146 -0
- data/lib/omnizip/algorithms/lzma/dictionary.rb +70 -0
- data/lib/omnizip/algorithms/lzma/distance_coder.rb +326 -0
- data/lib/omnizip/algorithms/lzma/encoder.rb +139 -0
- data/lib/omnizip/algorithms/lzma/length_coder.rb +172 -0
- data/lib/omnizip/algorithms/lzma/literal_decoder.rb +204 -0
- data/lib/omnizip/algorithms/lzma/literal_encoder.rb +208 -0
- data/lib/omnizip/algorithms/lzma/lzip_decoder.rb +368 -0
- data/lib/omnizip/algorithms/lzma/lzma1_encoder.rb +105 -0
- data/lib/omnizip/algorithms/lzma/lzma_alone_decoder.rb +194 -0
- data/lib/omnizip/algorithms/lzma/lzma_state.rb +128 -0
- data/lib/omnizip/algorithms/lzma/match.rb +32 -0
- data/lib/omnizip/algorithms/lzma/match_finder.rb +233 -0
- data/lib/omnizip/algorithms/lzma/match_finder_config.rb +142 -0
- data/lib/omnizip/algorithms/lzma/match_finder_factory.rb +84 -0
- data/lib/omnizip/algorithms/lzma/optimal_encoder.rb +159 -0
- data/lib/omnizip/algorithms/lzma/probability_models.rb +72 -0
- data/lib/omnizip/algorithms/lzma/range_coder.rb +82 -0
- data/lib/omnizip/algorithms/lzma/range_decoder.rb +274 -0
- data/lib/omnizip/algorithms/lzma/range_encoder.rb +202 -0
- data/lib/omnizip/algorithms/lzma/state.rb +127 -0
- data/lib/omnizip/algorithms/lzma/xz_buffered_range_encoder.rb +323 -0
- data/lib/omnizip/algorithms/lzma/xz_encoder.rb +420 -0
- data/lib/omnizip/algorithms/lzma/xz_encoder_fast.rb +640 -0
- data/lib/omnizip/algorithms/lzma/xz_match_finder_adapter.rb +224 -0
- data/lib/omnizip/algorithms/lzma/xz_price_calculator.rb +167 -0
- data/lib/omnizip/algorithms/lzma/xz_probability_models.rb +258 -0
- data/lib/omnizip/algorithms/lzma/xz_range_encoder.rb +223 -0
- data/lib/omnizip/algorithms/lzma/xz_range_encoder_exact.rb +314 -0
- data/lib/omnizip/algorithms/lzma/xz_state.rb +108 -0
- data/lib/omnizip/algorithms/lzma/xz_utils_decoder.rb +1311 -0
- data/lib/omnizip/algorithms/lzma.rb +266 -0
- data/lib/omnizip/algorithms/lzma2/chunk_manager.rb +180 -0
- data/lib/omnizip/algorithms/lzma2/constants.rb +38 -0
- data/lib/omnizip/algorithms/lzma2/encoder.rb +145 -0
- data/lib/omnizip/algorithms/lzma2/lzma2_chunk.rb +165 -0
- data/lib/omnizip/algorithms/lzma2/properties.rb +179 -0
- data/lib/omnizip/algorithms/lzma2/simple_lzma2_encoder.rb +122 -0
- data/lib/omnizip/algorithms/lzma2/xz_encoder_adapter.rb +85 -0
- data/lib/omnizip/algorithms/lzma2.rb +133 -0
- data/lib/omnizip/algorithms/ppmd7/constants.rb +74 -0
- data/lib/omnizip/algorithms/ppmd7/context.rb +151 -0
- data/lib/omnizip/algorithms/ppmd7/decoder.rb +127 -0
- data/lib/omnizip/algorithms/ppmd7/encoder.rb +153 -0
- data/lib/omnizip/algorithms/ppmd7/model.rb +245 -0
- data/lib/omnizip/algorithms/ppmd7/symbol_state.rb +57 -0
- data/lib/omnizip/algorithms/ppmd7.rb +146 -0
- data/lib/omnizip/algorithms/ppmd8/constants.rb +61 -0
- data/lib/omnizip/algorithms/ppmd8/context.rb +32 -0
- data/lib/omnizip/algorithms/ppmd8/decoder.rb +104 -0
- data/lib/omnizip/algorithms/ppmd8/encoder.rb +135 -0
- data/lib/omnizip/algorithms/ppmd8/model.rb +246 -0
- data/lib/omnizip/algorithms/ppmd8/restoration_method.rb +78 -0
- data/lib/omnizip/algorithms/ppmd8.rb +122 -0
- data/lib/omnizip/algorithms/ppmd_base.rb +142 -0
- data/lib/omnizip/algorithms/registration.rb +28 -0
- data/lib/omnizip/algorithms/zstandard/constants.rb +158 -0
- data/lib/omnizip/algorithms/zstandard/decoder.rb +249 -0
- data/lib/omnizip/algorithms/zstandard/dictionary.rb +73 -0
- data/lib/omnizip/algorithms/zstandard/encoder.rb +294 -0
- data/lib/omnizip/algorithms/zstandard/frame/block.rb +143 -0
- data/lib/omnizip/algorithms/zstandard/frame/header.rb +233 -0
- data/lib/omnizip/algorithms/zstandard/frame.rb +33 -0
- data/lib/omnizip/algorithms/zstandard/fse/bitstream.rb +183 -0
- data/lib/omnizip/algorithms/zstandard/fse/encoder.rb +534 -0
- data/lib/omnizip/algorithms/zstandard/fse/interleaved.rb +92 -0
- data/lib/omnizip/algorithms/zstandard/fse/table.rb +188 -0
- data/lib/omnizip/algorithms/zstandard/fse/table_description.rb +203 -0
- data/lib/omnizip/algorithms/zstandard/fse.rb +53 -0
- data/lib/omnizip/algorithms/zstandard/huffman.rb +276 -0
- data/lib/omnizip/algorithms/zstandard/huffman_encoder.rb +327 -0
- data/lib/omnizip/algorithms/zstandard/ldm.rb +121 -0
- data/lib/omnizip/algorithms/zstandard/literals.rb +241 -0
- data/lib/omnizip/algorithms/zstandard/literals_encoder.rb +96 -0
- data/lib/omnizip/algorithms/zstandard/match_finder.rb +483 -0
- data/lib/omnizip/algorithms/zstandard/sequences.rb +350 -0
- data/lib/omnizip/algorithms/zstandard/sequences_encoder.rb +333 -0
- data/lib/omnizip/algorithms/zstandard/xxhash.rb +159 -0
- data/lib/omnizip/algorithms/zstandard.rb +210 -0
- data/lib/omnizip/algorithms.rb +35 -0
- data/lib/omnizip/archive/builder.rb +48 -0
- data/lib/omnizip/archive/reader_session.rb +67 -0
- data/lib/omnizip/archive.rb +86 -0
- data/lib/omnizip/archive_handler.rb +82 -0
- data/lib/omnizip/archive_handlers/cpio_handler.rb +47 -0
- data/lib/omnizip/archive_handlers/iso_handler.rb +54 -0
- data/lib/omnizip/archive_handlers/ole_handler.rb +37 -0
- data/lib/omnizip/archive_handlers/rar_handler.rb +96 -0
- data/lib/omnizip/archive_handlers/rpm_handler.rb +45 -0
- data/lib/omnizip/archive_handlers/seven_zip_handler.rb +89 -0
- data/lib/omnizip/archive_handlers/tar_handler.rb +75 -0
- data/lib/omnizip/archive_handlers/xar_handler.rb +49 -0
- data/lib/omnizip/archive_handlers/zip_handler.rb +115 -0
- data/lib/omnizip/archive_handlers.rb +18 -0
- data/lib/omnizip/backends.rb +160 -0
- data/lib/omnizip/buffer/memory_archive.rb +246 -0
- data/lib/omnizip/buffer/memory_extractor.rb +234 -0
- data/lib/omnizip/buffer/seven_zip_bridge.rb +171 -0
- data/lib/omnizip/buffer.rb +187 -0
- data/lib/omnizip/checksum_registry.rb +41 -0
- data/lib/omnizip/checksums/crc32.rb +101 -0
- data/lib/omnizip/checksums/crc64.rb +102 -0
- data/lib/omnizip/checksums/crc_base.rb +158 -0
- data/lib/omnizip/checksums/registration.rb +16 -0
- data/lib/omnizip/checksums/verifier.rb +130 -0
- data/lib/omnizip/checksums.rb +11 -0
- data/lib/omnizip/chunked/memory_manager.rb +194 -0
- data/lib/omnizip/chunked/reader.rb +78 -0
- data/lib/omnizip/chunked/writer.rb +123 -0
- data/lib/omnizip/chunked.rb +123 -0
- data/lib/omnizip/cli/output_formatter.rb +112 -0
- data/lib/omnizip/cli.rb +604 -0
- data/lib/omnizip/commands/.keep +0 -0
- data/lib/omnizip/commands/archive_create_command.rb +245 -0
- data/lib/omnizip/commands/archive_extract_command.rb +231 -0
- data/lib/omnizip/commands/archive_list_command.rb +204 -0
- data/lib/omnizip/commands/archive_repair_command.rb +129 -0
- data/lib/omnizip/commands/archive_verify_command.rb +115 -0
- data/lib/omnizip/commands/compress_command.rb +115 -0
- data/lib/omnizip/commands/decompress_command.rb +149 -0
- data/lib/omnizip/commands/list_command.rb +51 -0
- data/lib/omnizip/commands/metadata_command.rb +215 -0
- data/lib/omnizip/commands/parity_create_command.rb +114 -0
- data/lib/omnizip/commands/parity_repair_command.rb +120 -0
- data/lib/omnizip/commands/parity_verify_command.rb +122 -0
- data/lib/omnizip/commands/profile_list_command.rb +54 -0
- data/lib/omnizip/commands/profile_show_command.rb +44 -0
- data/lib/omnizip/commands.rb +21 -0
- data/lib/omnizip/convenience.rb +389 -0
- data/lib/omnizip/converter/conversion_registry.rb +50 -0
- data/lib/omnizip/converter/conversion_strategy.rb +108 -0
- data/lib/omnizip/converter/extract_repack_strategy.rb +51 -0
- data/lib/omnizip/converter/seven_zip_to_zip_strategy.rb +43 -0
- data/lib/omnizip/converter/zip_to_seven_zip_strategy.rb +54 -0
- data/lib/omnizip/converter.rb +124 -0
- data/lib/omnizip/crypto/aes256/cipher.rb +104 -0
- data/lib/omnizip/crypto/aes256/constants.rb +28 -0
- data/lib/omnizip/crypto/aes256/key_derivation.rb +100 -0
- data/lib/omnizip/crypto/aes256.rb +102 -0
- data/lib/omnizip/crypto.rb +11 -0
- data/lib/omnizip/entry.rb +44 -0
- data/lib/omnizip/error.rb +110 -0
- data/lib/omnizip/eta/exponential_smoothing_estimator.rb +95 -0
- data/lib/omnizip/eta/moving_average_estimator.rb +96 -0
- data/lib/omnizip/eta/rate_calculator.rb +104 -0
- data/lib/omnizip/eta/sample_history.rb +143 -0
- data/lib/omnizip/eta/time_estimator.rb +106 -0
- data/lib/omnizip/eta.rb +68 -0
- data/lib/omnizip/extraction/filter_chain.rb +179 -0
- data/lib/omnizip/extraction/glob_pattern.rb +140 -0
- data/lib/omnizip/extraction/pattern_matcher.rb +66 -0
- data/lib/omnizip/extraction/predicate_pattern.rb +52 -0
- data/lib/omnizip/extraction/regex_pattern.rb +50 -0
- data/lib/omnizip/extraction/selective_extractor.rb +247 -0
- data/lib/omnizip/extraction.rb +115 -0
- data/lib/omnizip/file_type/mime_classifier.rb +144 -0
- data/lib/omnizip/file_type.rb +117 -0
- data/lib/omnizip/filter.rb +141 -0
- data/lib/omnizip/filter_pipeline.rb +108 -0
- data/lib/omnizip/filter_registry.rb +113 -0
- data/lib/omnizip/filters/bcj.rb +277 -0
- data/lib/omnizip/filters/bcj2/constants.rb +53 -0
- data/lib/omnizip/filters/bcj2/decoder.rb +263 -0
- data/lib/omnizip/filters/bcj2/encoder.rb +58 -0
- data/lib/omnizip/filters/bcj2/stream_data.rb +91 -0
- data/lib/omnizip/filters/bcj2.rb +93 -0
- data/lib/omnizip/filters/bcj_arm.rb +174 -0
- data/lib/omnizip/filters/bcj_arm64.rb +242 -0
- data/lib/omnizip/filters/bcj_ia64.rb +194 -0
- data/lib/omnizip/filters/bcj_ppc.rb +188 -0
- data/lib/omnizip/filters/bcj_sparc.rb +174 -0
- data/lib/omnizip/filters/bcj_x86.rb +191 -0
- data/lib/omnizip/filters/delta.rb +195 -0
- data/lib/omnizip/filters/xz_delta.rb +258 -0
- data/lib/omnizip/filters.rb +20 -0
- data/lib/omnizip/format_detector.rb +166 -0
- data/lib/omnizip/formats/.keep +0 -0
- data/lib/omnizip/formats/bzip2_file.rb +159 -0
- data/lib/omnizip/formats/cpio/bounded_io.rb +66 -0
- data/lib/omnizip/formats/cpio/constants.rb +55 -0
- data/lib/omnizip/formats/cpio/entry.rb +389 -0
- data/lib/omnizip/formats/cpio/reader.rb +194 -0
- data/lib/omnizip/formats/cpio/writer.rb +232 -0
- data/lib/omnizip/formats/cpio.rb +132 -0
- data/lib/omnizip/formats/format_spec_loader.rb +228 -0
- data/lib/omnizip/formats/gzip.rb +236 -0
- data/lib/omnizip/formats/iso/directory_builder.rb +321 -0
- data/lib/omnizip/formats/iso/directory_record.rb +162 -0
- data/lib/omnizip/formats/iso/joliet.rb +204 -0
- data/lib/omnizip/formats/iso/path_table.rb +125 -0
- data/lib/omnizip/formats/iso/reader.rb +194 -0
- data/lib/omnizip/formats/iso/rock_ridge.rb +349 -0
- data/lib/omnizip/formats/iso/volume_builder.rb +319 -0
- data/lib/omnizip/formats/iso/volume_descriptor.rb +168 -0
- data/lib/omnizip/formats/iso/writer.rb +543 -0
- data/lib/omnizip/formats/iso.rb +133 -0
- data/lib/omnizip/formats/lzip.rb +161 -0
- data/lib/omnizip/formats/lzma_alone.rb +149 -0
- data/lib/omnizip/formats/msi/cab_extractor.rb +181 -0
- data/lib/omnizip/formats/msi/constants.rb +157 -0
- data/lib/omnizip/formats/msi/directory_resolver.rb +188 -0
- data/lib/omnizip/formats/msi/entry.rb +134 -0
- data/lib/omnizip/formats/msi/reader.rb +301 -0
- data/lib/omnizip/formats/msi/string_pool.rb +246 -0
- data/lib/omnizip/formats/msi/table_parser.rb +244 -0
- data/lib/omnizip/formats/msi.rb +73 -0
- data/lib/omnizip/formats/ole/allocation_table.rb +263 -0
- data/lib/omnizip/formats/ole/constants.rb +61 -0
- data/lib/omnizip/formats/ole/dirent.rb +439 -0
- data/lib/omnizip/formats/ole/header.rb +199 -0
- data/lib/omnizip/formats/ole/ranges_io.rb +347 -0
- data/lib/omnizip/formats/ole/storage.rb +482 -0
- data/lib/omnizip/formats/ole/types/variant.rb +338 -0
- data/lib/omnizip/formats/ole.rb +143 -0
- data/lib/omnizip/formats/rar/archive_repairer.rb +240 -0
- data/lib/omnizip/formats/rar/archive_verifier.rb +192 -0
- data/lib/omnizip/formats/rar/block_parser.rb +282 -0
- data/lib/omnizip/formats/rar/compression/bit_stream.rb +180 -0
- data/lib/omnizip/formats/rar/compression/dispatcher.rb +210 -0
- data/lib/omnizip/formats/rar/compression/lz77_huffman/decoder.rb +212 -0
- data/lib/omnizip/formats/rar/compression/lz77_huffman/encoder.rb +154 -0
- data/lib/omnizip/formats/rar/compression/lz77_huffman/huffman_builder.rb +217 -0
- data/lib/omnizip/formats/rar/compression/lz77_huffman/huffman_coder.rb +189 -0
- data/lib/omnizip/formats/rar/compression/lz77_huffman/match_finder.rb +135 -0
- data/lib/omnizip/formats/rar/compression/lz77_huffman/sliding_window.rb +165 -0
- data/lib/omnizip/formats/rar/compression/lz77_huffman.rb +25 -0
- data/lib/omnizip/formats/rar/compression/ppmd/context.rb +103 -0
- data/lib/omnizip/formats/rar/compression/ppmd/decoder.rb +238 -0
- data/lib/omnizip/formats/rar/compression/ppmd/encoder.rb +250 -0
- data/lib/omnizip/formats/rar/compression/ppmd.rb +16 -0
- data/lib/omnizip/formats/rar/compression.rb +17 -0
- data/lib/omnizip/formats/rar/compression_method_registry.rb +106 -0
- data/lib/omnizip/formats/rar/constants.rb +88 -0
- data/lib/omnizip/formats/rar/decompressor.rb +316 -0
- data/lib/omnizip/formats/rar/external_writer.rb +311 -0
- data/lib/omnizip/formats/rar/header.rb +209 -0
- data/lib/omnizip/formats/rar/license_validator.rb +111 -0
- data/lib/omnizip/formats/rar/models/rar_archive.rb +77 -0
- data/lib/omnizip/formats/rar/models/rar_entry.rb +65 -0
- data/lib/omnizip/formats/rar/models/rar_volume.rb +56 -0
- data/lib/omnizip/formats/rar/models.rb +14 -0
- data/lib/omnizip/formats/rar/parity_handler.rb +299 -0
- data/lib/omnizip/formats/rar/rar5/compression/lzma.rb +200 -0
- data/lib/omnizip/formats/rar/rar5/compression/lzss.rb +584 -0
- data/lib/omnizip/formats/rar/rar5/compression/store.rb +60 -0
- data/lib/omnizip/formats/rar/rar5/crc32.rb +39 -0
- data/lib/omnizip/formats/rar/rar5/encryption/aes256_cbc.rb +96 -0
- data/lib/omnizip/formats/rar/rar5/encryption/encryption_header.rb +114 -0
- data/lib/omnizip/formats/rar/rar5/encryption/encryption_manager.rb +162 -0
- data/lib/omnizip/formats/rar/rar5/encryption/key_derivation.rb +97 -0
- data/lib/omnizip/formats/rar/rar5/header.rb +208 -0
- data/lib/omnizip/formats/rar/rar5/models/encryption_options.rb +74 -0
- data/lib/omnizip/formats/rar/rar5/models/recovery_options.rb +63 -0
- data/lib/omnizip/formats/rar/rar5/models/solid_options.rb +63 -0
- data/lib/omnizip/formats/rar/rar5/models/volume_options.rb +74 -0
- data/lib/omnizip/formats/rar/rar5/multi_volume/ARCHITECTURE.md +290 -0
- data/lib/omnizip/formats/rar/rar5/multi_volume/volume_manager.rb +260 -0
- data/lib/omnizip/formats/rar/rar5/multi_volume/volume_splitter.rb +155 -0
- data/lib/omnizip/formats/rar/rar5/multi_volume/volume_writer.rb +176 -0
- data/lib/omnizip/formats/rar/rar5/solid/solid_encoder.rb +108 -0
- data/lib/omnizip/formats/rar/rar5/solid/solid_manager.rb +139 -0
- data/lib/omnizip/formats/rar/rar5/solid/solid_stream.rb +121 -0
- data/lib/omnizip/formats/rar/rar5/vint.rb +53 -0
- data/lib/omnizip/formats/rar/rar5/writer.rb +540 -0
- data/lib/omnizip/formats/rar/rar_format_base.rb +239 -0
- data/lib/omnizip/formats/rar/reader.rb +377 -0
- data/lib/omnizip/formats/rar/recovery_record.rb +245 -0
- data/lib/omnizip/formats/rar/volume_manager.rb +166 -0
- data/lib/omnizip/formats/rar/writer.rb +437 -0
- data/lib/omnizip/formats/rar.rb +193 -0
- data/lib/omnizip/formats/rar3/compressor.rb +71 -0
- data/lib/omnizip/formats/rar3/decompressor.rb +64 -0
- data/lib/omnizip/formats/rar3/reader.rb +107 -0
- data/lib/omnizip/formats/rar3/writer.rb +220 -0
- data/lib/omnizip/formats/rar3.rb +15 -0
- data/lib/omnizip/formats/rar5/compressor.rb +71 -0
- data/lib/omnizip/formats/rar5/decompressor.rb +64 -0
- data/lib/omnizip/formats/rar5/reader.rb +130 -0
- data/lib/omnizip/formats/rar5/writer.rb +65 -0
- data/lib/omnizip/formats/rar5.rb +15 -0
- data/lib/omnizip/formats/rpm/constants.rb +58 -0
- data/lib/omnizip/formats/rpm/entry.rb +106 -0
- data/lib/omnizip/formats/rpm/header.rb +106 -0
- data/lib/omnizip/formats/rpm/lead.rb +132 -0
- data/lib/omnizip/formats/rpm/tag.rb +228 -0
- data/lib/omnizip/formats/rpm/writer.rb +652 -0
- data/lib/omnizip/formats/rpm.rb +458 -0
- data/lib/omnizip/formats/seven_zip/bcj2_stream_decompressor.rb +274 -0
- data/lib/omnizip/formats/seven_zip/coder_chain.rb +169 -0
- data/lib/omnizip/formats/seven_zip/constants.rb +126 -0
- data/lib/omnizip/formats/seven_zip/encoded_header.rb +110 -0
- data/lib/omnizip/formats/seven_zip/encrypted_header.rb +139 -0
- data/lib/omnizip/formats/seven_zip/file_collector.rb +143 -0
- data/lib/omnizip/formats/seven_zip/header.rb +102 -0
- data/lib/omnizip/formats/seven_zip/header_encryptor.rb +132 -0
- data/lib/omnizip/formats/seven_zip/header_writer.rb +425 -0
- data/lib/omnizip/formats/seven_zip/models/coder_info.rb +30 -0
- data/lib/omnizip/formats/seven_zip/models/file_entry.rb +65 -0
- data/lib/omnizip/formats/seven_zip/models/folder.rb +67 -0
- data/lib/omnizip/formats/seven_zip/models/stream_info.rb +42 -0
- data/lib/omnizip/formats/seven_zip/models.rb +20 -0
- data/lib/omnizip/formats/seven_zip/parser.rb +671 -0
- data/lib/omnizip/formats/seven_zip/reader.rb +626 -0
- data/lib/omnizip/formats/seven_zip/split_archive_reader.rb +611 -0
- data/lib/omnizip/formats/seven_zip/split_archive_writer.rb +308 -0
- data/lib/omnizip/formats/seven_zip/stream_compressor.rb +151 -0
- data/lib/omnizip/formats/seven_zip/stream_decompressor.rb +166 -0
- data/lib/omnizip/formats/seven_zip/writer.rb +801 -0
- data/lib/omnizip/formats/seven_zip.rb +179 -0
- data/lib/omnizip/formats/tar/constants.rb +73 -0
- data/lib/omnizip/formats/tar/entry.rb +98 -0
- data/lib/omnizip/formats/tar/header.rb +206 -0
- data/lib/omnizip/formats/tar/reader.rb +119 -0
- data/lib/omnizip/formats/tar/writer.rb +212 -0
- data/lib/omnizip/formats/tar.rb +74 -0
- data/lib/omnizip/formats/xar/constants.rb +119 -0
- data/lib/omnizip/formats/xar/entry.rb +268 -0
- data/lib/omnizip/formats/xar/header.rb +223 -0
- data/lib/omnizip/formats/xar/reader.rb +400 -0
- data/lib/omnizip/formats/xar/toc.rb +570 -0
- data/lib/omnizip/formats/xar/writer.rb +461 -0
- data/lib/omnizip/formats/xar.rb +145 -0
- data/lib/omnizip/formats/xz/reader.rb +121 -0
- data/lib/omnizip/formats/xz/writer.rb +416 -0
- data/lib/omnizip/formats/xz.rb +210 -0
- data/lib/omnizip/formats/xz_const.rb +49 -0
- data/lib/omnizip/formats/xz_impl/block_decoder.rb +761 -0
- data/lib/omnizip/formats/xz_impl/block_encoder.rb +304 -0
- data/lib/omnizip/formats/xz_impl/block_header.rb +210 -0
- data/lib/omnizip/formats/xz_impl/block_header_parser.rb +182 -0
- data/lib/omnizip/formats/xz_impl/index_decoder.rb +174 -0
- data/lib/omnizip/formats/xz_impl/index_encoder.rb +120 -0
- data/lib/omnizip/formats/xz_impl/stream_decoder.rb +470 -0
- data/lib/omnizip/formats/xz_impl/stream_encoder.rb +95 -0
- data/lib/omnizip/formats/xz_impl/stream_footer.rb +79 -0
- data/lib/omnizip/formats/xz_impl/stream_footer_parser.rb +115 -0
- data/lib/omnizip/formats/xz_impl/stream_header.rb +53 -0
- data/lib/omnizip/formats/xz_impl/stream_header_parser.rb +106 -0
- data/lib/omnizip/formats/xz_impl/vli.rb +128 -0
- data/lib/omnizip/formats/xz_impl.rb +52 -0
- data/lib/omnizip/formats/zip/central_directory_header.rb +223 -0
- data/lib/omnizip/formats/zip/constants.rb +69 -0
- data/lib/omnizip/formats/zip/end_of_central_directory.rb +132 -0
- data/lib/omnizip/formats/zip/local_file_header.rb +136 -0
- data/lib/omnizip/formats/zip/reader.rb +376 -0
- data/lib/omnizip/formats/zip/unix_extra_field.rb +153 -0
- data/lib/omnizip/formats/zip/writer.rb +489 -0
- data/lib/omnizip/formats/zip/zip64_end_of_central_directory.rb +102 -0
- data/lib/omnizip/formats/zip/zip64_end_of_central_directory_locator.rb +64 -0
- data/lib/omnizip/formats/zip/zip64_extra_field.rb +112 -0
- data/lib/omnizip/formats/zip.rb +50 -0
- data/lib/omnizip/formats.rb +29 -0
- data/lib/omnizip/implementations/base/lzma2_decoder_base.rb +75 -0
- data/lib/omnizip/implementations/base/lzma2_encoder_base.rb +128 -0
- data/lib/omnizip/implementations/base/lzma_decoder_base.rb +83 -0
- data/lib/omnizip/implementations/base/lzma_encoder_base.rb +108 -0
- data/lib/omnizip/implementations/base/state_machine_base.rb +182 -0
- data/lib/omnizip/implementations/base.rb +19 -0
- data/lib/omnizip/implementations/rust/archive.rb +93 -0
- data/lib/omnizip/implementations/rust/library.rb +221 -0
- data/lib/omnizip/implementations/rust.rb +26 -0
- data/lib/omnizip/implementations/seven_zip/lzma/decoder.rb +428 -0
- data/lib/omnizip/implementations/seven_zip/lzma/encoder.rb +456 -0
- data/lib/omnizip/implementations/seven_zip/lzma/match_finder.rb +285 -0
- data/lib/omnizip/implementations/seven_zip/lzma/range_decoder.rb +197 -0
- data/lib/omnizip/implementations/seven_zip/lzma/range_encoder.rb +194 -0
- data/lib/omnizip/implementations/seven_zip/lzma/state_machine.rb +139 -0
- data/lib/omnizip/implementations/seven_zip/lzma.rb +21 -0
- data/lib/omnizip/implementations/seven_zip/lzma2/encoder.rb +56 -0
- data/lib/omnizip/implementations/seven_zip/lzma2.rb +12 -0
- data/lib/omnizip/implementations/seven_zip.rb +11 -0
- data/lib/omnizip/implementations/xz_utils/lzma2/decoder.rb +547 -0
- data/lib/omnizip/implementations/xz_utils/lzma2/encoder.rb +748 -0
- data/lib/omnizip/implementations/xz_utils/lzma2.rb +13 -0
- data/lib/omnizip/implementations/xz_utils.rb +10 -0
- data/lib/omnizip/implementations.rb +25 -0
- data/lib/omnizip/io/buffered_input.rb +147 -0
- data/lib/omnizip/io/buffered_output.rb +106 -0
- data/lib/omnizip/io/source.rb +143 -0
- data/lib/omnizip/io/stream_manager.rb +117 -0
- data/lib/omnizip/io.rb +15 -0
- data/lib/omnizip/link_handler/hard_link.rb +79 -0
- data/lib/omnizip/link_handler/symbolic_link.rb +74 -0
- data/lib/omnizip/link_handler.rb +129 -0
- data/lib/omnizip/metadata/archive_metadata.rb +114 -0
- data/lib/omnizip/metadata/entry_metadata.rb +153 -0
- data/lib/omnizip/metadata/metadata_editor.rb +169 -0
- data/lib/omnizip/metadata/metadata_registry.rb +71 -0
- data/lib/omnizip/metadata/metadata_validator.rb +101 -0
- data/lib/omnizip/metadata.rb +58 -0
- data/lib/omnizip/models/.keep +0 -0
- data/lib/omnizip/models/algorithm_metadata.rb +41 -0
- data/lib/omnizip/models/attribute_apply.rb +40 -0
- data/lib/omnizip/models/compression_options.rb +53 -0
- data/lib/omnizip/models/conversion_options.rb +79 -0
- data/lib/omnizip/models/conversion_result.rb +141 -0
- data/lib/omnizip/models/eta_result.rb +45 -0
- data/lib/omnizip/models/extraction_rule.rb +115 -0
- data/lib/omnizip/models/filter_chain.rb +142 -0
- data/lib/omnizip/models/filter_config.rb +148 -0
- data/lib/omnizip/models/match_result.rb +141 -0
- data/lib/omnizip/models/optimization_suggestion.rb +95 -0
- data/lib/omnizip/models/parallel_options.rb +116 -0
- data/lib/omnizip/models/performance_result.rb +85 -0
- data/lib/omnizip/models/profile_report.rb +116 -0
- data/lib/omnizip/models/progress_options.rb +39 -0
- data/lib/omnizip/models/split_options.rb +116 -0
- data/lib/omnizip/optimization_registry.rb +45 -0
- data/lib/omnizip/parallel/engine.rb +52 -0
- data/lib/omnizip/parallel/job_queue.rb +209 -0
- data/lib/omnizip/parallel/job_scheduler.rb +225 -0
- data/lib/omnizip/parallel/parallel_compressor.rb +326 -0
- data/lib/omnizip/parallel/parallel_extractor.rb +238 -0
- data/lib/omnizip/parallel/thread_pool.rb +60 -0
- data/lib/omnizip/parallel/worker_pool.rb +227 -0
- data/lib/omnizip/parallel.rb +156 -0
- data/lib/omnizip/parity/chunked_block_processor.rb +194 -0
- data/lib/omnizip/parity/galois16.rb +145 -0
- data/lib/omnizip/parity/models/creator_packet.rb +71 -0
- data/lib/omnizip/parity/models/file_description_packet.rb +131 -0
- data/lib/omnizip/parity/models/ifsc_packet.rb +111 -0
- data/lib/omnizip/parity/models/main_packet.rb +126 -0
- data/lib/omnizip/parity/models/packet.rb +156 -0
- data/lib/omnizip/parity/models/packet_registry.rb +102 -0
- data/lib/omnizip/parity/models/recovery_slice_packet.rb +76 -0
- data/lib/omnizip/parity/models.rb +27 -0
- data/lib/omnizip/parity/par2_creator.rb +496 -0
- data/lib/omnizip/parity/par2_repairer.rb +409 -0
- data/lib/omnizip/parity/par2_verifier.rb +373 -0
- data/lib/omnizip/parity/par2cmdline_algorithm.rb +108 -0
- data/lib/omnizip/parity/par2cmdline_coefficients.rb +78 -0
- data/lib/omnizip/parity/reed_solomon_decoder.rb +263 -0
- data/lib/omnizip/parity/reed_solomon_encoder.rb +108 -0
- data/lib/omnizip/parity/reed_solomon_matrix.rb +339 -0
- data/lib/omnizip/parity.rb +207 -0
- data/lib/omnizip/password/encryption_registry.rb +26 -0
- data/lib/omnizip/password/encryption_strategy.rb +96 -0
- data/lib/omnizip/password/password_validator.rb +129 -0
- data/lib/omnizip/password/winzip_aes_strategy.rb +190 -0
- data/lib/omnizip/password/zip_crypto_strategy.rb +135 -0
- data/lib/omnizip/password.rb +88 -0
- data/lib/omnizip/pipe/stream_compressor.rb +124 -0
- data/lib/omnizip/pipe/stream_decompressor.rb +173 -0
- data/lib/omnizip/pipe.rb +120 -0
- data/lib/omnizip/platform/ntfs_streams.rb +200 -0
- data/lib/omnizip/platform.rb +189 -0
- data/lib/omnizip/profile/archive_profile.rb +36 -0
- data/lib/omnizip/profile/balanced_profile.rb +31 -0
- data/lib/omnizip/profile/binary_profile.rb +33 -0
- data/lib/omnizip/profile/compression_profile.rb +157 -0
- data/lib/omnizip/profile/custom_profile.rb +155 -0
- data/lib/omnizip/profile/fast_profile.rb +31 -0
- data/lib/omnizip/profile/maximum_profile.rb +31 -0
- data/lib/omnizip/profile/profile_detector.rb +108 -0
- data/lib/omnizip/profile/profile_registry.rb +160 -0
- data/lib/omnizip/profile/text_profile.rb +33 -0
- data/lib/omnizip/profile.rb +261 -0
- data/lib/omnizip/profiler/memory_profiler.rb +66 -0
- data/lib/omnizip/profiler/method_profiler.rb +49 -0
- data/lib/omnizip/profiler/report_generator.rb +158 -0
- data/lib/omnizip/profiler.rb +192 -0
- data/lib/omnizip/progress/callback_reporter.rb +34 -0
- data/lib/omnizip/progress/console_reporter.rb +59 -0
- data/lib/omnizip/progress/log_reporter.rb +89 -0
- data/lib/omnizip/progress/operation_progress.rb +118 -0
- data/lib/omnizip/progress/progress_bar.rb +156 -0
- data/lib/omnizip/progress/progress_reporter.rb +40 -0
- data/lib/omnizip/progress/progress_tracker.rb +215 -0
- data/lib/omnizip/progress/silent_reporter.rb +22 -0
- data/lib/omnizip/progress.rb +131 -0
- data/lib/omnizip/registry.rb +111 -0
- data/lib/omnizip/rubyzip_compat.rb +61 -0
- data/lib/omnizip/temp/safe_extract.rb +124 -0
- data/lib/omnizip/temp/temp_file.rb +123 -0
- data/lib/omnizip/temp/temp_file_pool.rb +109 -0
- data/lib/omnizip/temp.rb +184 -0
- data/lib/omnizip/version.rb +5 -0
- data/lib/omnizip/zip/entry.rb +160 -0
- data/lib/omnizip/zip/file.rb +485 -0
- data/lib/omnizip/zip/input_stream.rb +270 -0
- data/lib/omnizip/zip/output_stream.rb +320 -0
- data/lib/omnizip/zip.rb +23 -0
- data/lib/omnizip.rb +157 -0
- data/lib/tasks/msi_test_files.rake +66 -0
- data/lib/tasks/platform_gems.rake +147 -0
- data/lib/tasks/rust_backend.rake +48 -0
- data/readme-docs/advanced-features.adoc +514 -0
- data/readme-docs/api-usage.adoc +445 -0
- data/readme-docs/architecture.adoc +450 -0
- data/readme-docs/archive-formats.adoc +479 -0
- data/readme-docs/cli-usage.adoc +222 -0
- data/readme-docs/compression-algorithms.adoc +446 -0
- data/readme-docs/compression-profiles.adoc +247 -0
- data/readme-docs/encryption-checksums.adoc +328 -0
- data/readme-docs/format-converter.adoc +316 -0
- data/readme-docs/installation.adoc +228 -0
- data/readme-docs/par2-archives.adoc +608 -0
- data/readme-docs/performance-profiler.adoc +389 -0
- data/readme-docs/preprocessing-filters.adoc +280 -0
- data/vendor/libomnizip_ffi.so +0 -0
- data/xz-file-format-1.2.1.txt +1174 -0
- metadata +768 -0
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
# frozen_string: true
|
|
2
|
+
|
|
3
|
+
require "lutaml/model"
|
|
4
|
+
|
|
5
|
+
module Omnizip
|
|
6
|
+
module Models
|
|
7
|
+
# Represents the performance characteristics of a profiled operation.
|
|
8
|
+
#
|
|
9
|
+
# Serialized via lutaml-model — no hand-rolled +to_h+ / +to_json+.
|
|
10
|
+
# The derived-rate keys serialize the calculation methods; attribute
|
|
11
|
+
# names differ from the keys so generated readers do not shadow them.
|
|
12
|
+
class PerformanceResult < Lutaml::Model::Serializable
|
|
13
|
+
attribute :operation_name, :string
|
|
14
|
+
attribute :total_time, :double
|
|
15
|
+
attribute :cpu_time, :double
|
|
16
|
+
attribute :wall_time, :double
|
|
17
|
+
attribute :memory_allocated, :integer
|
|
18
|
+
attribute :memory_retained, :integer
|
|
19
|
+
attribute :object_allocations, :integer
|
|
20
|
+
attribute :gc_runs, :integer
|
|
21
|
+
attribute :call_count, :integer
|
|
22
|
+
attribute :timestamp, :date_time, default: -> { Time.now }
|
|
23
|
+
|
|
24
|
+
attribute :throughput, :double, method: :throughput_ops_per_second
|
|
25
|
+
attribute :average_time, :double, method: :average_time_per_operation
|
|
26
|
+
attribute :memory_per_op, :double, method: :memory_per_operation
|
|
27
|
+
attribute :pressure, :double, method: :gc_pressure
|
|
28
|
+
|
|
29
|
+
key_value do
|
|
30
|
+
map "operation_name", to: :operation_name,
|
|
31
|
+
render_default: true, render_nil: true
|
|
32
|
+
map "total_time", to: :total_time,
|
|
33
|
+
render_default: true, render_nil: true
|
|
34
|
+
map "cpu_time", to: :cpu_time,
|
|
35
|
+
render_default: true, render_nil: true
|
|
36
|
+
map "wall_time", to: :wall_time,
|
|
37
|
+
render_default: true, render_nil: true
|
|
38
|
+
map "memory_allocated", to: :memory_allocated,
|
|
39
|
+
render_default: true, render_nil: true
|
|
40
|
+
map "memory_retained", to: :memory_retained,
|
|
41
|
+
render_default: true, render_nil: true
|
|
42
|
+
map "object_allocations", to: :object_allocations,
|
|
43
|
+
render_default: true, render_nil: true
|
|
44
|
+
map "gc_runs", to: :gc_runs,
|
|
45
|
+
render_default: true, render_nil: true
|
|
46
|
+
map "call_count", to: :call_count,
|
|
47
|
+
render_default: true, render_nil: true
|
|
48
|
+
map "throughput_ops_per_second", to: :throughput,
|
|
49
|
+
render_default: true, render_nil: true
|
|
50
|
+
map "average_time_per_operation", to: :average_time,
|
|
51
|
+
render_default: true, render_nil: true
|
|
52
|
+
map "memory_per_operation", to: :memory_per_op,
|
|
53
|
+
render_default: true, render_nil: true
|
|
54
|
+
map "gc_pressure", to: :pressure,
|
|
55
|
+
render_default: true, render_nil: true
|
|
56
|
+
map "timestamp", to: :timestamp,
|
|
57
|
+
render_default: true, render_nil: true
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
def throughput_ops_per_second
|
|
61
|
+
return nil unless call_count && total_time&.positive?
|
|
62
|
+
|
|
63
|
+
call_count.to_f / total_time
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
def average_time_per_operation
|
|
67
|
+
return nil unless call_count && total_time && call_count.positive?
|
|
68
|
+
|
|
69
|
+
total_time / call_count.to_f
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
def memory_per_operation
|
|
73
|
+
return nil unless call_count && memory_allocated && call_count.positive?
|
|
74
|
+
|
|
75
|
+
memory_allocated / call_count.to_f
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
def gc_pressure
|
|
79
|
+
return nil unless gc_runs && total_time&.positive?
|
|
80
|
+
|
|
81
|
+
gc_runs.to_f / total_time
|
|
82
|
+
end
|
|
83
|
+
end
|
|
84
|
+
end
|
|
85
|
+
end
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "lutaml/model"
|
|
4
|
+
|
|
5
|
+
module Omnizip
|
|
6
|
+
module Models
|
|
7
|
+
# Aggregated profiling report with hot path analysis.
|
|
8
|
+
#
|
|
9
|
+
# Serialized via lutaml-model — no hand-rolled +to_h+ / +to_json+.
|
|
10
|
+
# The +summary+ key serializes a nested Summary model built from
|
|
11
|
+
# the report's aggregates; hot paths and bottlenecks are the
|
|
12
|
+
# analyzer-supplied hashes.
|
|
13
|
+
class ProfileReport < Lutaml::Model::Serializable
|
|
14
|
+
# Aggregate block of {ProfileReport#to_hash}.
|
|
15
|
+
class Summary < Lutaml::Model::Serializable
|
|
16
|
+
attribute :total_execution_time, :double, default: 0.0
|
|
17
|
+
attribute :total_memory_allocated, :integer, default: 0
|
|
18
|
+
attribute :total_gc_runs, :integer, default: 0
|
|
19
|
+
attribute :operation_count, :integer, default: 0
|
|
20
|
+
|
|
21
|
+
key_value do
|
|
22
|
+
map "total_execution_time", to: :total_execution_time,
|
|
23
|
+
render_default: true, render_nil: true
|
|
24
|
+
map "total_memory_allocated", to: :total_memory_allocated,
|
|
25
|
+
render_default: true, render_nil: true
|
|
26
|
+
map "total_gc_runs", to: :total_gc_runs,
|
|
27
|
+
render_default: true, render_nil: true
|
|
28
|
+
map "operation_count", to: :operation_count,
|
|
29
|
+
render_default: true, render_nil: true
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
attribute :profile_name, :string
|
|
34
|
+
attribute :results, PerformanceResult, collection: true, default: []
|
|
35
|
+
attribute :hot_paths, :hash, collection: true, default: []
|
|
36
|
+
attribute :bottlenecks, :hash, collection: true, default: []
|
|
37
|
+
attribute :timestamp, :date_time, default: -> { Time.now }
|
|
38
|
+
attribute :metadata, :hash, default: {}
|
|
39
|
+
attribute :summary, Summary, method: :build_summary
|
|
40
|
+
|
|
41
|
+
key_value do
|
|
42
|
+
map "profile_name", to: :profile_name,
|
|
43
|
+
render_default: true, render_nil: true
|
|
44
|
+
map "timestamp", to: :timestamp,
|
|
45
|
+
render_default: true, render_nil: true
|
|
46
|
+
map "summary", to: :summary,
|
|
47
|
+
render_default: true, render_nil: true
|
|
48
|
+
map "results", to: :results,
|
|
49
|
+
render_default: true, render_nil: true
|
|
50
|
+
map "hot_paths", to: :hot_paths,
|
|
51
|
+
render_default: true, render_nil: true
|
|
52
|
+
map "bottlenecks", to: :bottlenecks,
|
|
53
|
+
render_default: true, render_nil: true
|
|
54
|
+
map "metadata", to: :metadata,
|
|
55
|
+
render_default: true, render_nil: true
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
# lutaml-model 0.8.x does not render empty-collection defaults,
|
|
59
|
+
# so they are assigned explicitly to keep every key present.
|
|
60
|
+
def initialize(attrs = {})
|
|
61
|
+
super({ results: [], hot_paths: [], bottlenecks: [],
|
|
62
|
+
metadata: {} }.merge(attrs))
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
def total_execution_time
|
|
66
|
+
results.filter_map(&:total_time).sum
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
def total_memory_allocated
|
|
70
|
+
results.filter_map(&:memory_allocated).sum
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
def total_gc_runs
|
|
74
|
+
results.filter_map(&:gc_runs).sum
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
def slowest_operations(limit: 5)
|
|
78
|
+
results.select(&:total_time)
|
|
79
|
+
.sort_by(&:total_time)
|
|
80
|
+
.reverse
|
|
81
|
+
.take(limit)
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
def memory_intensive_operations(limit: 5)
|
|
85
|
+
results.select(&:memory_allocated)
|
|
86
|
+
.sort_by(&:memory_allocated)
|
|
87
|
+
.reverse
|
|
88
|
+
.take(limit)
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
def add_result(result)
|
|
92
|
+
results << result
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
def add_hot_path(hot_path)
|
|
96
|
+
hot_paths << hot_path
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
def add_bottleneck(bottleneck)
|
|
100
|
+
bottlenecks << bottleneck
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
# Serialized aggregate block.
|
|
104
|
+
#
|
|
105
|
+
# @return [Summary]
|
|
106
|
+
def build_summary
|
|
107
|
+
Summary.new(
|
|
108
|
+
total_execution_time: total_execution_time,
|
|
109
|
+
total_memory_allocated: total_memory_allocated,
|
|
110
|
+
total_gc_runs: total_gc_runs,
|
|
111
|
+
operation_count: results.size,
|
|
112
|
+
)
|
|
113
|
+
end
|
|
114
|
+
end
|
|
115
|
+
end
|
|
116
|
+
end
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
#
|
|
4
|
+
# Copyright (C) 2025 Ribose Inc.
|
|
5
|
+
#
|
|
6
|
+
|
|
7
|
+
require "lutaml/model"
|
|
8
|
+
|
|
9
|
+
module Omnizip
|
|
10
|
+
module Models
|
|
11
|
+
# Model representing progress tracking options.
|
|
12
|
+
#
|
|
13
|
+
# This class encapsulates configuration for progress tracking,
|
|
14
|
+
# including reporter type, update interval, and display preferences.
|
|
15
|
+
#
|
|
16
|
+
# Serialized via lutaml-model — no hand-rolled +to_h+ / +to_json+.
|
|
17
|
+
#
|
|
18
|
+
# +render_nil+ is deliberately absent: the previous +to_h+ ended in
|
|
19
|
+
# +.compact+, so an explicitly-nil value was dropped. +render_default+
|
|
20
|
+
# alone keeps that nil-dropping behaviour.
|
|
21
|
+
class ProgressOptions < Lutaml::Model::Serializable
|
|
22
|
+
attribute :reporter, :string, default: "auto"
|
|
23
|
+
attribute :update_interval, :float, default: 0.5
|
|
24
|
+
attribute :show_rate, :boolean, default: true
|
|
25
|
+
attribute :show_eta, :boolean, default: true
|
|
26
|
+
attribute :show_files, :boolean, default: true
|
|
27
|
+
attribute :show_bytes, :boolean, default: true
|
|
28
|
+
|
|
29
|
+
key_value do
|
|
30
|
+
map "reporter", to: :reporter, render_default: true
|
|
31
|
+
map "update_interval", to: :update_interval, render_default: true
|
|
32
|
+
map "show_rate", to: :show_rate, render_default: true
|
|
33
|
+
map "show_eta", to: :show_eta, render_default: true
|
|
34
|
+
map "show_files", to: :show_files, render_default: true
|
|
35
|
+
map "show_bytes", to: :show_bytes, render_default: true
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
end
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Omnizip
|
|
4
|
+
module Models
|
|
5
|
+
# Configuration for split archive (multi-volume) creation
|
|
6
|
+
# Defines how archives should be split into volumes
|
|
7
|
+
class SplitOptions
|
|
8
|
+
attr_accessor :volume_size, :naming_pattern, :span_strategy
|
|
9
|
+
|
|
10
|
+
# Naming pattern types
|
|
11
|
+
NAMING_NUMERIC = :numeric # .001, .002, .003
|
|
12
|
+
NAMING_ALPHA = :alpha # .aa, .ab, .ac
|
|
13
|
+
|
|
14
|
+
# Span strategies
|
|
15
|
+
STRATEGY_FIRST_FIT = :first_fit # Fill volumes sequentially
|
|
16
|
+
STRATEGY_BALANCED = :balanced # Balance files across volumes
|
|
17
|
+
|
|
18
|
+
# Default volume size (100 MB)
|
|
19
|
+
DEFAULT_VOLUME_SIZE = 100 * 1024 * 1024
|
|
20
|
+
|
|
21
|
+
# Initialize with default options
|
|
22
|
+
def initialize
|
|
23
|
+
@volume_size = DEFAULT_VOLUME_SIZE
|
|
24
|
+
@naming_pattern = NAMING_NUMERIC
|
|
25
|
+
@span_strategy = STRATEGY_FIRST_FIT
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
# Parse volume size from string (e.g., "100M", "4.7G")
|
|
29
|
+
#
|
|
30
|
+
# @param size_str [String] Size string with unit
|
|
31
|
+
# @return [Integer] Size in bytes
|
|
32
|
+
def self.parse_volume_size(size_str)
|
|
33
|
+
return size_str if size_str.is_a?(Integer)
|
|
34
|
+
|
|
35
|
+
size_str = size_str.to_s.strip.upcase
|
|
36
|
+
multiplier = case size_str
|
|
37
|
+
when /(\d+(?:\.\d+)?)\s*K(?:B)?$/
|
|
38
|
+
1024
|
|
39
|
+
when /(\d+(?:\.\d+)?)\s*M(?:B)?$/
|
|
40
|
+
1024 * 1024
|
|
41
|
+
when /(\d+(?:\.\d+)?)\s*G(?:B)?$/
|
|
42
|
+
1024 * 1024 * 1024
|
|
43
|
+
when /(\d+(?:\.\d+)?)\s*T(?:B)?$/
|
|
44
|
+
1024 * 1024 * 1024 * 1024
|
|
45
|
+
else
|
|
46
|
+
return size_str.to_i
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
(Regexp.last_match(1).to_f * multiplier).to_i
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
# Generate volume filename
|
|
53
|
+
#
|
|
54
|
+
# @param base_path [String] Base archive path (e.g., "backup.7z.001")
|
|
55
|
+
# @param volume_number [Integer] Volume number (1-based)
|
|
56
|
+
# @return [String] Volume filename
|
|
57
|
+
def volume_filename(base_path, volume_number)
|
|
58
|
+
# Extract base and extension
|
|
59
|
+
base = base_path.sub(/\.\d{3}$/, "")
|
|
60
|
+
base = base.sub(/\.[a-z]{2,}$/, "") if @naming_pattern == NAMING_ALPHA
|
|
61
|
+
|
|
62
|
+
case @naming_pattern
|
|
63
|
+
when NAMING_NUMERIC
|
|
64
|
+
format("%s.%03d", base, volume_number)
|
|
65
|
+
when NAMING_ALPHA
|
|
66
|
+
format("%s.%s", base, alpha_suffix(volume_number))
|
|
67
|
+
else
|
|
68
|
+
format("%s.%03d", base, volume_number)
|
|
69
|
+
end
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
# Validate options
|
|
73
|
+
#
|
|
74
|
+
# @raise [ArgumentError] if options are invalid
|
|
75
|
+
def validate!
|
|
76
|
+
raise ArgumentError, "volume_size must be positive" unless
|
|
77
|
+
@volume_size.positive?
|
|
78
|
+
|
|
79
|
+
valid_patterns = [NAMING_NUMERIC, NAMING_ALPHA]
|
|
80
|
+
unless valid_patterns.include?(@naming_pattern)
|
|
81
|
+
raise ArgumentError,
|
|
82
|
+
"naming_pattern must be one of #{valid_patterns.inspect}"
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
valid_strategies = [STRATEGY_FIRST_FIT, STRATEGY_BALANCED]
|
|
86
|
+
unless valid_strategies.include?(@span_strategy)
|
|
87
|
+
raise ArgumentError,
|
|
88
|
+
"span_strategy must be one of #{valid_strategies.inspect}"
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
true
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
private
|
|
95
|
+
|
|
96
|
+
# Generate alpha suffix for volume number
|
|
97
|
+
#
|
|
98
|
+
# @param volume_number [Integer] Volume number (1-based)
|
|
99
|
+
# @return [String] Alpha suffix (aa, ab, ..., az, ba, ..., zz, aaa, ...)
|
|
100
|
+
def alpha_suffix(volume_number)
|
|
101
|
+
# Convert 1 -> aa, 2 -> ab, ..., 26 -> az, 27 -> ba, etc.
|
|
102
|
+
num = volume_number - 1 # Convert to 0-based
|
|
103
|
+
|
|
104
|
+
# For two-character format (minimum):
|
|
105
|
+
# Second character cycles through a-z (rightmost, least significant)
|
|
106
|
+
second = ("a".ord + (num % 26)).chr
|
|
107
|
+
|
|
108
|
+
# First character represents which group of 26 we're in
|
|
109
|
+
first_index = num / 26
|
|
110
|
+
first = ("a".ord + first_index).chr
|
|
111
|
+
|
|
112
|
+
first + second
|
|
113
|
+
end
|
|
114
|
+
end
|
|
115
|
+
end
|
|
116
|
+
end
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Omnizip
|
|
4
|
+
class OptimizationRegistry < Omnizip::Registry
|
|
5
|
+
class << self
|
|
6
|
+
def not_found_error_class
|
|
7
|
+
Omnizip::OptimizationNotFoundError
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def label
|
|
11
|
+
"Optimization strategy"
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def apply(name, target, **options)
|
|
15
|
+
get(name).new(**options).optimize(target)
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def metadata(name)
|
|
19
|
+
get(name).metadata
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
class Strategy
|
|
24
|
+
attr_reader :options
|
|
25
|
+
|
|
26
|
+
def initialize(**options)
|
|
27
|
+
@options = options
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def optimize(_target)
|
|
31
|
+
raise NotImplementedError,
|
|
32
|
+
"#{self.class} must implement #optimize"
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def self.metadata
|
|
36
|
+
{
|
|
37
|
+
name: name,
|
|
38
|
+
description: "No description provided",
|
|
39
|
+
category: :general,
|
|
40
|
+
impact: :unknown,
|
|
41
|
+
}
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
end
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "fractor"
|
|
4
|
+
|
|
5
|
+
module Omnizip
|
|
6
|
+
module Parallel
|
|
7
|
+
# Engine owns the Fractor worker-pool dance: build the pool, submit
|
|
8
|
+
# a batch of work, run it to completion, return successful and
|
|
9
|
+
# failed results. Callers (ParallelCompressor, ParallelExtractor,
|
|
10
|
+
# future operations) supply the worker class and the work items;
|
|
11
|
+
# Engine handles the threading.
|
|
12
|
+
#
|
|
13
|
+
# This is the deep module behind the parallel API: the threading
|
|
14
|
+
# shape is identical across every consumer, so it lives here once.
|
|
15
|
+
# Domain-specific concerns (which file to read, which archive to
|
|
16
|
+
# open, what stats to track) stay with the caller.
|
|
17
|
+
class Engine
|
|
18
|
+
# @param worker_class [Class] a +Fractor::Worker+ subclass whose
|
|
19
|
+
# +#process(work)+ turns one work item into a result.
|
|
20
|
+
# @param threads [Integer] worker count.
|
|
21
|
+
def initialize(worker_class:, threads:)
|
|
22
|
+
@worker_class = worker_class
|
|
23
|
+
@threads = threads
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
# Run +work_items+ through the pool and yield each successful
|
|
27
|
+
# +Fractor::WorkResult+ to the caller-supplied block.
|
|
28
|
+
#
|
|
29
|
+
# @param work_items [Array<Fractor::Work>] batch to submit.
|
|
30
|
+
# @yieldparam result [Fractor::WorkResult] a successful result.
|
|
31
|
+
# @return [Array<Fractor::WorkResult>] the failed results, for
|
|
32
|
+
# the caller to decide how to surface.
|
|
33
|
+
def run(work_items)
|
|
34
|
+
pool = WorkerPool.new(
|
|
35
|
+
worker_class: @worker_class,
|
|
36
|
+
num_workers: @threads,
|
|
37
|
+
continuous: false,
|
|
38
|
+
)
|
|
39
|
+
pool.start
|
|
40
|
+
begin
|
|
41
|
+
pool.submit_batch(work_items)
|
|
42
|
+
pool.run
|
|
43
|
+
|
|
44
|
+
pool.successful_results.each { |r| yield r if block_given? }
|
|
45
|
+
pool.failed_results
|
|
46
|
+
ensure
|
|
47
|
+
pool.shutdown
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
end
|
|
@@ -0,0 +1,209 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Omnizip
|
|
4
|
+
module Parallel
|
|
5
|
+
# Thread-safe job queue for parallel compression/extraction
|
|
6
|
+
#
|
|
7
|
+
# Manages a queue of compression or extraction jobs with priority support.
|
|
8
|
+
# Jobs are ordered by priority (large files first for better load balancing).
|
|
9
|
+
#
|
|
10
|
+
# @example Create and use job queue
|
|
11
|
+
# queue = Omnizip::Parallel::JobQueue.new(max_size: 100)
|
|
12
|
+
# queue.push(file: 'large.dat', size: 1_000_000, priority: :high)
|
|
13
|
+
# job = queue.pop
|
|
14
|
+
#
|
|
15
|
+
# @example Size-based priority
|
|
16
|
+
# queue.push_with_size(file: 'file.txt', size: 1024)
|
|
17
|
+
class JobQueue
|
|
18
|
+
# Job structure for queue items
|
|
19
|
+
Job = Struct.new(:file, :data, :size, :priority, :metadata,
|
|
20
|
+
keyword_init: true) do
|
|
21
|
+
def <=>(other)
|
|
22
|
+
# Higher priority first, then larger files first
|
|
23
|
+
priority_order = { high: 0, normal: 1, low: 2 }
|
|
24
|
+
priority_cmp = (priority_order[priority] || 1) <=> (priority_order[other.priority] || 1)
|
|
25
|
+
return priority_cmp unless priority_cmp.zero?
|
|
26
|
+
|
|
27
|
+
# If same priority, larger files first
|
|
28
|
+
-(size <=> other.size)
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
# @return [Integer] maximum queue size
|
|
33
|
+
attr_reader :max_size
|
|
34
|
+
|
|
35
|
+
# @return [Integer] current queue size
|
|
36
|
+
attr_reader :size
|
|
37
|
+
|
|
38
|
+
# Initialize job queue
|
|
39
|
+
#
|
|
40
|
+
# @param max_size [Integer] maximum number of jobs in queue
|
|
41
|
+
def initialize(max_size: 1000)
|
|
42
|
+
@max_size = max_size
|
|
43
|
+
@queue = []
|
|
44
|
+
@mutex = Mutex.new
|
|
45
|
+
@cond = ConditionVariable.new
|
|
46
|
+
@closed = false
|
|
47
|
+
@size = 0
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
# Push a job onto the queue
|
|
51
|
+
#
|
|
52
|
+
# @param file [String] file path
|
|
53
|
+
# @param data [Object] job data
|
|
54
|
+
# @param size [Integer] file size in bytes
|
|
55
|
+
# @param priority [Symbol] job priority (:high, :normal, :low)
|
|
56
|
+
# @param metadata [Hash] additional metadata
|
|
57
|
+
# @raise [ClosedQueueError] if queue is closed
|
|
58
|
+
# @return [Job] the created job
|
|
59
|
+
def push(file:, data: nil, size: 0, priority: :normal, metadata: {})
|
|
60
|
+
@mutex.synchronize do
|
|
61
|
+
raise ClosedQueueError, "Queue is closed" if @closed
|
|
62
|
+
|
|
63
|
+
# Wait if queue is full
|
|
64
|
+
@cond.wait(@mutex) while @size >= @max_size && !@closed
|
|
65
|
+
|
|
66
|
+
raise ClosedQueueError, "Queue is closed" if @closed
|
|
67
|
+
|
|
68
|
+
job = Job.new(
|
|
69
|
+
file: file,
|
|
70
|
+
data: data,
|
|
71
|
+
size: size,
|
|
72
|
+
priority: priority,
|
|
73
|
+
metadata: metadata,
|
|
74
|
+
)
|
|
75
|
+
|
|
76
|
+
@queue << job
|
|
77
|
+
@size += 1
|
|
78
|
+
|
|
79
|
+
# Keep queue sorted by priority
|
|
80
|
+
@queue.sort!
|
|
81
|
+
|
|
82
|
+
@cond.signal
|
|
83
|
+
job
|
|
84
|
+
end
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
# Push a job with automatic priority based on file size
|
|
88
|
+
#
|
|
89
|
+
# @param file [String] file path
|
|
90
|
+
# @param size [Integer] file size in bytes
|
|
91
|
+
# @param data [Object] job data
|
|
92
|
+
# @param metadata [Hash] additional metadata
|
|
93
|
+
# @return [Job] the created job
|
|
94
|
+
def push_with_size(file:, size:, data: nil, metadata: {})
|
|
95
|
+
# Determine priority based on size
|
|
96
|
+
# Large files (>10MB) get high priority for better load balancing
|
|
97
|
+
priority = if size > 10 * 1024 * 1024
|
|
98
|
+
:high
|
|
99
|
+
elsif size > 1024 * 1024
|
|
100
|
+
:normal
|
|
101
|
+
else
|
|
102
|
+
:low
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
push(file: file, data: data, size: size, priority: priority,
|
|
106
|
+
metadata: metadata)
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
# Pop a job from the queue
|
|
110
|
+
#
|
|
111
|
+
# @param timeout [Numeric, nil] timeout in seconds, nil for no timeout
|
|
112
|
+
# @return [Job, nil] job or nil if timeout or closed
|
|
113
|
+
def pop(timeout: nil)
|
|
114
|
+
@mutex.synchronize do
|
|
115
|
+
if timeout
|
|
116
|
+
deadline = Time.now + timeout
|
|
117
|
+
while @queue.empty? && !@closed
|
|
118
|
+
remaining = deadline - Time.now
|
|
119
|
+
return nil if remaining <= 0
|
|
120
|
+
|
|
121
|
+
@cond.wait(@mutex, remaining)
|
|
122
|
+
end
|
|
123
|
+
else
|
|
124
|
+
@cond.wait(@mutex) while @queue.empty? && !@closed
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
return nil if @queue.empty?
|
|
128
|
+
|
|
129
|
+
job = @queue.shift
|
|
130
|
+
@size -= 1
|
|
131
|
+
@cond.signal # Signal waiting pushers
|
|
132
|
+
job
|
|
133
|
+
end
|
|
134
|
+
end
|
|
135
|
+
|
|
136
|
+
# Pop multiple jobs in batch
|
|
137
|
+
#
|
|
138
|
+
# @param count [Integer] maximum number of jobs to pop
|
|
139
|
+
# @param timeout [Numeric, nil] timeout in seconds
|
|
140
|
+
# @return [Array<Job>] array of jobs (may be empty)
|
|
141
|
+
def pop_batch(count, timeout: nil)
|
|
142
|
+
jobs = []
|
|
143
|
+
count.times do
|
|
144
|
+
job = pop(timeout: timeout)
|
|
145
|
+
break unless job
|
|
146
|
+
|
|
147
|
+
jobs << job
|
|
148
|
+
end
|
|
149
|
+
jobs
|
|
150
|
+
end
|
|
151
|
+
|
|
152
|
+
# Check if queue is empty
|
|
153
|
+
#
|
|
154
|
+
# @return [Boolean] true if empty
|
|
155
|
+
def empty?
|
|
156
|
+
@mutex.synchronize { @queue.empty? }
|
|
157
|
+
end
|
|
158
|
+
|
|
159
|
+
# Check if queue is closed
|
|
160
|
+
#
|
|
161
|
+
# @return [Boolean] true if closed
|
|
162
|
+
def closed?
|
|
163
|
+
@mutex.synchronize { @closed }
|
|
164
|
+
end
|
|
165
|
+
|
|
166
|
+
# Close the queue
|
|
167
|
+
#
|
|
168
|
+
# No more jobs can be pushed after closing.
|
|
169
|
+
# Pending pops will return nil.
|
|
170
|
+
def close
|
|
171
|
+
@mutex.synchronize do
|
|
172
|
+
@closed = true
|
|
173
|
+
@cond.broadcast # Wake up all waiting threads
|
|
174
|
+
end
|
|
175
|
+
end
|
|
176
|
+
|
|
177
|
+
# Clear all jobs from queue
|
|
178
|
+
#
|
|
179
|
+
# @return [Integer] number of jobs cleared
|
|
180
|
+
def clear
|
|
181
|
+
@mutex.synchronize do
|
|
182
|
+
count = @queue.size
|
|
183
|
+
@queue.clear
|
|
184
|
+
@size = 0
|
|
185
|
+
@cond.broadcast
|
|
186
|
+
count
|
|
187
|
+
end
|
|
188
|
+
end
|
|
189
|
+
|
|
190
|
+
# Get queue statistics
|
|
191
|
+
#
|
|
192
|
+
# @return [Hash] statistics hash
|
|
193
|
+
def stats
|
|
194
|
+
@mutex.synchronize do
|
|
195
|
+
{
|
|
196
|
+
size: @size,
|
|
197
|
+
max_size: @max_size,
|
|
198
|
+
closed: @closed,
|
|
199
|
+
utilization: @max_size.zero? ? 0.0 : @size.to_f / @max_size,
|
|
200
|
+
priority_counts: @queue.group_by(&:priority).transform_values(&:count),
|
|
201
|
+
}
|
|
202
|
+
end
|
|
203
|
+
end
|
|
204
|
+
end
|
|
205
|
+
|
|
206
|
+
# Exception raised when trying to push to a closed queue
|
|
207
|
+
class ClosedQueueError < StandardError; end
|
|
208
|
+
end
|
|
209
|
+
end
|