dictsqlite 2.1.1__tar.gz → 2.1.2__tar.gz

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.
Files changed (153) hide show
  1. {dictsqlite-2.1.1 → dictsqlite-2.1.2}/Cargo.lock +1 -1
  2. {dictsqlite-2.1.1 → dictsqlite-2.1.2}/Cargo.toml +1 -1
  3. {dictsqlite-2.1.1 → dictsqlite-2.1.2}/PKG-INFO +1 -1
  4. {dictsqlite-2.1.1 → dictsqlite-2.1.2}/pyproject.toml +1 -1
  5. {dictsqlite-2.1.1 → dictsqlite-2.1.2}/src/async_ops.rs +10 -9
  6. {dictsqlite-2.1.1 → dictsqlite-2.1.2}/src/lib.rs +49 -73
  7. {dictsqlite-2.1.1 → dictsqlite-2.1.2}/.bandit +0 -0
  8. {dictsqlite-2.1.1 → dictsqlite-2.1.2}/.gitignore +0 -0
  9. {dictsqlite-2.1.1 → dictsqlite-2.1.2}/Pypi.md +0 -0
  10. {dictsqlite-2.1.1 → dictsqlite-2.1.2}/benches/ops_benchmark.rs +0 -0
  11. {dictsqlite-2.1.1 → dictsqlite-2.1.2}/benchmark/README.md +0 -0
  12. {dictsqlite-2.1.1 → dictsqlite-2.1.2}/benchmark/analyze_results.py +0 -0
  13. {dictsqlite-2.1.1 → dictsqlite-2.1.2}/benchmark/benchmark_all.py +0 -0
  14. {dictsqlite-2.1.1 → dictsqlite-2.1.2}/benchmark/benchmark_results.csv +0 -0
  15. {dictsqlite-2.1.1 → dictsqlite-2.1.2}/benchmark/images/benchmark_avg_latency.png +0 -0
  16. {dictsqlite-2.1.1 → dictsqlite-2.1.2}/benchmark/images/benchmark_by_data_size.png +0 -0
  17. {dictsqlite-2.1.1 → dictsqlite-2.1.2}/benchmark/images/benchmark_category_comparison.png +0 -0
  18. {dictsqlite-2.1.1 → dictsqlite-2.1.2}/benchmark/images/benchmark_ops_per_sec.png +0 -0
  19. {dictsqlite-2.1.1 → dictsqlite-2.1.2}/build.sh +0 -0
  20. {dictsqlite-2.1.1 → dictsqlite-2.1.2}/build_production.sh +0 -0
  21. {dictsqlite-2.1.1 → dictsqlite-2.1.2}/build_result.txt +0 -0
  22. {dictsqlite-2.1.1 → dictsqlite-2.1.2}/check_result.txt +0 -0
  23. {dictsqlite-2.1.1 → dictsqlite-2.1.2}/deny.toml +0 -0
  24. {dictsqlite-2.1.1 → dictsqlite-2.1.2}/docs/EXAMPLES_EN.md +0 -0
  25. {dictsqlite-2.1.1 → dictsqlite-2.1.2}/docs/EXAMPLES_JP.md +0 -0
  26. {dictsqlite-2.1.1 → dictsqlite-2.1.2}/docs/FIX_SUMMARY.md +0 -0
  27. {dictsqlite-2.1.1 → dictsqlite-2.1.2}/docs/INDEX.md +0 -0
  28. {dictsqlite-2.1.1 → dictsqlite-2.1.2}/docs/MIGRATION_FROM_1.8.8_EN.md +0 -0
  29. {dictsqlite-2.1.1 → dictsqlite-2.1.2}/docs/MIGRATION_FROM_1.8.8_JP.md +0 -0
  30. {dictsqlite-2.1.1 → dictsqlite-2.1.2}/docs/README_EN.md +0 -0
  31. {dictsqlite-2.1.1 → dictsqlite-2.1.2}/docs/README_JP.md +0 -0
  32. {dictsqlite-2.1.1 → dictsqlite-2.1.2}/docs/TABLE_PROXY_REPR_REPORT.md +0 -0
  33. {dictsqlite-2.1.1 → dictsqlite-2.1.2}/docs/optimization_v5/01_overview.md +0 -0
  34. {dictsqlite-2.1.1 → dictsqlite-2.1.2}/docs/optimization_v5/02_storage_engine.md +0 -0
  35. {dictsqlite-2.1.1 → dictsqlite-2.1.2}/docs/optimization_v5/03_async_layer.md +0 -0
  36. {dictsqlite-2.1.1 → dictsqlite-2.1.2}/docs/optimization_v5/04_integration.md +0 -0
  37. {dictsqlite-2.1.1 → dictsqlite-2.1.2}/docs/optimization_v5/05_verification.md +0 -0
  38. {dictsqlite-2.1.1 → dictsqlite-2.1.2}/examples/README.md +0 -0
  39. {dictsqlite-2.1.1 → dictsqlite-2.1.2}/examples/async_await_example.py +0 -0
  40. {dictsqlite-2.1.1 → dictsqlite-2.1.2}/examples/async_jsonb_table_usage.py +0 -0
  41. {dictsqlite-2.1.1 → dictsqlite-2.1.2}/examples/jsonb_table_usage_example.py +0 -0
  42. {dictsqlite-2.1.1 → dictsqlite-2.1.2}/examples/v4.2_advanced_examples.py +0 -0
  43. {dictsqlite-2.1.1 → dictsqlite-2.1.2}/examples/v4.2_basic_usage.py +0 -0
  44. {dictsqlite-2.1.1 → dictsqlite-2.1.2}/examples/v4.2_migration_example.py +0 -0
  45. {dictsqlite-2.1.1 → dictsqlite-2.1.2}/examples/v4.2_performance_examples.py +0 -0
  46. {dictsqlite-2.1.1 → dictsqlite-2.1.2}/others/ASYNC_IMPLEMENTATION_SUMMARY.md +0 -0
  47. {dictsqlite-2.1.1 → dictsqlite-2.1.2}/others/ASYNC_SUPPORT_README.md +0 -0
  48. {dictsqlite-2.1.1 → dictsqlite-2.1.2}/others/BENCHMARK_RESULTS_JP.md +0 -0
  49. {dictsqlite-2.1.1 → dictsqlite-2.1.2}/others/BUILD_WARNINGS_EXPLANATION_JP.md +0 -0
  50. {dictsqlite-2.1.1 → dictsqlite-2.1.2}/others/CLIPPY_FIXES_SUMMARY.md +0 -0
  51. {dictsqlite-2.1.1 → dictsqlite-2.1.2}/others/COMPREHENSIVE_BENCHMARK_RESULTS.md +0 -0
  52. {dictsqlite-2.1.1 → dictsqlite-2.1.2}/others/COMPREHENSIVE_TEST_IMPLEMENTATION_REPORT_JP.md +0 -0
  53. {dictsqlite-2.1.1 → dictsqlite-2.1.2}/others/DEVELOPER_GUIDE_JP.md +0 -0
  54. {dictsqlite-2.1.1 → dictsqlite-2.1.2}/others/DICTSQLITE_V2_SPECIFICATION_JP.md +0 -0
  55. {dictsqlite-2.1.1 → dictsqlite-2.1.2}/others/DOCUMENTATION_INDEX_JP.md +0 -0
  56. {dictsqlite-2.1.1 → dictsqlite-2.1.2}/others/DOCUMENTATION_VERIFICATION_SUMMARY.md +0 -0
  57. {dictsqlite-2.1.1 → dictsqlite-2.1.2}/others/FIX_SUMMARY_JP.md +0 -0
  58. {dictsqlite-2.1.1 → dictsqlite-2.1.2}/others/GITHUB_ACTIONS_FIXES.md +0 -0
  59. {dictsqlite-2.1.1 → dictsqlite-2.1.2}/others/IMPLEMENTATION_COMPLETION_REPORT.md +0 -0
  60. {dictsqlite-2.1.1 → dictsqlite-2.1.2}/others/IMPLEMENTATION_COMPLETION_REPORT_JP.md +0 -0
  61. {dictsqlite-2.1.1 → dictsqlite-2.1.2}/others/IMPROVEMENT_ACTION_PLAN_JP.md +0 -0
  62. {dictsqlite-2.1.1 → dictsqlite-2.1.2}/others/INVESTIGATION_SUMMARY_JP.md +0 -0
  63. {dictsqlite-2.1.1 → dictsqlite-2.1.2}/others/ISSUE_RESPONSE_JSON_TABLE_SUPPORT_JP.md +0 -0
  64. {dictsqlite-2.1.1 → dictsqlite-2.1.2}/others/JSONB_TABLE_IMPLEMENTATION_SUMMARY_JP.md +0 -0
  65. {dictsqlite-2.1.1 → dictsqlite-2.1.2}/others/JSON_MODE_TABLE_SUPPORT_FEASIBILITY_JP.md +0 -0
  66. {dictsqlite-2.1.1 → dictsqlite-2.1.2}/others/MIGRATION_GUIDE_V4.2_JP.md +0 -0
  67. {dictsqlite-2.1.1 → dictsqlite-2.1.2}/others/PERFORMANCE_OPTIMIZATION_GUIDE_JP.md +0 -0
  68. {dictsqlite-2.1.1 → dictsqlite-2.1.2}/others/PERFORMANCE_TESTING_GUIDE.md +0 -0
  69. {dictsqlite-2.1.1 → dictsqlite-2.1.2}/others/PERFORMANCE_TEST_IMPLEMENTATION.md +0 -0
  70. {dictsqlite-2.1.1 → dictsqlite-2.1.2}/others/PERFORMANCE_TEST_RESULTS.md +0 -0
  71. {dictsqlite-2.1.1 → dictsqlite-2.1.2}/others/PYTEST_INTEGRATION_SUMMARY.md +0 -0
  72. {dictsqlite-2.1.1 → dictsqlite-2.1.2}/others/PYTEST_WARNINGS_FIX.md +0 -0
  73. {dictsqlite-2.1.1 → dictsqlite-2.1.2}/others/QUICK_REFERENCE_JSONB_TABLE_JP.md +0 -0
  74. {dictsqlite-2.1.1 → dictsqlite-2.1.2}/others/README_INVESTIGATION_JP.md +0 -0
  75. {dictsqlite-2.1.1 → dictsqlite-2.1.2}/others/README_V4.2_JP.md +0 -0
  76. {dictsqlite-2.1.1 → dictsqlite-2.1.2}/others/TESTING_DOCUMENTATION_JP.md +0 -0
  77. {dictsqlite-2.1.1 → dictsqlite-2.1.2}/others/TEST_AND_DOCUMENTATION_REVIEW_JP.md +0 -0
  78. {dictsqlite-2.1.1 → dictsqlite-2.1.2}/others/TEST_COMPLETION_REPORT.md +0 -0
  79. {dictsqlite-2.1.1 → dictsqlite-2.1.2}/others/V4.2_IMPLEMENTATION_SUMMARY.md +0 -0
  80. {dictsqlite-2.1.1 → dictsqlite-2.1.2}/others/WINDOWS_PERMISSION_FIX.md +0 -0
  81. {dictsqlite-2.1.1 → dictsqlite-2.1.2}/python/dictsqlite/__init__.py +0 -0
  82. {dictsqlite-2.1.1 → dictsqlite-2.1.2}/python/dictsqlite/modules/__init__.py +0 -0
  83. {dictsqlite-2.1.1 → dictsqlite-2.1.2}/python/dictsqlite/modules/safe_pickle.py +0 -0
  84. {dictsqlite-2.1.1 → dictsqlite-2.1.2}/setup.cfg +0 -0
  85. {dictsqlite-2.1.1 → dictsqlite-2.1.2}/src/cache.rs +0 -0
  86. {dictsqlite-2.1.1 → dictsqlite-2.1.2}/src/crypto.rs +0 -0
  87. {dictsqlite-2.1.1 → dictsqlite-2.1.2}/src/storage.rs +0 -0
  88. {dictsqlite-2.1.1 → dictsqlite-2.1.2}/src/tests_compression.rs +0 -0
  89. {dictsqlite-2.1.1 → dictsqlite-2.1.2}/src/tests_jsonb.rs +0 -0
  90. {dictsqlite-2.1.1 → dictsqlite-2.1.2}/src/tests_lru.rs +0 -0
  91. {dictsqlite-2.1.1 → dictsqlite-2.1.2}/src/tests_storage.rs +0 -0
  92. {dictsqlite-2.1.1 → dictsqlite-2.1.2}/src/tests_v6.rs +0 -0
  93. {dictsqlite-2.1.1 → dictsqlite-2.1.2}/test_debug.py +0 -0
  94. {dictsqlite-2.1.1 → dictsqlite-2.1.2}/tests/ISSUE_RESPONSE.md +0 -0
  95. {dictsqlite-2.1.1 → dictsqlite-2.1.2}/tests/README.md +0 -0
  96. {dictsqlite-2.1.1 → dictsqlite-2.1.2}/tests/README_COMPREHENSIVE_TESTS.md +0 -0
  97. {dictsqlite-2.1.1 → dictsqlite-2.1.2}/tests/README_NEW_COMPREHENSIVE_TESTS.md +0 -0
  98. {dictsqlite-2.1.1 → dictsqlite-2.1.2}/tests/TEST_DOCUMENTATION.md +0 -0
  99. {dictsqlite-2.1.1 → dictsqlite-2.1.2}/tests/TEST_FIXES_REPORT_JP.md +0 -0
  100. {dictsqlite-2.1.1 → dictsqlite-2.1.2}/tests/__init__.py +0 -0
  101. {dictsqlite-2.1.1 → dictsqlite-2.1.2}/tests/_check_safe_pickle.py +0 -0
  102. {dictsqlite-2.1.1 → dictsqlite-2.1.2}/tests/_reproduce_test.py +0 -0
  103. {dictsqlite-2.1.1 → dictsqlite-2.1.2}/tests/benchmark_comprehensive.py +0 -0
  104. {dictsqlite-2.1.1 → dictsqlite-2.1.2}/tests/conftest.py +0 -0
  105. {dictsqlite-2.1.1 → dictsqlite-2.1.2}/tests/test_advanced_features.py +0 -0
  106. {dictsqlite-2.1.1 → dictsqlite-2.1.2}/tests/test_async_awaitable.py +0 -0
  107. {dictsqlite-2.1.1 → dictsqlite-2.1.2}/tests/test_async_operations.py +0 -0
  108. {dictsqlite-2.1.1 → dictsqlite-2.1.2}/tests/test_async_persistence.py +0 -0
  109. {dictsqlite-2.1.1 → dictsqlite-2.1.2}/tests/test_async_table_contains.py +0 -0
  110. {dictsqlite-2.1.1 → dictsqlite-2.1.2}/tests/test_basic_operations.py +0 -0
  111. {dictsqlite-2.1.1 → dictsqlite-2.1.2}/tests/test_boundary_edge_cases.py +0 -0
  112. {dictsqlite-2.1.1 → dictsqlite-2.1.2}/tests/test_comprehensive_all_functions.py +0 -0
  113. {dictsqlite-2.1.1 → dictsqlite-2.1.2}/tests/test_comprehensive_edge_cases.py +0 -0
  114. {dictsqlite-2.1.1 → dictsqlite-2.1.2}/tests/test_comprehensive_integration.py +0 -0
  115. {dictsqlite-2.1.1 → dictsqlite-2.1.2}/tests/test_comprehensive_stress.py +0 -0
  116. {dictsqlite-2.1.1 → dictsqlite-2.1.2}/tests/test_dict_compat_api.py +0 -0
  117. {dictsqlite-2.1.1 → dictsqlite-2.1.2}/tests/test_exhaustive_async.py +0 -0
  118. {dictsqlite-2.1.1 → dictsqlite-2.1.2}/tests/test_exhaustive_async_table_proxy.py +0 -0
  119. {dictsqlite-2.1.1 → dictsqlite-2.1.2}/tests/test_exhaustive_dictsqlite_v4.py +0 -0
  120. {dictsqlite-2.1.1 → dictsqlite-2.1.2}/tests/test_exhaustive_table_proxy.py +0 -0
  121. {dictsqlite-2.1.1 → dictsqlite-2.1.2}/tests/test_issue_fixes.py +0 -0
  122. {dictsqlite-2.1.1 → dictsqlite-2.1.2}/tests/test_jsonb_table_support.py +0 -0
  123. {dictsqlite-2.1.1 → dictsqlite-2.1.2}/tests/test_lru_eviction.py +0 -0
  124. {dictsqlite-2.1.1 → dictsqlite-2.1.2}/tests/test_performance.py +0 -0
  125. {dictsqlite-2.1.1 → dictsqlite-2.1.2}/tests/test_persistence_modes.py +0 -0
  126. {dictsqlite-2.1.1 → dictsqlite-2.1.2}/tests/test_pool_size.py +0 -0
  127. {dictsqlite-2.1.1 → dictsqlite-2.1.2}/tests/test_return_type_validation.py +0 -0
  128. {dictsqlite-2.1.1 → dictsqlite-2.1.2}/tests/test_storage_modes.py +0 -0
  129. {dictsqlite-2.1.1 → dictsqlite-2.1.2}/tests/test_table_mode.py +0 -0
  130. {dictsqlite-2.1.1 → dictsqlite-2.1.2}/tests/test_table_proxy_eq.py +0 -0
  131. {dictsqlite-2.1.1 → dictsqlite-2.1.2}/tests/test_table_proxy_repr.py +0 -0
  132. {dictsqlite-2.1.1 → dictsqlite-2.1.2}/tests/test_v4.2_comprehensive_performance.py +0 -0
  133. {dictsqlite-2.1.1 → dictsqlite-2.1.2}/tests/test_v4_security.py +0 -0
  134. {dictsqlite-2.1.1 → dictsqlite-2.1.2}/tests/test_v6_migration.py +0 -0
  135. {dictsqlite-2.1.1 → dictsqlite-2.1.2}/tests/test_v7_batch_async.py +0 -0
  136. {dictsqlite-2.1.1 → dictsqlite-2.1.2}/tests/verify_optimization_opportunities.py +0 -0
  137. {dictsqlite-2.1.1 → dictsqlite-2.1.2}/twine/__init__.py +0 -0
  138. {dictsqlite-2.1.1 → dictsqlite-2.1.2}/twine/__main__.py +0 -0
  139. {dictsqlite-2.1.1 → dictsqlite-2.1.2}/twine/auth.py +0 -0
  140. {dictsqlite-2.1.1 → dictsqlite-2.1.2}/twine/cli.py +0 -0
  141. {dictsqlite-2.1.1 → dictsqlite-2.1.2}/twine/commands/__init__.py +0 -0
  142. {dictsqlite-2.1.1 → dictsqlite-2.1.2}/twine/commands/check.py +0 -0
  143. {dictsqlite-2.1.1 → dictsqlite-2.1.2}/twine/commands/register.py +0 -0
  144. {dictsqlite-2.1.1 → dictsqlite-2.1.2}/twine/commands/upload.py +0 -0
  145. {dictsqlite-2.1.1 → dictsqlite-2.1.2}/twine/distribution.py +0 -0
  146. {dictsqlite-2.1.1 → dictsqlite-2.1.2}/twine/exceptions.py +0 -0
  147. {dictsqlite-2.1.1 → dictsqlite-2.1.2}/twine/package.py +0 -0
  148. {dictsqlite-2.1.1 → dictsqlite-2.1.2}/twine/py.typed +0 -0
  149. {dictsqlite-2.1.1 → dictsqlite-2.1.2}/twine/repository.py +0 -0
  150. {dictsqlite-2.1.1 → dictsqlite-2.1.2}/twine/sdist.py +0 -0
  151. {dictsqlite-2.1.1 → dictsqlite-2.1.2}/twine/settings.py +0 -0
  152. {dictsqlite-2.1.1 → dictsqlite-2.1.2}/twine/utils.py +0 -0
  153. {dictsqlite-2.1.1 → dictsqlite-2.1.2}/twine/wheel.py +0 -0
