예제 #1
0
 public List<SegmentHeader> getSegmentHeaders() {
   // Special case 0 and 1 workers, for which the 'union' operation
   // is trivial.
   switch (workers.size()) {
     case 0:
       return Collections.emptyList();
     case 1:
       return workers.get(0).getSegmentHeaders();
     default:
       final List<SegmentHeader> list = new ArrayList<SegmentHeader>();
       final Set<SegmentHeader> set = new HashSet<SegmentHeader>();
       for (SegmentCacheWorker worker : workers) {
         for (SegmentHeader header : worker.getSegmentHeaders()) {
           if (set.add(header)) {
             list.add(header);
           }
         }
       }
       return list;
   }
 }
 /**
  * Returns the hierarchies on a non-filter axis.
  *
  * @return List of hierarchies, never null
  */
 private List<Hierarchy> getHierarchiesNonFilter() {
   final Exp exp = queryAxis.getSet();
   if (exp == null) {
     return Collections.emptyList();
   }
   Type type = exp.getType();
   if (type instanceof SetType) {
     type = ((SetType) type).getElementType();
   }
   final MondrianOlap4jConnection olap4jConnection =
       cellSetMetaData.olap4jStatement.olap4jConnection;
   if (type instanceof TupleType) {
     final TupleType tupleType = (TupleType) type;
     List<Hierarchy> hierarchyList = new ArrayList<Hierarchy>();
     for (Type elementType : tupleType.elementTypes) {
       hierarchyList.add(olap4jConnection.toOlap4j(elementType.getHierarchy()));
     }
     return hierarchyList;
   } else {
     return Collections.singletonList((Hierarchy) olap4jConnection.toOlap4j(type.getHierarchy()));
   }
 }
예제 #3
0
    public FlushResult call() throws Exception {
      // For each measure and each star, ask the index
      // which headers intersect.
      final List<SegmentHeader> headers = new ArrayList<SegmentHeader>();
      final List<Member> measures = CacheControlImpl.findMeasures(region);
      final SegmentColumn[] flushRegion = CacheControlImpl.findAxisValues(region);
      final List<RolapStar> starList = CacheControlImpl.getStarList(region);

      for (Member member : measures) {
        if (!(member instanceof RolapStoredMeasure)) {
          continue;
        }
        final RolapStoredMeasure storedMeasure = (RolapStoredMeasure) member;
        final RolapStar star = storedMeasure.getCube().getStar();
        final SegmentCacheIndex index = cacheMgr.indexRegistry.getIndex(star);
        headers.addAll(
            index.intersectRegion(
                member.getDimension().getSchema().getName(),
                ((RolapSchema) member.getDimension().getSchema()).getChecksum(),
                storedMeasure.getCube().getName(),
                storedMeasure.getName(),
                storedMeasure.getCube().getStar().getFactTable().getAlias(),
                flushRegion));
      }

      // If flushRegion is empty, this means we must clear all
      // segments for the region's measures.
      if (flushRegion.length == 0) {
        for (final SegmentHeader header : headers) {
          for (RolapStar star : starList) {
            cacheMgr.indexRegistry.getIndex(star).remove(header);
          }

          // Remove the segment from external caches. Use an
          // executor, because it may take some time. We discard
          // the future, because we don't care too much if it fails.
          cacheControlImpl.trace(
              "discard segment - it cannot be constrained and maintain consistency:\n"
                  + header.getDescription());

          final Future<?> task =
              cacheMgr.cacheExecutor.submit(
                  new Runnable() {
                    public void run() {
                      try {
                        // Note that the SegmentCache API doesn't
                        // require us to verify that the segment
                        // exists (by calling "contains") before we
                        // call "remove".
                        cacheMgr.compositeCache.remove(header);
                      } catch (Throwable e) {
                        LOGGER.warn("remove header failed: " + header, e);
                      }
                    }
                  });
          Util.safeGet(task, "SegmentCacheManager.flush");
        }
        return new FlushResult(Collections.<Callable<Boolean>>emptyList());
      }

      // Now we know which headers intersect. For each of them,
      // we append an excluded region.
      //
      // TODO: Optimize the logic here. If a segment is mostly
      // empty, we should trash it completely.
      final List<Callable<Boolean>> callableList = new ArrayList<Callable<Boolean>>();
      for (final SegmentHeader header : headers) {
        if (!header.canConstrain(flushRegion)) {
          // We have to delete that segment altogether.
          cacheControlImpl.trace(
              "discard segment - it cannot be constrained and maintain consistency:\n"
                  + header.getDescription());
          for (RolapStar star : starList) {
            cacheMgr.indexRegistry.getIndex(star).remove(header);
          }
          continue;
        }
        final SegmentHeader newHeader = header.constrain(flushRegion);
        for (final SegmentCacheWorker worker : cacheMgr.segmentCacheWorkers) {
          callableList.add(
              new Callable<Boolean>() {
                public Boolean call() throws Exception {
                  boolean existed;
                  if (worker.supportsRichIndex()) {
                    final SegmentBody sb = worker.get(header);
                    existed = worker.remove(header);
                    if (sb != null) {
                      worker.put(newHeader, sb);
                    }
                  } else {
                    // The cache doesn't support rich index. We
                    // have to clear the segment entirely.
                    existed = worker.remove(header);
                  }
                  return existed;
                }
              });
        }
        for (RolapStar star : starList) {
          SegmentCacheIndex index = cacheMgr.indexRegistry.getIndex(star);
          index.remove(header);
          index.add(newHeader, false, null);
        }
      }

      // Done
      return new FlushResult(callableList);
    }