Search in sources :

Example 6 with Statistics

use of org.opensolaris.opengrok.web.Statistics in project OpenGrok by OpenGrok.

the class AuthorizationFramework method checkAll.

/**
 * Checks if the request should have an access to a resource. This method is
 * thread safe with respect to the concurrent reload of plugins.
 *
 * <p>
 * Internally performed with a predicate. Using cache in request
 * attributes.</p>
 *
 * <h3>Order of plugin invocation</h3>
 *
 * <p>
 * The order of plugin invocation is given by the stack and appropriate
 * actions are taken when traversing the stack with set of keywords,
 * such as:</p>
 *
 * <h4>required</h4>
 * Failure of such a plugin will ultimately lead to the authorization
 * framework returning failure but only after the remaining plugins have
 * been invoked.
 *
 * <h4>requisite</h4>
 * Like required, however, in the case that such a plugin returns a failure,
 * control is directly returned to the application. The return value is that
 * associated with the first required or requisite plugin to fail.
 *
 * <h4>sufficient</h4>
 * If such a plugin succeeds and no prior required plugin has failed the
 * authorization framework returns success to the application immediately
 * without calling any further plugins in the stack. A failure of a
 * sufficient plugin is ignored and processing of the plugin list continues
 * unaffected.
 *
 * <p>
 * Loaded plugins which do not occur in the configuration are appended to
 * the list with "required" keyword. As of the nature of the class discovery
 * this means that the order of invocation of these plugins is rather
 * random.</p>
 *
 * <p>
 * Plugins in the configuration which have not been loaded are skipped.</p>
 *
 * @param request request object
 * @param cache cache
 * @param name name
 * @param predicate predicate
 * @return true if yes
 *
 * @see RuntimeEnvironment#getPluginStack()
 */
@SuppressWarnings("unchecked")
private boolean checkAll(HttpServletRequest request, String cache, Nameable entity, AuthorizationEntity.PluginDecisionPredicate pluginPredicate, AuthorizationEntity.PluginSkippingPredicate skippingPredicate) {
    if (stack == null) {
        return true;
    }
    Statistics stats = RuntimeEnvironment.getInstance().getStatistics();
    Boolean val;
    Map<String, Boolean> m = (Map<String, Boolean>) request.getAttribute(cache);
    if (m == null) {
        m = new TreeMap<>();
    } else if ((val = m.get(entity.getName())) != null) {
        // cache hit
        stats.addRequest("authorization_cache_hits");
        return val;
    }
    stats.addRequest("authorization_cache_misses");
    long time = 0;
    boolean overallDecision = false;
    lock.readLock().lock();
    try {
        // Make sure there is a HTTP session that corresponds to current plugin version.
        HttpSession session;
        if (((session = request.getSession(false)) != null) && isSessionInvalid(session)) {
            session.invalidate();
            stats.addRequest("authorization_sessions_invalidated");
        }
        request.getSession().setAttribute(SESSION_VERSION, getPluginVersion());
        time = System.currentTimeMillis();
        overallDecision = performCheck(entity, pluginPredicate, skippingPredicate);
    } finally {
        lock.readLock().unlock();
    }
    if (time > 0) {
        time = System.currentTimeMillis() - time;
        stats.addRequestTime("authorization", time);
        stats.addRequestTime(String.format("authorization_%s", overallDecision ? "positive" : "negative"), time);
        stats.addRequestTime(String.format("authorization_%s_of_%s", overallDecision ? "positive" : "negative", entity.getName()), time);
        stats.addRequestTime(String.format("authorization_of_%s", entity.getName()), time);
    }
    m.put(entity.getName(), overallDecision);
    request.setAttribute(cache, m);
    return overallDecision;
}
Also used : HttpSession(javax.servlet.http.HttpSession) Statistics(org.opensolaris.opengrok.web.Statistics) Map(java.util.Map) TreeMap(java.util.TreeMap)

Example 7 with Statistics

use of org.opensolaris.opengrok.web.Statistics in project OpenGrok by OpenGrok.

the class AuthorizationStack method processStack.

/**
 * Process the stack.
 *
 * @param entity the given entity
 * @param pluginPredicate predicate returning true or false for the given
 * entity which determines if the authorization for such entity is
 * successful or failed for particular request and plugin
 * @param skippingPredicate predicate returning true if this authorization
 * entity should be omitted from the authorization process
 * @return true if entity is allowed; false otherwise
 */
