private void reindex(
     boolean dryRun,
     JDBCStorageClient jdbcClient,
     CacheAwareMigrationManager migrationManager,
     String keySpace,
     String columnFamily,
     Indexer indexer,
     DependencySequence propertyMigrators,
     IdExtractor idExtractor,
     int limit,
     Feedback feedback,
     boolean reindexAll)
     throws StorageClientException {
   long objectCount = jdbcClient.allCount(keySpace, columnFamily);
   LOGGER.info(
       "DryRun:{} Migrating {} objects in {} ", new Object[] {dryRun, objectCount, columnFamily});
   feedback.log(
       "DryRun:{0} Migrating {1} objects in {2} ",
       new Object[] {dryRun, objectCount, columnFamily});
   if (objectCount > 0) {
     DisposableIterator<SparseRow> allObjects = jdbcClient.listAll(keySpace, columnFamily);
     try {
       long c = 0;
       while (allObjects.hasNext()) {
         Map<String, PreparedStatement> statementCache = Maps.newHashMap();
         SparseRow r = allObjects.next();
         c++;
         if (c % 1000 == 0) {
           LOGGER.info(
               "DryRun:{} {}% remaining {} ",
               new Object[] {dryRun, ((c * 100) / objectCount), objectCount - c});
           feedback.progress(dryRun, c, objectCount);
         }
         try {
           Map<String, Object> properties = r.getProperties();
           String rid = r.getRowId();
           boolean save = false;
           for (PropertyMigrator propertyMigrator : propertyMigrators) {
             save = propertyMigrator.migrate(rid, properties) || save;
           }
           String key = idExtractor.getKey(properties);
           if (key != null) {
             if (!dryRun) {
               if (save) {
                 migrationManager.insert(keySpace, columnFamily, key, properties, false);
               } else if (reindexAll) {
                 indexer.index(statementCache, keySpace, columnFamily, key, rid, properties);
               }
             } else {
               if (c > limit) {
                 LOGGER.info("Dry Run Migration Stoped at {} Objects ", limit);
                 feedback.log("Dry Run Migration Stoped at {0} Objects ", limit);
                 break;
               }
             }
           } else {
             LOGGER.info("DryRun:{} Skipped Reindexing, no key in  {}", dryRun, properties);
             feedback.log("DryRun:{0} Skipped Reindexing, no key in  {1}", dryRun, properties);
           }
         } catch (SQLException e) {
           LOGGER.warn(e.getMessage(), e);
           feedback.exception(e);
         } catch (StorageClientException e) {
           LOGGER.warn(e.getMessage(), e);
           feedback.exception(e);
         } finally {
           jdbcClient.closeStatementCache(statementCache);
         }
       }
     } finally {
       allObjects.close();
     }
   }
 }
  public synchronized void migrate(boolean dryRun, int limit, boolean reindexAll, Feedback feedback)
      throws ClientPoolException, StorageClientException, AccessDeniedException, IOException,
          PropertyMigrationException {
    SessionImpl session = (SessionImpl) repository.loginAdministrative();
    StorageClient client = session.getClient();
    FileRedoLogger migrateRedoLog = new FileRedoLogger(redoLogLocation, maxLogFileSize, feedback);
    client.setStorageClientListener(migrateRedoLog);
    try {
      if (client instanceof JDBCStorageClient) {
        JDBCStorageClient jdbcClient = (JDBCStorageClient) client;
        String keySpace = configuration.getKeySpace();

        Indexer indexer = jdbcClient.getIndexer();

        PropertyMigrator[] propertyMigrators = propertyMigratorTracker.getPropertyMigrators();

        DependencySequence migratorDependencySequence =
            getMigratorSequence(session, propertyMigrators);

        for (PropertyMigrator p : migratorDependencySequence) {
          LOGGER.info("DryRun:{} Using Property Migrator {} ", dryRun, p);
          feedback.log("DryRun:{0} Using Property Migrator {1} ", dryRun, p);
        }
        for (PropertyMigrator p : migratorDependencySequence.getUnresolved()) {
          LOGGER.info("DryRun:{} Unresolved Property Migrator {} ", dryRun, p);
          feedback.log("DryRun:{0} Unresolved Property Migrator {1} ", dryRun, p);
        }
        for (Entry<String, Object> p : migratorDependencySequence.getAlreadyRun().entrySet()) {
          LOGGER.info("DryRun:{} Migrator Last Run {} ", dryRun, p);
          feedback.log("DryRun:{0} Migrator Last Run {1} ", dryRun, p);
        }
        if (migratorDependencySequence.hasUnresolved()) {
          throw new PropertyMigrationException(
              "There are unresolved dependencies " + migratorDependencySequence.getUnresolved());
        }
        CacheAwareMigrationManager cacheAwareMigrationManager =
            new CacheAwareMigrationManager(
                jdbcClient, session.getCache(configuration.getAuthorizableColumnFamily()));
        reindex(
            dryRun,
            jdbcClient,
            cacheAwareMigrationManager,
            keySpace,
            configuration.getAuthorizableColumnFamily(),
            indexer,
            migratorDependencySequence,
            new IdExtractor() {

              public String getKey(Map<String, Object> properties) {
                if (properties.containsKey(Authorizable.ID_FIELD)) {
                  return (String) properties.get(Authorizable.ID_FIELD);
                }
                return null;
              }
            },
            limit,
            feedback,
            reindexAll);

        cacheAwareMigrationManager =
            new CacheAwareMigrationManager(
                jdbcClient, session.getCache(configuration.getContentColumnFamily()));
        reindex(
            dryRun,
            jdbcClient,
            cacheAwareMigrationManager,
            keySpace,
            configuration.getContentColumnFamily(),
            indexer,
            migratorDependencySequence,
            new IdExtractor() {

              public String getKey(Map<String, Object> properties) {
                if (properties.containsKey(BlockSetContentHelper.CONTENT_BLOCK_ID)) {
                  // blocks of a bit stream
                  return (String) properties.get(BlockSetContentHelper.CONTENT_BLOCK_ID);
                } else if (properties.containsKey(Content.UUID_FIELD)) {
                  // a content item and content block item
                  return (String) properties.get(Content.UUID_FIELD);
                } else if (properties.containsKey(Content.STRUCTURE_UUID_FIELD)) {
                  // a structure item
                  return (String) properties.get(Content.PATH_FIELD);
                }
                return null;
              }
            },
            limit,
            feedback,
            reindexAll);

        cacheAwareMigrationManager =
            new CacheAwareMigrationManager(
                jdbcClient, session.getCache(configuration.getAclColumnFamily()));
        reindex(
            dryRun,
            jdbcClient,
            cacheAwareMigrationManager,
            keySpace,
            configuration.getAclColumnFamily(),
            indexer,
            migratorDependencySequence,
            new IdExtractor() {
              public String getKey(Map<String, Object> properties) {
                if (properties.containsKey(AccessControlManagerImpl._KEY)) {
                  return (String) properties.get(AccessControlManagerImpl._KEY);
                }
                return null;
              }
            },
            limit,
            feedback,
            reindexAll);

        saveMigratorSequence(session, migratorDependencySequence);

      } else {
        LOGGER.warn("This class will only re-index content for the JDBCStorageClients");
      }
    } finally {
      client.setStorageClientListener(null);
      migrateRedoLog.close();
      session.logout();
    }
  }