use of com.orientechnologies.orient.server.distributed.impl.ODistributedDatabaseChunk in project orientdb by orientechnologies.
the class OCommandExecutorSQLHASyncCluster method replaceCluster.
public static Object replaceCluster(final ODistributedAbstractPlugin dManager, final OServer serverInstance, final String databaseName, final String clusterName) {
final ODistributedConfiguration cfg = dManager.getDatabaseConfiguration(databaseName);
final String dbPath = serverInstance.getDatabaseDirectory() + databaseName;
final String nodeName = dManager.getLocalNodeName();
final List<String> nodesWhereClusterIsCfg = cfg.getServers(clusterName, null);
nodesWhereClusterIsCfg.remove(nodeName);
if (nodesWhereClusterIsCfg.isEmpty())
throw new OCommandExecutionException("Cannot synchronize cluster '" + clusterName + "' because is not configured on any running nodes");
final OSyncClusterTask task = new OSyncClusterTask(clusterName);
final ODistributedResponse response = dManager.sendRequest(databaseName, null, nodesWhereClusterIsCfg, task, dManager.getNextMessageIdCounter(), ODistributedRequest.EXECUTION_MODE.RESPONSE, null, null, null);
final Map<String, Object> results = (Map<String, Object>) response.getPayload();
File tempFile = null;
FileOutputStream out = null;
try {
tempFile = new File(Orient.getTempPath() + "/backup_" + databaseName + "_" + clusterName + "_server" + dManager.getLocalNodeId() + "_toInstall.zip");
if (tempFile.exists())
tempFile.delete();
else
tempFile.getParentFile().mkdirs();
tempFile.createNewFile();
long fileSize = 0;
out = new FileOutputStream(tempFile, false);
for (Map.Entry<String, Object> r : results.entrySet()) {
final Object value = r.getValue();
if (value instanceof Boolean) {
continue;
} else if (value instanceof Throwable) {
ODistributedServerLog.error(null, nodeName, r.getKey(), ODistributedServerLog.DIRECTION.IN, "error on installing cluster %s in %s", (Exception) value, databaseName, dbPath);
} else if (value instanceof ODistributedDatabaseChunk) {
ODistributedDatabaseChunk chunk = (ODistributedDatabaseChunk) value;
// DELETE ANY PREVIOUS .COMPLETED FILE
final File completedFile = new File(tempFile.getAbsolutePath() + ".completed");
if (completedFile.exists())
completedFile.delete();
fileSize = writeDatabaseChunk(nodeName, 1, chunk, out);
for (int chunkNum = 2; !chunk.last; chunkNum++) {
final Object result = dManager.sendRequest(databaseName, null, OMultiValue.getSingletonList(r.getKey()), new OCopyDatabaseChunkTask(chunk.filePath, chunkNum, chunk.offset + chunk.buffer.length, false), dManager.getNextMessageIdCounter(), ODistributedRequest.EXECUTION_MODE.RESPONSE, null, null, null);
if (result instanceof Boolean)
continue;
else if (result instanceof Exception) {
ODistributedServerLog.error(null, nodeName, r.getKey(), ODistributedServerLog.DIRECTION.IN, "error on installing database %s in %s (chunk #%d)", (Exception) result, databaseName, dbPath, chunkNum);
} else if (result instanceof ODistributedDatabaseChunk) {
chunk = (ODistributedDatabaseChunk) result;
fileSize += writeDatabaseChunk(nodeName, chunkNum, chunk, out);
}
}
out.flush();
// CREATE THE .COMPLETED FILE TO SIGNAL EOF
new File(tempFile.getAbsolutePath() + ".completed").createNewFile();
}
}
final String tempDirectoryPath = Orient.getTempPath() + "/backup_" + databaseName + "_" + clusterName + "_toInstall";
final File tempDirectory = new File(tempDirectoryPath);
tempDirectory.mkdirs();
OZIPCompressionUtil.uncompressDirectory(new FileInputStream(tempFile), tempDirectory.getAbsolutePath(), null);
ODatabaseDocumentInternal db = ODatabaseRecordThreadLocal.INSTANCE.getIfDefined();
final boolean openDatabaseHere = db == null;
if (db == null)
db = serverInstance.openDatabase("plocal:" + dbPath, "", "", null, true);
try {
final OAbstractPaginatedStorage stg = (OAbstractPaginatedStorage) db.getStorage().getUnderlying();
// TODO: FREEZE COULD IT NOT NEEDED
stg.freeze(false);
try {
final OPaginatedCluster cluster = (OPaginatedCluster) stg.getClusterByName(clusterName);
final File tempClusterFile = new File(tempDirectoryPath + "/" + clusterName + OPaginatedCluster.DEF_EXTENSION);
cluster.replaceFile(tempClusterFile);
} finally {
stg.release();
}
db.getLocalCache().invalidate();
} finally {
if (openDatabaseHere)
db.close();
}
return String.format("Cluster correctly replaced, transferred %d bytes", fileSize);
} catch (Exception e) {
ODistributedServerLog.error(null, nodeName, null, ODistributedServerLog.DIRECTION.NONE, "error on transferring database '%s' to '%s'", e, databaseName, tempFile);
throw OException.wrapException(new ODistributedException("Error on transferring database"), e);
} finally {
try {
if (out != null) {
out.flush();
out.close();
}
} catch (IOException e) {
}
}
}
use of com.orientechnologies.orient.server.distributed.impl.ODistributedDatabaseChunk in project orientdb by orientechnologies.
the class OCopyDatabaseChunkTask method execute.
@Override
public Object execute(ODistributedRequestId requestId, final OServer iServer, ODistributedServerManager iManager, final ODatabaseDocumentInternal database) throws Exception {
final File f = new File(fileName);
if (!f.exists())
throw new IllegalArgumentException("File name '" + fileName + "' not found");
final ODistributedDatabaseChunk result = new ODistributedDatabaseChunk(f, offset, OSyncDatabaseTask.CHUNK_MAX_SIZE, null, false);
ODistributedServerLog.info(this, iManager.getLocalNodeName(), getNodeSource(), ODistributedServerLog.DIRECTION.OUT, "- transferring chunk #%d offset=%d size=%s...", chunkNum, result.offset, OFileUtils.getSizeAsNumber(result.buffer.length));
if (result.last)
// NO MORE CHUNKS: SET THE NODE ONLINE (SYNCHRONIZING ENDED)
iManager.setDatabaseStatus(iManager.getLocalNodeName(), database.getName(), ODistributedServerManager.DB_STATUS.ONLINE);
return result;
}
use of com.orientechnologies.orient.server.distributed.impl.ODistributedDatabaseChunk in project orientdb by orientechnologies.
the class OSyncDatabaseDeltaTask method deltaBackup.
protected Object deltaBackup(final ODistributedRequestId requestId, final ODistributedServerManager iManager, final ODatabaseDocumentInternal database, final String databaseName) throws IOException, InterruptedException {
final Long lastDeployment = (Long) iManager.getConfigurationMap().get(DEPLOYDB + databaseName);
if (lastDeployment != null && lastDeployment.longValue() == random) {
// SKIP IT
ODistributedServerLog.debug(this, iManager.getLocalNodeName(), getNodeSource(), DIRECTION.NONE, "Skip deploying delta database '%s' because already executed", databaseName);
return Boolean.FALSE;
}
iManager.getConfigurationMap().put(DEPLOYDB + databaseName, random);
final ODistributedDatabase dDatabase = checkIfCurrentDatabaseIsNotOlder(iManager, databaseName, startLSN);
iManager.setDatabaseStatus(getNodeSource(), databaseName, ODistributedServerManager.DB_STATUS.SYNCHRONIZING);
ODistributedServerLog.info(this, iManager.getLocalNodeName(), getNodeSource(), DIRECTION.OUT, "Deploying database '%s' with delta of changes...", databaseName);
// CREATE A BACKUP OF DATABASE
final File backupFile = new File(Orient.getTempPath() + "/backup_" + getNodeSource() + "_" + database.getName() + "_server" + iManager.getLocalNodeId() + ".zip");
ODistributedServerLog.info(this, iManager.getLocalNodeName(), getNodeSource(), DIRECTION.OUT, "Creating delta backup of database '%s' (startLSN=%s) in directory: %s...", databaseName, startLSN, backupFile.getAbsolutePath());
if (backupFile.exists())
backupFile.delete();
else
backupFile.getParentFile().mkdirs();
backupFile.createNewFile();
final FileOutputStream fileOutputStream = new FileOutputStream(backupFile);
// final GZIPOutputStream gzipOutputStream = new GZIPOutputStream(fileOutputStream);
final File completedFile = new File(backupFile.getAbsolutePath() + ".completed");
if (completedFile.exists())
completedFile.delete();
final OStorage storage = database.getStorage().getUnderlying();
if (!(storage instanceof OAbstractPaginatedStorage))
throw new UnsupportedOperationException("Storage '" + storage.getName() + "' does not support distributed delta backup");
final AtomicReference<OLogSequenceNumber> endLSN = new AtomicReference<OLogSequenceNumber>();
final AtomicReference<ODistributedDatabaseDeltaSyncException> exception = new AtomicReference<ODistributedDatabaseDeltaSyncException>();
try {
final AtomicLong counter = new AtomicLong(0);
endLSN.set(((OAbstractPaginatedStorage) storage).recordsChangedAfterLSN(startLSN, fileOutputStream, excludedClusterNames, new OCommandOutputListener() {
@Override
public void onMessage(final String iText) {
if (iText.startsWith("read")) {
if (counter.incrementAndGet() % 100000 == 0) {
ODistributedServerLog.info(this, iManager.getLocalNodeName(), getNodeSource(), DIRECTION.OUT, "- %s", iText);
}
} else if (counter.incrementAndGet() % 10000 == 0) {
ODistributedServerLog.info(this, iManager.getLocalNodeName(), getNodeSource(), DIRECTION.OUT, "- %s", iText);
}
}
}));
if (endLSN.get() == null) {
// DELTA NOT AVAILABLE, TRY WITH FULL BACKUP
exception.set(new ODistributedDatabaseDeltaSyncException(startLSN));
} else
ODistributedServerLog.info(this, iManager.getLocalNodeName(), getNodeSource(), DIRECTION.OUT, "Delta backup of database '%s' completed. range=%s-%s", databaseName, startLSN, endLSN.get());
} catch (Exception e) {
// UNKNOWN ERROR, DELTA NOT AVAILABLE, TRY WITH FULL BACKUP
exception.set(new ODistributedDatabaseDeltaSyncException(startLSN, e.getMessage()));
} finally {
try {
fileOutputStream.close();
} catch (IOException e) {
}
try {
completedFile.createNewFile();
} catch (IOException e) {
OLogManager.instance().error(this, "Cannot create file of delta backup completed: %s", e, completedFile);
}
}
if (exception.get() instanceof ODistributedDatabaseDeltaSyncException) {
throw exception.get();
}
ODistributedServerLog.info(this, iManager.getLocalNodeName(), getNodeSource(), DIRECTION.OUT, "Deploy delta database task completed");
// GET THE MOMENTUM, BUT OVERWRITE THE LAST LSN RECEIVED FROM THE DELTA
final ODistributedMomentum momentum = dDatabase.getSyncConfiguration().getMomentum().copy();
momentum.setLSN(iManager.getLocalNodeName(), endLSN.get());
final ODistributedDatabaseChunk chunk = new ODistributedDatabaseChunk(backupFile, 0, CHUNK_MAX_SIZE, momentum, false);
ODistributedServerLog.info(this, iManager.getLocalNodeName(), getNodeSource(), DIRECTION.OUT, "- transferring chunk #%d offset=%d size=%s...", 1, 0, OFileUtils.getSizeAsNumber(chunk.buffer.length));
if (chunk.last)
// NO MORE CHUNKS: SET THE NODE ONLINE (SYNCHRONIZING ENDED)
iManager.setDatabaseStatus(iManager.getLocalNodeName(), databaseName, ODistributedServerManager.DB_STATUS.ONLINE);
return chunk;
}
use of com.orientechnologies.orient.server.distributed.impl.ODistributedDatabaseChunk in project orientdb by orientechnologies.
the class OSyncDatabaseTask method execute.
@Override
public Object execute(final ODistributedRequestId requestId, final OServer iServer, final ODistributedServerManager iManager, final ODatabaseDocumentInternal database) throws Exception {
if (!iManager.getLocalNodeName().equals(getNodeSource())) {
if (database == null)
throw new ODistributedException("Database instance is null");
final String databaseName = database.getName();
final ODistributedDatabase dDatabase = checkIfCurrentDatabaseIsNotOlder(iManager, databaseName, null);
try {
final Long lastDeployment = (Long) iManager.getConfigurationMap().get(DEPLOYDB + databaseName);
if (lastDeployment != null && lastDeployment.longValue() == random) {
// SKIP IT
ODistributedServerLog.debug(this, iManager.getLocalNodeName(), getNodeSource(), DIRECTION.NONE, "Skip deploying database '%s' because already executed", databaseName);
return Boolean.FALSE;
}
iManager.getConfigurationMap().put(DEPLOYDB + databaseName, random);
iManager.setDatabaseStatus(getNodeSource(), databaseName, ODistributedServerManager.DB_STATUS.SYNCHRONIZING);
// PROPAGATE THE UPDATE TO ALL THE NODES
// iManager.sendRequest(databaseName, null, iManager.getActiveServers(),
// new OUpdateDatabaseStatusTask(databaseName, ODistributedServerManager.DB_STATUS.SYNCHRONIZING.name()),
// iManager.getNextMessageIdCounter(), ODistributedRequest.EXECUTION_MODE.RESPONSE, null, null);
ODistributedServerLog.info(this, iManager.getLocalNodeName(), getNodeSource(), DIRECTION.OUT, "Deploying database %s...", databaseName);
final AtomicReference<ODistributedMomentum> momentum = new AtomicReference<ODistributedMomentum>();
File backupFile = ((ODistributedStorage) database.getStorage()).getLastValidBackup();
if (backupFile == null || !backupFile.exists()) {
// CREATE A BACKUP OF DATABASE FROM SCRATCH
backupFile = new File(Orient.getTempPath() + "/backup_" + database.getName() + ".zip");
final int compressionRate = OGlobalConfiguration.DISTRIBUTED_DEPLOYDB_TASK_COMPRESSION.getValueAsInteger();
if (backupFile.exists())
backupFile.delete();
else
backupFile.getParentFile().mkdirs();
backupFile.createNewFile();
final FileOutputStream fileOutputStream = new FileOutputStream(backupFile);
final File completedFile = new File(backupFile.getAbsolutePath() + ".completed");
if (completedFile.exists())
completedFile.delete();
ODistributedServerLog.info(this, iManager.getLocalNodeName(), getNodeSource(), DIRECTION.OUT, "Creating backup of database '%s' (compressionRate=%d) in directory: %s...", databaseName, compressionRate, backupFile.getAbsolutePath());
new Thread(new Runnable() {
@Override
public void run() {
Thread.currentThread().setName("OrientDB SyncDatabase node=" + iManager.getLocalNodeName() + " db=" + databaseName);
try {
database.activateOnCurrentThread();
ODistributedServerLog.info(this, iManager.getLocalNodeName(), getNodeSource(), DIRECTION.OUT, "Compressing database '%s' %d clusters %s...", databaseName, database.getClusterNames().size(), database.getClusterNames());
database.backup(fileOutputStream, null, new Callable<Object>() {
@Override
public Object call() throws Exception {
momentum.set(dDatabase.getSyncConfiguration().getMomentum().copy());
return null;
}
}, ODistributedServerLog.isDebugEnabled() ? new OCommandOutputListener() {
@Override
public void onMessage(String iText) {
if (iText.startsWith("\n"))
iText = iText.substring(1);
OLogManager.instance().debug(this, iText);
}
} : null, OGlobalConfiguration.DISTRIBUTED_DEPLOYDB_TASK_COMPRESSION.getValueAsInteger(), CHUNK_MAX_SIZE);
ODistributedServerLog.info(this, iManager.getLocalNodeName(), getNodeSource(), DIRECTION.OUT, "Backup of database '%s' completed. lastOperationId=%s...", databaseName, requestId);
} catch (Throwable e) {
OLogManager.instance().error(this, "Cannot execute backup of database '%s' for deploy database", e, databaseName);
} finally {
try {
fileOutputStream.close();
} catch (IOException e) {
}
try {
completedFile.createNewFile();
} catch (IOException e) {
OLogManager.instance().error(this, "Cannot create file of backup completed: %s", e, completedFile);
}
}
}
}).start();
// RECORD LAST BACKUP TO BE REUSED IN CASE ANOTHER NODE ASK FOR THE SAME IN SHORT TIME WHILE THE DB IS NOT UPDATED
((ODistributedStorage) database.getStorage()).setLastValidBackup(backupFile);
} else {
momentum.set(dDatabase.getSyncConfiguration().getMomentum().copy());
ODistributedServerLog.info(this, iManager.getLocalNodeName(), getNodeSource(), DIRECTION.OUT, "Reusing last backup of database '%s' in directory: %s...", databaseName, backupFile.getAbsolutePath());
}
for (int retry = 0; momentum.get() == null && retry < 10; ++retry) Thread.sleep(300);
final ODistributedDatabaseChunk chunk = new ODistributedDatabaseChunk(backupFile, 0, CHUNK_MAX_SIZE, momentum.get(), false);
ODistributedServerLog.info(this, iManager.getLocalNodeName(), getNodeSource(), ODistributedServerLog.DIRECTION.OUT, "- transferring chunk #%d offset=%d size=%s lsn=%s...", 1, 0, OFileUtils.getSizeAsNumber(chunk.buffer.length), momentum.get());
if (chunk.last)
// NO MORE CHUNKS: SET THE NODE ONLINE (SYNCHRONIZING ENDED)
iManager.setDatabaseStatus(iManager.getLocalNodeName(), databaseName, ODistributedServerManager.DB_STATUS.ONLINE);
return chunk;
} catch (OLockException e) {
ODistributedServerLog.debug(this, iManager.getLocalNodeName(), getNodeSource(), DIRECTION.NONE, "Skip deploying database %s because another node is doing it", databaseName);
} finally {
ODistributedServerLog.info(this, iManager.getLocalNodeName(), getNodeSource(), ODistributedServerLog.DIRECTION.OUT, "Deploy database task completed");
}
} else
ODistributedServerLog.debug(this, iManager.getLocalNodeName(), getNodeSource(), DIRECTION.NONE, "Skip deploying database from the same node");
return Boolean.FALSE;
}
use of com.orientechnologies.orient.server.distributed.impl.ODistributedDatabaseChunk in project orientdb by orientechnologies.
the class OSyncClusterTask method execute.
@Override
public Object execute(ODistributedRequestId requestId, final OServer iServer, final ODistributedServerManager iManager, final ODatabaseDocumentInternal database) throws Exception {
if (getNodeSource() == null || !getNodeSource().equals(iManager.getLocalNodeName())) {
if (database == null)
throw new ODistributedException("Database instance is null");
final String databaseName = database.getName();
try {
final Long lastDeployment = (Long) iManager.getConfigurationMap().get(DEPLOYCLUSTER + databaseName + "." + clusterName);
if (lastDeployment != null && lastDeployment.longValue() == random) {
// SKIP IT
ODistributedServerLog.debug(this, iManager.getLocalNodeName(), getNodeSource(), DIRECTION.NONE, "Skip deploying cluster '%s' because already executed", clusterName);
return Boolean.FALSE;
}
iManager.getConfigurationMap().put(DEPLOYCLUSTER + databaseName + "." + clusterName, random);
ODistributedServerLog.info(this, iManager.getLocalNodeName(), getNodeSource(), DIRECTION.OUT, "deploying cluster %s...", databaseName);
final File backupFile = new File(Orient.getTempPath() + "/backup_" + databaseName + "_" + clusterName + "_server" + iManager.getLocalNodeId() + ".zip");
if (backupFile.exists())
backupFile.delete();
else
backupFile.getParentFile().mkdirs();
backupFile.createNewFile();
ODistributedServerLog.info(this, iManager.getLocalNodeName(), getNodeSource(), DIRECTION.OUT, "Creating backup of cluster '%s' in directory: %s...", databaseName, backupFile.getAbsolutePath());
final OPaginatedCluster cluster = (OPaginatedCluster) database.getStorage().getClusterByName(clusterName);
switch(mode) {
case MERGE:
throw new IllegalArgumentException("Merge mode not supported");
case FULL_REPLACE:
final FileOutputStream fileOutputStream = new FileOutputStream(backupFile);
final File completedFile = new File(backupFile.getAbsolutePath() + ".completed");
if (completedFile.exists())
completedFile.delete();
new Thread(new Runnable() {
@Override
public void run() {
Thread.currentThread().setName("OrientDB SyncCluster node=" + iManager.getLocalNodeName() + " db=" + databaseName + " cluster=" + clusterName);
try {
database.activateOnCurrentThread();
database.freeze();
try {
final String fileName = cluster.getFileName();
final String dbPath = iServer.getDatabaseDirectory() + databaseName;
final ArrayList<String> fileNames = new ArrayList<String>();
// COPY PCL AND CPM FILE
fileNames.add(fileName);
fileNames.add(fileName.substring(0, fileName.length() - 4) + OClusterPositionMap.DEF_EXTENSION);
final OClass clazz = database.getMetadata().getSchema().getClassByClusterId(cluster.getId());
if (clazz != null) {
// CHECK FOR AUTO-SHARDED INDEXES
final OIndex<?> asIndex = clazz.getAutoShardingIndex();
if (asIndex != null) {
final int partition = OCollections.indexOf(clazz.getClusterIds(), cluster.getId());
final String indexName = asIndex.getName();
fileNames.add(indexName + "_" + partition + OAutoShardingIndexEngine.SUBINDEX_METADATA_FILE_EXTENSION);
fileNames.add(indexName + "_" + partition + OAutoShardingIndexEngine.SUBINDEX_TREE_FILE_EXTENSION);
fileNames.add(indexName + "_" + partition + OAutoShardingIndexEngine.SUBINDEX_BUCKET_FILE_EXTENSION);
fileNames.add(indexName + "_" + partition + OAutoShardingIndexEngine.SUBINDEX_NULL_BUCKET_FILE_EXTENSION);
}
}
OZIPCompressionUtil.compressFiles(dbPath, fileNames.toArray(new String[fileNames.size()]), fileOutputStream, null, OGlobalConfiguration.DISTRIBUTED_DEPLOYDB_TASK_COMPRESSION.getValueAsInteger());
} catch (IOException e) {
OLogManager.instance().error(this, "Cannot execute backup of cluster '%s.%s' for deploy cluster", e, databaseName, clusterName);
} finally {
database.release();
}
} finally {
try {
fileOutputStream.close();
} catch (IOException e) {
}
try {
completedFile.createNewFile();
} catch (IOException e) {
OLogManager.instance().error(this, "Cannot create file of backup completed: %s", e, completedFile);
}
}
}
}).start();
// TODO: SUPPORT BACKUP ON CLUSTER
final long fileSize = backupFile.length();
ODistributedServerLog.info(this, iManager.getLocalNodeName(), getNodeSource(), DIRECTION.OUT, "Sending the compressed cluster '%s.%s' over the NETWORK to node '%s', size=%s...", databaseName, clusterName, getNodeSource(), OFileUtils.getSizeAsString(fileSize));
final ODistributedDatabaseChunk chunk = new ODistributedDatabaseChunk(backupFile, 0, CHUNK_MAX_SIZE, null, false);
ODistributedServerLog.info(this, iManager.getLocalNodeName(), getNodeSource(), DIRECTION.OUT, "- transferring chunk #%d offset=%d size=%s...", 1, 0, OFileUtils.getSizeAsNumber(chunk.buffer.length));
return chunk;
}
} catch (OLockException e) {
ODistributedServerLog.debug(this, iManager.getLocalNodeName(), getNodeSource(), DIRECTION.NONE, "Skip deploying cluster %s.%s because another node is doing it", databaseName, clusterName);
} finally {
ODistributedServerLog.info(this, iManager.getLocalNodeName(), getNodeSource(), ODistributedServerLog.DIRECTION.OUT, "Deploy cluster %s task completed", clusterName);
}
} else
ODistributedServerLog.debug(this, iManager.getLocalNodeName(), getNodeSource(), DIRECTION.NONE, "Skip deploying cluster %s.%s from the same node");
return Boolean.FALSE;
}
Aggregations