org/sonews/storage/AggregatedGroup.java
author cli
Mon, 17 Aug 2009 11:00:51 +0200
changeset 11 961a8a3acb9a
parent 3 2fdc9cc89502
permissions -rw-r--r--
Fix wrong handling of byte values > 127 in ArticleInputStream.
chris@3
     1
/*
chris@3
     2
 *   SONEWS News Server
chris@3
     3
 *   see AUTHORS for the list of contributors
chris@3
     4
 *
chris@3
     5
 *   This program is free software: you can redistribute it and/or modify
chris@3
     6
 *   it under the terms of the GNU General Public License as published by
chris@3
     7
 *   the Free Software Foundation, either version 3 of the License, or
chris@3
     8
 *   (at your option) any later version.
chris@3
     9
 *
chris@3
    10
 *   This program is distributed in the hope that it will be useful,
chris@3
    11
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
chris@3
    12
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
chris@3
    13
 *   GNU General Public License for more details.
chris@3
    14
 *
chris@3
    15
 *   You should have received a copy of the GNU General Public License
chris@3
    16
 *   along with this program.  If not, see <http://www.gnu.org/licenses/>.
chris@3
    17
 */
chris@3
    18
chris@3
    19
package org.sonews.storage;
chris@3
    20
chris@3
    21
import java.util.ArrayList;
chris@3
    22
import java.util.Collections;
chris@3
    23
import java.util.List;
chris@3
    24
import org.sonews.util.Pair;
chris@3
    25
chris@3
    26
/**
chris@3
    27
 * An aggregated group is a group consisting of several "real" group.
chris@3
    28
 * @author Christian Lins
chris@3
    29
 * @since sonews/1.0
chris@3
    30
 */
chris@3
    31
