/*
* Copyright 2011 Future Systems
*
* Licensed 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.
*/
package org.krakenapps.dom.api.impl;
import java.util.Arrays;
import java.util.Collection;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.atomic.AtomicInteger;
import org.apache.felix.ipojo.annotations.Component;
import org.apache.felix.ipojo.annotations.Invalidate;
import org.apache.felix.ipojo.annotations.Provides;
import org.apache.felix.ipojo.annotations.Requires;
import org.apache.felix.ipojo.annotations.Validate;
import org.krakenapps.api.PrimitiveConverter;
import org.krakenapps.dom.api.HostApi;
import org.krakenapps.dom.api.HostUpdateApi;
import org.krakenapps.dom.api.OrganizationApi;
import org.krakenapps.dom.model.Host;
import org.krakenapps.dom.model.windows.WindowsHost;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@Component(name = "dom-host-update-api")
@Provides
public class HostUpdateApiImpl implements HostUpdateApi, Runnable {
private final Logger logger = LoggerFactory.getLogger(HostUpdateApiImpl.class.getName());
private final Set<String> validHardeningKeys;
@Requires
private HostApi hostApi;
@Requires
private OrganizationApi orgApi;
private ConcurrentLinkedQueue<Host> queue = new ConcurrentLinkedQueue<Host>();
private Thread t;
private volatile boolean doStop;
public HostUpdateApiImpl() {
validHardeningKeys = new HashSet<String>(Arrays.asList("UseFirewall", "UseLogonPassword", "UseScreenSaver",
"UseScreenSaverPassword", "UseShareFolderPassword", "UseManagementShareFolder", "UseWindowsUpdate",
"UseAutoLogin", "UseGuestAccount", "MinimumPasswordLength", "PasswordExpiry", "ScreenSaverIdleInterval"));
}
@Validate
public void start() {
doStop = false;
t = new Thread(this, "DOM Host Updater");
t.start();
}
@Invalidate
public void stop() {
doStop = true;
t.interrupt();
}
/**
* batch update using
*/
@Override
public void run() {
try {
logger.info("kraken dom: starting host updater thread");
while (!doStop) {
try {
Thread.sleep(10000);
runOnce();
} catch (InterruptedException e) {
logger.debug("kraken dom: host batch update interrupted");
} catch (Exception e) {
logger.error("kraken dom: host batch update error", e);
}
}
} catch (Throwable e) {
logger.error("kraken dom: host batch update error", e);
} finally {
logger.info("kraken dom: host updater thread stopped");
}
}
@Override
public void update(Host host) {
Object windows = host.getData().get("windows");
if (windows != null) {
WindowsHost whost = PrimitiveConverter.parse(WindowsHost.class, windows);
validateHardeningKeys(whost);
}
queue.add(host);
}
private void validateHardeningKeys(WindowsHost whost) {
if (!validHardeningKeys.containsAll(whost.getHardenings().keySet())) {
logger.error("kraken dom: invalidate Hardening key");
Set<String> invalids = new HashSet<String>(whost.getHardenings().keySet());
invalids.removeAll(validHardeningKeys);
throw new IllegalArgumentException("invalidate Hardening key: " + invalids.toString());
}
}
private void runOnce() {
if (orgApi.findOrganization("localhost") == null)
return;
Map<String, Host> hosts = new HashMap<String, Host>();
Map<String, Host> recordedHosts = new HashMap<String, Host>();
Map<String, Host> addHosts = new HashMap<String, Host>();
Map<String, Host> updateHosts = new HashMap<String, Host>();
AtomicInteger aleadyExist = new AtomicInteger(0);
while (true) {
Host host = queue.poll();
if (host == null)
break;
if (hosts.get(host.getGuid()) != null)
aleadyExist.incrementAndGet();
hosts.put(host.getGuid(), host);
}
long begin = new Date().getTime();
Collection<Host> existedHost = hostApi.findHosts("localhost", hosts.keySet());
for (Host h : existedHost)
recordedHosts.put(h.getGuid(), h);
for (String guid : hosts.keySet()) {
Host h = recordedHosts.get(guid);
if (h == null)
addHosts.put(guid, hosts.get(guid));
else
updateHosts.put(guid, h);
}
long lockBegin = new Date().getTime();
if (addHosts.size() > 0)
hostApi.createHosts("localhost", addHosts.values());
if (updateHosts.size() > 0)
hostApi.updateHosts("localhost", updateHosts.values());
long lockEnd = new Date().getTime();
long end = new Date().getTime();
if (hosts.size() > 0)
logger.trace(
"kraken dom: added [{}] hosts, updated [{}] hosts, remained [{}] hosts, [{}]ms elapsed, [{}]ms lock, [{}] exist host",
new Object[] { hosts.size() - existedHost.size(), existedHost.size(), queue.size(), end - begin,
lockEnd - lockBegin, aleadyExist });
}
@Override
public int getPendingCount() {
return queue.size();
}
}