@@ -917,7 +917,6 @@ struct Iterator final : public BaseIterator {
917917 nexting_(false ),
918918 isClosing_(false ),
919919 ended_(false ),
920- closeWorker_(NULL ),
921920 state_(state),
922921 ref_(NULL ) {
923922 }
@@ -980,7 +979,6 @@ struct Iterator final : public BaseIterator {
980979 bool nexting_;
981980 bool isClosing_;
982981 bool ended_;
983- BaseWorker* closeWorker_;
984982 unsigned char * state_;
985983 std::vector<Entry> cache_;
986984
@@ -996,7 +994,7 @@ struct Iterator final : public BaseIterator {
996994static void env_cleanup_hook (void * arg) {
997995 Database* database = (Database*)arg;
998996
999- // Do everything that db_close () does but synchronously. We're expecting that GC
997+ // Do everything that db.close () does but synchronously. We're expecting that GC
1000998 // did not (yet) collect the database because that would be a user mistake (not
1001999 // closing their db) made during the lifetime of the environment. That's different
10021000 // from an environment being torn down (like the main process or a worker thread)
@@ -1099,6 +1097,7 @@ NAPI_METHOD(db_open) {
10991097 NAPI_ARGV (3 );
11001098 NAPI_DB_CONTEXT ();
11011099 NAPI_ARGV_UTF8_NEW (location, 1 );
1100+ NAPI_PROMISE ();
11021101
11031102 napi_value options = argv[2 ];
11041103 const bool createIfMissing = BooleanProperty (env, options, " createIfMissing" , true );
@@ -1116,8 +1115,6 @@ NAPI_METHOD(db_open) {
11161115
11171116 database->blockCache_ = leveldb::NewLRUCache (cacheSize);
11181117
1119- NAPI_PROMISE ();
1120-
11211118 OpenWorker* worker = new OpenWorker (
11221119 env, database, deferred, location,
11231120 createIfMissing, errorIfExists,
@@ -1159,36 +1156,15 @@ NAPI_METHOD(db_close) {
11591156 NAPI_DB_CONTEXT ();
11601157 NAPI_PROMISE ();
11611158
1159+ // AbstractLevel should not call _close() before iterators are closed
1160+ assert (database->iterators_ .size () == 0 );
1161+
11621162 CloseWorker* worker = new CloseWorker (env, database, deferred);
11631163
11641164 if (!database->HasPriorityWork ()) {
11651165 worker->Queue (env);
1166- return promise;
1167- }
1168-
1169- database->pendingCloseWorker_ = worker;
1170-
1171- std::map<uint32_t , Iterator*> iterators = database->iterators_ ;
1172- std::map<uint32_t , Iterator*>::iterator it;
1173-
1174- for (it = iterators.begin (); it != iterators.end (); ++it) {
1175- Iterator* iterator = it->second ;
1176-
1177- // TODO (v2): should no longer be necessary? Also not in abstract-level v1. But
1178- // if it is, then find a cleaner solution than creating a whole bunch of throwaway promises.
1179- if (!iterator->isClosing_ && !iterator->hasClosed_ ) {
1180- // napi_value iteratorPromise;
1181- // napi_deferred iteratorDeferred;
1182- // NAPI_STATUS_THROWS(napi_create_promise(env, &iteratorDeferred, &iteratorPromise));
1183- // CloseIteratorWorker* worker = new CloseIteratorWorker(env, iterator, iteratorPromise, iteratorDeferred);
1184- // iterator->isClosing_ = true;
1185- //
1186- // if (iterator->nexting_) {
1187- // iterator->closeWorker_ = worker;
1188- // } else {
1189- // worker->Queue(env);
1190- // }
1191- }
1166+ } else {
1167+ database->pendingCloseWorker_ = worker;
11921168 }
11931169
11941170 return promise;
@@ -1757,9 +1733,9 @@ NAPI_METHOD(iterator_seek) {
17571733 NAPI_ARGV (2 );
17581734 NAPI_ITERATOR_CONTEXT ();
17591735
1760- if (iterator-> isClosing_ || iterator-> hasClosed_ ) {
1761- NAPI_RETURN_UNDEFINED ( );
1762- }
1736+ // AbstractIterator should not call _seek() after _close()
1737+ assert (!iterator-> isClosing_ );
1738+ assert (!iterator-> hasClosed_ );
17631739
17641740 leveldb::Slice target = ToSlice (env, argv[1 ]);
17651741 iterator->first_ = true ;
@@ -1801,20 +1777,16 @@ NAPI_METHOD(iterator_close) {
18011777 NAPI_ITERATOR_CONTEXT ();
18021778 NAPI_PROMISE ();
18031779
1804- if (!iterator-> isClosing_ && !iterator-> hasClosed_ ) {
1805- CloseIteratorWorker* worker = new CloseIteratorWorker (env, iterator, deferred );
1806- iterator->isClosing_ = true ;
1780+ // AbstractIterator should not call _close() more than once
1781+ assert (! iterator-> isClosing_ );
1782+ assert (! iterator->hasClosed_ ) ;
18071783
1808- if (iterator->nexting_ ) {
1809- iterator->closeWorker_ = worker;
1810- } else {
1811- worker->Queue (env);
1812- }
1813- } else {
1814- // TODO (v2): I think we can remove the isClosing_ checks
1815- napi_value argv = CreateCodeError (env, " LEVEL_XYZ" , " Should not happen?" );
1816- NAPI_STATUS_THROWS (napi_reject_deferred (env, deferred, argv));
1817- }
1784+ // AbstractIterator should not call _close() while next() is in-progress
1785+ assert (!iterator->nexting_ );
1786+
1787+ CloseIteratorWorker* worker = new CloseIteratorWorker (env, iterator, deferred);
1788+ iterator->isClosing_ = true ;
1789+ worker->Queue (env);
18181790
18191791 return promise;
18201792}
@@ -1864,15 +1836,7 @@ struct NextWorker final : public BaseWorker {
18641836 }
18651837
18661838 void DoFinally (napi_env env) override {
1867- // clean up & handle the next/close state
18681839 iterator_->nexting_ = false ;
1869-
1870- // TODO (v2): check if still needed
1871- if (iterator_->closeWorker_ != NULL ) {
1872- iterator_->closeWorker_ ->Queue (env);
1873- iterator_->closeWorker_ = NULL ;
1874- }
1875-
18761840 BaseWorker::DoFinally (env);
18771841 }
18781842
@@ -1894,11 +1858,11 @@ NAPI_METHOD(iterator_nextv) {
18941858 NAPI_STATUS_THROWS (napi_get_value_uint32 (env, argv[1 ], &size));
18951859 if (size == 0 ) size = 1 ;
18961860
1897- if (iterator-> isClosing_ || iterator-> hasClosed_ ) {
1898- // TODO (v2): test, or remove
1899- napi_value argv = CreateCodeError (env, " LEVEL_ITERATOR_NOT_OPEN " , " Iterator is not open " );
1900- NAPI_STATUS_THROWS ( napi_reject_deferred (env, deferred, argv));
1901- } else if (iterator->ended_ ) {
1861+ // AbstractIterator should not call _next() or _nextv() after _close()
1862+ assert (!iterator-> isClosing_ );
1863+ assert (!iterator-> hasClosed_ );
1864+
1865+ if (iterator->ended_ ) {
19021866 napi_value empty;
19031867 napi_create_array_with_length (env, 0 , &empty);
19041868 napi_resolve_deferred (env, deferred, empty);
0 commit comments