protected boolean processStack(Nameable entity, PluginDecisionPredicate pluginPredicate, PluginSkippingPredicate skippingPredicate) {
    Statistics stats = RuntimeEnvironment.getInstance().getStatistics();
    long time = System.currentTimeMillis();
    boolean overallDecision = true;
    for (AuthorizationEntity authEntity : getStack()) {
        if (skippingPredicate.shouldSkip(authEntity)) {
            LOGGER.log(Level.FINEST, "AuthEntity \"{0}\" [{1}] skipping testing of name \"{2}\"", new Object[] { authEntity.getName(), authEntity.getFlag(), entity.getName() });
            continue;
        }
        // run the plugin's test method
        try {
            LOGGER.log(Level.FINEST, "AuthEntity \"{0}\" [{1}] testing a name \"{2}\"", new Object[] { authEntity.getName(), authEntity.getFlag(), entity.getName() });
            boolean pluginDecision = authEntity.isAllowed(entity, pluginPredicate, skippingPredicate);
            LOGGER.log(Level.FINEST, "AuthEntity \"{0}\" [{1}] testing a name \"{2}\" => {3}", new Object[] { authEntity.getName(), authEntity.getFlag(), entity.getName(), pluginDecision ? "true" : "false" });
            if (!pluginDecision && authEntity.isRequired()) {
                // required sets a failure but still invokes all other plugins
                overallDecision = false;
                continue;
            } else if (!pluginDecision && authEntity.isRequisite()) {
                // requisite sets a failure and immediately returns the failure
                overallDecision = false;
                break;
            } else if (overallDecision && pluginDecision && authEntity.isSufficient()) {
                // sufficient immediately returns the success
                overallDecision = true;
                break;
            }
        } catch (Throwable ex) {
            LOGGER.log(Level.WARNING, String.format("AuthEntity \"%s\" has failed the testing of \"%s\" with an exception.", authEntity.getName(), entity.getName()), ex);
            LOGGER.log(Level.FINEST, "AuthEntity \"{0}\" [{1}] testing a name \"{2}\" => {3}", new Object[] { authEntity.getName(), authEntity.getFlag(), entity.getName(), "false (failed)" });
            // set the return value to false for this faulty plugin
            if (!authEntity.isSufficient()) {
                overallDecision = false;
            }
            // requisite plugin may immediately return the failure
            if (authEntity.isRequisite()) {
                break;
            }
        }
    }
    time = System.currentTimeMillis() - time;
    stats.addRequestTime(String.format("authorization_in_stack_%s_%s", getName(), overallDecision ? "positive" : "negative"), time);
    stats.addRequestTime(String.format("authorization_in_stack_%s_%s_of_%s", getName(), overallDecision ? "positive" : "negative", entity.getName()), time);
    stats.addRequestTime(String.format("authorization_in_stack_%s_of_%s", getName(), entity.getName()), time);
    return overallDecision;
}
Also used : Statistics(org.opensolaris.opengrok.web.Statistics)

Example 8 with Statistics

use of org.opensolaris.opengrok.web.Statistics in project OpenGrok by OpenGrok.

the class AuthorizationFrameworkReloadTest method testReloadCycle.

/**
 * Sort of a stress test - call isAllowed() and reload() in parallel.
 * This might uncover any snags with locking within AuthorizationFramework.
 */
@Test
public void testReloadCycle() {
    Statistics stats = RuntimeEnvironment.getInstance().getStatistics();
    Long reloads;
    String projectName = "project" + Math.random();
    // Create authorization stack for single project.
    AuthorizationStack stack = new AuthorizationStack(AuthControlFlag.REQUIRED, "stack for project " + projectName);
    assertNotNull(stack);
    stack.add(new AuthorizationPlugin(AuthControlFlag.REQUIRED, "opengrok.auth.plugin.FalsePlugin"));
    stack.setForProjects(projectName);
    AuthorizationFramework framework = new AuthorizationFramework(pluginDirectory.getPath(), stack);
    // to avoid noise when loading classes of other tests
    framework.setLoadClasses(false);
    framework.reload();
    // Perform simple sanity check before long run is entered. If this fails,
    // it will be waste of time to continue with the test.
    Project p = new Project(projectName);
    DummyHttpServletRequest req = new DummyHttpServletRequest();
    assertFalse(framework.isAllowed(req, p));
    // Create a thread that does reload() every now and then.
    runThread = true;
    final int maxReloadSleep = 10;
    Thread t = new Thread(new Runnable() {

        @Override
        public void run() {
            while (runThread) {
                framework.reload();
                try {
                    Thread.sleep((long) (Math.random() % maxReloadSleep) + 1);
                } catch (InterruptedException ex) {
                }
            }
        }
    });
    t.start();
    reloads = stats.getRequest("authorization_stack_reload");
    assertNotNull(reloads);
    // Process number or requests and check that framework decision is consistent.
    for (int i = 0; i < 1000; i++) {
        req = new DummyHttpServletRequest();
        assertFalse(framework.isAllowed(req, p));
        try {
            // Should run more frequently than the thread performing reload().
            Thread.sleep((long) (Math.random() % (maxReloadSleep / 3)) + 1);
        } catch (InterruptedException ex) {
        }
    }
    try {
        // Terminate the thread.
        runThread = false;
        t.join();
    } catch (InterruptedException ex) {
    }
    // Double check that at least one reload() was done.
    reloads = stats.getRequest("authorization_stack_reload") - reloads;
    System.out.println("number of reloads: " + reloads);
    assertTrue(reloads > 0);
}
Also used : DummyHttpServletRequest(org.opensolaris.opengrok.web.DummyHttpServletRequest) Statistics(org.opensolaris.opengrok.web.Statistics) Project(org.opensolaris.opengrok.configuration.Project) Test(org.junit.Test)

