Skip to content
Permalink
Browse files

Split Box and LazyBox

  • Loading branch information
leisim committed Nov 17, 2019
1 parent 2b07a34 commit edffb58415d4c8b93e4c6b066bedc47990ede6ef
@@ -18,7 +18,7 @@ jobs:
run: |
pub get
pub global activate test_coverage
pub global run test_coverage --exclude "**_js_test.dart"
pub global run test_coverage --exclude "**/js/**"
- uses: codecov/codecov-action@v1.0.0
with:
token: ${{ secrets.CODECOV_TOKEN }}
@@ -2,10 +2,22 @@

### Breaking changes
- Removed the `Hive.path` getter
- Renamed `Hive.openBoxFromBytes()` to `Hive.openMemoryBox()`
- Removed `Hive.openBoxFromBytes()` (use the `bytes` parameter of `Hive.openBox()` instead)
- `LazyBox` and `Box` now have a common parent class: `BoxBase`
- Lazy boxes need to be opened using `Hive.openLazyBox()`
- Open lazy boxes can be aquired using `Hive.lazyBox()`

## Enhancements
- Lazy boxes can now have a type argument `LazyBox<SomeClass>`
- Added method to delete boxes without opening them `Hive.deleteBoxFromDisk()`
- Added `path` parameter to open boxes in a custom path

### Fixes
- HiveObjects have not been initialized correctly in lazy boxes
- Fixed bug where uppercase box name resulted in uppercase file name

### More
- Changed type of `encryptionKey` from `Uint8List` to `List<int>`

## 1.1.1

@@ -6,20 +6,22 @@ import 'dart:async';
import 'dart:convert';
import 'dart:typed_data';

import 'package:hive/src/box/default_compaction_strategy.dart';
import 'package:hive/src/box/default_key_comparator.dart';
import 'package:hive/src/hive_impl.dart';
import 'package:meta/meta.dart';

export 'src/hive_object.dart';

part 'src/annotations/hive_field.dart';
part 'src/annotations/hive_type.dart';
part 'src/binary/binary_reader.dart';
part 'src/binary/binary_writer.dart';
part 'src/box/box_base.dart';
part 'src/box/box.dart';
part 'src/box/lazy_box.dart';
part 'src/registry/type_registry.dart';
part 'src/registry/type_adapter.dart';
part 'src/hive_error.dart';
part 'src/hive_object.dart';
part 'src/hive.dart';

/// Global constant to access Hive.
@@ -0,0 +1,27 @@
import 'dart:html';
import 'dart:indexed_db';

import 'package:hive/src/backend/js/storage_backend.dart';
import 'package:hive/src/backend/storage_backend.dart';
import 'package:hive/src/crypto_helper.dart';

class BackendManager implements BackendManagerInterface {
@override
Future<StorageBackend> open(
String name, String path, bool crashRecovery, CryptoHelper crypto) async {
var db =
await window.indexedDB.open(name, version: 1, onUpgradeNeeded: (e) {
var db = e.target.result as Database;
if (!db.objectStoreNames.contains('box')) {
db.createObjectStore('box');
}
});

return StorageBackendJs(db, crypto);
}

@override
Future<void> deleteBox(String name, String path) {
return window.indexedDB.deleteDatabase(name);
}
}
@@ -12,26 +12,13 @@ import 'package:hive/src/box/keystore.dart';
import 'package:hive/src/crypto_helper.dart';
import 'package:meta/meta.dart';

Future<StorageBackend> openBackend(HiveInterface hive, String name, bool lazy,
bool crashRecovery, CryptoHelper crypto) async {
var db = await window.indexedDB.open(name, version: 1, onUpgradeNeeded: (e) {
var db = e.target.result as Database;
if (!db.objectStoreNames.contains('box')) {
db.createObjectStore('box');
}
});

return StorageBackendJs(db, lazy, crypto);
}

