/** * personium.io * Copyright 2014 FUJITSU LIMITED * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.fujitsu.dc.core.model.impl.es.accessor; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.fujitsu.dc.common.ads.AdsWriteFailureLogInfo; import com.fujitsu.dc.common.es.EsIndex; import com.fujitsu.dc.common.es.response.DcActionResponse; import com.fujitsu.dc.common.es.response.DcDeleteResponse; import com.fujitsu.dc.common.es.response.DcIndexResponse; import com.fujitsu.dc.common.es.util.DcUUID; import com.fujitsu.dc.core.DcCoreConfig; import com.fujitsu.dc.core.DcCoreException; import com.fujitsu.dc.core.DcCoreLog; import com.fujitsu.dc.core.model.file.BinaryDataAccessException; import com.fujitsu.dc.core.model.file.BinaryDataAccessor; import com.fujitsu.dc.core.model.impl.es.DavNode; import com.fujitsu.dc.core.model.impl.es.ads.AdsException; import com.fujitsu.dc.core.model.lock.Lock; import com.fujitsu.dc.core.model.lock.LockKeyComposer; /** * DavNode情報のアクセス処理を実装したクラス. */ public class DavNodeAccessor extends DataSourceAccessor { /** * ログ. */ static Logger log = LoggerFactory.getLogger(DavNodeAccessor.class); /** * コンストラクタ. * @param index インデックス * @param name タイプ名 * @param routingId routingID */ public DavNodeAccessor(EsIndex index, String name, String routingId) { super(index, name, routingId); } /** * UUIDでDavNodeのデータ登録を行う. * @param davNode Davコンポーネント * @return 登録結果 */ public DcIndexResponse create(final DavNode davNode) { String id = DcUUID.randomUUID(); return this.create(id, davNode); } /** * DavNodeのデータ登録を行う. * @param id 登録データのID * @param davNode Davコンポーネント * @return 登録結果 */ public DcIndexResponse create(String id, DavNode davNode) { // マスタ書き込みでエラーが発生したためES更新を不可能とする super.prepareDataUpdate(getIndex().getName()); davNode.setId(id); DcIndexResponse response = super.create(id, davNode.getSource()); createAds(davNode); return response; } /** * DavNodeファイルのデータ登録を行う. * @param id 登録データのID * @param davNode Davコンポーネント * @return 登録結果 */ public DcActionResponse createForFile(String id, DavNode davNode) { // マスタ書き込みでエラーが発生したためES更新を不可能とする prepareDataUpdate(getIndex().getName()); davNode.setId(id); DcActionResponse response = null; try { // ElasticSearch更新 response = createForDavNodeFile(id, davNode.getSource()); // 一時ファイルコピー String unitUserName = getIndex().getName().replace(DcCoreConfig.getEsUnitPrefix() + "_", ""); BinaryDataAccessor binaryDataAccessor = new BinaryDataAccessor(DcCoreConfig.getBlobStoreRoot(), unitUserName, DcCoreConfig.getFsyncEnabled()); binaryDataAccessor.copyFile(id); // MySQL更新 createAds(davNode); } catch (BinaryDataAccessException ex) { // 一時ファイルコピー失敗 throw DcCoreException.Dav.FS_INCONSISTENCY_FOUND.reason(ex); } finally { // 一時ファイル削除 deleteTmpFile(id); } return response; } private void deleteTmpFile(String id) { String unitUserName = getIndex().getName().replace(DcCoreConfig.getEsUnitPrefix() + "_", ""); BinaryDataAccessor binaryDataAccessor = new BinaryDataAccessor(DcCoreConfig.getBlobStoreRoot(), unitUserName, DcCoreConfig.getFsyncEnabled()); try { // 一時ファイル物理削除 binaryDataAccessor.deletePhysicalFile(id + ".tmp"); } catch (BinaryDataAccessException e1) { log.info(e1.getMessage()); } } /** * マスターデータを登録する. * @param davNode 登録データ */ protected void createAds(DavNode davNode) { // 登録に成功した場合、マスタデータを書き込む if (getAds() != null) { try { getAds().createDavNode(getIndex().getName(), davNode); } catch (AdsException e) { DcCoreLog.Server.DATA_STORE_ENTITY_CREATE_FAIL.params(e.getMessage()).reason(e).writeLog(); // Adsの登録に失敗した場合は、専用のログに書込む String lockKey = LockKeyComposer.fullKeyFromCategoryAndKey(Lock.CATEGORY_DAV, null, davNode.getBoxId(), null); AdsWriteFailureLogInfo loginfo = new AdsWriteFailureLogInfo( this.getIndex().getName(), "dav", lockKey, davNode.getCellId(), davNode.getId(), AdsWriteFailureLogInfo.OperationKind.CREATE, 1, davNode.getUpdated()); recordAdsWriteFailureLog(loginfo); } } } /** * DavNodeのデータ削除を行う. * @param davNode 削除データ * @return 削除結果 */ public DcDeleteResponse delete(DavNode davNode) { return this.delete(davNode, -1); } /** * DavNodeのデータ削除を行う. * @param version バージョン情報 * @param davNode 削除データ * @return 削除結果 */ public DcDeleteResponse delete(DavNode davNode, long version) { String id = davNode.getId(); // マスタ書き込みでエラーが発生したためES更新を不可能とする super.prepareDataUpdate(getIndex().getName()); DcDeleteResponse response = super.delete(id, version); deleteAds(davNode, response.getVersion()); return response; } /** * マスターデータを削除する. * @param davNode 削除データ * @param version 削除したデータのバージョン */ protected void deleteAds(DavNode davNode, long version) { String id = davNode.getId(); // 削除に成功した場合、マスタデータを書き込む if (getAds() != null) { try { getAds().deleteDavNode(getIndex().getName(), id); } catch (AdsException e) { DcCoreLog.Server.DATA_STORE_ENTITY_DELETE_FAIL.params(e.getMessage()).reason(e).writeLog(); // Adsの登録に失敗した場合は、専用のログに書込む String lockKey = LockKeyComposer.fullKeyFromCategoryAndKey(Lock.CATEGORY_DAV, null, davNode.getBoxId(), null); AdsWriteFailureLogInfo loginfo = new AdsWriteFailureLogInfo( this.getIndex().getName(), "dav", lockKey, davNode.getCellId(), davNode.getId(), AdsWriteFailureLogInfo.OperationKind.DELETE, version, davNode.getUpdated()); recordAdsWriteFailureLog(loginfo); } } } /** * DavNodeのデータ更新を行う. * @param id 更新データのID * @param davNode Davコンポーネント * @return 更新結果 */ public DcIndexResponse update(String id, DavNode davNode) { return this.update(id, davNode, -1); } /** * バージョン指定ありでDavNodeのデータ更新を行う. * @param id 更新データのID * @param davNode Davコンポーネント * @param version バージョン情報 * @return 更新結果 */ public DcIndexResponse update(String id, DavNode davNode, long version) { // マスタ書き込みでエラーが発生したためES更新を不可能とする super.prepareDataUpdate(getIndex().getName()); DcIndexResponse response = super.update(id, davNode.getSource(), version); updateAds(davNode, response.getVersion()); return response; } /** * バージョン指定ありでDavNodeファイルのデータ更新を行う. * @param id 更新データのID * @param davNode Davコンポーネント * @param version バージョン情報 * @return 更新結果 */ public DcIndexResponse updateForFile(String id, DavNode davNode, long version) { // マスタ書き込みでエラーが発生したためES更新を不可能とする super.prepareDataUpdate(getIndex().getName()); DcIndexResponse response = null; try { // ElasticSearch更新 response = super.update(id, davNode.getSource(), version); // 一時ファイルコピー String unitUserName = getIndex().getName().replace(DcCoreConfig.getEsUnitPrefix() + "_", ""); BinaryDataAccessor binaryDataAccessor = new BinaryDataAccessor(DcCoreConfig.getBlobStoreRoot(), unitUserName, DcCoreConfig.getFsyncEnabled()); binaryDataAccessor.copyFile(id); // MySQL更新 updateAds(davNode, response.getVersion()); } catch (BinaryDataAccessException ex) { // 一時ファイルコピー失敗 throw DcCoreException.Dav.FS_INCONSISTENCY_FOUND.reason(ex); } finally { // 一時ファイル削除 deleteTmpFile(id); } return response; } /** * マスターデータを更新する. * @param davNode 更新データ * @param version Elasticsearchに登録されたドキュメントのバージョン */ protected void updateAds(DavNode davNode, long version) { // 更新に成功した場合、マスタデータを書き込む if (getAds() != null) { try { getAds().updateDavNode(getIndex().getName(), davNode); } catch (AdsException e) { DcCoreLog.Server.DATA_STORE_ENTITY_UPDATE_FAIL.params(e.getMessage()).reason(e).writeLog(); // Adsの登録に失敗した場合は、専用のログに書込む String lockKey = LockKeyComposer.fullKeyFromCategoryAndKey(Lock.CATEGORY_DAV, null, davNode.getBoxId(), null); AdsWriteFailureLogInfo loginfo = new AdsWriteFailureLogInfo( this.getIndex().getName(), "dav", lockKey, davNode.getCellId(), davNode.getId(), AdsWriteFailureLogInfo.OperationKind.UPDATE, version, davNode.getUpdated()); recordAdsWriteFailureLog(loginfo); } } } }