Index: contrib/splitindex/src/java/org/apache/lucene/index/CronSplitRule.java =================================================================== --- contrib/splitindex/src/java/org/apache/lucene/index/CronSplitRule.java (revision 0) +++ contrib/splitindex/src/java/org/apache/lucene/index/CronSplitRule.java (revision 0) @@ -0,0 +1,195 @@ +package org.apache.lucene.index; + +/** + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import java.io.Serializable; +import java.util.Map; + +import org.quartz.CronTrigger; +import org.quartz.JobDataMap; +import org.quartz.JobDetail; +import org.quartz.Scheduler; +import org.quartz.SchedulerException; +import org.quartz.SchedulerFactory; +import org.quartz.impl.StdSchedulerFactory; + +/** + * The CronSplitRule causes a split to occur in the + * {@link SplitPolicy} to which it applies, at the points in time specified in + * the {@link CronTrigger} for which it is configured. + * + * @author Karthick Sankarachary + */ +public class CronSplitRule extends SplitRuleAdapter implements SplitRule { + private static final long serialVersionUID = 3536740140589552908L; + + // A configuration option that specifies the cron trigger expression. + public static final String CRON_SPLIT_RULE_TRIGGER = "cron.split.rule.trigger"; + + // A standard Quartz scheduler factory. + private static transient SchedulerFactory sf = new StdSchedulerFactory(); + + // A Quartz scheduler that knows how to run jobs whenever the {@link + // #cronTrigger} is satisfied. + private transient Scheduler scheduler; + + // A string representation of the {@link CronTrigger} object + private String cronTrigger; + + /** + * Construct a cron split rule using the default configuration options. + */ + public CronSplitRule() { + super(); + } + + /** + * Construct a cron split rule using the specified configuration options. + * + * @param options + * the configuration options + */ + public CronSplitRule(Map options) { + super(options); + } + + /** + * Default the cron trigger to activate at midnight every day + */ + @Override + public Map getOptionDefaults() { + Map options = super.getOptionDefaults(); + options.put(CronSplitRule.CRON_SPLIT_RULE_TRIGGER, "0 0 0/24 * * ?"); + return options; + } + + /** + * Ensure that the cron trigger is a non-empty string. + */ + @Override + public java.util.Map getOptionBounds() { + Map bounds = super.getOptionBounds(); + bounds.put(CronSplitRule.CRON_SPLIT_RULE_TRIGGER, new OptionBound() { + public boolean isInbounds(String key, Serializable value) { + return value instanceof String && ((String) value).length() > 0; + } + }); + return bounds; + } + + /** + * @return the scheduled job's name, which equates to the split policy's id + */ + private String getJobName() { + return getSplitPolicyId(); + } + + /** + * @return the name of the trigger, which equates to the split policy's id + */ + private String getTriggerName() { + return getSplitPolicyId(); + } + + /** + * @return the scheduled group's name, which equates to the split policy's id + */ + private String getJobGroup() { + return getSplitPolicyId(); + } + + /** + * When the split index is opened, schedule a stateful cron job that is + * triggered based on the {@link #cronTrigger} specified in the configuration + * options. + */ + public void onOpen(SplitPolicy splitPolicy) { + super.onOpen(splitPolicy); + try { + scheduler = sf.getScheduler(); + + // Create a job detail based on the {@link SplitCronJob} job. + JobDetail jobDetail = new JobDetail(getJobName(), getJobGroup(), + SplitCronJob.class); + JobDataMap context = jobDetail.getJobDataMap(); + context.put(SplitRule.SPLIT_RULE_SPLIT_POLICY_ID, getSplitPolicyId()); + context.put(SplitRule.SPLIT_RULE_LAST_SPLIT_TIME, 0L); + context.put(SplitRule.SPLIT_RULE_LAST_SEGMENT_NAME, null); + context.put(SplitRule.SPLIT_RULE_LAST_SEGMENT_SIZE, 0L); + context.putAll(this.context); + + cronTrigger = (String) this.splitPolicy + .getOption(CRON_SPLIT_RULE_TRIGGER); + + // Define the cron trigger and schedule the above job based on that. + CronTrigger trigger = new CronTrigger(getTriggerName(), getJobGroup(), + getSplitPolicyId(), getJobGroup(), cronTrigger); + scheduler.addJob(jobDetail, true); + scheduler.scheduleJob(trigger); + + scheduler.start(); + } catch (Exception e) { + System.out.println("The scheduled split failed (" + e.getMessage() + + "), hence pausing split rule"); + onPause(); + } + } + + /** + * When the split index is closed, shutdown the scheduler. + */ + public SplitVote onClose() throws SplitException { + try { + if (scheduler != null) { + scheduler.shutdown(); + } + } catch (SchedulerException e) { + throw new SplitException("Could not shutdown cron scheduler", e); + } + return SplitVote.CARRY_ON; + } + + /** + * When the split index is paused, pause the scheduler. + */ + public SplitVote onPause() throws SplitException { + try { + if (scheduler != null) { + scheduler.pauseAll(); + } + } catch (SchedulerException e) { + throw new SplitException("Could not shutdown cron scheduler", e); + } + return SplitVote.CARRY_ON; + } + + /** + * When the split index is resumed, resume the scheduler. + */ + public SplitVote onResume() throws SplitException { + try { + if (scheduler != null) { + scheduler.resumeAll(); + } + } catch (SchedulerException e) { + throw new SplitException("Could not shutdown cron scheduler", e); + } + return SplitVote.CARRY_ON; + } + +}