@@ -412,7 +412,7 @@ dependencies = [
412
412
 
413
413
  [[package]]
414
414
  name = "dictsqlite"
415
- version = "2.1.1"
415
+ version = "2.1.2"
416
416
  dependencies = [
417
417
  "aes-gcm",
418
418
  "ahash",
@@ -1,6 +1,6 @@
1
1
  [package]
2
2
  name = "dictsqlite"
3
- version = "2.1.1"
3
+ version = "2.1.2"
4
4
  edition = "2021"
5
5
  authors = ["Disnana <support@disnana.com>"]
6
6
  description = "High-performance DictSQLite v2 with I/O optimizations (300x async, 43x sync speedup) - Buffered writes and batch operations"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: dictsqlite
3
- Version: 2.1.1
3
+ Version: 2.1.2
4
4
  Classifier: License :: OSI Approved :: MIT License
5
5
  Classifier: Development Status :: 4 - Beta
6
6
  Classifier: Operating System :: OS Independent
@@ -7,7 +7,7 @@ build-backend = "maturin"
7
7
  # PEP 621 project metadata required by maturin >= 0.14
8
8
  [project]
9
9
  name = "dictsqlite"
10
- version = "2.1.1"
10
+ version = "2.1.2"
11
11
  description = "High-performance DictSQLite v2 with I/O optimizations"
12
12
  readme = "Pypi.md"
13
13
  requires-python = ">=3.9"
@@ -1,11 +1,12 @@
1
1
  // v6.0: PyO3 0.27 API完全移行
2
2
 
3
3
  use dashmap::DashMap;
4
+ use parking_lot::Mutex;
4
5
  use pyo3::prelude::*;
5
6
  use pyo3::types::{PyBytes, PyDict};
6
7
  use rayon::prelude::*;
7
8
  use std::collections::HashMap;
8
- use std::sync::{Arc, Mutex, OnceLock};
9
+ use std::sync::{Arc, OnceLock};
9
10
  use tokio::runtime::Runtime;
10
11
 
11
12
  use crate::{
@@ -162,7 +163,7 @@ impl AsyncDictSQLite {
162
163
  if self.config.persist_mode == PersistMode::WriteThrough {
163
164
  // Add to write buffer
164
165
  {
165
- let mut buffer = self.write_buffer.lock().unwrap();
166
+ let mut buffer = self.write_buffer.lock();
166
167
  buffer.insert(key, value);
167
168
  }
168
169
 
@@ -177,7 +178,7 @@ impl AsyncDictSQLite {
177
178
  /// Flush write buffer to storage (v4.2 optimization)
178
179
  /// Batches multiple writes into a single transaction
179
180
  fn flush_write_buffer(&self) -> PyResult<()> {
180
- let mut buffer = self.write_buffer.lock().unwrap();
181
+ let mut buffer = self.write_buffer.lock();
181
182
 
182
183
  if buffer.is_empty() {
183
184
  return Ok(());
@@ -373,7 +374,7 @@ impl AsyncDictSQLite {
373
374
  if config.persist_mode == PersistMode::WriteThrough {
374
375
  // Add to write buffer
375
376
  let should_flush = {
376
- let mut buffer = write_buffer.lock().unwrap();
377
+ let mut buffer = write_buffer.lock();
377
378
  buffer.insert(key, value);
378
379
  buffer.len() >= buffer_size
379
380
  };
@@ -382,7 +383,7 @@ impl AsyncDictSQLite {
382
383
  if should_flush {
383
384
  runtime
384
385
  .spawn_blocking(move || {
385
- let mut buffer = write_buffer.lock().unwrap();
386
+ let mut buffer = write_buffer.lock();
386
387
  if buffer.is_empty() {
387
388
  return Ok(());
388
389
  }
@@ -475,7 +476,7 @@ impl AsyncDictSQLite {
475
476
  if config.persist_mode == PersistMode::WriteThrough {
476
477
  // Add to write buffer
477
478
  let should_flush = {
478
- let mut buffer = write_buffer.lock().unwrap();
479
+ let mut buffer = write_buffer.lock();
479
480
  for (key, value) in items {
480
481
  buffer.insert(key, value);
481
482
  }
@@ -488,7 +489,7 @@ impl AsyncDictSQLite {
488
489
  if should_flush {
489
490
  runtime
490
491
  .spawn_blocking(move || {
491
- let mut buffer = write_buffer.lock().unwrap();
492
+ let mut buffer = write_buffer.lock();
492
493
  if buffer.is_empty() {
493
494
  return Ok(());
494
495
  }
@@ -587,7 +588,7 @@ impl AsyncDictSQLite {
587
588
  runtime
588
589
  .spawn_blocking(move || {
589
590
  // First, flush any pending writes in the buffer
590
- let mut buffer = write_buffer.lock().unwrap();
591
+ let mut buffer = write_buffer.lock();
591
592
  if !buffer.is_empty() {
592
593
  if let Some(ref storage_engine) = *storage {
593
594
  for (k, v) in buffer.drain() {
@@ -771,7 +772,7 @@ impl AsyncDictSQLite {
771
772
 
772
773
  // Remove from write buffer
773
774
  if self.config.persist_mode == PersistMode::WriteThrough {
774
- let mut buffer = self.write_buffer.lock().unwrap();
775
+ let mut buffer = self.write_buffer.lock();
775
776
  buffer.remove(&full_key);
776
777
  }
777
778
 
@@ -49,13 +49,14 @@
49
49
 
50
50
  use dashmap::DashMap;
51
51
  use lru::LruCache;
52
+ use parking_lot::Mutex;
52
53
  use pyo3::prelude::*;
53
54
  use pyo3::types::{PyAny, PyBytes, PyDict};
54
55
  use serde::{Deserialize, Serialize};
55
56
  use std::collections::HashMap;
56
57
  use std::num::NonZeroUsize;
57
58
  use std::str::FromStr;
58
- use std::sync::{Arc, Mutex};
59
+ use std::sync::Arc;
59
60
 
60
61
  // v4.2.4 パフォーマンス最適化定数
61
62
  /// 小容量キャパシティの閾値 (この値以下では厳密なキャパシティ管理)
@@ -698,8 +699,9 @@ pub struct DictSQLiteV4 {
698
699
  /// ストレージエンジン: warm/cold tierの管理
699
700
  ///
700
701
  /// Memory以外の永続化モードで使用。
701
- /// SQLiteへの読み書きを担当。
702
- storage: Arc<Mutex<Option<StorageEngine>>>,
702
+ /// StorageEngineは内部でr2d2コネクションプール + DashMapを使用するため
703
+ /// スレッドセーフであり、外部のMutexは不要。
704
+ storage: Option<Arc<StorageEngine>>,
703
705
 
704
706
  /// 設定
705
707
  config: Config,
@@ -950,13 +952,14 @@ impl DictSQLiteV4 {
950
952
  )));
951
953
 
952
954
  // 純粋なメモリモードでない場合のみストレージを作成
955
+ // StorageEngineは内部でスレッドセーフなので Arc だけでラップする
953
956
  let storage = if config.persist_mode == PersistMode::Memory {
954
- Arc::new(Mutex::new(None))
957
+ None
955
958
  } else {
956
- Arc::new(Mutex::new(Some(
959
+ Some(Arc::new(
957
960
  StorageEngine::new(&db_path, &config)
958
961
  .map_err(|e| PyErr::new::<pyo3::exceptions::PyIOError, _>(e.to_string()))?,
959
- )))
962
+ ))
960
963
  };
961
964
 
962
965
  // パスワードが提供された場合、暗号化エンジンを初期化
@@ -1021,8 +1024,8 @@ impl DictSQLiteV4 {
1021
1024
  /// - 復号化に失敗した場合: ValueError
1022
1025
  #[pyo3(signature = (key, default=None))]
1023
1026
  fn get(&self, key: String, default: Option<Vec<u8>>, py: Python) -> PyResult<Py<PyAny>> {
1024
- // v4.2.4最適化: LRU追跡は必要な場合のみ実行(Memory/Lazyモードではスキップ)
1025
- // WriteThroughモードまたはキャパシティ超過時のみLRU追跡
1027
+ // v7.1最適化: LRU追跡はキャパシティ超過時のみ実行(エビクション判定が必要な場合のみ)
1028
+ // WriteThroughモードの特別扱いを廃止し、全モードで同一の閾値を使用
1026
1029
  let current_size = self.hot_tier.len();
1027
1030
  let tracking_threshold = if self.config.hot_tier_capacity <= SMALL_CAPACITY_THRESHOLD {
1028
1031
  // 小容量: 常に追跡(テスト互換性)
@@ -1031,11 +1034,10 @@ impl DictSQLiteV4 {
1031
1034
  // 大容量: LRU_TRACKING_THRESHOLD_PERCENT%から追跡(パフォーマンス優先)
1032
1035
  (self.config.hot_tier_capacity * LRU_TRACKING_THRESHOLD_PERCENT) / 100
1033
1036
  };
1034
- let needs_lru = self.config.persist_mode == PersistMode::WriteThrough
1035
- || current_size >= tracking_threshold;
1037
+ let needs_lru = current_size >= tracking_threshold;
1036
1038
 
1037
1039
  if needs_lru {
1038
- self.access_tracker.lock().unwrap().put(key.clone(), ());
1040
+ self.access_tracker.lock().put(key.clone(), ());
1039
1041
  }
1040
1042
 
1041
1043
  // Hot tierを最初に試行(ロックフリー読み取り)
@@ -1066,8 +1068,7 @@ impl DictSQLiteV4 {
1066
1068
  }
1067
1069
 
1068
1070
  // 他のモードではストレージ(Cold tier)も検索
1069
- let storage_guard = self.storage.lock().unwrap();
1070
- if let Some(ref storage) = *storage_guard {
1071
+ if let Some(ref storage) = self.storage {
1071
1072
  if let Ok(Some(value)) = storage.get(&key) {
1072
1073
  // 暗号化されているがパスワードがない場合のチェック
1073
1074
  if self.crypto.is_none() && crate::crypto::CryptoEngine::is_encrypted(&value) {
@@ -1087,7 +1088,6 @@ impl DictSQLiteV4 {
1087
1088
 
1088
1089
  // Hot tierにプロモート(暗号化状態で保存)
1089
1090
  // これにより次回アクセス時の速度が向上
1090
- drop(storage_guard);
1091
1091
  self.hot_tier.insert(key, value);
1092
1092
  return Ok(PyBytes::new(py, &data).into());
1093
1093
  }
@@ -1154,9 +1154,8 @@ impl DictSQLiteV4 {
1154
1154
  (is_new, None)
1155
1155
  };
1156
1156
 
1157
- // v4.2.4最適化: LRUアクセス追跡の条件付き更新(パフォーマンス向上)
1158
- // Memory/Lazyモードでは大容量を前提としているため、LRU追跡を最小化
1159
- // WriteThroughモードまたはキャパシティ超過時のみLRU追跡を有効化
1157
+ // v7.1最適化: LRUアクセス追跡はキャパシティ超過時のみ実行
1158
+ // WriteThroughモードの特別扱いを廃止し、全モードで同一の閾値を使用
1160
1159
  let current_size = self.hot_tier.len();
1161
1160
  let tracking_threshold = if self.config.hot_tier_capacity <= SMALL_CAPACITY_THRESHOLD {
1162
1161
  // 小容量: 常に追跡(テスト互換性)
@@ -1165,17 +1164,16 @@ impl DictSQLiteV4 {
1165
1164
  // 大容量: LRU_TRACKING_THRESHOLD_PERCENT%から追跡(パフォーマンス優先)
1166
1165
  (self.config.hot_tier_capacity * LRU_TRACKING_THRESHOLD_PERCENT) / 100
1167
1166
  };
1168
- let needs_lru = self.config.persist_mode == PersistMode::WriteThrough
1169
- || current_size >= tracking_threshold;
1167
+ let needs_lru = current_size >= tracking_threshold;
1170
1168
 
1171
1169
  if is_new_key && needs_lru {
1172
- self.access_tracker.lock().unwrap().put(key.clone(), ());
1170
+ self.access_tracker.lock().put(key.clone(), ());
1173
1171
  }
1174
1172
 
1175
1173
  // v4.2.2最適化: WriteThroughモードでは書き込みバッファを使用
1176
1174
  if self.config.persist_mode == PersistMode::WriteThrough {
1177
1175
  let should_flush = {
1178
- let mut buffer = self.write_buffer.lock().unwrap();
1176
+ let mut buffer = self.write_buffer.lock();
1179
1177
  buffer.push((key.clone(), data_for_buffer.unwrap()));
1180
1178
  // バッファサイズに達したらフラッシュ
1181
1179
  // buffer_size=1の場合は即時フラッシュ
@@ -1219,7 +1217,7 @@ impl DictSQLiteV4 {
1219
1217
  /// # エラー
1220
1218
  /// - ストレージ書き込みに失敗した場合: IOError
1221
1219
  fn evict_to_warm_tier(&self) -> PyResult<()> {
1222
- let mut tracker = self.access_tracker.lock().unwrap();
1220
+ let mut tracker = self.access_tracker.lock();
1223
1221
 
1224
1222
  // v4.2.4最適化: 一度にBATCH_EVICTION_PERCENT%のエントリをエビクション(バッチ処理)
1225
1223
  let eviction_count = std::cmp::max(
@@ -1245,8 +1243,7 @@ impl DictSQLiteV4 {
1245
1243
 
1246
1244
  // Memoryモードでない場合はストレージに一括書き込み
1247
1245
  if self.config.persist_mode != PersistMode::Memory && !evicted_items.is_empty() {
1248
- let mut storage_guard = self.storage.lock().unwrap();
1249
- if let Some(ref mut storage) = *storage_guard {
1246
+ if let Some(ref storage) = self.storage {
1250
1247
  // bulk_insertで一括書き込み(単一トランザクション)
1251
1248
  storage
1252
1249
  .bulk_insert(&evicted_items)
@@ -1269,7 +1266,7 @@ impl DictSQLiteV4 {
1269
1266
  /// - `Ok(())`: フラッシュ成功
1270
1267
  /// - `Err(PyErr)`: ストレージ書き込みエラー
1271
1268
  fn flush_write_buffer(&self) -> PyResult<()> {
1272
- let mut buffer = self.write_buffer.lock().unwrap();
1269
+ let mut buffer = self.write_buffer.lock();
1273
1270
 
1274
1271
  // バッファが空の場合は何もしない
1275
1272
  if buffer.is_empty() {
@@ -1283,8 +1280,7 @@ impl DictSQLiteV4 {
1283
1280
  drop(buffer);
1284
1281
 
1285
1282
  // ストレージハンドルを取得してバルクインサート
1286
- let mut storage_guard = self.storage.lock().unwrap();
1287
- if let Some(ref mut storage) = *storage_guard {
1283
+ if let Some(ref storage) = self.storage {
1288
1284
  // bulk_insert()を使用して単一トランザクションで高速書き込み
1289
1285
  storage
1290
1286
  .bulk_insert(&items)
@@ -1331,8 +1327,7 @@ impl DictSQLiteV4 {
1331
1327
  .collect();
1332
1328
 
1333
1329
  // バルクインサートで一括永続化(単一トランザクション)
1334
- let mut storage_guard = self.storage.lock().unwrap();
1335
- if let Some(ref mut storage) = *storage_guard {
1330
+ if let Some(ref storage) = self.storage {
1336
1331
  storage
1337
1332
  .bulk_insert(&items)
1338
1333
  .map_err(|e| PyErr::new::<pyo3::exceptions::PyIOError, _>(e.to_string()))?;
@@ -1352,21 +1347,20 @@ impl DictSQLiteV4 {
1352
1347
  }
1353
1348
 
1354
1349
  // Track that we're removing this
1355
- self.access_tracker.lock().unwrap().pop(&key);
1350
+ self.access_tracker.lock().pop(&key);
1356
1351
 
1357
1352
  // Remove from hot tier
1358
1353
  self.hot_tier.remove(&key);
1359
1354
 
1360
1355
  // Remove from write buffer (v4.2)
1361
1356
  if self.config.persist_mode == PersistMode::WriteThrough {
1362
- let mut buffer = self.write_buffer.lock().unwrap();
1357
+ let mut buffer = self.write_buffer.lock();
1363
1358
  buffer.retain(|(k, _)| k != &key);
1364
1359
  }
1365
1360
 
1366
1361
  // Also remove from storage
1367
1362
  if self.config.persist_mode != PersistMode::Memory {
1368
- let mut storage_guard = self.storage.lock().unwrap();
1369
- if let Some(ref mut storage) = *storage_guard {
1363
+ if let Some(ref storage) = self.storage {
1370
1364
  let _ = storage.delete(&key);
1371
1365
  }
1372
1366
  }
@@ -1424,8 +1418,7 @@ impl DictSQLiteV4 {
1424
1418
  }
1425
1419
 
1426
1420
  // 3. ストレージからキャッシュミスを取得
1427
- let storage_guard = self.storage.lock().unwrap();
1428
- if let Some(ref storage) = *storage_guard {
1421
+ if let Some(ref storage) = self.storage {
1429
1422
  for key in cache_misses {
1430
1423
  if let Ok(Some(value)) = storage.get(&key) {
1431
1424
  let data = if let Some(ref crypto) = self.crypto {
@@ -1463,7 +1456,7 @@ impl DictSQLiteV4 {
1463
1456
 
1464
1457
  // WriteThroughモードではバッファに追加
1465
1458
  if self.config.persist_mode == PersistMode::WriteThrough {
1466
- let mut buffer = self.write_buffer.lock().unwrap();
1459
+ let mut buffer = self.write_buffer.lock();
1467
1460
  buffer.push((key, data));
1468
1461
  }
1469
1462
  }
@@ -1489,8 +1482,7 @@ impl DictSQLiteV4 {
1489
1482
 
1490
1483
  // Also get keys from storage if not in memory-only mode
1491
1484
  if self.config.persist_mode != PersistMode::Memory {
1492
- let storage_guard = self.storage.lock().unwrap();
1493
- if let Some(ref storage) = *storage_guard {
1485
+ if let Some(ref storage) = self.storage {
1494
1486
  if let Ok(storage_keys) = storage.keys() {
1495
1487
  all_keys.extend(storage_keys);
1496
1488
  }
@@ -1508,8 +1500,7 @@ impl DictSQLiteV4 {
1508
1500
  let mut all_items: HashMap<String, Vec<u8>> = HashMap::new();
1509
1501
 
1510
1502
  if self.config.persist_mode != PersistMode::Memory {
1511
- let storage_guard = self.storage.lock().unwrap();
1512
- if let Some(ref storage) = *storage_guard {
1503
+ if let Some(ref storage) = self.storage {
1513
1504
  if let Ok(keys) = storage.keys() {
1514
1505
  for key in keys {
1515
1506
  if let Ok(Some(value)) = storage.get(&key) {
@@ -1548,8 +1539,7 @@ impl DictSQLiteV4 {
1548
1539
  let mut all_items: HashMap<String, Vec<u8>> = HashMap::new();
1549
1540
 
1550
1541
  if self.config.persist_mode != PersistMode::Memory {
1551
- let storage_guard = self.storage.lock().unwrap();
1552
- if let Some(ref storage) = *storage_guard {
1542
+ if let Some(ref storage) = self.storage {
1553
1543
  if let Ok(keys) = storage.keys() {
1554
1544
  for key in keys {
1555
1545
  if let Ok(Some(value)) = storage.get(&key) {
@@ -1589,7 +1579,7 @@ impl DictSQLiteV4 {
1589
1579
  #[pyo3(signature = (key, default=None))]
1590
1580
  fn pop(&self, key: String, default: Option<Vec<u8>>, py: Python) -> PyResult<Py<PyAny>> {
1591
1581
  // Track that we're removing this
1592
- self.access_tracker.lock().unwrap().pop(&key);
1582
+ self.access_tracker.lock().pop(&key);
1593
1583
 
1594
1584
  if let Some((_, value)) = self.hot_tier.remove(&key) {
1595
1585
  let data = if let Some(ref crypto) = self.crypto {
@@ -1604,8 +1594,7 @@ impl DictSQLiteV4 {
1604
1594
 
1605
1595
  // Also try to remove from storage if it exists there
1606
1596
  if self.config.persist_mode != PersistMode::Memory {
1607
- let mut storage_guard = self.storage.lock().unwrap();
1608
- if let Some(ref mut storage) = *storage_guard {
1597
+ if let Some(ref storage) = self.storage {
1609
1598
  if let Ok(Some(value)) = storage.get(&key) {
1610
1599
  // Delete from storage
1611
1600
  let _ = storage.delete(&key);
@@ -1642,8 +1631,7 @@ impl DictSQLiteV4 {
1642
1631
 
1643
1632
  // Not in hot tier, check storage
1644
1633
  if self.config.persist_mode != PersistMode::Memory {
1645
- let storage_guard = self.storage.lock().unwrap();
1646
- if let Some(ref storage) = *storage_guard {
1634
+ if let Some(ref storage) = self.storage {
1647
1635
  if let Ok(Some(value)) = storage.get(&key) {
1648
1636
  let data = if let Some(ref crypto) = self.crypto {
1649
1637
  crypto.decrypt(&value).map_err(|e| {
@@ -1652,7 +1640,6 @@ impl DictSQLiteV4 {
1652
1640
  } else {
1653
1641
  value.clone()
1654
1642
  };
1655
- drop(storage_guard);
1656
1643
  // Promote to hot tier
1657
1644
  self.hot_tier.insert(key, value);
1658
1645
  return Ok(PyBytes::new(py, &data).into());
@@ -1702,8 +1689,7 @@ impl DictSQLiteV4 {
1702
1689
 
1703
1690
  // Also get keys from storage if not in memory-only mode
1704
1691
  if self.config.persist_mode != PersistMode::Memory {
1705
- let storage_guard = self.storage.lock().unwrap();
1706
- if let Some(ref storage) = *storage_guard {
1692
+ if let Some(ref storage) = self.storage {
1707
1693
  if let Ok(storage_keys) = storage.keys() {
1708
1694
  for key in storage_keys {
1709
1695
  // Apply same filtering logic
@@ -1741,8 +1727,7 @@ impl DictSQLiteV4 {
1741
1727
 
1742
1728
  // Then check storage
1743
1729
  if self.config.persist_mode != PersistMode::Memory {
1744
- let storage_guard = self.storage.lock().unwrap();
1745
- if let Some(ref storage) = *storage_guard {
1730
+ if let Some(ref storage) = self.storage {
1746
1731
  if let Ok(Some(_)) = storage.get(&full_key) {
1747
1732
  return Ok(true);
1748
1733
  }
@@ -1758,12 +1743,11 @@ impl DictSQLiteV4 {
1758
1743
  self.hot_tier.clear();
1759
1744
 
1760
1745
  // Clear write buffer to prevent pending writes from re-populating the database
1761
- self.write_buffer.lock().unwrap().clear();
1746
+ self.write_buffer.lock().clear();
1762
1747
 
1763
1748
  // Clear storage if not in memory-only mode
1764
1749
  if self.config.persist_mode != PersistMode::Memory {
1765
- let mut storage_guard = self.storage.lock().unwrap();
1766
- if let Some(ref mut storage) = *storage_guard {
1750
+ if let Some(ref storage) = self.storage {
1767
1751
  storage.clear().map_err(|e| {
1768
1752
  PyErr::new::<pyo3::exceptions::PyRuntimeError, _>(format!(
1769
1753
  "Failed to clear storage: {}",
@@ -1986,8 +1970,7 @@ impl DictSQLiteV4 {
1986
1970
  tables.insert("main".to_string());
1987
1971
  Ok(tables.into_iter().collect())
1988
1972
  } else {
1989
- let storage_guard = self.storage.lock().unwrap();
1990
- if let Some(ref storage) = *storage_guard {
1973
+ if let Some(ref storage) = self.storage {
1991
1974
  storage.list_tables().map_err(|e| {
1992
1975
  PyErr::new::<pyo3::exceptions::PyIOError, _>(e.to_string())
1993
1976
  })
@@ -2042,12 +2025,10 @@ impl TableProxy {
2042
2025
  }
2043
2026
  } else {
2044
2027
  // Check storage
2045
- let storage_guard = db.storage.lock().unwrap();
2046
- if let Some(ref storage) = *storage_guard {
2028
+ if let Some(ref storage) = db.storage {
2047
2029
  match storage.get_with_table(&self.table_name, &key) {
2048
2030
  Ok(Some(value)) => {
2049
2031
  // Promote to hot tier
2050
- drop(storage_guard);
2051
2032
  db.hot_tier.insert(cache_key, value.clone());
2052
2033
  // Decrypt if needed
2053
2034
  if let Some(ref crypto) = db.crypto {
@@ -2167,12 +2148,11 @@ impl TableProxy {
2167
2148
  // Update hot tier
2168
2149
  db.hot_tier
2169
2150
  .insert(cache_key.clone(), encrypted_data.clone());
2170
- db.access_tracker.lock().unwrap().put(cache_key, ());
2151
+ db.access_tracker.lock().put(cache_key, ());
2171
2152
 
2172
2153
  // Write to storage in WriteThrough mode
2173
2154
  if db.config.persist_mode == PersistMode::WriteThrough {
2174
- let mut storage_guard = db.storage.lock().unwrap();
2175
- if let Some(ref mut storage) = *storage_guard {
2155
+ if let Some(ref storage) = db.storage {
2176
2156
  storage
2177
2157
  .set_with_table(&self.table_name, &key, &encrypted_data)
2178
2158
  .map_err(|e| {
@@ -2199,13 +2179,12 @@ impl TableProxy {
2199
2179
  let cache_key = format!("{}:{}", self.table_name, key);
2200
2180
 
2201
2181
  // Remove from hot tier
2202
- db.access_tracker.lock().unwrap().pop(&cache_key);
2182
+ db.access_tracker.lock().pop(&cache_key);
2203
2183
  db.hot_tier.remove(&cache_key);
2204
2184
 
2205
2185
  // Remove from storage
2206
2186
  if db.config.persist_mode != PersistMode::Memory {
2207
- let mut storage_guard = db.storage.lock().unwrap();
2208
- if let Some(ref mut storage) = *storage_guard {
2187
+ if let Some(ref storage) = db.storage {
2209
2188
  let _ = storage.delete_with_table(&self.table_name, &key);
2210
2189
  }
2211
2190
  }
@@ -2234,8 +2213,7 @@ impl TableProxy {
2234
2213
 
2235
2214
  // Check storage
2236
2215
  if db.config.persist_mode != PersistMode::Memory {
2237
- let storage_guard = db.storage.lock().unwrap();
2238
- if let Some(ref storage) = *storage_guard {
2216
+ if let Some(ref storage) = db.storage {
2239
2217
  if let Ok(Some(_)) = storage.get_with_table(&self.table_name, &key) {
2240
2218
  return Ok(true);
2241
2219
  }
@@ -2282,8 +2260,7 @@ impl TableProxy {
2282
2260
 
2283
2261
  // Get keys from storage
2284
2262
  if db.config.persist_mode != PersistMode::Memory {
2285
- let storage_guard = db.storage.lock().unwrap();
2286
- if let Some(ref storage) = *storage_guard {
2263
+ if let Some(ref storage) = db.storage {
2287
2264
  if let Ok(storage_keys) = storage.keys_with_table(&self.table_name) {
2288
2265
  all_keys.extend(storage_keys);
2289
2266
  }
@@ -2399,13 +2376,12 @@ impl TableProxy {
2399
2376
 
2400
2377
  for key in keys_to_remove {
2401
2378
  db.hot_tier.remove(&key);
2402
- db.access_tracker.lock().unwrap().pop(&key);
2379
+ db.access_tracker.lock().pop(&key);
2403
2380
  }
2404
2381
 
2405
2382
  // Clear storage table
2406
2383
  if db.config.persist_mode != PersistMode::Memory {
2407
- let mut storage_guard = db.storage.lock().unwrap();
2408
- if let Some(ref mut storage) = *storage_guard {
2384
+ if let Some(ref storage) = db.storage {
2409
2385
  storage.clear_table(&self.table_name).map_err(|e| {
2410
2386
  PyErr::new::<pyo3::exceptions::PyIOError, _>(e.to_string())
2411
2387
  })?;
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes