mirror of
https://github.com/apple/foundationdb.git
synced 2025-05-14 18:02:31 +08:00
add python bindings and revise test code
This commit is contained in:
parent
718119af83
commit
c683795f6b
91
TenantTest.java
Normal file
91
TenantTest.java
Normal file
@ -0,0 +1,91 @@
|
|||||||
|
import java.io.UnsupportedEncodingException;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.concurrent.CompletableFuture;
|
||||||
|
import java.util.concurrent.ThreadLocalRandom;
|
||||||
|
|
||||||
|
import com.apple.foundationdb.Database;
|
||||||
|
import com.apple.foundationdb.FDB;
|
||||||
|
import com.apple.foundationdb.KeyValue;
|
||||||
|
import com.apple.foundationdb.Tenant;
|
||||||
|
import com.apple.foundationdb.Transaction;
|
||||||
|
import com.apple.foundationdb.tuple.Tuple;
|
||||||
|
import com.apple.foundationdb.KeyArrayResult;
|
||||||
|
import com.apple.foundationdb.TenantManagement;
|
||||||
|
import com.apple.foundationdb.async.AsyncUtil;
|
||||||
|
import static com.apple.foundationdb.async.AsyncUtil.collectRemaining;
|
||||||
|
import com.apple.foundationdb.async.CloseableAsyncIterator;
|
||||||
|
|
||||||
|
public class TenantTest {
|
||||||
|
private FDB fdb;
|
||||||
|
private Database db;
|
||||||
|
CloseableAsyncIterator<KeyValue> tenants;
|
||||||
|
|
||||||
|
public TenantTest() {
|
||||||
|
try {
|
||||||
|
fdb = FDB.selectAPIVersion(710);
|
||||||
|
fdb.options().setTraceEnable(null);
|
||||||
|
db = fdb.open();
|
||||||
|
///*
|
||||||
|
Tuple t1 = Tuple.from("tenant");
|
||||||
|
Tuple t2 = Tuple.from("tenant2");
|
||||||
|
Tuple t3 = Tuple.from("tenant3");
|
||||||
|
//*/
|
||||||
|
/*
|
||||||
|
byte[] t1 = Tuple.from("tenant").pack();
|
||||||
|
byte[] t2 = Tuple.from("tenant2").pack();
|
||||||
|
byte[] t3 = Tuple.from("tenant3").pack();
|
||||||
|
*/
|
||||||
|
System.out.println(t1);
|
||||||
|
System.out.println(t2);
|
||||||
|
System.out.println(t3);
|
||||||
|
|
||||||
|
TenantManagement.createTenant(db, t1).join();
|
||||||
|
TenantManagement.createTenant(db, t2).join();
|
||||||
|
TenantManagement.createTenant(db, t3).join();
|
||||||
|
|
||||||
|
tenants = TenantManagement.listTenants(db, Tuple.from("a").pack(), Tuple.from("z").pack(), 100);
|
||||||
|
|
||||||
|
try {
|
||||||
|
/*
|
||||||
|
List<KeyValue> result = AsyncUtil.collectRemaining(tenants).join();
|
||||||
|
System.out.println("Size: " + result.size());
|
||||||
|
for(int i = 0; i < result.size(); i++) {
|
||||||
|
System.out.println(i);
|
||||||
|
KeyValue res = result.get(i);
|
||||||
|
System.out.println(new String(res.getKey()));
|
||||||
|
System.out.println(new String(res.getValue()));
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
// /*
|
||||||
|
while (tenants.hasNext()) {
|
||||||
|
KeyValue res = tenants.next();
|
||||||
|
System.out.println(new String(res.getKey()));
|
||||||
|
System.out.println(new String(res.getValue()));
|
||||||
|
}
|
||||||
|
// */
|
||||||
|
}
|
||||||
|
finally {
|
||||||
|
tenants.close();
|
||||||
|
}
|
||||||
|
TenantManagement.deleteTenant(db, t1).join();
|
||||||
|
TenantManagement.deleteTenant(db, t2).join();
|
||||||
|
TenantManagement.deleteTenant(db, t3).join();
|
||||||
|
}
|
||||||
|
catch(Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void close() {
|
||||||
|
db.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void main(String[] args) {
|
||||||
|
new TenantTest().close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -219,23 +219,35 @@ public class TenantManagement {
|
|||||||
* @param begin The beginning of the range of tenants to list.
|
* @param begin The beginning of the range of tenants to list.
|
||||||
* @param end The end of the range of the tenants to list.
|
* @param end The end of the range of the tenants to list.
|
||||||
* @param limit The maximum number of tenants to return from this request.
|
* @param limit The maximum number of tenants to return from this request.
|
||||||
* @return an iterator where each item is a byte array with the tenant name and value.
|
* @return an iterator where each item is a KeyValue object where the key is the tenant name
|
||||||
|
* and the value is the unprocessed JSON string containing the tenant's metadata
|
||||||
*/
|
*/
|
||||||
public static CloseableAsyncIterator<byte[]> listTenants(Database db, byte[] begin, byte[] end, int limit) {
|
public static CloseableAsyncIterator<KeyValue> listTenants(Database db, byte[] begin, byte[] end, int limit) {
|
||||||
return listTenants_internal(db.createTransaction(), begin, end, limit);
|
return listTenants_internal(db.createTransaction(), begin, end, limit);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static CloseableAsyncIterator<byte[]> listTenants(Database db, Tuple begin, Tuple end, int limit) {
|
/**
|
||||||
|
* Lists all tenants in between the range specified. The number of tenants listed can be restricted.
|
||||||
|
* This is a convenience method that generates the begin and end ranges by packing two {@code Tuple}s.
|
||||||
|
*
|
||||||
|
* @param db The database used to create a transaction for listing the tenants.
|
||||||
|
* @param begin The beginning of the range of tenants to list.
|
||||||
|
* @param end The end of the range of the tenants to list.
|
||||||
|
* @param limit The maximum number of tenants to return from this request.
|
||||||
|
* @return an iterator where each item is a KeyValue object where the key is the tenant name
|
||||||
|
* and the value is the unprocessed JSON string containing the tenant's metadata
|
||||||
|
*/
|
||||||
|
public static CloseableAsyncIterator<KeyValue> listTenants(Database db, Tuple begin, Tuple end, int limit) {
|
||||||
return listTenants_internal(db.createTransaction(), begin.pack(), end.pack(), limit);
|
return listTenants_internal(db.createTransaction(), begin.pack(), end.pack(), limit);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static CloseableAsyncIterator<byte[]> listTenants_internal(Transaction tr, byte[] begin, byte[] end,
|
private static CloseableAsyncIterator<KeyValue> listTenants_internal(Transaction tr, byte[] begin, byte[] end,
|
||||||
int limit) {
|
int limit) {
|
||||||
return new TenantAsyncIterator(tr, begin, end, limit);
|
return new TenantAsyncIterator(tr, begin, end, limit);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Templates taken from BoundaryIterator LocalityUtil.java
|
// Templates taken from BoundaryIterator LocalityUtil.java
|
||||||
static class TenantAsyncIterator implements CloseableAsyncIterator<byte[]> {
|
static class TenantAsyncIterator implements CloseableAsyncIterator<KeyValue> {
|
||||||
Transaction tr;
|
Transaction tr;
|
||||||
final byte[] begin;
|
final byte[] begin;
|
||||||
final byte[] end;
|
final byte[] end;
|
||||||
@ -268,15 +280,12 @@ public class TenantManagement {
|
|||||||
return iter.hasNext();
|
return iter.hasNext();
|
||||||
}
|
}
|
||||||
@Override
|
@Override
|
||||||
public byte[] next() {
|
public KeyValue next() {
|
||||||
KeyValue kv = iter.next();
|
KeyValue kv = iter.next();
|
||||||
byte[] tenant = ByteArrayUtil.replace(kv.getKey(), 0, kv.getKey().length, TENANT_MAP_PREFIX, null);
|
byte[] tenant = ByteArrayUtil.replace(kv.getKey(), 0, kv.getKey().length, TENANT_MAP_PREFIX, null);
|
||||||
byte[] value = kv.getValue();
|
byte[] value = kv.getValue();
|
||||||
|
|
||||||
List<byte[]> parts = Arrays.asList(tenant, value);
|
KeyValue result = new KeyValue(tenant, value);
|
||||||
byte[] separator = ": ".getBytes();
|
|
||||||
|
|
||||||
byte[] result = ByteArrayUtil.join(separator, parts);
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -71,6 +71,11 @@ import types
|
|||||||
import struct
|
import struct
|
||||||
|
|
||||||
|
|
||||||
|
def remove_prefix(text, prefix):
|
||||||
|
if text.startswith(prefix):
|
||||||
|
return text[len(prefix):]
|
||||||
|
return text
|
||||||
|
|
||||||
def option_wrap(code):
|
def option_wrap(code):
|
||||||
def setfunc(self):
|
def setfunc(self):
|
||||||
self._parent._set_option(code, None, 0)
|
self._parent._set_option(code, None, 0)
|
||||||
|
@ -78,6 +78,41 @@ def _delete_tenant_impl(tr, tenant_name, existence_check_marker, force_existence
|
|||||||
|
|
||||||
del tr[key]
|
del tr[key]
|
||||||
|
|
||||||
|
class FDBTenantList(object):
|
||||||
|
"""Iterates over the results of list_tenants query. Returns
|
||||||
|
KeyValue objects.
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(self, rangeresult):
|
||||||
|
self._range = rangeresult
|
||||||
|
self._iter = iter(self._range)
|
||||||
|
|
||||||
|
def to_list(self):
|
||||||
|
return list(self.__iter__())
|
||||||
|
|
||||||
|
def __iter__(self, mode=None):
|
||||||
|
while True:
|
||||||
|
result = self._iter.__next__()
|
||||||
|
|
||||||
|
tenant_name = _impl.remove_prefix(result.key, _tenant_map_prefix)
|
||||||
|
yield _impl.KeyValue(tenant_name, result.value)
|
||||||
|
|
||||||
|
# Lists the tenants created in the cluster, specified by the begin and end range.
|
||||||
|
# Also limited in number of results by the limit parameter.
|
||||||
|
# Returns an iterable object that yields KeyValue objects
|
||||||
|
# where the keys are the tenant names and the values are the unprocessed
|
||||||
|
# JSON strings of the tenant metadata
|
||||||
|
@_impl.transactional
|
||||||
|
def _list_tenants_impl(tr, begin, end, limit):
|
||||||
|
tr.options.set_read_system_keys()
|
||||||
|
begin_key = b'%s%s' % (_tenant_map_prefix, begin)
|
||||||
|
end_key = b'%s%s' % (_tenant_map_prefix, end)
|
||||||
|
|
||||||
|
rangeresult = tr.get_range(begin_key, end_key, limit)
|
||||||
|
|
||||||
|
return FDBTenantList(rangeresult)
|
||||||
|
|
||||||
def create_tenant(db_or_tr, tenant_name):
|
def create_tenant(db_or_tr, tenant_name):
|
||||||
tenant_name = _impl.process_tenant_name(tenant_name)
|
tenant_name = _impl.process_tenant_name(tenant_name)
|
||||||
|
|
||||||
@ -93,3 +128,9 @@ def delete_tenant(db_or_tr, tenant_name):
|
|||||||
# Callers using a transaction are expected to check existence themselves if required
|
# Callers using a transaction are expected to check existence themselves if required
|
||||||
existence_check_marker = [] if not isinstance(db_or_tr, _impl.TransactionRead) else [None]
|
existence_check_marker = [] if not isinstance(db_or_tr, _impl.TransactionRead) else [None]
|
||||||
_delete_tenant_impl(db_or_tr, tenant_name, existence_check_marker)
|
_delete_tenant_impl(db_or_tr, tenant_name, existence_check_marker)
|
||||||
|
|
||||||
|
def list_tenants(db_or_tr, begin, end, limit):
|
||||||
|
begin = _impl.process_tenant_name(begin)
|
||||||
|
end = _impl.process_tenant_name(end)
|
||||||
|
|
||||||
|
return _list_tenants_impl(db_or_tr, begin, end, limit)
|
@ -980,7 +980,7 @@ ThreadFuture<MappedRangeResult> MultiVersionTransaction::getMappedRange(const Ke
|
|||||||
auto tr = getTransaction();
|
auto tr = getTransaction();
|
||||||
auto f = tr.transaction ? tr.transaction->getMappedRange(begin, end, mapper, limits, snapshot, reverse)
|
auto f = tr.transaction ? tr.transaction->getMappedRange(begin, end, mapper, limits, snapshot, reverse)
|
||||||
: makeTimeout<MappedRangeResult>();
|
: makeTimeout<MappedRangeResult>();
|
||||||
return abortableFuture(f, tr.onChange, cluster_version_changed());
|
return abortableFuture(f, tr.onChange);
|
||||||
}
|
}
|
||||||
|
|
||||||
ThreadFuture<Standalone<StringRef>> MultiVersionTransaction::getVersionstamp() {
|
ThreadFuture<Standalone<StringRef>> MultiVersionTransaction::getVersionstamp() {
|
||||||
|
33
test_tenant.py
Executable file
33
test_tenant.py
Executable file
@ -0,0 +1,33 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
|
import fdb
|
||||||
|
import sys
|
||||||
|
|
||||||
|
fdb.api_version(710)
|
||||||
|
db=fdb.open()
|
||||||
|
|
||||||
|
db.options.set_transaction_timeout(2000)
|
||||||
|
|
||||||
|
#tenant = b'tenant'
|
||||||
|
#tenant2 = b'tenant2'
|
||||||
|
#tenant3 = b'tenant3'
|
||||||
|
|
||||||
|
tenant = (u"tenant",)
|
||||||
|
tenant2 = (u"tenant2",)
|
||||||
|
tenant3 = (u"tenant3",)
|
||||||
|
|
||||||
|
fdb.tenant_management.create_tenant(db, tenant)
|
||||||
|
fdb.tenant_management.create_tenant(db, tenant2)
|
||||||
|
fdb.tenant_management.create_tenant(db, tenant3)
|
||||||
|
|
||||||
|
res = fdb.tenant_management.list_tenants(db, (u"a",), (u"z",), 10)
|
||||||
|
#res = fdb.tenant_management.list_tenants(db, b'a', b'z', 10)
|
||||||
|
for t in res:
|
||||||
|
print(t.key.decode())
|
||||||
|
print(t.value.decode())
|
||||||
|
|
||||||
|
fdb.tenant_management.delete_tenant(db, tenant)
|
||||||
|
fdb.tenant_management.delete_tenant(db, tenant2)
|
||||||
|
fdb.tenant_management.delete_tenant(db, tenant3)
|
||||||
|
|
||||||
|
sys.exit(0)
|
Loading…
x
Reference in New Issue
Block a user