blob: 0e29070a3ff2adc51e107488a2623a58ef979ad2 [file] [log] [blame]
// Copyright 2015 The Vanadium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package io.v.android.apps.syncslides.db;
import android.util.Log;
import io.v.impl.google.naming.NamingUtil;
import io.v.v23.syncbase.nosql.BatchDatabase;
import io.v.v23.syncbase.nosql.ChangeType;
import io.v.v23.syncbase.nosql.Stream;
import io.v.v23.syncbase.nosql.Table;
import io.v.v23.syncbase.nosql.WatchChange;
import io.v.v23.verror.VException;
import io.v.v23.vom.VomUtil;
/**
* Watches for a new driver (person controlling the slides) in a given presentation.
*/
class DriverWatcher {
private static final String TAG = "DriverWatcher";
private final WatcherState mState;
private final DB.DriverListener mListener;
private boolean mIsDiscarded;
/**
* Creates a new watcher for the presentation in state.
*
* @param state objects necessary to do the watching
* @param listener notified whenever the driver changes
*/
public DriverWatcher(WatcherState state, DB.DriverListener listener) {
mState = state;
mListener = listener;
mState.thread = new Thread(new Runnable() {
@Override
public void run() {
watch();
}
});
mState.thread.start();
mIsDiscarded = false;
}
/**
* Stops watching the presentation for a new driver.
*/
public void discard() {
mState.vContext.cancel(); // this will cause the watcher thread to exit
mState.handler.removeCallbacksAndMessages(null);
// We've canceled all the pending callbacks, but the handler might be just about
// to execute put()/get() and those messages wouldn't get canceled. So we mark
// the list as discarded and count on put()/get() checking for it.
mIsDiscarded = true;
}
private void watch() {
try {
String row = NamingUtil.join(mState.deckId, mState.presentationId);
Log.i(TAG, "Watching driver: " + row);
BatchDatabase batch = mState.db.beginBatch(mState.vContext, null);
Table presentations = batch.getTable(SyncbaseDB.PRESENTATIONS_TABLE);
if (presentations.getRow(row).exists(mState.vContext)) {
VPresentation presentation = (VPresentation) presentations.get(
mState.vContext, row, VPresentation.class);
postInUiThread(presentation.getDriver().getElem());
}
Stream<WatchChange> watch = mState.db.watch(
mState.vContext, SyncbaseDB.PRESENTATIONS_TABLE, row,
batch.getResumeMarker(mState.vContext));
for (WatchChange change : watch) {
Log.i(TAG, "Found change " + change.getChangeType());
if (!change.getRowName().equals(row)) {
continue;
}
if (change.getChangeType().equals(ChangeType.PUT_CHANGE)) {
final VPresentation presentation = (VPresentation) VomUtil.decode(
change.getVomValue(), VPresentation.class);
postInUiThread(presentation.getDriver().getElem());
} else { // ChangeType.DELETE_CHANGE
postInUiThread(null);
}
}
} catch (VException e) {
e.printStackTrace();
}
}
private void postInUiThread(final VPerson driver) {
mState.handler.post(new Runnable() {
@Override
public void run() {
if (!mIsDiscarded) {
mListener.onChange(driver);
}
}
});
}
}