chris@3: /* chris@3: * SONEWS News Server chris@3: * see AUTHORS for the list of contributors chris@3: * chris@3: * This program is free software: you can redistribute it and/or modify chris@3: * it under the terms of the GNU General Public License as published by chris@3: * the Free Software Foundation, either version 3 of the License, or chris@3: * (at your option) any later version. chris@3: * chris@3: * This program is distributed in the hope that it will be useful, chris@3: * but WITHOUT ANY WARRANTY; without even the implied warranty of chris@3: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the chris@3: * GNU General Public License for more details. chris@3: * chris@3: * You should have received a copy of the GNU General Public License chris@3: * along with this program. If not, see . chris@3: */ chris@3: chris@3: package org.sonews.storage; chris@3: chris@3: import java.util.ArrayList; chris@3: import java.util.Collections; chris@3: import java.util.List; chris@3: import org.sonews.util.Pair; chris@3: chris@3: /** chris@3: * An aggregated group is a group consisting of several "real" group. chris@3: * @author Christian Lins chris@3: * @since sonews/1.0 chris@3: */ chris@3: class AggregatedGroup extends Channel chris@3: { chris@3: chris@3: static class GroupElement chris@3: { chris@3: private Group group; chris@3: private long offsetStart, offsetEnd; chris@3: chris@3: public GroupElement(Group group, long offsetStart, long offsetEnd) chris@3: { chris@3: this.group = group; chris@3: this.offsetEnd = offsetEnd; chris@3: this.offsetStart = offsetStart; chris@3: } chris@3: } chris@3: chris@3: public static List getAll() chris@3: { chris@3: List all = new ArrayList(); chris@3: all.add(getByName("agg.test")); chris@3: return all; chris@3: } chris@3: chris@3: public static AggregatedGroup getByName(String name) chris@3: { chris@3: if("agg.test".equals(name)) chris@3: { chris@3: AggregatedGroup agroup = new AggregatedGroup(name); chris@3: agroup.addGroup(Group.getByName("agg.test0"), 0, 1000); chris@3: agroup.addGroup(Group.getByName("agg.test1"), 2000, 4000); chris@3: return agroup; chris@3: } chris@3: else chris@3: return null; chris@3: } chris@3: chris@3: private GroupElement[] groups = new GroupElement[2]; chris@3: private String name; chris@3: chris@3: public AggregatedGroup(String name) chris@3: { chris@3: this.name = name; chris@3: } chris@3: chris@3: private long aggIdxToIdx(long aggIdx) chris@3: throws StorageBackendException chris@3: { chris@3: assert groups != null && groups.length == 2; chris@3: assert groups[0] != null; chris@3: assert groups[1] != null; chris@3: chris@3: // Search in indices of group one chris@3: List idxs0 = groups[0].group.getArticleNumbers(); chris@3: Collections.sort(idxs0); chris@3: for(long idx : idxs0) chris@3: { chris@3: if(idx == aggIdx) chris@3: { chris@3: return idx; chris@3: } chris@3: } chris@3: chris@3: // Given aggIdx must be an index of group two chris@3: List idxs1 = groups[1].group.getArticleNumbers(); chris@3: return 0; chris@3: } chris@3: chris@3: private long idxToAggIdx(long idx) chris@3: { chris@3: return 0; chris@3: } chris@3: chris@3: /** chris@3: * Adds the given group to this aggregated set. chris@3: * @param group chris@3: * @param offsetStart Lower limit for the article ids range chris@3: */ chris@3: public void addGroup(Group group, long offsetStart, long offsetEnd) chris@3: { chris@3: this.groups[groups[0] == null ? 0 : 1] chris@3: = new GroupElement(group, offsetStart, offsetEnd); chris@3: } chris@3: chris@3: @Override chris@3: public Article getArticle(long idx) chris@3: throws StorageBackendException chris@3: { chris@3: Article article = null; chris@3: chris@3: for(GroupElement groupEl : groups) chris@3: { chris@3: if(groupEl.offsetStart <= idx && groupEl.offsetEnd >= idx) chris@3: { chris@3: article = groupEl.group.getArticle(idx - groupEl.offsetStart); chris@3: break; chris@3: } chris@3: } chris@3: chris@3: return article; chris@3: } chris@3: chris@3: @Override chris@3: public List> getArticleHeads( chris@3: final long first, final long last) chris@3: throws StorageBackendException chris@3: { chris@3: List> heads = new ArrayList>(); chris@3: chris@3: for(GroupElement groupEl : groups) chris@3: { chris@3: List> partHeads = new ArrayList>(); chris@3: if(groupEl.offsetStart <= first && groupEl.offsetEnd >= first) chris@3: { chris@3: long end = Math.min(groupEl.offsetEnd, last); chris@3: partHeads = groupEl.group.getArticleHeads chris@3: (first - groupEl.offsetStart, end - groupEl.offsetStart); chris@3: } chris@3: else if(groupEl.offsetStart <= last && groupEl.offsetEnd >= last) chris@3: { chris@3: long start = Math.max(groupEl.offsetStart, first); chris@3: partHeads = groupEl.group.getArticleHeads chris@3: (start - groupEl.offsetStart, last - groupEl.offsetStart); chris@3: } chris@3: chris@3: for(Pair partHead : partHeads) chris@3: { chris@3: heads.add(new Pair( chris@3: partHead.getA() + groupEl.offsetStart, partHead.getB())); chris@3: } chris@3: } chris@3: chris@3: return heads; chris@3: } chris@3: chris@3: @Override chris@3: public List getArticleNumbers() chris@3: throws StorageBackendException chris@3: { chris@3: List articleNumbers = new ArrayList(); chris@3: chris@3: for(GroupElement groupEl : groups) chris@3: { chris@3: List partNums = groupEl.group.getArticleNumbers(); chris@3: for(Long partNum : partNums) chris@3: { chris@3: articleNumbers.add(partNum + groupEl.offsetStart); chris@3: } chris@3: } chris@3: chris@3: return articleNumbers; chris@3: } chris@3: chris@3: @Override chris@3: public long getIndexOf(Article art) chris@3: throws StorageBackendException chris@3: { chris@3: for(GroupElement groupEl : groups) chris@3: { chris@3: long idx = groupEl.group.getIndexOf(art); chris@3: if(idx > 0) chris@3: { chris@3: return idx; chris@3: } chris@3: } chris@3: return -1; chris@3: } chris@3: chris@3: public long getInternalID() chris@3: { chris@3: return -1; chris@3: } chris@3: chris@3: @Override chris@3: public String getName() chris@3: { chris@3: return this.name; chris@3: } chris@3: chris@3: @Override chris@3: public long getFirstArticleNumber() chris@3: throws StorageBackendException chris@3: { chris@3: long first = Long.MAX_VALUE; chris@3: chris@3: for(GroupElement groupEl : groups) chris@3: { chris@3: first = Math.min(first, groupEl.group.getFirstArticleNumber() + groupEl.offsetStart); chris@3: } chris@3: chris@3: return first; chris@3: } chris@3: chris@3: @Override chris@3: public long getLastArticleNumber() chris@3: throws StorageBackendException chris@3: { chris@3: long last = 1; chris@3: chris@3: for(GroupElement groupEl : groups) chris@3: { chris@3: last = Math.max(last, groupEl.group.getLastArticleNumber() + groupEl.offsetStart); chris@3: } chris@3: chris@3: return last + getPostingsCount(); // This is a hack chris@3: } chris@3: chris@3: public long getPostingsCount() chris@3: throws StorageBackendException chris@3: { chris@3: long postings = 0; chris@3: chris@3: for(GroupElement groupEl : groups) chris@3: { chris@3: postings += groupEl.group.getPostingsCount(); chris@3: } chris@3: chris@3: return postings; chris@3: } chris@3: chris@3: public boolean isDeleted() chris@3: { chris@3: return false; chris@3: } chris@3: chris@3: public boolean isWriteable() chris@3: { chris@3: return false; chris@3: } chris@3: chris@3: }