use of org.apache.helix.zookeeper.datamodel.ZNRecord in project ambry by linkedin.
the class HelixAccountServiceTest method testReadBadZNRecordCase3.
/**
* Tests reading {@link ZNRecord} from {@link HelixPropertyStore}, where the {@link ZNRecord} has a map field
* ("key": someValidAccountMap), but ({@link LegacyMetadataStore#ACCOUNT_METADATA_MAP_KEY}: someValidMap)
* is missing. This is a good {@link ZNRecord} format that should NOT fail fetch or update.
* @throws Exception Any unexpected exception.
*/
@Test
public void testReadBadZNRecordCase3() throws Exception {
Map<String, String> mapValue = new HashMap<>();
mapValue.put(String.valueOf(refAccount.getId()), objectMapper.writeValueAsString(new AccountBuilder(refAccount).snapshotVersion(refAccount.getSnapshotVersion() + 1).build()));
ZNRecord zNRecord = makeZNRecordWithMapField(null, "key", mapValue);
updateAndWriteZNRecord(zNRecord, true);
}
use of org.apache.helix.zookeeper.datamodel.ZNRecord in project ambry by linkedin.
the class HelixAccountServiceTest method testReadBadZNRecordCase8.
/**
* Tests reading {@link ZNRecord} from {@link HelixPropertyStore} and ambry, where the ambry has valid accounts
* record but {@link ZNRecord} has an invalid list item and a valid list item. This is a NOT good {@link ZNRecord}
* format and it should fail fetch or update operations, with none of the record should be read.
* @throws Exception Any unexpected exception.
*/
@Test
public void testReadBadZNRecordCase8() throws Exception {
if (!useNewZNodePath) {
return;
}
ZNRecord zNRecord = new ZNRecord(String.valueOf(System.currentTimeMillis()));
Map<String, String> accountMap = new HashMap<>();
accountMap.put(String.valueOf(refAccount.getId()), objectMapper.writeValueAsString(new AccountBuilder(refAccount).snapshotVersion(refAccount.getSnapshotVersion() + 1).build()));
String blobID = RouterStore.writeAccountMapToRouter(accountMap, mockRouter);
List<String> list = new ArrayList<>();
list.add("badliststring");
list.add(new RouterStore.BlobIDAndVersion(blobID, 1).toJson());
zNRecord.setListField(RouterStore.ACCOUNT_METADATA_BLOB_IDS_LIST_KEY, list);
updateAndWriteZNRecord(zNRecord, false);
}
use of org.apache.helix.zookeeper.datamodel.ZNRecord in project ambry by linkedin.
the class AccountMetadataStore method fetchAccountMetadata.
/**
* fetchAccountMetadata would fetch the latest full set of {@link Account} metadata from the store. It returns null
* when there is no {@link Account} created.
* @return A collection of {@link Account} metadata.
*/
Collection<Account> fetchAccountMetadata() {
long startTimeMs = System.currentTimeMillis();
logger.trace("Start reading ZNRecord from path={}", znRecordPath);
Stat stat = new Stat();
ZNRecord znRecord = helixStore.get(znRecordPath, stat, AccessOption.PERSISTENT);
long helixFetchTime = System.currentTimeMillis() - startTimeMs;
accountServiceMetrics.fetchRemoteAccountTimeInMs.update(helixFetchTime);
logger.trace("Fetched ZNRecord from path={}, took time={} ms", znRecordPath, helixFetchTime);
if (znRecord == null) {
logger.info("The ZNRecord to read does not exist on path={}", znRecordPath);
return null;
}
Map<String, String> newAccountMap = fetchAccountMetadataFromZNRecord(znRecord);
Map<Short, Account> idToAccountMap = new HashMap<>();
Map<String, Account> nameToAccountMap = new HashMap<>();
for (Map.Entry<String, String> entry : newAccountMap.entrySet()) {
String idKey = entry.getKey();
if (idKey == null) {
accountServiceMetrics.remoteDataCorruptionErrorCount.inc();
throw new IllegalStateException("Invalid account record when reading accountMap because idKey=null");
}
String valueString = entry.getValue();
Account account;
try {
account = objectMapper.readValue(valueString, Account.class);
} catch (JsonProcessingException e) {
logger.error("Failed to deserialize {} to an Account object", valueString, e);
throw new RuntimeException(e);
}
if (account.getId() != Short.parseShort(idKey)) {
accountServiceMetrics.remoteDataCorruptionErrorCount.inc();
throw new IllegalStateException("Invalid account record when reading accountMap because idKey and accountId do not match. idKey=" + idKey + " accountId=" + account.getId());
}
if (idToAccountMap.containsKey(account.getId()) || nameToAccountMap.containsKey(account.getName())) {
throw new IllegalStateException("Duplicate account id or name exists. id=" + account.getId() + " name=" + account.getName());
}
idToAccountMap.put(account.getId(), account);
nameToAccountMap.put(account.getName(), account);
}
if (newAccountMap != null) {
backupFileManager.persistAccountMap(idToAccountMap.values(), stat.getVersion(), stat.getMtime() / 1000);
}
return idToAccountMap.values();
}
use of org.apache.helix.zookeeper.datamodel.ZNRecord in project ambry by linkedin.
the class HelixAccountServiceFactory method getAccountService.
@Override
public AccountService getAccountService() {
try {
long startTimeMs = System.currentTimeMillis();
logger.info("Starting a HelixAccountService");
HelixPropertyStore<ZNRecord> helixStore = CommonUtils.createHelixPropertyStore(accountServiceConfig.zkClientConnectString, storeConfig, null);
logger.info("HelixPropertyStore started with zkClientConnectString={}, zkClientSessionTimeoutMs={}, " + "zkClientConnectionTimeoutMs={}, rootPath={}", accountServiceConfig.zkClientConnectString, storeConfig.zkClientSessionTimeoutMs, storeConfig.zkClientConnectionTimeoutMs, storeConfig.rootPath);
ScheduledExecutorService scheduler = accountServiceConfig.updaterPollingIntervalMs > 0 ? Utils.newScheduler(1, HELIX_ACCOUNT_UPDATER_PREFIX, false) : null;
HelixAccountService helixAccountService = new HelixAccountService(helixStore, accountServiceMetrics, notifier, scheduler, accountServiceConfig);
long spentTimeMs = System.currentTimeMillis() - startTimeMs;
logger.info("HelixAccountService started, took {} ms", spentTimeMs);
accountServiceMetrics.startupTimeInMs.update(spentTimeMs);
return helixAccountService;
} catch (Exception e) {
throw new IllegalStateException("Could not instantiate HelixAccountService", e);
}
}
use of org.apache.helix.zookeeper.datamodel.ZNRecord in project ambry by linkedin.
the class RouterStore method fetchAllBlobIDAndVersions.
/**
* Get the list of {@link BlobIDAndVersion} from {@link ZNRecord}. This function returns null when there
* is any error.
* @return list of {@link BlobIDAndVersion}.
*/
private List<BlobIDAndVersion> fetchAllBlobIDAndVersions() {
if (router.get() == null) {
logger.error("Router is not yet initialized");
return null;
}
long startTimeMs = System.currentTimeMillis();
logger.trace("Start reading ZNRecord from path={}", znRecordPath);
Stat stat = new Stat();
ZNRecord znRecord = helixStore.get(znRecordPath, stat, AccessOption.PERSISTENT);
logger.trace("Fetched ZNRecord from path={}, took time={} ms", znRecordPath, System.currentTimeMillis() - startTimeMs);
if (znRecord == null) {
logger.info("The ZNRecord to read does not exist on path={}", znRecordPath);
return null;
}
List<String> blobIDAndVersionsJson = znRecord.getListField(ACCOUNT_METADATA_BLOB_IDS_LIST_KEY);
if (blobIDAndVersionsJson == null || blobIDAndVersionsJson.size() == 0) {
logger.info("ZNRecord={} to read on path={} does not have a simple list with key={}", znRecord, ACCOUNT_METADATA_BLOB_IDS_PATH, ACCOUNT_METADATA_BLOB_IDS_LIST_KEY);
return null;
} else {
return blobIDAndVersionsJson.stream().map(BlobIDAndVersion::fromJson).collect(Collectors.toList());
}
}
Aggregations