class StorageBackendJs extends StorageBackend {
final Database db;
final bool lazy;
final CryptoHelper crypto;

TypeRegistry _registry;

StorageBackendJs(this.db, this.lazy, this.crypto, [this._registry]);
StorageBackendJs(this.db, this.crypto, [this._registry]);

@override
String get path => null;
@@ -120,7 +107,8 @@ class StorageBackendJs extends StorageBackend {
}

@override
Future<int> initialize(TypeRegistry registry, Keystore keystore) async {
Future<int> initialize(
TypeRegistry registry, Keystore keystore, bool lazy) async {
_registry = registry;
var keys = await getKeys();
if (!lazy) {
@@ -1,17 +1,18 @@
import 'package:hive/hive.dart';
import 'package:hive/src/binary/frame.dart';
import 'package:hive/src/box/keystore.dart';
import 'package:hive/src/crypto_helper.dart';

export 'package:hive/src/backend/storage_backend_stub.dart'
if (dart.library.io) 'package:hive/src/backend/storage_backend_vm.dart'
if (dart.library.html) 'package:hive/src/backend/storage_backend_js.dart';
export 'package:hive/src/backend/stub/backend_manager.dart'
if (dart.library.io) 'package:hive/src/backend/vm/backend_manager.dart'
if (dart.library.html) 'package:hive/src/backend/js/backend_manager.dart';

abstract class StorageBackend {
String get path;

bool get supportsCompaction;

Future<void> initialize(TypeRegistry registry, Keystore keystore);
Future<void> initialize(TypeRegistry registry, Keystore keystore, bool lazy);

Future<dynamic> readValue(Frame frame);

@@ -25,3 +26,10 @@ abstract class StorageBackend {

Future<void> deleteFromDisk();
}

abstract class BackendManagerInterface {
Future<StorageBackend> open(
String name, String path, bool crashRecovery, CryptoHelper crypto);

Future<void> deleteBox(String name, String path);
}
@@ -23,7 +23,7 @@ class StorageBackendMemory extends StorageBackend {
bool supportsCompaction = false;

@override
Future<void> initialize(TypeRegistry registry, Keystore keystore) async {
Future<void> initialize(TypeRegistry registry, Keystore keystore, bool lazy) {
var recoveryOffset =
frameHelper.framesFromBytes(_bytes, keystore, registry, crypto);

@@ -32,6 +32,8 @@ class StorageBackendMemory extends StorageBackend {
}

_bytes = null;

return Future.value();
}

@override

This file was deleted.

@@ -0,0 +1,15 @@
import 'package:hive/src/backend/storage_backend.dart';
import 'package:hive/src/crypto_helper.dart';

class BackendManager implements BackendManagerInterface {
@override
Future<StorageBackend> open(
String name, String path, bool crashRecovery, CryptoHelper crypto) {
throw UnimplementedError();
}

@override
Future<void> deleteBox(String name, String path) {
throw UnimplementedError();
}
}
@@ -0,0 +1,51 @@
import 'dart:io';

import 'package:hive/src/backend/storage_backend.dart';
import 'package:hive/src/backend/vm/storage_backend.dart';
import 'package:hive/src/crypto_helper.dart';
import 'package:meta/meta.dart';
import 'package:path/path.dart' as path_helper;

class BackendManager implements BackendManagerInterface {
@override
Future<StorageBackend> open(
String name, String path, bool crashRecovery, CryptoHelper crypto) async {
var dir = Directory(path);
if (!await dir.exists()) {
await dir.create(recursive: true);
}

var file = await findHiveFileAndCleanUp(name, path);
var lockFile = File(path_helper.join(path, '$name.lock'));

var backend = StorageBackendVm(file, lockFile, crashRecovery, crypto);
await backend.open();
return backend;
}

@visibleForTesting
Future<File> findHiveFileAndCleanUp(String name, String path) async {
var hiveFile = File(path_helper.join(path, '$name.hive'));
var compactedFile = File(path_helper.join(path, '$name.hivec'));

if (await hiveFile.exists()) {
if (await compactedFile.exists()) {
await compactedFile.delete();
}
return hiveFile;
} else if (await compactedFile.exists()) {
print('Restoring compacted file.');
return await compactedFile.rename(hiveFile.path);
} else {
await hiveFile.create();
return hiveFile;
}
}

@override
Future<void> deleteBox(String name, String path) async {
await File(path_helper.join(path, '$name.hive')).delete();
await File(path_helper.join(path, '$name.hivec')).delete();
await File(path_helper.join(path, '$name.lock')).delete();
}
}
@@ -15,57 +15,9 @@ import 'package:hive/src/io/frame_io_helper.dart';
import 'package:meta/meta.dart';
import 'package:path/path.dart' as p;

Future<StorageBackend> openBackend(HiveInterface hive, String name, bool lazy,
bool crashRecovery, CryptoHelper crypto) async {
var dir = Directory(hive.path);
if (!await dir.exists()) {
await dir.create(recursive: true);
}

var file = await findHiveFileAndCleanUp(name, dir);
var lockFile = File(p.join(dir.path, '$name.lock'));

var backend = StorageBackendVm(file, lockFile, lazy, crashRecovery, crypto);
await backend.open();
return backend;
}

@visibleForTesting
Future<File> findHiveFileAndCleanUp(String boxName, Directory dir) async {
File hiveFile;
File compactedFile;

var files = await dir.list(followLinks: false).toList();
for (var file in files) {
if (file is File) {
if (file.path.endsWith('$boxName.hive')) {
hiveFile = file;
} else if (file.path.endsWith('$boxName.hivec')) {
compactedFile = file;
}
}
}

if (hiveFile != null) {
if (compactedFile != null) {
await compactedFile.delete();
}
return hiveFile;
} else if (compactedFile != null) {
print('Restoring compacted file.');
var newPath = p.setExtension(compactedFile.path, '.hive');
return await compactedFile.rename(newPath);
} else {
hiveFile = File(p.join(dir.path, '$boxName.hive'));
await hiveFile.create();
return hiveFile;
}
}

class StorageBackendVm extends StorageBackend {
final File file;
final File lockFile;
final bool lazy;
final bool crashRecovery;
final CryptoHelper crypto;
final FrameIoHelper frameHelper;
@@ -87,13 +39,12 @@ class StorageBackendVm extends StorageBackend {
@visibleForTesting
TypeRegistry registry;

StorageBackendVm(
this.file, this.lockFile, this.lazy, this.crashRecovery, this.crypto)
StorageBackendVm(this.file, this.lockFile, this.crashRecovery, this.crypto)
: frameHelper = FrameIoHelper(),
_sync = ReadWriteSync();

StorageBackendVm.debug(this.file, this.lockFile, this.lazy,
this.crashRecovery, this.crypto, this.frameHelper, this._sync);
StorageBackendVm.debug(this.file, this.lockFile, this.crashRecovery,
this.crypto, this.frameHelper, this._sync);

@override
String get path => file.path;
@@ -108,7 +59,8 @@ class StorageBackendVm extends StorageBackend {
}

@override
Future<void> initialize(TypeRegistry registry, Keystore keystore) async {
Future<void> initialize(
TypeRegistry registry, Keystore keystore, bool lazy) async {
this.registry = registry;

lockRaf = await lockFile.open(mode: FileMode.write);

0 comments on commit edffb58

Please sign in to comment.
You can’t perform that action at this time.