class AggregatedGroup extends Channel
chris@3
    32
{
chris@3
    33
chris@3
    34
  static class GroupElement
chris@3
    35
  {
chris@3
    36
    private Group group;
chris@3
    37
    private long  offsetStart, offsetEnd;
chris@3
    38
    
chris@3
    39
    public GroupElement(Group group, long offsetStart, long offsetEnd)
chris@3
    40
    {
chris@3
    41
      this.group       = group;
chris@3
    42
      this.offsetEnd   = offsetEnd;
chris@3
    43
      this.offsetStart = offsetStart;
chris@3
    44
    }
chris@3
    45
  }
chris@3
    46
chris@3
    47
  public static List<Channel> getAll()
chris@3
    48
  {
chris@3
    49
    List<Channel> all = new ArrayList<Channel>();
chris@3
    50
    all.add(getByName("agg.test"));
chris@3
    51
    return all;
chris@3
    52
  }
chris@3
    53
chris@3
    54
  public static AggregatedGroup getByName(String name)
chris@3
    55
  {
chris@3
    56
    if("agg.test".equals(name))
chris@3
    57
    {
chris@3
    58
      AggregatedGroup agroup = new AggregatedGroup(name);
chris@3
    59
      agroup.addGroup(Group.getByName("agg.test0"), 0, 1000);
chris@3
    60
      agroup.addGroup(Group.getByName("agg.test1"), 2000, 4000);
chris@3
    61
      return agroup;
chris@3
    62
    }
chris@3
    63
    else
chris@3
    64
      return null;
chris@3
    65
  }
chris@3
    66
chris@3
    67
  private GroupElement[] groups = new GroupElement[2];
chris@3
    68
  private String         name;
chris@3
    69
chris@3
    70
  public AggregatedGroup(String name)
chris@3
    71
  {
chris@3
    72
    this.name = name;
chris@3
    73
  }
chris@3
    74
chris@3
    75
  private long aggIdxToIdx(long aggIdx)
chris@3
    76
    throws StorageBackendException
chris@3
    77
  {
chris@3
    78
    assert groups != null && groups.length == 2;
chris@3
    79
    assert groups[0] != null;
chris@3
    80
    assert groups[1] != null;
chris@3
    81
chris@3
    82
    // Search in indices of group one
chris@3
    83
    List<Long> idxs0 = groups[0].group.getArticleNumbers();
chris@3
    84
    Collections.sort(idxs0);
chris@3
    85
    for(long idx : idxs0)
chris@3
    86
    {
chris@3
    87
      if(idx == aggIdx)
chris@3
    88
      {
chris@3
    89
        return idx;
chris@3
    90
      }
chris@3
    91
    }
chris@3
    92
chris@3
    93
    // Given aggIdx must be an index of group two
chris@3
    94
    List<Long> idxs1 = groups[1].group.getArticleNumbers();
chris@3
    95
    return 0;
chris@3
    96
  }
chris@3
    97
  
chris@3
    98
  private long idxToAggIdx(long idx)
chris@3
    99
  {
chris@3
   100
    return 0;
chris@3
   101
  }
chris@3
   102
chris@3
   103
  /**
chris@3
   104
   * Adds the given group to this aggregated set.
chris@3
   105
   * @param group
chris@3
   106
   * @param offsetStart Lower limit for the article ids range
chris@3
   107
   */
chris@3
   108
  public void addGroup(Group group, long offsetStart, long offsetEnd)
chris@3
   109
  {
chris@3
   110
    this.groups[groups[0] == null ? 0 : 1]
chris@3
   111
      = new GroupElement(group, offsetStart, offsetEnd);
chris@3
   112
  }
chris@3
   113
chris@3
   114
  @Override
chris@3
   115
  public Article getArticle(long idx)
chris@3
   116
    throws StorageBackendException
chris@3
   117
  {
chris@3
   118
    Article article = null;
chris@3
   119
chris@3
   120
    for(GroupElement groupEl : groups)
chris@3
   121
    {
chris@3
   122
      if(groupEl.offsetStart <= idx && groupEl.offsetEnd >= idx)
chris@3
   123
      {
chris@3
   124
        article = groupEl.group.getArticle(idx - groupEl.offsetStart);
chris@3
   125
        break;
chris@3
   126
      }
chris@3
   127
    }
chris@3
   128
chris@3
   129
    return article;
chris@3
   130
  }
chris@3
   131
chris@3
   132
  @Override
chris@3
   133
  public List<Pair<Long, ArticleHead>> getArticleHeads(
chris@3
   134
    final long first, final long last)
chris@3
   135
    throws StorageBackendException
chris@3
   136
  {
chris@3
   137
    List<Pair<Long, ArticleHead>> heads = new ArrayList<Pair<Long, ArticleHead>>();
chris@3
   138
    
chris@3
   139
    for(GroupElement groupEl : groups)
chris@3
   140
    {
chris@3
   141
      List<Pair<Long, ArticleHead>> partHeads = new ArrayList<Pair<Long, ArticleHead>>();
chris@3
   142
      if(groupEl.offsetStart <= first && groupEl.offsetEnd >= first)
chris@3
   143
      {
chris@3
   144
        long end = Math.min(groupEl.offsetEnd, last);
chris@3
   145
        partHeads = groupEl.group.getArticleHeads
chris@3
   146
          (first - groupEl.offsetStart, end - groupEl.offsetStart);
chris@3
   147
      }
chris@3
   148
      else if(groupEl.offsetStart <= last && groupEl.offsetEnd >= last)
chris@3
   149
      {
chris@3
   150
        long start = Math.max(groupEl.offsetStart, first);
chris@3
   151
        partHeads = groupEl.group.getArticleHeads
chris@3
   152
          (start - groupEl.offsetStart, last - groupEl.offsetStart);
chris@3
   153
      }
chris@3
   154
chris@3
   155
      for(Pair<Long, ArticleHead> partHead : partHeads)
chris@3
   156
      {
chris@3
   157
        heads.add(new Pair<Long, ArticleHead>(
chris@3
   158
          partHead.getA() + groupEl.offsetStart, partHead.getB()));
chris@3
   159
      }
chris@3
   160
    }
chris@3
   161
chris@3
   162
    return heads;
chris@3
   163
  }
chris@3
   164
chris@3
   165
  @Override
chris@3
   166
  public List<Long> getArticleNumbers()
chris@3
   167
    throws StorageBackendException
chris@3
   168
  {
chris@3
   169
    List<Long> articleNumbers = new ArrayList<Long>();
chris@3
   170
    
chris@3
   171
    for(GroupElement groupEl : groups)
chris@3
   172
    {
chris@3
   173
      List<Long> partNums = groupEl.group.getArticleNumbers();
chris@3
   174
      for(Long partNum : partNums)
chris@3
   175
      {
chris@3
   176
        articleNumbers.add(partNum + groupEl.offsetStart);
chris@3
   177
      }
chris@3
   178
    }
chris@3
   179
chris@3
   180
    return articleNumbers;
chris@3
   181
  }
chris@3
   182
chris@3
   183
  @Override
chris@3
   184
  public long getIndexOf(Article art)
chris@3
   185
    throws StorageBackendException
chris@3
   186
  {
chris@3
   187
    for(GroupElement groupEl : groups)
chris@3
   188
    {
chris@3
   189
      long idx = groupEl.group.getIndexOf(art);
chris@3
   190
      if(idx > 0)
chris@3
   191
      {
chris@3
   192
        return idx;
chris@3
   193
      }
chris@3
   194
    }
chris@3
   195
    return -1;
chris@3
   196
  }
chris@3
   197
chris@3
   198
  public long getInternalID()
chris@3
   199
  {
chris@3
   200
    return -1;
chris@3
   201
  }
chris@3
   202
chris@3
   203
  @Override
chris@3
   204
  public String getName()
chris@3
   205
  {
chris@3
   206
    return this.name;
chris@3
   207
  }
chris@3
   208
chris@3
   209
  @Override
chris@3
   210
  public long getFirstArticleNumber()
chris@3
   211
    throws StorageBackendException
chris@3
   212
  {
chris@3
   213
    long first = Long.MAX_VALUE;
chris@3
   214
chris@3
   215
    for(GroupElement groupEl : groups)
chris@3
   216
    {
chris@3
   217
      first = Math.min(first, groupEl.group.getFirstArticleNumber() + groupEl.offsetStart);
chris@3
   218
    }
chris@3
   219
chris@3
   220
    return first;
chris@3
   221
  }
chris@3
   222
chris@3
   223
  @Override
chris@3
   224
  public long getLastArticleNumber()
chris@3
   225
    throws StorageBackendException
chris@3
   226
  {
chris@3
   227
    long last = 1;
chris@3
   228
chris@3
   229
    for(GroupElement groupEl : groups)
chris@3
   230
    {
chris@3
   231
      last = Math.max(last, groupEl.group.getLastArticleNumber() + groupEl.offsetStart);
chris@3
   232
    }
chris@3
   233
chris@3
   234
    return last + getPostingsCount(); // This is a hack
chris@3
   235
  }
chris@3
   236
  
chris@3
   237
  public long getPostingsCount()
chris@3
   238
    throws StorageBackendException
chris@3
   239
  {
chris@3
   240
    long postings = 0;
chris@3
   241
chris@3
   242
    for(GroupElement groupEl : groups)
chris@3
   243
    {
chris@3
   244
      postings += groupEl.group.getPostingsCount();
chris@3
   245
    }
chris@3
   246
chris@3
   247
    return postings;
chris@3
   248
  }
chris@3
   249
chris@3
   250
  public boolean isDeleted()
chris@3
   251
  {
chris@3
   252
    return false;
chris@3
   253
  }
chris@3
   254
chris@3
   255
  public boolean isWriteable()
chris@3
   256
  {
chris@3
   257
    return false;
chris@3
   258
  }
chris@3
   259
chris@3
   260
}