@@ -178,17 +178,24 @@ class JavaFirestoreMap {
178
178
jni::Global<jni::HashMap> firestores_;
179
179
};
180
180
181
- // Governed by init_mutex_below as well.
182
- JavaFirestoreMap* java_firestores_ = nullptr ;
181
+ // init_mutex protects all the globals below.
182
+ Mutex init_mutex; // NOLINT
183
+ int initialize_count = 0 ;
184
+ Loader* global_loader = nullptr ;
185
+
186
+ JavaFirestoreMap* java_firestores = nullptr ;
187
+
188
+ // The initial value for setLoggingEnabled.
189
+ enum class InitialLogState {
190
+ kUnset ,
191
+ kSetEnabled ,
192
+ kSetDisabled ,
193
+ } initial_log_state = InitialLogState::kUnset ;
183
194
184
195
} // namespace
185
196
186
197
const char kApiIdentifier [] = " Firestore" ;
187
198
188
- Mutex FirestoreInternal::init_mutex_; // NOLINT
189
- int FirestoreInternal::initialize_count_ = 0 ;
190
- Loader* FirestoreInternal::loader_ = nullptr ;
191
-
192
199
FirestoreInternal::FirestoreInternal (App* app) {
193
200
FIREBASE_ASSERT (app != nullptr );
194
201
if (!Initialize (app)) return ;
@@ -200,7 +207,7 @@ FirestoreInternal::FirestoreInternal(App* app) {
200
207
FIREBASE_ASSERT (java_firestore.get () != nullptr );
201
208
obj_ = java_firestore;
202
209
203
- java_firestores_ ->Put (env, java_firestore, this );
210
+ java_firestores ->Put (env, java_firestore, this );
204
211
205
212
// Mainly for enabling TimestampsInSnapshotsEnabled. The rest comes from the
206
213
// default in native SDK. The C++ implementation relies on that for reading
@@ -218,12 +225,12 @@ FirestoreInternal::FirestoreInternal(App* app) {
218
225
219
226
/* static */
220
227
bool FirestoreInternal::Initialize (App* app) {
221
- MutexLock init_lock (init_mutex_ );
222
- if (initialize_count_ == 0 ) {
228
+ MutexLock init_lock (init_mutex );
229
+ if (initialize_count == 0 ) {
223
230
jni::Initialize (app->java_vm ());
224
231
225
- FIREBASE_DEV_ASSERT (java_firestores_ == nullptr );
226
- java_firestores_ = new JavaFirestoreMap ();
232
+ FIREBASE_DEV_ASSERT (java_firestores == nullptr );
233
+ java_firestores = new JavaFirestoreMap ();
227
234
228
235
Loader loader (app);
229
236
loader.AddEmbeddedFile (::firebase_firestore::firestore_resources_filename,
@@ -272,32 +279,43 @@ bool FirestoreInternal::Initialize(App* app) {
272
279
TransactionInternal::Initialize (loader);
273
280
WriteBatchInternal::Initialize (loader);
274
281
if (!loader.ok ()) {
275
- ReleaseClasses (app);
282
+ ReleaseClassesLocked (app);
276
283
return false ;
277
284
}
278
285
279
- FIREBASE_DEV_ASSERT (loader_ == nullptr );
280
- loader_ = new Loader (Move (loader));
286
+ FIREBASE_DEV_ASSERT (global_loader == nullptr );
287
+ global_loader = new Loader (Move (loader));
288
+
289
+ if (initial_log_state != InitialLogState::kUnset ) {
290
+ Env env;
291
+ bool enabled = initial_log_state == InitialLogState::kSetEnabled ;
292
+ env.Call (kSetLoggingEnabled , enabled);
293
+
294
+ // If this fails it's unimportant. If there's some broad systemic failure
295
+ // the next real operation will trigger it too.
296
+ env.ExceptionClear ();
297
+ }
281
298
}
282
- initialize_count_ ++;
299
+ initialize_count ++;
283
300
return true ;
284
301
}
285
302
286
303
/* static */
287
- void FirestoreInternal::ReleaseClasses (App* app) {
288
- delete loader_;
289
- loader_ = nullptr ;
304
+ void FirestoreInternal::ReleaseClassesLocked (App* app) {
305
+ // Assumes `init_mutex` is held.
306
+ delete global_loader;
307
+ global_loader = nullptr ;
290
308
}
291
309
292
310
/* static */
293
311
void FirestoreInternal::Terminate (App* app) {
294
- MutexLock init_lock (init_mutex_ );
295
- FIREBASE_ASSERT (initialize_count_ > 0 );
296
- initialize_count_ --;
297
- if (initialize_count_ == 0 ) {
298
- ReleaseClasses (app);
299
- delete java_firestores_ ;
300
- java_firestores_ = nullptr ;
312
+ MutexLock init_lock (init_mutex );
313
+ FIREBASE_ASSERT (initialize_count > 0 );
314
+ initialize_count --;
315
+ if (initialize_count == 0 ) {
316
+ ReleaseClassesLocked (app);
317
+ delete java_firestores ;
318
+ java_firestores = nullptr ;
301
319
}
302
320
}
303
321
@@ -316,7 +334,7 @@ FirestoreInternal::~FirestoreInternal() {
316
334
317
335
future_manager_.ReleaseFutureApi (this );
318
336
319
- java_firestores_ ->Remove (env, obj_);
337
+ java_firestores ->Remove (env, obj_);
320
338
321
339
Terminate (app_);
322
340
app_ = nullptr ;
@@ -512,13 +530,28 @@ void Firestore::set_log_level(LogLevel log_level) {
512
530
// "Info", "warning", "error", and "assert" map to logging disabled.
513
531
bool logging_enabled = log_level < LogLevel::kLogLevelInfo ;
514
532
533
+ {
534
+ MutexLock lock (init_mutex);
535
+
536
+ // Set the initial_log_state on every invocation, just in case Firestore
537
+ // is terminated for long enough to unload the Firestore classes within
538
+ // the JVM.
539
+ initial_log_state = logging_enabled ? InitialLogState::kSetEnabled
540
+ : InitialLogState::kSetDisabled ;
541
+
542
+ if (initialize_count < 1 ) {
543
+ // Avoid invoking Java methods before Firestore has been initialized.
544
+ return ;
545
+ }
546
+ }
547
+
515
548
Env env = FirestoreInternal::GetEnv ();
516
549
env.Call (kSetLoggingEnabled , logging_enabled);
517
550
}
518
551
519
552
FirestoreInternal* FirestoreInternal::RecoverFirestore (
520
553
Env& env, const Object& java_firestore) {
521
- return java_firestores_ ->Get (env, java_firestore);
554
+ return java_firestores ->Get (env, java_firestore);
522
555
}
523
556
524
557
void FirestoreInternal::SetClientLanguage (const std::string& language_token) {
0 commit comments