blob: 737398116844895ff14c6f4753cbb8827d24b735 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You 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.
*/
import React, { useState, useEffect } from "react";
import { Layout, Col, Row, Image, notification, Tooltip } from 'antd';
import styles from '../style.less'
import { getChunkGroupInfoUsingPOST, getTimeseriesIndexInfoUsingPOST, getVersionUsingPOST, getMetaDataSizeUsingPOST, getMetaDataUsingPOST } from '@/services/swagger1/tsfileViewerController'
import PopDetails from "./popDetails"
import { useIntl } from 'umi';
const { Sider, Content } = Layout;
const Tsfile = (props) => {
const { fileName, baseInfo } = props;
const doMessageShow = (msg, offset) => {
props.showStructureContext()
props.doChange(msg, offset)
}
const getMessage = (wrap) => {
let message;
let messageShow;
if (wrap == undefined) {
message = "";
messageShow = "";
} else {
message = <div className={styles.hcenter}>{wrap.deviceName}<br />{"[" + wrap.offset + "]"}</div>;
messageShow = wrap.deviceName + "\n[" + wrap.offset + "]";
}
return (
<Tooltip placement="bottomLeft" title={<span style={{ "whiteSpace": "pre-line" }}>{messageShow}</span>}>
<h3 className={styles.hcenter}>{message}</h3>
</Tooltip>
)
}
const getMessageIndex = (wrap) => {
let message;
let messageShow;
if (wrap == undefined) {
message = "";
messageShow = "";
} else {
if (!wrap.aligned) {
message = <div className={styles.hcenter}>{wrap.deviceId}<br />{"[" + wrap.measurementId + "]"}<br />{"[" + wrap.offset + "]"}</div>;
messageShow = wrap.deviceId + "\n[" + wrap.measurementId + "]\n[" + wrap.offset + "]";
} else {
message = <div className={styles.hcenter}>{wrap.deviceId}<br />{"[" + wrap.offset + "]"}</div>;
messageShow = wrap.deviceId + "\n[" + wrap.offset + "]";
}
}
return (
<Tooltip placement="bottomLeft" title={<span style={{ "whiteSpace": "pre-line" }}>{message}</span>}>
<h3 className={styles.hcenter}>{message}</h3>
</Tooltip>
)
}
return (
<>
<div className={styles.row}>
<Row gutter={[8, 8]} align="middle" justify="center" style={{ height: "50px" }}>
<Col span={23} style={{ height: "40px" }}>
<div className={styles.shortStyle} onClick={() => doMessageShow("TSFILE")}><h3 className={styles.hcenter}>TSFILE VERSION{"[" + baseInfo.version + "]"}</h3></div>
</Col>
</Row>
</div>
<div className={styles.notoplinerow}>
<Row gutter={[8, 8]} align="middle" justify="center" style={{ height: "200px", padding: 5 }}>
<Col span={6} style={{ height: "160px" }}>
<div className={styles.longStyle} onClick={() => doMessageShow("ChunkGroup", baseInfo.chunkGroupList[0] ? baseInfo.chunkGroupList[0].offset : undefined)}>{getMessage(baseInfo.chunkGroupList[0])}</div>
</Col>
<Col span={6} style={{ height: "160px" }}>
<div className={styles.longStyle} hidden={baseInfo.chunkGroupList[1] ? false : true} onClick={() => doMessageShow("ChunkGroup", baseInfo.chunkGroupList[1] ? baseInfo.chunkGroupList[1].offset : undefined)}>{getMessage(baseInfo.chunkGroupList[1])}</div>
</Col>
<Col span={6} style={{ height: "160px" }}>
<div className={styles.longStyle} hidden={baseInfo.chunkGroupList[2] ? false : true} onClick={() => doMessageShow("ChunkGroup", baseInfo.chunkGroupList[2] ? baseInfo.chunkGroupList[2].offset : undefined)}>{getMessage(baseInfo.chunkGroupList[2])}</div>
</Col>
<Col span={6} style={{ height: "160px" }}>
<div className={styles.longStyle} onClick={() => doMessageShow("CGMORE")}><h3 className={styles.hcenter}>more infos</h3></div>
</Col>
</Row>
</div>
<div className={styles.notoplinerow}>
<Row gutter={[8, 8]} align="middle" justify="center" style={{ height: "200px", padding: 5 }}>
<Col span={6} style={{ height: "160px" }}>
<div className={styles.longStyle} onClick={() => doMessageShow("TimeseriesIndex", baseInfo.timeseriesIndexList[0] ? baseInfo.timeseriesIndexList[0].offset : undefined)}>{getMessageIndex(baseInfo.timeseriesIndexList[0])}</div>
</Col>
<Col span={6} style={{ height: "160px" }}>
<div className={styles.longStyle} hidden={baseInfo.timeseriesIndexList[1] ? false : true} onClick={() => doMessageShow("TimeseriesIndex", baseInfo.timeseriesIndexList[1] ? baseInfo.timeseriesIndexList[1].offset : undefined)}>{getMessageIndex(baseInfo.timeseriesIndexList[1])}</div>
</Col>
<Col span={6} style={{ height: "160px" }}>
<div className={styles.longStyle} hidden={baseInfo.timeseriesIndexList[2] ? false : true} onClick={() => doMessageShow("TimeseriesIndex", baseInfo.timeseriesIndexList[2] ? baseInfo.timeseriesIndexList[2].offset : undefined)}>{getMessageIndex(baseInfo.timeseriesIndexList[2])}</div>
</Col>
<Col span={6} style={{ height: "160px" }}>
<div className={styles.longStyle} onClick={() => doMessageShow("TIMORE")}><h3 className={styles.hcenter}>more infos</h3></div>
</Col>
</Row>
</div>
<div className={styles.rowEntry}>
<Row gutter={[8, 8]} align="middle" justify="center" style={{ height: "45px" }}>
<Col span={17} style={{ height: "40px" }}>
<div className={styles.shortStyle} onClick={() => doMessageShow("IndexOfTimeseriesIndex")}><h3 className={styles.hcenter}>TsfileMetaData[IndexOfTimeseriesIndex]</h3></div>
</Col>
<Col span={5} style={{ height: "40px" }}>
<div className={styles.shortStyle} onClick={() => doMessageShow("ITIMORE")}><h3 className={styles.hcenter}>more infos</h3></div>
</Col>
</Row>
</div>
{/* <div className={styles.row1}>
<Row align="middle" justify="center" style={{ height: "45px" }}>
<Col span={22} style={{ height: "40px" }}>
<div className={styles.col1} onClick={() => doMessageShow("TsfileMetaData")}><h3 className={styles.hcenter}>TsfileMetaData</h3></div>
</Col>
</Row>
</div> */}
<div className={styles.notoplinerow}>
<Row align="middle" justify="center" style={{ height: "45px" }}>
<Col span={22} style={{ height: "40px" }}>
<div className={styles.shortStyle} onClick={() => doMessageShow("TsfileMetaDataSize")}><h3 className={styles.hcenter}>TsfileMetaDataSize{"[" + baseInfo.metadataSize + " bytes]"}</h3></div>
</Col>
</Row>
</div>
<div className={styles.notoplinerow}>
<Row align="middle" justify="center" style={{ height: "45px" }}>
<Col span={22} style={{ height: "40px" }}>
<div className={styles.shortStyle} onClick={() => doMessageShow("TSFILE")}><h3 className={styles.hcenter}>TSFILE</h3></div>
</Col>
</Row>
</div>
</>
)
}
const ImageMessage = (props) => {
const intl = useIntl();
const { value, offset, showStructureContext, filePath } = props;
const [version, setVersion] = useState();
const [tsfileMetaDataSize, setTsfileMetaDataSize] = useState();
const getVersion = async () => {
let res = await getVersionUsingPOST({ filePath: filePath })
if (res.code == 0) {
setVersion(res.data.version)
} else {
notification.error({
message: res.message,
});
}
}
const getTsFileMetada = async () => {
let res = await getMetaDataSizeUsingPOST({ filePath: filePath })
if (res.code == 0) {
setTsfileMetaDataSize(res.data)
} else {
notification.error({
message: res.message,
});
}
}
const showImage = (key, offset) => {
if (key == "TSFILE") {
getVersion();
let message = intl.formatMessage({ id: 'overview.explanation', }) + ':\n' +
'TSFILE, ' + intl.formatMessage({ id: 'overview.magicNumber', }) + ' offset=0 size=6\n' +
'VERSION:' + version + ', ' + intl.formatMessage({ id: 'overview.version', }) + ' offset=6 size=1\n' +
intl.formatMessage({ id: 'overview.endExplanation', }) + ' offset= file.length-6 size=6';
return (<pre style={{ height: "55vh", overflow: "auto", whiteSpace: "pre-wrap" }}>{message}</pre>);
}
if (key == "ChunkGroup" && offset != undefined) {
return (
<div className={styles.detailRow}>
<div className={styles.chunkgroup} >
<Row style={{ height: "30vh" }}>
<Col span={3}><div className={styles.chunkgroupheader} onClick={() => { showStructureContext(key, 'CGH') }}>CGH</div></Col>
<Col span={16}>
<div className={styles.chunk1} >
<Row style={{ height: "25vh" }}>
<Col span={3}><div className={styles.chunkheader} onClick={() => { showStructureContext(key, 'CH') }}>CH</div></Col>
<Col span={20}>
<div className={styles.chunkdata} >
<Row style={{ height: "20vh" }}>
<Col span={4}><div className={styles.pageheader} onClick={() => { showStructureContext(key, 'PH') }}>PH</div></Col>
<Col span={4}><div className={styles.pagedata} onClick={() => { showStructureContext('', '') }}>PD</div></Col>
<Col span={4}><div className={styles.pageheader1} onClick={() => { showStructureContext('', '') }}>PH</div></Col>
<Col span={4}><div className={styles.pagedata1} onClick={() => { showStructureContext('', '') }}>PD</div></Col>
<Col span={4}><div className={styles.pageheader1} onClick={() => { showStructureContext('', '') }}>more infos</div></Col>
</Row>
</div>
</Col>
</Row>
</div>
</Col>
<Col span={3}><div className={styles.chunk} >more infos</div></Col>
</Row>
</div>
</div>
)
}
if (key != undefined && key.indexOf("MORE") > -1) {
return <div></div>
}
// || key == "TIMORE"
if (key == "TimeseriesIndex" && offset != undefined) {
return (
<div className={styles.detailRow}>
<div className={styles.chunkgroup} >
<Row style={{ height: "30vh" }}>
<Col span={3}><div className={styles.timeseriesmetadata} onClick={() => { showStructureContext(key, 'TM') }}>TM</div></Col>
<Col span={3}>
<div className={styles.chunkmetadata} onClick={() => { showStructureContext(key, 'CM') }}>
CM
</div>
</Col>
<Col span={3}><div className={styles.chunkmetadata1} onClick={() => { showStructureContext('', '') }}>CM</div></Col>
<Col span={3}><div className={styles.timeseriesmetadata1} onClick={() => { showStructureContext('', '') }}>TM</div></Col>
<Col span={3}>
<div className={styles.chunkmetadata1} onClick={() => { showStructureContext('', '') }}>
CM
</div>
</Col>
<Col span={3}><div className={styles.chunkmetadata1} onClick={() => { showStructureContext('', '') }}>CM</div></Col>
<Col span={3}><div className={styles.timeseriesmetadata1} onClick={() => { showStructureContext('', '') }}>more infos</div></Col>
</Row>
</div>
</div>
)
}
// || key == "ITIMORE"
if (key == "IndexOfTimeseriesIndex") {
return (
<div className={styles.detailRow}>
<div className={styles.chunkgroup} >
<Row style={{ height: "30vh" }}>
<Col span={17}>
<div className={styles.metadataIndexNode}>
<Row style={{ height: "25vh" }}>
<Col span={5}><div className={styles.childSize} onClick={() => { showStructureContext(key, 'childSize') }}>childSize</div></Col>
<Col span={5}><div className={styles.list} onClick={() => { showStructureContext(key, 'list') }}>{'List<ITI>'}</div></Col>
<Col span={5}><div className={styles.childSize} onClick={() => { showStructureContext(key, 'offset') }}>offset</div></Col>
<Col span={5}><div className={styles.list} onClick={() => { showStructureContext(key, 'NodeType') }}>NodeType</div></Col>
</Row>
</div>
</Col>
<Col span={3}>
<div className={styles.metaOffset} onClick={() => { showStructureContext(key, 'metaOffset') }}>metaOffset</div>
</Col>
<Col span={3}>
<div className={styles.bloomFilter} onClick={() => { showStructureContext('', '') }}>bloomFilter</div>
</Col>
</Row>
</div>
</div>
)
}
// if (key == "TsfileMetaData") { TsfileMetaData 中 包含IndexoftimeseriesIndex信息
// // return (<Image align="center" width="100%" height="100%" src={tsfilemetadata}></Image>);
// }
if (key == "TsfileMetaDataSize") {
getTsFileMetada()
return (<pre style={{ height: "55vh", overflow: "auto", whiteSpace: "pre-wrap" }}>TsfileMetaDataSize:{tsfileMetaDataSize}</pre>);
}
}
return (
<div style={{ width: "100%", height: "100%" }}>
{showImage(value, offset)}
</div>
)
}
const Overview = (props) => {
const [clickArea, setClickArea] = useState()
const [clickAreaOffset, setClickAreaOffset] = useState(undefined)
const [popShow, setPpoShow] = useState(false)
const [chunkGroupBrief, setChunkGroupBrief] = useState()
const [timeseriesIndexBrief, setTimeseriesIndexBrief] = useState()
const [indexTimeseriesIndexBrief, setIndexTimeseriesIndexBrief] = useState()
// 结构CGH/CH/PH点击所对应的内容
const [structureContext, setStructureContext] = useState()
const intl = useIntl();
const { fileName, filePath, baseInfo } = props;
const doChange = (structureName, offset) => {
setClickArea(structureName)
setClickAreaOffset(offset)
if (structureName.indexOf("MORE") > -1) {
setStructureContext();
setPpoShow({ flag: true, structureName: structureName, fileName: fileName, filePath: filePath })
}
if (structureName == 'ChunkGroup') {
if (offset != undefined) {
getCGBriefInfo(offset)
} else {
setStructureContext();
}
}
if (structureName == 'TimeseriesIndex') {
if (offset != undefined) {
getTIBriefInfo(offset)
} else {
setStructureContext();
}
}
if (structureName == 'IndexOfTimeseriesIndex') {
getITIBriefInfo()
}
}
const getCGBriefInfo = async (offset) => {
let res = await getChunkGroupInfoUsingPOST({ offset: offset, filePath: filePath })
if (res.code == 0) {
setChunkGroupBrief(res.data)
} else {
notification.error({
message: res.message,
});
}
}
const getTIBriefInfo = async (offset) => {
let res = await getTimeseriesIndexInfoUsingPOST({ offset: offset, filePath: filePath })
if (res.code == 0) {
setTimeseriesIndexBrief(res.data)
} else {
notification.error({
message: res.message,
});
}
}
const getITIBriefInfo = async () => {
let res = await getMetaDataUsingPOST({ filePath: filePath })
if (res.code == 0) {
setIndexTimeseriesIndexBrief(res.data)
} else {
notification.error({
message: res.message,
});
}
}
// flag1 代表chunkgroup、timeseriesIndex、等,flag2代表flag1下的二级标志
const showStructureContext = (level1Flag, level2Flag) => {
if (level1Flag == 'ChunkGroup') {
if (level2Flag == 'CGH') {
let info = intl.formatMessage({ id: 'overview.structureDescription', }) + ":\n"
+ "\t CGH = ChunkGroupHeader \n"
+ "\t CGD = ChunkGroupData \n"
+ "\t CGD = n * Chunk \n"
+ "\t ChunkGroup = CGH +CGD \n"
+ intl.formatMessage({ id: 'overview.details', }) + ": \n"
setStructureContext(<pre style={{ height: "55vh", overflow: "auto", whiteSpace: "pre-wrap" }}>{info}{JSON.stringify(chunkGroupBrief.cgh, null, '\t')}</pre>)
}
if (level2Flag == 'CH') {
let info = intl.formatMessage({ id: 'overview.structureDescription', }) + ":\n"
+ "\t CH = ChunkHeader \n"
+ "\t CD = ChunkData \n"
+ "\t CD = n * Page \n"
+ "\t Chunk = CH +CD \n"
+ intl.formatMessage({ id: 'overview.details', }) + ": \n"
setStructureContext(<pre style={{ height: "55vh", overflow: "auto", whiteSpace: "pre-wrap" }}>{info}{JSON.stringify(chunkGroupBrief.ch, null, '\t')}</pre>)
}
if (level2Flag == 'PH') {
let info = intl.formatMessage({ id: 'overview.structureDescription', }) + ":\n"
+ "\t PH = PageHeader \n"
+ "\t PD = PageData \n"
+ "\t Page = PH + PD \n"
+ intl.formatMessage({ id: 'overview.details', }) + ": \n"
setStructureContext(<pre style={{ height: "55vh", overflow: "auto", whiteSpace: "pre-wrap" }}>{info}{JSON.stringify(chunkGroupBrief.ph, null, '\t')}</pre>)
}
} else if (level1Flag == 'TimeseriesIndex') {
if (level2Flag == 'TM') {
let info = intl.formatMessage({ id: 'overview.structureDescription', }) + ":\n"
+ "\t TM = TimeseriesMetadata \n"
+ "\t TimeseriesIndex = TM + n*CM \n"
+ intl.formatMessage({ id: 'overview.details', }) + ": \n"
setStructureContext(<pre style={{ height: "55vh", overflow: "auto", whiteSpace: "pre-wrap" }}>{info}{JSON.stringify(timeseriesIndexBrief.tm, null, '\t')}</pre>)
}
if (level2Flag == 'CM') {
let info = intl.formatMessage({ id: 'overview.structureDescription', }) + ":\n"
+ "\t CM = ChunkMetadata \n"
+ intl.formatMessage({ id: 'overview.details', }) + ": \n"
setStructureContext(<pre style={{ height: "55vh", overflow: "auto", whiteSpace: "pre-wrap" }}>{info}{JSON.stringify(timeseriesIndexBrief.cm, null, '\t')}</pre>)
}
} else if (level1Flag == 'IndexOfTimeseriesIndex') {
if (level2Flag == 'childSize') {
let info = " \n childSize:"
setStructureContext(<pre style={{ height: "55vh", overflow: "auto", whiteSpace: "pre-wrap" }}>{info}{indexTimeseriesIndexBrief.metadataIndexNodeVo.childSize}</pre>)
}
if (level2Flag == 'list') {
let info = " \n List<ITI>:"
setStructureContext(<pre style={{ height: "55vh", overflow: "auto", whiteSpace: "pre-wrap" }}>{info}{JSON.stringify(indexTimeseriesIndexBrief.metadataIndexNodeVo.metadataIndexEntryList, null, '\t')}</pre>)
}
if (level2Flag == 'offset') {
let info = "\n offset:"
setStructureContext(<pre style={{ height: "55vh", overflow: "auto", whiteSpace: "pre-wrap" }}>{info}{indexTimeseriesIndexBrief.metadataIndexNodeVo.offset}</pre>)
}
if (level2Flag == 'NodeType') {
let info = "\n NodeType:"
setStructureContext(<pre style={{ height: "55vh", overflow: "auto", whiteSpace: "pre-wrap" }}>{info}{indexTimeseriesIndexBrief.metadataIndexNodeVo.nodeType}</pre>)
}
if (level2Flag == 'metaOffset') {
let info = "\n metaOffset:"
setStructureContext(<pre style={{ height: "55vh", overflow: "auto", whiteSpace: "pre-wrap" }}>{info}{indexTimeseriesIndexBrief.metaOffset}</pre>)
}
} else {
setStructureContext()
}
}
const closePop = () => {
setPpoShow({ flag: false })
}
return (
<>
<Layout>
<Sider width="50%" style={{ height: "100vh", background: "white", paddingTop: 60, paddingLeft: 15, paddingRight: 15 }}>
<Tsfile doChange={doChange} showStructureContext={showStructureContext} fileName={fileName} baseInfo={baseInfo}></Tsfile>
</Sider>
<Layout style={{ background: "white", paddingTop: 60, paddingLeft: 15, paddingRight: 15 }}>
<Content style={{ height: "33vh", background: "white" }}>
<ImageMessage value={clickArea} offset={clickAreaOffset} showStructureContext={showStructureContext} filePath={filePath}></ImageMessage>
</Content>
<Content style={{ height: "60vh", background: "white" }}>
{structureContext}
</Content>
<PopDetails popShow={popShow} closePop={() => closePop()}></PopDetails>
</Layout>
</Layout>
</>
)
}
export default Overview