use of org.eclipse.hono.service.base.jdbc.store.Statement in project hono by eclipse.
the class TableManagementStore method getDeviceCount.
/**
* Gets the number of devices that are registered for a tenant.
*
* @param tenantId The tenant to count devices for.
* @param spanContext The span to contribute to.
* @return A future tracking the outcome of the operation.
* @throws NullPointerException if tenant is {@code null}.
*/
public Future<Integer> getDeviceCount(final String tenantId, final SpanContext spanContext) {
Objects.requireNonNull(tenantId);
final Span span = TracingHelper.buildChildSpan(this.tracer, spanContext, "get device count", getClass().getSimpleName()).withTag(TracingHelper.TAG_TENANT_ID, tenantId).start();
final var expanded = this.countDevicesOfTenantStatement.expand(params -> {
params.put("tenant_id", tenantId);
});
log.debug("count - statement: {}", expanded);
return expanded.trace(this.tracer, span.context()).query(this.client).map(r -> {
final var entries = r.getRows(true);
switch(entries.size()) {
case 1:
final Integer count = entries.get(0).getInteger("DEVICECOUNT");
log.debug("found {} devices registered for tenant [tenant-id: {}]", count, tenantId);
return count;
default:
throw new IllegalStateException("Could not count devices of tenant");
}
}).onComplete(x -> span.finish());
}
use of org.eclipse.hono.service.base.jdbc.store.Statement in project hono by eclipse.
the class TableManagementStore method createDevice.
/**
* Creates a new device.
* <p>
* This method executes the {@code create} statement, providing the named parameters
* {@code tenant_id}, {@code device_id}, {@code version}, and {@code data}.
* <p>
* It returns the plain update result. In case a device with the same ID already
* exists, the underlying database must throw an {@link java.sql.SQLException}, indicating
* a duplicate entity or constraint violation. This will be translated into a
* failed future with an {@link org.eclipse.hono.service.base.jdbc.store.DuplicateKeyException}.
*
* @param key The key of the device to create.
* @param device The device data.
* @param tenant The configuration of the tenant that the device belongs to.
* @param globalDevicesPerTenantLimit The globally defined maximum number of devices per tenant. A value
* <= 0 will be interpreted as no limit being defined.
* @param spanContext The span to contribute to.
* @return A future, tracking the outcome of the operation.
*/
public Future<Versioned<Void>> createDevice(final DeviceKey key, final Device device, final Tenant tenant, final int globalDevicesPerTenantLimit, final SpanContext spanContext) {
final Span span = TracingHelper.buildChildSpan(this.tracer, spanContext, "create device", getClass().getSimpleName()).withTag(TracingHelper.TAG_TENANT_ID, key.getTenantId()).withTag(TracingHelper.TAG_DEVICE_ID, key.getDeviceId()).start();
final JdbcBasedDeviceDto deviceDto = JdbcBasedDeviceDto.forCreation(key, device, DeviceRegistryUtils.getUniqueIdentifier());
return SQL.runTransactionally(this.client, this.tracer, span.context(), (connection, context) -> {
final var expanded = this.createStatement.expand(params -> {
params.put("tenant_id", deviceDto.getTenantId());
params.put("device_id", deviceDto.getDeviceId());
params.put("version", deviceDto.getVersion());
params.put("data", deviceDto.getDeviceJson());
params.put("created", Timestamp.from(deviceDto.getCreationTime()));
params.put("auto_provisioned", deviceDto.isAutoProvisioned());
});
log.debug("createDevice - statement: {}", expanded);
return getDeviceCount(key.getTenantId(), span.context()).compose(currentDeviceCount -> tenant.checkDeviceLimitReached(key.getTenantId(), currentDeviceCount, globalDevicesPerTenantLimit)).compose(ok -> expanded.trace(this.tracer, context).update(this.client).recover(SQL::translateException)).compose(x -> createGroups(connection, key, new HashSet<>(device.getMemberOf()), context));
}).map(new Versioned<Void>(deviceDto.getVersion(), null)).onComplete(x -> span.finish());
}
use of org.eclipse.hono.service.base.jdbc.store.Statement in project hono by eclipse.
the class TableAdapterStore method resolveGroupMembers.
/**
* Resolve a list of group members.
*
* @param tenantId The tenant the device belongs to.
* @param viaGroups The viaGroups list of a device. This list contains the ids of groups.
* @param spanContext The span to contribute to.
*
* @return A future tracking the outcome of the operation.
*
* @see org.eclipse.hono.deviceregistry.service.device.AbstractRegistrationService#resolveGroupMembers(String, JsonArray, Span)
*/
public Future<Set<String>> resolveGroupMembers(final String tenantId, final Set<String> viaGroups, final SpanContext spanContext) {
final Span span = TracingHelper.buildChildSpan(this.tracer, spanContext, "resolve group members", getClass().getSimpleName()).withTag(TracingHelper.TAG_TENANT_ID, tenantId).withTag("via_groups", String.join(", ", viaGroups)).start();
final var expanded = this.resolveGroupsStatement.expand(params -> {
params.put("tenant_id", tenantId);
params.put("group_ids", convertToArrayValue(viaGroups));
});
log.debug("resolveGroupMembers - statement: {}", expanded);
return expanded.trace(this.tracer, span.context()).query(this.client).flatMap(r -> {
final var entries = r.getRows(true);
span.log(Map.of("event", "read result", "rows", entries.size()));
return Future.succeededFuture(entries.stream().map(o -> o.getString("device_id")).filter(Objects::nonNull).collect(Collectors.toSet()));
}).onComplete(x -> span.finish());
}
use of org.eclipse.hono.service.base.jdbc.store.Statement in project hono by eclipse.
the class TableAdapterStore method findCredentials.
/**
* Find credentials for a device.
*
* @param key The credentials key to look for.
* @param spanContext The span context.
*
* @return A future tracking the outcome of the operation.
*/
public Future<Optional<CredentialsReadResult>> findCredentials(final CredentialKey key, final SpanContext spanContext) {
final Span span = TracingHelper.buildChildSpan(this.tracer, spanContext, "find credentials", getClass().getSimpleName()).withTag(TracingHelper.TAG_AUTH_ID, key.getAuthId()).withTag(TracingHelper.TAG_CREDENTIALS_TYPE, key.getType()).withTag(TracingHelper.TAG_TENANT_ID, key.getTenantId()).start();
final var expanded = this.findCredentialsStatement.expand(params -> {
params.put("tenant_id", key.getTenantId());
params.put("type", key.getType());
params.put("auth_id", key.getAuthId());
});
log.debug("findCredentials - statement: {}", expanded);
return expanded.trace(this.tracer, span.context()).query(this.client).<Optional<CredentialsReadResult>>flatMap(r -> {
final var entries = r.getRows(true);
span.log(Map.of("event", "read result", "rows", entries.size()));
final Set<String> deviceIds = entries.stream().map(o -> o.getString("device_id")).filter(Objects::nonNull).collect(Collectors.toSet());
final int num = deviceIds.size();
if (num <= 0) {
return Future.succeededFuture(Optional.empty());
} else if (num > 1) {
TracingHelper.logError(span, "Found multiple entries for a single device");
return Future.failedFuture(new IllegalStateException("Found multiple entries for a single device"));
}
// we know now that we have exactly one entry
final String deviceId = deviceIds.iterator().next();
final List<CommonCredential> credentials = entries.stream().map(o -> o.getString("data")).map(s -> Json.decodeValue(s, CommonCredential.class)).collect(Collectors.toList());
return Future.succeededFuture(Optional.of(new CredentialsReadResult(deviceId, credentials, Optional.empty())));
}).onComplete(x -> span.finish());
}
use of org.eclipse.hono.service.base.jdbc.store.Statement in project hono by eclipse.
the class AbstractTenantStore method readTenantBy.
/**
* Read a tenant, using the provided statement.
*
* @param operations The operations to use.
* @param expanded The statement to use.
* @param spanContext The span to contribute to.
* @return A future, tracking the outcome of the operation.
*/
protected Future<Optional<TenantReadResult>> readTenantBy(final SQLOperations operations, final ExpandedStatement expanded, final SpanContext spanContext) {
final Span span = TracingHelper.buildChildSpan(this.tracer, spanContext, "read tenant by", getClass().getSimpleName()).start();
return expanded.trace(this.tracer, span.context()).query(operations).<Optional<TenantReadResult>>flatMap(r -> {
final var entries = r.getRows(true);
span.log(Map.of("event", "read result", "rows", entries.size()));
switch(entries.size()) {
case 0:
return Future.succeededFuture(Optional.empty());
case 1:
return Future.succeededFuture(entries.get(0)).map(entry -> {
final var id = entry.getString("tenant_id");
final var tenant = Json.decodeValue(entry.getString("data"), Tenant.class);
final var version = Optional.ofNullable(entry.getString("version"));
return Optional.of(new TenantReadResult(id, tenant, version));
});
default:
return Future.failedFuture(new IllegalStateException("Found multiple entries for a single tenant"));
}
}).flatMap(result -> {
if (result.isPresent()) {
return fillTrustAnchors(operations, result.get(), span.context()).map(Optional::ofNullable);
} else {
return Future.succeededFuture(result);
}
}).onComplete(x -> span.finish());
}
Aggregations