@@ -900,142 +900,117 @@ Future<void> _worker(
900900 rethrow ;
901901 }
902902
903- final storesQuery = root
904- .box <ObjectBoxStore >()
905- .query (ObjectBoxStore_ .name.oneOf (storeNames))
906- .build ();
903+ try {
904+ final storesQuery = root
905+ .box <ObjectBoxStore >()
906+ .query (ObjectBoxStore_ .name.oneOf (storeNames))
907+ .build ();
908+ final tilesQuery = (root.box <ObjectBoxTile >().query ()
909+ ..linkMany (
910+ ObjectBoxTile_ .stores,
911+ ObjectBoxStore_ .name.oneOf (storeNames),
912+ ))
913+ .build ();
907914
908- final tilesQuery = (root.box <ObjectBoxTile >().query ()
909- ..linkMany (
910- ObjectBoxTile_ .stores,
911- ObjectBoxStore_ .name.oneOf (storeNames),
912- ))
913- .build ();
915+ // Copy all stores to external root
916+ // Then, to make sure relations work 100%, we go through the stores
917+ // just copied to the external root and add them to the map below
918+ final storesToExport = storesQuery.find ();
919+ if (! listEquals (
920+ storesToExport.map ((s) => s.name).toList (growable: false ),
921+ storeNames,
922+ )) {
923+ throw ArgumentError (
924+ 'Specified stores did not match the resolved existing stores' ,
925+ 'storeNames' ,
926+ );
927+ }
928+ final storesObjectsForRelations =
929+ Map <String , ObjectBoxStore >.fromEntries (
930+ (exportingRoot.box <ObjectBoxStore >()
931+ ..putMany (
932+ storesQuery
933+ .find ()
934+ .map (
935+ (store) => ObjectBoxStore (
936+ name: store.name,
937+ maxLength: store.maxLength,
938+ length: store.length,
939+ size: store.size,
940+ hits: store.hits,
941+ misses: store.misses,
942+ metadataJson: store.metadataJson,
943+ ),
944+ )
945+ .toList (growable: false ),
946+ mode: PutMode .insert,
947+ ))
948+ .getAll ()
949+ .map ((s) => MapEntry (s.name, s)),
950+ );
914951
915- final storesObjectsForRelations = < String , ObjectBoxStore > {};
952+ // Copy all tiles to external root
953+ int numExportedTiles = 0 ;
954+ tilesQuery.chunkedMultiTransaction (
955+ chunkSize: 300 ,
956+ root: root,
957+ runInTransaction: (tile) {
958+ exportingRoot.box <ObjectBoxTile >().put (
959+ ObjectBoxTile (
960+ url: tile.url,
961+ bytes: tile.bytes,
962+ lastModified: tile.lastModified,
963+ )..stores.addAll (
964+ tile.stores
965+ .map ((s) => storesObjectsForRelations[s.name])
966+ .nonNulls,
967+ ),
968+ mode: PutMode .insert,
969+ );
970+ numExportedTiles++ ;
971+ },
972+ );
916973
917- final exportingStores = root.runInTransaction (
918- TxMode .read,
919- storesQuery.stream,
920- );
974+ storesQuery.close ();
975+ tilesQuery.close ();
976+ exportingRoot.close ();
921977
922- exportingRoot
923- .runInTransaction (
924- TxMode .write,
925- () => exportingStores.map (
926- (exportingStore) {
927- exportingRoot.box <ObjectBoxStore >().put (
928- storesObjectsForRelations[exportingStore.name] =
929- ObjectBoxStore (
930- name: exportingStore.name,
931- maxLength: exportingStore.maxLength,
932- length: exportingStore.length,
933- size: exportingStore.size,
934- hits: exportingStore.hits,
935- misses: exportingStore.misses,
936- metadataJson: exportingStore.metadataJson,
937- ),
938- mode: PutMode .insert,
939- );
940- },
941- ),
942- )
943- .length
944- .then (
945- (numExportedStores) {
946- if (numExportedStores == 0 ) throw StateError ('Unpossible' );
947-
948- final exportingTiles = root.runInTransaction (
949- TxMode .read,
950- tilesQuery.stream,
951- );
978+ final dbFile = File (path.join (workingDir.absolute.path, 'data.mdb' ));
952979
953- exportingRoot
954- .runInTransaction (
955- TxMode .write,
956- () => exportingTiles.map (
957- (exportingTile) {
958- exportingRoot.box <ObjectBoxTile >().put (
959- ObjectBoxTile (
960- url: exportingTile.url,
961- bytes: exportingTile.bytes,
962- lastModified: exportingTile.lastModified,
963- )..stores.addAll (
964- exportingTile.stores
965- .map (
966- (s) => storesObjectsForRelations[s.name],
967- )
968- .nonNulls,
969- ),
970- mode: PutMode .insert,
971- );
972- },
973- ),
974- )
975- .length
976- .then (
977- (numExportedTiles) {
978- if (numExportedTiles == 0 ) {
979- throw ArgumentError (
980- 'Specified stores must include at least one tile total' ,
981- 'storeNames' ,
982- );
983- }
980+ final ram = dbFile.openSync (mode: FileMode .writeOnlyAppend);
981+ try {
982+ ram
983+ ..writeFromSync (List .filled (4 , 255 ))
984+ ..writeStringSync ('ObjectBox' ) // Backend identifier
985+ ..writeByteSync (255 )
986+ ..writeByteSync (255 )
987+ ..writeStringSync ('FMTC' ); // Signature
988+ } finally {
989+ ram.closeSync ();
990+ }
984991
985- storesQuery.close ();
986- tilesQuery.close ();
987- exportingRoot.close ();
988-
989- final dbFile =
990- File (path.join (workingDir.absolute.path, 'data.mdb' ));
991-
992- final ram = dbFile.openSync (mode: FileMode .writeOnlyAppend);
993- try {
994- ram
995- ..writeFromSync (List .filled (4 , 255 ))
996- ..writeStringSync ('ObjectBox' ) // Backend identifier
997- ..writeByteSync (255 )
998- ..writeByteSync (255 )
999- ..writeStringSync ('FMTC' ); // Signature
1000- } finally {
1001- ram.closeSync ();
1002- }
992+ try {
993+ dbFile.renameSync (outputPath);
994+ } on FileSystemException {
995+ dbFile.copySync (outputPath);
996+ } finally {
997+ workingDir.deleteSync (recursive: true );
998+ }
1003999
1004- try {
1005- dbFile.renameSync (outputPath);
1006- } on FileSystemException {
1007- dbFile.copySync (outputPath);
1008- } finally {
1009- workingDir.deleteSync (recursive: true );
1010- }
1000+ sendRes (
1001+ id: cmd.id,
1002+ data: {'numExportedTiles' : numExportedTiles},
1003+ );
10111004
1012- sendRes (
1013- id: cmd.id,
1014- data: {'numExportedTiles' : numExportedTiles},
1015- );
1016- },
1017- ).catchError ((error, stackTrace) {
1018- exportingRoot.close ();
1019- try {
1020- workingDir.deleteSync (recursive: true );
1021- // If the working dir didn't exist, that's fine
1022- // We don't want to spend time checking if exists, as it likely
1023- // does
1024- // ignore: empty_catches
1025- } on FileSystemException {}
1026- Error .throwWithStackTrace (error, stackTrace);
1027- });
1028- },
1029- ).catchError ((error, stackTrace) {
1005+ // We don't care what type, we always need to clean up and rethrow
1006+ // ignore: avoid_catches_without_on_clauses
1007+ } catch (e) {
10301008 exportingRoot.close ();
1031- try {
1009+ if (workingDir. existsSync ()) {
10321010 workingDir.deleteSync (recursive: true );
1033- // If the working dir didn't exist, that's fine
1034- // We don't want to spend time checking if exists, as it likely does
1035- // ignore: empty_catches
1036- } on FileSystemException {}
1037- Error .throwWithStackTrace (error, stackTrace);
1038- });
1011+ }
1012+ rethrow ;
1013+ }
10391014 case _CmdType .importStores:
10401015 final importPath = cmd.args['path' ]! as String ;
10411016 final strategy = cmd.args['strategy' ] as ImportConflictStrategy ;
0 commit comments