/** * Record time-stamped information about the activity of the connection. This information can * originate from either the connector or from the framework. The reason it is here is that it is * viewed as 'belonging' to an individual connection, and is segregated accordingly. * * @param connectionName is the connection to which the record belongs. If the connection is * deleted, the corresponding records will also be deleted. Cannot be null. * @param startTime is either null or the time since the start of epoch in milliseconds (Jan 1, * 1970). Every activity has an associated time; the startTime field records when the activity * began. A null value indicates that the start time and the finishing time are the same. * @param activityType is a string which is fully interpretable only in the context of the * connector involved, which is used to categorize what kind of activity is being recorded. * For example, a web connector might record a "fetch document" activity, while the framework * might record "ingest document", "job start", "job finish", "job abort", etc. Cannot be * null. * @param dataSize is the number of bytes of data involved in the activity, or null if not * applicable. * @param entityIdentifier is a (possibly long) string which identifies the object involved in the * history record. The interpretation of this field will differ from connector to connector. * May be null. * @param resultCode contains a terse description of the result of the activity. The description * is limited in size to 255 characters, and can be interpreted only in the context of the * current connector. May be null. * @param resultDescription is a (possibly long) human-readable string which adds detail, if * required, to the result described in the resultCode field. This field is not meant to be * queried on. May be null. * @param childIdentifiers is a set of child entity identifiers associated with this activity. May * be null. */ public void recordHistory( String connectionName, Long startTime, String activityType, Long dataSize, String entityIdentifier, String resultCode, String resultDescription, String[] childIdentifiers) throws ManifoldCFException { long endTimeValue = System.currentTimeMillis(); long startTimeValue; if (startTime == null) startTimeValue = endTimeValue - 1L; else { startTimeValue = startTime.longValue(); if (startTimeValue == endTimeValue) startTimeValue -= 1L; // Zero-time events are not allowed. } long dataSizeValue; if (dataSize == null) dataSizeValue = 0L; else dataSizeValue = dataSize.longValue(); Long rowID = historyManager.addRow( connectionName, startTimeValue, endTimeValue, dataSizeValue, activityType, entityIdentifier, resultCode, resultDescription); // child identifiers are not stored, for now. // MHL }
/** * Generate a report, listing the result bucket and identifier bucket. The records selected for * this report are based on the filtering criteria object passed into this method. The record * order is based on the sorting criteria object passed into this method. The result code bucket * description is specified by a bucket description object. The identifier bucket description is * specified by a bucket description object. The resultset returned should have the following * columns: "resultcodebucket","idbucket". * * @param connectionName is the name of the connection. * @param criteria is the filtering criteria, which selects the records of interest. * @param sort is the sorting order, which can specify sort based on the result columns. * @param resultCodeBucket is the description of the bucket based on processed result codes. * @param idBucket is the description of the bucket based on processed entity identifiers. * @param startRow is the first row to include (beginning with 0) * @param maxRowCount is the maximum number of rows to include. */ public IResultSet genHistoryResultCodes( String connectionName, FilterCriteria criteria, SortOrder sort, BucketDescription resultCodeBucket, BucketDescription idBucket, int startRow, int maxRowCount) throws ManifoldCFException { return historyManager.resultCodesReport( connectionName, criteria, sort, resultCodeBucket, idBucket, startRow, maxRowCount); }
/** * Generate a report, listing the start time, bytes processed, and identifier bucket, given a time * slice (interval) size. The records selected for this report are based on the filtering criteria * object passed into this method. The record order is based on the sorting criteria object passed * into this method. The identifier bucket description is specified by the bucket description * object. The resultset returned should have the following columns: * "starttime","endtime","bytecount","idbucket". * * @param connectionName is the name of the connection. * @param criteria is the filtering criteria, which selects the records of interest. * @param sort is the sorting order, which can specify sort based on the result columns. * @param idBucket is the description of the bucket based on processed entity identifiers. * @param interval is the time interval, in milliseconds, to locate. There will be one row in the * resultset for each distinct idBucket value, and the returned activity count will the * maximum found over the specified interval size. * @param startRow is the first row to include (beginning with 0) * @param maxRowCount is the maximum number of rows to include. */ public IResultSet genHistoryByteCount( String connectionName, FilterCriteria criteria, SortOrder sort, BucketDescription idBucket, long interval, int startRow, int maxRowCount) throws ManifoldCFException { return historyManager.maxByteCountReport( connectionName, criteria, sort, idBucket, interval, startRow, maxRowCount); }
/** Uninstall the manager. */ public void deinstall() throws ManifoldCFException { beginTransaction(); try { throttleSpecManager.deinstall(); historyManager.deinstall(); performDrop(null); } catch (ManifoldCFException e) { signalRollback(); throw e; } catch (Error e) { signalRollback(); throw e; } finally { endTransaction(); } }
/** * Delete a repository connection. * * @param name is the name of the connection to delete. If the name does not exist, no error is * returned. */ public void delete(String name) throws ManifoldCFException { // Grab a job manager handle. We will need to check if any jobs refer to this connection. IJobManager jobManager = JobManagerFactory.make(threadContext); StringSetBuffer ssb = new StringSetBuffer(); ssb.add(getRepositoryConnectionsKey()); ssb.add(getRepositoryConnectionKey(name)); StringSet cacheKeys = new StringSet(ssb); ICacheHandle ch = cacheManager.enterCache(null, cacheKeys, getTransactionID()); try { beginTransaction(); try { // Check if any jobs refer to this connection name if (jobManager.checkIfReference(name)) throw new ManifoldCFException( "Can't delete repository connection '" + name + "': existing jobs refer to it"); ManifoldCF.noteConfigurationChange(); throttleSpecManager.deleteRows(name); historyManager.deleteOwner(name); ArrayList params = new ArrayList(); String query = buildConjunctionClause( params, new ClauseDescription[] {new UnitaryClause(nameField, name)}); performDelete("WHERE " + query, params, null); cacheManager.invalidateKeys(ch); } catch (ManifoldCFException e) { signalRollback(); throw e; } catch (Error e) { signalRollback(); throw e; } finally { endTransaction(); } } finally { cacheManager.leaveCache(ch); } }
/** Install the manager. */ public void install() throws ManifoldCFException { // First, get the authority manager table name and name column IAuthorityGroupManager authMgr = AuthorityGroupManagerFactory.make(threadContext); // Always use a loop, and no transaction, as we may need to retry due to upgrade while (true) { Map existing = getTableSchema(null, null); if (existing == null) { // Install the "objects" table. HashMap map = new HashMap(); map.put(nameField, new ColumnDescription("VARCHAR(32)", true, false, null, null, false)); map.put( descriptionField, new ColumnDescription("VARCHAR(255)", false, true, null, null, false)); map.put( classNameField, new ColumnDescription("VARCHAR(255)", false, false, null, null, false)); map.put( groupNameField, new ColumnDescription( "VARCHAR(32)", false, true, authMgr.getTableName(), authMgr.getGroupNameColumn(), false)); map.put(maxCountField, new ColumnDescription("BIGINT", false, false, null, null, false)); map.put(configField, new ColumnDescription("LONGTEXT", false, true, null, null, false)); performCreate(map, null); } else { // Upgrade code ColumnDescription cd = (ColumnDescription) existing.get(groupNameField); if (cd == null) { Map addMap = new HashMap(); addMap.put( groupNameField, new ColumnDescription( "VARCHAR(32)", false, true, authMgr.getTableName(), authMgr.getGroupNameColumn(), false)); performAlter(addMap, null, null, null); } // Get rid of the authorityName field. When we do this we need to copy into the group name // field, adding groups if they don't yet exist first cd = (ColumnDescription) existing.get(authorityNameField); if (cd != null) { ArrayList params = new ArrayList(); IResultSet set = performQuery( "SELECT " + nameField + "," + authorityNameField + " FROM " + getTableName(), null, null, null); for (int i = 0; i < set.getRowCount(); i++) { IResultRow row = set.getRow(i); String repoName = (String) row.getValue(nameField); String authName = (String) row.getValue(authorityNameField); if (authName != null && authName.length() > 0) { // Attempt to create a matching auth group. This will fail if the group // already exists IAuthorityGroup grp = authMgr.create(); grp.setName(authName); try { authMgr.save(grp); } catch (ManifoldCFException e) { if (e.getErrorCode() == ManifoldCFException.INTERRUPTED) throw e; // Fall through; the row exists already } Map<String, String> map = new HashMap<String, String>(); map.put(groupNameField, authName); params.clear(); String query = buildConjunctionClause( params, new ClauseDescription[] {new UnitaryClause(nameField, repoName)}); performUpdate(map, " WHERE " + query, params, null); } } List<String> deleteList = new ArrayList<String>(); deleteList.add(authorityNameField); performAlter(null, null, deleteList, null); } } // Install dependent tables. historyManager.install(getTableName(), nameField); throttleSpecManager.install(getTableName(), nameField); // Index management IndexDescription authorityIndex = new IndexDescription(false, new String[] {groupNameField}); IndexDescription classIndex = new IndexDescription(false, new String[] {classNameField}); // Get rid of indexes that shouldn't be there Map indexes = getTableIndexes(null, null); Iterator iter = indexes.keySet().iterator(); while (iter.hasNext()) { String indexName = (String) iter.next(); IndexDescription id = (IndexDescription) indexes.get(indexName); if (authorityIndex != null && id.equals(authorityIndex)) authorityIndex = null; else if (classIndex != null && id.equals(classIndex)) classIndex = null; else if (indexName.indexOf("_pkey") == -1) // This index shouldn't be here; drop it performRemoveIndex(indexName); } // Add the ones we didn't find if (authorityIndex != null) performAddIndex(null, authorityIndex); if (classIndex != null) performAddIndex(null, classIndex); break; } }
/** * Generate a report, listing the start time, elapsed time, result code and description, number of * bytes, and entity identifier. The records selected for this report are based on the filtering * criteria object passed into this method. The record order is based on the sorting criteria * object passed into this method. The resultset returned should have the following columns: * "starttime","elapsedtime","resultcode","resultdesc","bytes","identifier". * * @param connectionName is the name of the connection. * @param criteria is the filtering criteria, which selects the records of interest. * @param sort is the sorting order, which can specify sort based on the result columns. * @param startRow is the first row to include (beginning with 0) * @param maxRowCount is the maximum number of rows to include. */ public IResultSet genHistorySimple( String connectionName, FilterCriteria criteria, SortOrder sort, int startRow, int maxRowCount) throws ManifoldCFException { return historyManager.simpleReport(connectionName, criteria, sort, startRow, maxRowCount); }
/** * Get the maximum number of rows a window-based report can work with. * * @return the maximum rows. */ public long getMaxRows() throws ManifoldCFException { return historyManager.getMaxRows(); }
/** * Count the number of rows specified by a given set of criteria. This can be used to make * decisions as to whether a query based on those rows will complete in an acceptable amount of * time. * * @param connectionName is the name of the connection. * @param criteria is the filtering criteria, which selects the records of interest. * @return the number of rows included by the criteria. */ public long countHistoryRows(String connectionName, FilterCriteria criteria) throws ManifoldCFException { return historyManager.countHistoryRows(connectionName, criteria); }
/** * Delete history rows older than a specified timestamp. * * @param timeCutoff is the timestamp to delete older rows before. */ @Override public void cleanUpHistoryData(long timeCutoff) throws ManifoldCFException { historyManager.deleteOldRows(timeCutoff); }
/** * Delete history rows related to a specific connection, upon user request. * * @param connectionName is the connection whose history records should be removed. */ @Override public void cleanUpHistoryData(String connectionName) throws ManifoldCFException { historyManager.deleteOwner(connectionName); }