blob: e4fe3ca419cd6b45e293573ad41eede902d90b13 [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.
import 'discovery_client.dart' show DiscoveryClient;
import 'util.dart' as util;
import 'dart:async';
import 'dart:io' show Platform;
import 'package:v23discovery/discovery.dart' as discovery;
import 'package:flutter/services.dart' show shell;
import 'package:syncbase/src/naming/util.dart' as naming;
import 'package:syncbase/syncbase_client.dart' as sc;
class CroupierClient {
final sc.SyncbaseClient _syncbaseClient;
final DiscoveryClient _discoveryClient;
static final String syncbaseServerUrl = Platform.environment[
'SYNCBASE_SERVER_URL'] ??
'https://mojo.v.io/syncbase_server.mojo';
static final String discoveryTestKey = "TEST";
// We want CroupierClient to be a singleton for simplicity purposes.
// This prevents duplicate table/database creation.
static final CroupierClient _singleton = new CroupierClient._internal();
factory CroupierClient() {
return _singleton;
}
CroupierClient._internal()
: _syncbaseClient =
new sc.SyncbaseClient(shell.connectToService, syncbaseServerUrl),
_discoveryClient = new DiscoveryClient() {
print('Fetching syncbase_server.mojo from $syncbaseServerUrl');
// TODO(alexfandrianto): Remove this test advertisement once we are more
// comfortable with Discovery.
String interfaceName = "HelloWorld!";
_discoveryClient.scan(discoveryTestKey,
'v.InterfaceName="${interfaceName}"', new MyScanHandler());
_discoveryClient.advertise(
discoveryTestKey,
DiscoveryClient.serviceMaker(
interfaceName: interfaceName, addrs: ["dummy address"]));
}
DiscoveryClient get discoveryClient => _discoveryClient;
// TODO(alexfandrianto): Try not to call this twice at the same time.
// That would lead to very race-y behavior.
Future<sc.SyncbaseDatabase> createDatabase() async {
util.log('CroupierClient.createDatabase');
var app = _syncbaseClient.app(util.appName);
if (!(await app.exists())) {
await app.create(util.openPerms);
}
util.log('CroupierClient.got app');
var db = app.noSqlDatabase(util.dbName);
if (!(await db.exists())) {
await db.create(util.openPerms);
}
util.log('CroupierClient.got db');
return db;
}
Completer _tableLock;
// TODO(alexfandrianto): Try not to call this twice at the same time.
// That would lead to very race-y behavior.
Future<sc.SyncbaseTable> createTable(
sc.SyncbaseDatabase db, String tableName) async {
if (_tableLock != null) {
await _tableLock.future;
}
_tableLock = new Completer();
var table = db.table(tableName);
if (!(await table.exists())) {
await table.create(util.openPerms);
}
util.log('CroupierClient: ${tableName} is ready');
_tableLock.complete();
return table;
}
// Creates (or joins) a syncgroup with the associated parameters.
Future<sc.SyncbaseSyncgroup> createSyncgroup(String sgName, String tableName,
{String prefix, String description, sc.Perms permissions}) async {
util.log("CroupierClient: Creating syncgroup ${sgName}");
// TODO(alexfandrianto): destroy is still unimplemented. Thus, we must do a
// join or create for this syncgroup.
try {
util.log("CroupierClient: But first attempting to join ${sgName}");
sc.SyncbaseSyncgroup sg = await joinSyncgroup(sgName);
util.log("CroupierClient: Successfully joined ${sgName}");
return sg;
} catch (e) {
util.log(
"CroupierClient: ${sgName} doesn't exist, so actually creating it.");
}
var myInfo = sc.SyncbaseClient.syncgroupMemberInfo(syncPriority: 3);
String mtName = util.mtAddr;
sc.SyncbaseSyncgroup sg = await _getSyncgroup(sgName);
var sgSpec = sc.SyncbaseClient.syncgroupSpec(
// Sync the entire table.
[sc.SyncbaseClient.syncgroupPrefix(tableName, prefix ?? "")],
description: description ?? 'test syncgroup',
perms: permissions ?? util.openPerms,
mountTables: [mtName]);
util.log('SGSPEC = $sgSpec');
await sg.create(sgSpec, myInfo);
return sg;
}
// Joins a syncgroup with the given name.
Future<sc.SyncbaseSyncgroup> joinSyncgroup(String sgName) async {
util.log("CroupierClient: Joining syncgroup ${sgName}");
var myInfo = sc.SyncbaseClient.syncgroupMemberInfo(syncPriority: 3);
sc.SyncbaseSyncgroup sg = await _getSyncgroup(sgName);
await sg.join(myInfo);
return sg;
}
// Helper to get the SyncbaseSyncgroup object from the string.
Future<sc.SyncbaseSyncgroup> _getSyncgroup(String sgName) async {
sc.SyncbaseDatabase db = await createDatabase();
return db.syncgroup(sgName);
}
// Helper that converts a suffix to a syncgroup name.
String makeSyncgroupName(String suffix) {
String mtName = util.mtAddr;
String sgPrefix = naming.join(mtName, util.sgPrefix);
String sgName = naming.join(sgPrefix, suffix);
return sgName;
}
}
// Example implementation of a ScanHandler.
class MyScanHandler extends discovery.ScanHandler {
void found(discovery.Service s) {
util.log("MYSCANHANDLER Found ${s.instanceId} ${s.instanceName}");
}
void lost(String instanceId) {
util.log("MYSCANHANDLER Lost ${instanceId}");
}
}