Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix remaining count error when query edge in page #515

Merged
merged 5 commits into from
May 22, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@

import com.baidu.hugegraph.HugeException;
import com.baidu.hugegraph.api.API;
import com.baidu.hugegraph.backend.page.PageState;
import com.baidu.hugegraph.backend.page.PageInfo;
import com.baidu.hugegraph.iterator.Metadatable;
import com.baidu.hugegraph.schema.EdgeLabel;
import com.baidu.hugegraph.schema.IndexLabel;
Expand Down Expand Up @@ -101,7 +101,7 @@ private String writeIterator(String label, Iterator<?> iter,
if (iter instanceof GraphTraversal<?, ?>) {
page = TraversalUtil.page((GraphTraversal<?, ?>) iter);
} else if (iter instanceof Metadatable) {
page = PageState.page(iter);
page = PageInfo.page(iter);
} else {
throw new HugeException("Invalid paging iterator: %s",
iter.getClass());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
import java.util.Iterator;
import java.util.function.BiFunction;

import com.baidu.hugegraph.backend.page.PageState;
import com.baidu.hugegraph.backend.query.Query;
import com.baidu.hugegraph.backend.store.BackendEntry;
import com.baidu.hugegraph.backend.store.BackendEntryIterator;
Expand Down Expand Up @@ -115,6 +116,7 @@ protected String pageState() {
if (page == null || this.results.isExhausted()) {
return null;
}
return page.toString();
byte[] position = page.toBytes();
return new PageState(position, 0, (int) this.count()).toString();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@

import com.baidu.hugegraph.backend.BackendException;
import com.baidu.hugegraph.backend.id.Id;
import com.baidu.hugegraph.backend.page.PageState;
import com.baidu.hugegraph.backend.query.Condition;
import com.baidu.hugegraph.backend.query.Condition.Relation;
import com.baidu.hugegraph.backend.query.Query;
Expand Down Expand Up @@ -168,8 +169,9 @@ protected void setPageState(Query query, List<Select> selects) {
select.setFetchSize((int) total);
// It's the first time if page is empty
if (!page.isEmpty()) {
byte[] position = PageState.fromString(page).position();
try {
select.setPagingState(PagingState.fromString(page));
select.setPagingState(PagingState.fromBytes(position));
} catch (PagingStateException e) {
throw new BackendException(e);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,24 +33,24 @@ public class PageEntryIterator implements Iterator<BackendEntry>, Metadatable {
private final QueryList queries;
private final long pageSize;
private QueryList.PageIterator results;
private PageState pageState;
private PageInfo pageInfo;
private long remaining;

public PageEntryIterator(QueryList queries, long pageSize) {
this.queries = queries;
this.pageSize = pageSize;
this.results = QueryList.PageIterator.EMPTY;
this.pageState = this.parsePageState();
this.pageInfo = this.parsePageState();
this.remaining = queries.parent().limit();
}

private PageState parsePageState() {
private PageInfo parsePageState() {
String page = this.queries.parent().pageWithoutCheck();
PageState pageState = PageState.fromString(page);
E.checkState(pageState.offset() < this.queries.total(),
PageInfo pageInfo = PageInfo.fromString(page);
E.checkState(pageInfo.offset() < this.queries.total(),
"Invalid page '%s' with an offset '%s' exceeds " +
"the size of IdHolderList", page, pageState.offset());
return pageState;
"the size of IdHolderList", page, pageInfo.offset());
return pageInfo;
}

@Override
Expand All @@ -63,26 +63,27 @@ public boolean hasNext() {

private boolean fetch() {
if ((this.remaining != Query.NO_LIMIT && this.remaining <= 0L) ||
this.pageState.offset() >= this.queries.total()) {
this.pageInfo.offset() >= this.queries.total()) {
return false;
}

long pageSize = this.pageSize;
if (this.remaining != Query.NO_LIMIT && this.remaining < pageSize) {
pageSize = this.remaining;
}
this.results = this.queries.fetchNext(this.pageState, pageSize);
this.results = this.queries.fetchNext(this.pageInfo, pageSize);
assert this.results != null;

if (this.results.iterator().hasNext()) {
if (this.results.page() == null) {
this.pageState.increase();
this.pageInfo.increase();
} else {
this.pageState.page(this.results.page());
this.pageInfo.page(this.results.page());
this.remaining -= this.results.total();
}
return true;
} else {
this.pageState.increase();
this.pageInfo.increase();
return this.fetch();
}
}
Expand All @@ -92,21 +93,16 @@ public BackendEntry next() {
if (!this.hasNext()) {
throw new NoSuchElementException();
}
BackendEntry entry = this.results.iterator().next();
if (this.remaining != Query.NO_LIMIT) {
// Assume one result in each entry (just for index query)
this.remaining--;
}
return entry;
return this.results.iterator().next();
}

@Override
public Object metadata(String meta, Object... args) {
if (PageState.PAGE.equals(meta)) {
if (this.pageState.offset() >= this.queries.total()) {
if (PageInfo.PAGE.equals(meta)) {
if (this.pageInfo.offset() >= this.queries.total()) {
return null;
}
return this.pageState.toString();
return this.pageInfo.toString();
}
throw new NotSupportException("Invalid meta '%s'", meta);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
/*
* Copyright 2017 HugeGraph Authors
*
* 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.
*/

package com.baidu.hugegraph.backend.page;

import java.util.Base64;
import java.util.Iterator;

import com.baidu.hugegraph.HugeException;
import com.baidu.hugegraph.backend.serializer.BytesBuffer;
import com.baidu.hugegraph.iterator.Metadatable;
import com.baidu.hugegraph.util.Bytes;
import com.baidu.hugegraph.util.E;

public final class PageInfo {

public static final String PAGE = "page";
public static final String PAGE_NONE = "";

private int offset;
private String page;

public PageInfo(int offset, String page) {
E.checkArgument(offset >= 0, "The offset must be >= 0");
E.checkNotNull(page, "page");
this.offset = offset;
this.page = page;
}

public void increase() {
this.offset++;
this.page = PAGE_NONE;
}

public int offset() {
return this.offset;
}

public void page(String page) {
this.page = page;
}

public String page() {
return this.page;
}

@Override
public String toString() {
return Base64.getEncoder().encodeToString(this.toBytes());
}

public byte[] toBytes() {
byte[] pageState = PageState.toBytes(this.page);
int length = 2 + BytesBuffer.INT_LEN + pageState.length;
BytesBuffer buffer = BytesBuffer.allocate(length);
buffer.writeInt(this.offset);
buffer.writeBytes(pageState);
return buffer.bytes();
}

public static PageInfo fromString(String page) {
byte[] bytes;
try {
bytes = Base64.getDecoder().decode(page);
} catch (Exception e) {
throw new HugeException("Invalid page: '%s'", e, page);
}
return fromBytes(bytes);
}

public static PageInfo fromBytes(byte[] bytes) {
if (bytes.length == 0) {
// The first page
return new PageInfo(0, PAGE_NONE);
}
try {
BytesBuffer buffer = BytesBuffer.wrap(bytes);
int offset = buffer.readInt();
byte[] pageState = buffer.readBytes();
String page = PageState.toString(pageState);
return new PageInfo(offset, page);
} catch (Exception e) {
throw new HugeException("Invalid page: '0x%s'",
e, Bytes.toHex(bytes));
}
}

public static String page(Iterator<?> iterator) {
E.checkState(iterator instanceof Metadatable,
"Invalid paging iterator: %s", iterator.getClass());
Object page = ((Metadatable) iterator).metadata(PAGE);
return (String) page;
}
}
Loading