Example 9 with Statistics

use of org.opensolaris.opengrok.web.Statistics in project OpenGrok by OpenGrok.

the class RuntimeEnvironmentTest method testSaveEmptyStatistics.

@Test
public void testSaveEmptyStatistics() throws IOException {
    RuntimeEnvironment env = RuntimeEnvironment.getInstance();
    env.setStatistics(new Statistics());
    try (ByteArrayOutputStream out = new ByteArrayOutputStream()) {
        env.saveStatistics(out);
        Assert.assertEquals("{}", out.toString());
    }
}
Also used : ByteArrayOutputStream(java.io.ByteArrayOutputStream) Statistics(org.opensolaris.opengrok.web.Statistics) Test(org.junit.Test)

Example 10 with Statistics

use of org.opensolaris.opengrok.web.Statistics in project OpenGrok by OpenGrok.

the class RuntimeEnvironmentTest method testLoadStatistics.

@Test
public void testLoadStatistics() throws IOException, ParseException {
    RuntimeEnvironment env = RuntimeEnvironment.getInstance();
    String json = "{" + "\"requests_per_minute_max\":3," + "\"timing\":{" + "\"*\":2288," + "\"xref\":53," + "\"root\":2235" + "}," + "\"minutes\":756," + "\"timing_min\":{" + "\"*\":2," + "\"xref\":2," + "\"root\":2235" + "}," + "\"timing_avg\":{" + "\"*\":572.0," + "\"xref\":17.666666666666668," + "\"root\":2235.0" + "}," + "\"request_categories\":{" + "\"*\":4," + "\"xref\":3," + "\"root\":1" + "}," + "\"day_histogram\":[0,0,0,0,0,0,0,0,0,0,0,0,3,0,0,0,0,0,0,0,0,0,0,1]," + "\"requests\":4," + "\"requests_per_minute_min\":1," + "\"requests_per_minute\":3," + "\"requests_per_minute_avg\":0.005291005291005291," + "\"month_histogram\":[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,3,0]," + "\"timing_max\":{" + "\"*\":2235," + "\"xref\":48," + "\"root\":2235" + "}" + "}";
    try (InputStream in = new StringInputStream(json)) {
        env.loadStatistics(in);
    }
    Statistics stats = env.getStatistics();
    Assert.assertNotNull(stats);
    Assert.assertEquals(756, stats.getMinutes());
    Assert.assertEquals(4, stats.getRequests());
    Assert.assertEquals(3, stats.getRequestsPerMinute());
    Assert.assertEquals(1, stats.getRequestsPerMinuteMin());
    Assert.assertEquals(3, stats.getRequestsPerMinuteMax());
    Assert.assertEquals(0.005291005291005291, stats.getRequestsPerMinuteAvg(), 0.00005);
    Assert.assertArrayEquals(new long[] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 }, stats.getDayHistogram());
    Assert.assertArrayEquals(new long[] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 3, 0 }, stats.getMonthHistogram());
    Assert.assertEquals(createMap(new Object[][] { { "*", 4L }, { "xref", 3L }, { "root", 1L } }), stats.getRequestCategories());
    Assert.assertEquals(createMap(new Object[][] { { "*", 2288L }, { "xref", 53L }, { "root", 2235L } }), stats.getTiming());
    Assert.assertEquals(createMap(new Object[][] { { "*", 2L }, { "xref", 2L }, { "root", 2235L } }), stats.getTimingMin());
    Assert.assertEquals(createMap(new Object[][] { { "*", 2235L }, { "xref", 48L }, { "root", 2235L } }), stats.getTimingMax());
}
Also used : StringInputStream(org.apache.tools.ant.filters.StringInputStream) StringInputStream(org.apache.tools.ant.filters.StringInputStream) InputStream(java.io.InputStream) Statistics(org.opensolaris.opengrok.web.Statistics) Test(org.junit.Test)

Aggregations

Statistics (org.opensolaris.opengrok.web.Statistics)10 Test (org.junit.Test)7 ByteArrayOutputStream (java.io.ByteArrayOutputStream)2 InputStream (java.io.InputStream)2 HttpSession (javax.servlet.http.HttpSession)2 StringInputStream (org.apache.tools.ant.filters.StringInputStream)2 Project (org.opensolaris.opengrok.configuration.Project)2 DummyHttpServletRequest (org.opensolaris.opengrok.web.DummyHttpServletRequest)2 PrivilegedAction (java.security.PrivilegedAction)1 Map (java.util.Map)1 TreeMap (java.util.TreeMap)1 JSONObject (org.json.simple.JSONObject)1 JSONParser (org.json.simple.parser.JSONParser)1 ParseException (org.json.simple.parser.ParseException)1