View Javadoc

1   /*
2    * #%L
3    * Bitrepository Integrity Service
4    * %%
5    * Copyright (C) 2010 - 2012 The State and University Library, The Royal Library and The State Archives, Denmark
6    * %%
7    * This program is free software: you can redistribute it and/or modify
8    * it under the terms of the GNU Lesser General Public License as 
9    * published by the Free Software Foundation, either version 2.1 of the 
10   * License, or (at your option) any later version.
11   * 
12   * This program is distributed in the hope that it will be useful,
13   * but WITHOUT ANY WARRANTY; without even the implied warranty of
14   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15   * GNU General Lesser Public License for more details.
16   * 
17   * You should have received a copy of the GNU General Lesser Public 
18   * License along with this program.  If not, see
19   * <http://www.gnu.org/licenses/lgpl-2.1.html>.
20   * #L%
21   */
22  package org.bitrepository.integrityservice.collector;
23  
24  import java.util.ArrayList;
25  import java.util.List;
26  import java.util.concurrent.BlockingQueue;
27  import java.util.concurrent.LinkedBlockingQueue;
28  import java.util.concurrent.TimeUnit;
29  
30  import org.bitrepository.access.getchecksums.conversation.ChecksumsCompletePillarEvent;
31  import org.bitrepository.access.getfileids.conversation.FileIDsCompletePillarEvent;
32  import org.bitrepository.client.eventhandler.ContributorFailedEvent;
33  import org.bitrepository.client.eventhandler.EventHandler;
34  import org.bitrepository.client.eventhandler.OperationEvent;
35  import org.bitrepository.client.eventhandler.OperationEvent.OperationEventType;
36  import org.bitrepository.common.utils.SettingsUtils;
37  import org.bitrepository.integrityservice.alerter.IntegrityAlerter;
38  import org.bitrepository.integrityservice.cache.IntegrityModel;
39  import org.slf4j.Logger;
40  import org.slf4j.LoggerFactory;
41  
42  /**
43   * The eventhandler for the integrity collector.
44   * 
45   * Notifies the monitor 
46   */
47  public class IntegrityCollectorEventHandler implements EventHandler {
48      /** The log.*/
49      private Logger log = LoggerFactory.getLogger(getClass());
50      /** The model where the integrity data is stored.*/
51      private final IntegrityModel store;
52      /** The alerter for issuing alarms.*/
53      private final IntegrityAlerter alerter;
54      /** The amount of milliseconds before the results are required.*/
55      private final long timeout;
56      
57      /** The queue used to store the received operation events. */
58      private final BlockingQueue<OperationEvent> finalEventQueue = new LinkedBlockingQueue<OperationEvent>();
59      /** The list of contributors which has only delivered a partial result set.*/
60      private final List<String> contributorsWithPartialResults = new ArrayList<String>();
61      
62      /**
63       * Constructor.
64       * @param model The integrity model, where the results of GetChecksums or GetFileIDs are to be delivered.
65       * @param alerter The alerter for sending failures.
66       * @param timeout The maximum amount of millisecond to wait for an result.
67       */
68      public IntegrityCollectorEventHandler(IntegrityModel model, IntegrityAlerter alerter, long timeout) {
69          this.store = model;
70          this.alerter = alerter;
71          this.timeout = timeout;
72      }
73      
74      @Override
75      public void handleEvent(OperationEvent event) {
76          if(event.getEventType() == OperationEventType.COMPONENT_COMPLETE) {
77              log.debug("Component complete: " + event.toString());
78              handleResult(event);
79          } else if(event.getEventType() == OperationEventType.COMPLETE) {
80              log.debug("Complete: " + event.toString());
81              finalEventQueue.add(event);
82          } else if(event.getEventType() == OperationEventType.FAILED) {
83              log.warn("Failure: " + event.toString());
84              alerter.operationFailed("Failed integrity operation: " + event.toString(), event.getCollectionID());
85              
86              for(String pillarId : SettingsUtils.getPillarIDsForCollection(event.getCollectionID())) {
87                  store.setPreviouslySeenToExisting(event.getCollectionID(), pillarId);
88              }
89              
90              finalEventQueue.add(event);
91          } else if(event.getEventType() == OperationEventType.COMPONENT_FAILED) {
92              ContributorFailedEvent cfe = (ContributorFailedEvent) event;
93              log.warn("Component failure for '" + cfe.getContributorID() 
94                      + "'. Settings previously seen files to existing.");
95              store.setPreviouslySeenToExisting(cfe.getCollectionID(), cfe.getContributorID());
96          } else {
97              log.debug("Received event: " + event.toString());
98          }
99      }
100     
101     /**
102      * Retrieves the final event when the operation finishes. The final event is awaited for 'timeout' amount 
103      * of milliseconds. If no final events has occurred, then an InterruptedException is thrown.
104      * @return The final event.
105      * @throws InterruptedException If it timeouts before the final event.
106      */
107     public OperationEvent getFinish() throws InterruptedException {
108         return finalEventQueue.poll(timeout, TimeUnit.MILLISECONDS);
109     }
110     
111     /**
112      * @return The list of pillars with only a partial result set.
113      */
114     public List<String> getPillarsWithPartialResult() {
115         return contributorsWithPartialResults;
116     }
117     
118     /**
119      * Handle the results of the GetChecksums operation at a single pillar.
120      * @param event The event for the completion of a GetChecksums for a single pillar.
121      */
122     private void handleResult(OperationEvent event) {
123         if(event instanceof ChecksumsCompletePillarEvent) {
124             ChecksumsCompletePillarEvent checksumEvent = (ChecksumsCompletePillarEvent) event;
125             log.trace("Receiving GetChecksums result: {}", 
126                     checksumEvent.getChecksums().getChecksumDataItems().toString());
127             store.addChecksums(checksumEvent.getChecksums().getChecksumDataItems(), checksumEvent.getContributorID(), 
128                     checksumEvent.getCollectionID());
129             if(checksumEvent.isPartialResult()) {
130                 contributorsWithPartialResults.add(checksumEvent.getContributorID());
131             }
132         } else if(event instanceof FileIDsCompletePillarEvent) {
133             FileIDsCompletePillarEvent fileidEvent = (FileIDsCompletePillarEvent) event;
134             log.trace("Receiving GetFileIDs result: {}", fileidEvent.getFileIDs().getFileIDsData().toString());
135             store.addFileIDs(fileidEvent.getFileIDs().getFileIDsData(), fileidEvent.getContributorID(),
136                     fileidEvent.getCollectionID());
137             if(fileidEvent.isPartialResult()) {
138                 contributorsWithPartialResults.add(fileidEvent.getContributorID());
139             }
140         } else {
141             log.warn("Unexpected component complete event: " + event.toString());
142         }
143     }
144 }