segment.java

来自「数据仓库展示程序」· Java 代码 · 共 438 行 · 第 1/2 页

JAVA
438
字号
     * when it finishes loading.
     **/
    boolean wouldContain(Object[] keys) {
        Util.assertTrue(keys.length == axes.length);
        for (int i = 0; i < keys.length; i++) {
            Object key = keys[i];
            if (!axes[i].contains(key)) {
                return false;
            }
        }
        return true;
    }

    /**
     * Reads a segment of <code>measure</code>, where <code>columns</code> are
     * constrained to <code>values</code>.  Each entry in <code>values</code>
     * can be null, meaning don't constrain, or can have several values. For
     * example, <code>getSegment({Unit_sales}, {Region, State, Year}, {"West"},
     * {"CA", "OR", "WA"}, null})</code> returns sales in states CA, OR and WA
     * in the Western region, for all years.
     *
     * @pre segments[i].aggregation == aggregation
     **/
    static void load(final Segment[] segments,
                     final BitKey bitKey,
                     final boolean isDistinct,
                     final Collection pinnedSegments,
                     final Aggregation.Axis[] axes) {
        String sql = AggregationManager.instance().generateSQL(segments,
                                                               bitKey,
                                                               isDistinct);
        Segment segment0 = segments[0];
        RolapStar star = segment0.aggregation.getStar();
        RolapStar.Column[] columns = segment0.aggregation.getColumns();
        int arity = columns.length;

        // execute
        ResultSet resultSet = null;
        final int measureCount = segments.length;
        java.sql.Connection jdbcConnection = star.getJdbcConnection();
        try {
            resultSet = RolapUtil.executeQuery(
                    jdbcConnection, sql, "Segment.load");
            List rows = new ArrayList();
            while (resultSet.next()) {
                Object[] row = new Object[arity + measureCount];
                // get the columns
                int k = 1;
                for (int i = 0; i < arity; i++) {
                    Object o = resultSet.getObject(k++);
                    if (o == null) {
                        o = RolapUtil.sqlNullValue;
                    }
                    Integer offsetInteger = axes[i].getOffset(o);
                    if (offsetInteger == null) {
                        axes[i].addNextOffset(o);
                    }
                    row[i] = o;
                }
                // get the measure
                for (int i = 0; i < measureCount; i++) {
                    Object o = resultSet.getObject(k++);
                    if (o == null) {
                        o = Util.nullValue; // convert to placeholder
                    }
                    row[arity + i] = o;
                }
                rows.add(row);
            }

            // figure out size of dense array, and allocate it (todo: use
            // sparse array sometimes)
            boolean sparse = false;
            int n = 1;
            for (int i = 0; i < arity; i++) {
                Aggregation.Axis axis = axes[i];
                int size = axis.loadKeys();

                int previous = n;
                n *= size;
                if ((n < previous) || (n < size)) {
                    // Overflow has occurred.
                    n = Integer.MAX_VALUE;
                    sparse = true;
                }
            }
            SegmentDataset[] datas = new SegmentDataset[segments.length];
            sparse = sparse || useSparse((double) n, (double) rows.size());
            for (int i = 0; i < segments.length; i++) {
                datas[i] = sparse
                    ? (SegmentDataset) new SparseSegmentDataset(segments[i])
                    : new DenseSegmentDataset(segments[i], new Object[n]);
            }
            // now convert the rows into a sparse array
            int[] pos = new int[arity];
            for (int i = 0, count = rows.size(); i < count; i++) {
                Object[] row = (Object[]) rows.get(i);
                int k = 0;
                for (int j = 0; j < arity; j++) {
                    k *= axes[j].getKeys().length;
                    Object o = row[j];
                    Aggregation.Axis axis = axes[j];
                    Integer offsetInteger = axis.getOffset(o);
                    int offset = offsetInteger.intValue();
                    pos[j] = offset;
                    k += offset;
                }
                CellKey key = null;
                if (sparse) {
                    key = new CellKey((int[]) pos.clone());
                }
                for (int j = 0; j < segments.length; j++) {
                    final Object o = row[arity + j];
                    if (sparse) {
                        ((SparseSegmentDataset) datas[j]).put(key, o);
                    } else {
                        ((DenseSegmentDataset) datas[j]).set(k, o);
                    }
                }
            }

            for (int i = 0; i < segments.length; i++) {
                segments[i].setData(datas[i], pinnedSegments);
            }

        } catch (SQLException e) {
            throw Util.newInternal(e,
                    "Error while loading segment; sql=[" + sql + "]");
        } finally {
            try {
                if (resultSet != null) {
                    resultSet.getStatement().close();
                    resultSet.close();
                }
            } catch (SQLException e) {
                // ignore
            }
            try {
                jdbcConnection.close();
            } catch (SQLException e) {
                //ignore
            }
            // Any segments which are still loading have failed.
            for (int i = 0; i < segments.length; i++) {
                segments[i].setFailed();
            }
        }
    }

    /**
     * Decides whether to use a sparse representation for this segment, using
     * the formula described
     * {@link MondrianProperties#SparseSegmentCountThreshold here}.
     *
     * @param possibleCount Number of values in the space.
     * @param actualCount Actual number of values.
     * @return Whether to use a sparse representation.
     */
    private static boolean useSparse(
            final double possibleCount,
            final double actualCount) {
        final MondrianProperties properties = MondrianProperties.instance();
        double densityThreshold = properties.SparseSegmentDensityThreshold.get();
        if (densityThreshold < 0) {
            densityThreshold = 0;
        }
        if (densityThreshold > 1) {
            densityThreshold = 1;
        }
        int countThreshold = properties.SparseSegmentCountThreshold.get();
        if (countThreshold < 0) {
            countThreshold = 0;
        }
        boolean sparse =
            (possibleCount - countThreshold) * densityThreshold > actualCount;
        if (possibleCount < countThreshold) {
            assert !sparse :
                    "Should never use sparse if count is less " +
                    "than threshold, possibleCount=" + possibleCount +
                    ", actualCount=" + actualCount +
                    ", countThreshold=" + countThreshold +
                    ", densityThreshold=" + densityThreshold;
        }
        if (possibleCount == actualCount) {
            assert !sparse :
                    "Should never use sparse if result is 100% dense: " +
                    "possibleCount=" + possibleCount +
                    ", actualCount=" + actualCount +
                    ", countThreshold=" + countThreshold +
                    ", densityThreshold=" + densityThreshold;
        }
        return sparse;
    }

    /**
     * Blocks until this segment has finished loading; if this segment has
     * already loaded, returns immediately.
     */
    public synchronized void waitUntilLoaded() {
        if (!isReady()) {
            try {
                wait();
            } catch (InterruptedException e) {
            }
            switch (state) {
            case State.Ready:
                return; // excellent!
            case State.Failed:
                throw Util.newError("Pending segment failed to load: "
                    + toString());
            default:
                throw State.instance.badValue(state);
            }
        }
    }
}

// End Segment.java

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?