[IOTDB-1931] Adapt tree structrued Template with MManager#4391
[IOTDB-1931] Adapt tree structrued Template with MManager#4391qiaojialin merged 115 commits intoapache:masterfrom
Conversation
…ctorMeasurementSchema in metadata module (apache#4255)
| if (!(par instanceof IEntityMNode)) { | ||
| throw new MetadataException("Measurement not under entity: " + currentNode.getName()); | ||
| } |
There was a problem hiding this comment.
Avoid instanceof. Use IMNode.isEntity instead.
There was a problem hiding this comment.
actually it is not necessary, will be removed then
| if (!(par instanceof IEntityMNode)) { | ||
| throw new MetadataException("Measurement not under entity: " + currentNode.getName()); | ||
| } |
There was a problem hiding this comment.
Is this necessary? How could the parent MNode of current MeasurementMNode not be Entity?
| retPath.setUnderAlignedEntity(((IEntityMNode) par).isAligned()); | ||
| return retPath; |
There was a problem hiding this comment.
Replace (IEntityMNode) par with par.getAsEntity
| traverseContext.push(node); | ||
| traverse(child, idx + 1, level + 1); | ||
| traverseContext.pop(); | ||
| } |
There was a problem hiding this comment.
If you want to make the context contains node from root to current node's parent, maybe put this push and pop out of the for loop is better?
There was a problem hiding this comment.
all push and pop are out of loop now
| * Before to insert, set using template if template accessed. Better performance if refactored | ||
| * with getDeviceNodeWithAutoCreate | ||
| */ | ||
| private void activateTemplateBeforeAccess(PartialPath deviceId, String[] measurements) | ||
| throws MetadataException { | ||
| StringBuilder builder = new StringBuilder(deviceId.getFullPath()); | ||
| if (builder.length() != 0) { | ||
| builder.append(TsFileConstant.PATH_SEPARATOR); | ||
| } | ||
| for (String measurement : measurements) { | ||
| builder.append(measurement); | ||
| IMNode mountedNode = mtree.getTemplateMountedNode(new PartialPath(builder.toString())); | ||
| if (mountedNode != null && !mountedNode.isUseTemplate()) { | ||
| setUsingSchemaTemplate(mountedNode); | ||
| } | ||
| builder.delete(builder.length() - measurement.length(), builder.length()); | ||
| } | ||
| } |
There was a problem hiding this comment.
If the mountedNode has not been created on MTree, how could you activate it?
There was a problem hiding this comment.
Thanks for you insight!
Now, I will get the template mounted node index, rather than IMNode, so that auto create process methods are decoupled from mounted node detecting.
| activateTemplateBeforeAccess(devicePath, measurementList); | ||
| IMNode deviceMNode = getDeviceNodeWithAutoCreate(devicePath); |
There was a problem hiding this comment.
If the device now is represented by template, this method maybe invalid.
There was a problem hiding this comment.
As fixed above, this methods no longer exists.
SilverNarcissus
left a comment
There was a problem hiding this comment.
Nice work! Only one format issue and one question. Please have a look~
| for (MeasurementPath measurementPath : | ||
| manager.getMeasurementPaths(new PartialPath("root.sg1.d1.*"))) { | ||
| allSchema.remove(measurementPath.getMeasurementSchema()); | ||
| manager.getMeasurementPaths(new PartialPath("root.sg1.d1.**"))) { |
There was a problem hiding this comment.
What's the ** means currently? Maybe I miss something in the design part.
There was a problem hiding this comment.
Sorry for the confusion, the usage of '**' has not change ever, it is still a multil-level wildcard.
The reason to change here, is that template converted to a tree structured one now. As before, this template has 2 schemasName which won't present in measurement path, 's11' and 'vector'. Now measurements of the template contain 2 sublist, which is 's11' and 'vector.s1....s10'.
So, in order to traverse this template, I modify it to '**' as above.
|
|
||
| // 1. get device node | ||
| // 1. get device node, set using template if accessed. | ||
|
|
There was a problem hiding this comment.
remove this empty line
There was a problem hiding this comment.
Thanks! It has been removed now.
| try { | ||
| resultSet.add(getCurrentPartialPath(node)); | ||
| } catch (MetadataException e) { | ||
| logger.error(e.getMessage()); |
There was a problem hiding this comment.
Should we throw exception again here?
There was a problem hiding this comment.
I'm not sure how to deal with this. It is a exception will not happen actually, so I did not throw it again here.
The exception is caused by a construct of ParitialPath where content are nodes during a traverse which should assure to avoid illegal path. But this method override an abstract method which does not throw exception, so this catch did not throw again.
| } else { | ||
| for (IMNode child : mountedNode.getChildren().values()) { | ||
| if (child.isMeasurement()) { | ||
| if (template.getAlignedPrefixSet().contains("") |
There was a problem hiding this comment.
What's the meaning of empty string here? Maybe we need some comment
There was a problem hiding this comment.
Thanks! This string tries to represent alignment of direct measurement of a template. I will add more comment.
| protected MeasurementPath getCurrentMeasurementPathInTraverse(IMeasurementMNode currentNode) | ||
| throws MetadataException { | ||
| IMNode par = traverseContext.peek(); | ||
|
|
||
| Iterator<IMNode> nodes = traverseContext.descendingIterator(); | ||
| StringBuilder builder = new StringBuilder(nodes.next().getName()); | ||
| while (nodes.hasNext()) { | ||
| builder.append(TsFileConstant.PATH_SEPARATOR); | ||
| builder.append(nodes.next().getName()); | ||
| } | ||
| if (builder.length() != 0) { | ||
| builder.append(TsFileConstant.PATH_SEPARATOR); | ||
| } | ||
| builder.append(currentNode.getName()); | ||
| MeasurementPath retPath = | ||
| new MeasurementPath(new PartialPath(builder.toString()), currentNode.getSchema()); | ||
| retPath.setUnderAlignedEntity(par.getAsEntityMNode().isAligned()); | ||
| return retPath; | ||
| } |
There was a problem hiding this comment.
Maybe move this method to MeasurementCollector is better, if this method is only used in that kind of tasks.
There was a problem hiding this comment.
It has been moved now
| throw new MetadataException( | ||
| String.format( | ||
| "Path [%s] overlaps but not matches template [%s] under node [%s]", | ||
| measurementPath.getFullPath(), upperTemplate.getName(), fullPathNodes[index])); |
There was a problem hiding this comment.
Shall we make this kind exception message as a specific Exception class?
There was a problem hiding this comment.
A new exception TemplateImcompatibleException replaces all these usages.
| // node might be replaced when check with alignment | ||
| node = mtree.checkTemplateAlignmentWithMountedNode(node, template); | ||
|
|
||
| node.setSchemaTemplate(template); |
There was a problem hiding this comment.
If this node is not using template, why should it be replaced by entityMNode?
There was a problem hiding this comment.
That's true. This check should be a part of setUsingTemplate methods rather than this one. Fixed now.
| // this operation may change mtree structure and node type | ||
| // invoke mnode.setUseTemplate is invalid | ||
| IEntityMNode entityMNode = mtree.setToEntity(node); | ||
|
|
||
| // to ensure alignment adapt with former node or template | ||
| entityMNode.setAligned( | ||
| node.isEntity() | ||
| ? node.getAsEntityMNode().isAligned() | ||
| : node.getUpperTemplate().isDirectAligned()); | ||
| entityMNode.setUseTemplate(true); |
There was a problem hiding this comment.
Currently, a MNode using template is possibly not an entityMNode since the template may not has direct measurement. Thus the node type transform need check first.
There was a problem hiding this comment.
Move the field "isUsingTemplate" from EntityMNode to InternalMNode. This may be better to adapt to Tree template.
There was a problem hiding this comment.
In this method (setUsingTemplate), it will check alignment and replace it if direct measurement exists now.
To implement this, I add setUseTemplate into Interface IMNode.
And this method will return an IMNode rather than IEntityNode now.
| int indexRecord = -1; | ||
| // check every measurement path | ||
| for (String measurementId : measurementList) { | ||
| PartialPath fullPath = devicePath.concatNode(measurementId); | ||
| int index = mtree.getMountedNodeIndexOnMeasurementPath(fullPath); | ||
| if (index != fullPath.getNodeLength() - 1) { | ||
| // this measurement is in template, need to assure mounted node exists and set using | ||
| // template. | ||
| if (index != indexRecord) { | ||
| // Without allowing overlap of template and MTree, this block run only once | ||
| String[] mountedPathNodes = Arrays.copyOfRange(fullPath.getNodes(), 0, index + 1); | ||
| IMNode mountedNode = getDeviceNodeWithAutoCreate(new PartialPath(mountedPathNodes)); | ||
| setUsingSchemaTemplate(mountedNode); | ||
| indexRecord = index; | ||
| } | ||
| } | ||
| } |
There was a problem hiding this comment.
Since insertPlan only process one device, it is unnecessary to finish the whole loop. Break as early as the device has been checked.
There was a problem hiding this comment.
Since it needs to check each measurementPath with template whether compatible, I use a boolean to avoid reduntant process.
SilverNarcissus
left a comment
There was a problem hiding this comment.
Only one issue in IT. Other part are look good to me~
|
|
||
| // delete series inside template | ||
| try { | ||
| session.deleteTimeseries("root.sg.loc1.sector.x"); |
There was a problem hiding this comment.
add a fail() after this line
There was a problem hiding this comment.
Thanks! And it has been added now.
5a38e3f to
6d5d384
Compare
This PR has been merged with new_vector branch in apache repository.
All CI in metadata package passed, while some other packages remaining to be fixed as new_vector branch.