package org.hwo.pulscounter; import java.io.File; import java.io.FileNotFoundException; import java.io.IOException; import java.io.RandomAccessFile; import java.nio.ByteBuffer; import java.util.Hashtable; import org.hwo.servicelink.ServiceLinkException; import org.hwo.servicelink.ServiceLinkRequestFailedException; import org.hwo.tasklet.Tasklet; import org.hwo.tasklet.TaskletManager; public class SnapshotManager { public enum Notification { INITIALIZE, SHUTDOWN, SYNC, FULLSYNC }; private RandomAccessFile file; private Hashtable hashList; private Integer lastNewest, snapshotSize; public SnapshotManager() throws FileNotFoundException { this.file = new RandomAccessFile("snapshots.dat", "rws"); this.initialize(); } public SnapshotManager(File file) throws FileNotFoundException { this.file = new RandomAccessFile(file, "rws"); this.initialize(); } private synchronized void initialize(){ hashList = new Hashtable(); } private PulsCounter2Application application(){ return PulsCounter2Application.getApplication(); } public synchronized void notify(Notification notification){ switch (notification){ case INITIALIZE: TaskletManager.instance().enqueue(new Tasklet("SnapShot Manager initialisieren") { @Override public void run() { doInitialize(); } }); break; case SHUTDOWN: doShutdown(); return; case FULLSYNC: TaskletManager.instance().enqueue(new Tasklet("Volle Synchronisation") { @Override public void run() { doFullSync(); } }); break; case SYNC: TaskletManager.instance().enqueue(new Tasklet("Schnelle Synchronisation") { @Override public void run() { doSync(); } }); break; } } public synchronized void doInitialize(){ try { byte[] buffer = new byte[256]; ByteBuffer bb = ByteBuffer.wrap(buffer); Integer ind = 0; application().message("SnapShotManager: Initialisieren"); hashList.clear(); file.seek(0); while (file.read(buffer)==256){ Integer timestamp,field0; Long hash; timestamp = bb.getInt(0); field0 = bb.getInt(4); hash = ((long)timestamp << 32) | field0; hashList.put(hash, ind++); } application().message(String.format("SnapShotManager: %d SnapShots lokal", hashList.size())); } catch (Exception e){ e.printStackTrace(); application().message("SnapShotManager meldet Fehler: " + e.toString()); } } public synchronized void doShutdown(){ } public synchronized void doFullSync(){ Integer ind_oldest,ind_newest,ind; int n = 0; application().message("SnapShotManager: Beginne volle synchronisation"); try { try { snapshotSize = application().getServiceLink().readInt(13, 0, 0x0582); } catch (ServiceLinkRequestFailedException e){ snapshotSize = 512; } ind_oldest = application().getServiceLink().readInt(13, 0, 0x0580); ind_newest = application().getServiceLink().readInt(13, 0, 0x0581); lastNewest = ind_newest; System.out.println(String.format("ind_oldest: %d", ind_oldest)); System.out.println(String.format("ind_newest: %d", ind_newest)); ind = ind_oldest; do { TaskletManager.instance().setProgress(String.format("%d / %d", n++, snapshotSize)); Integer id; try { application().getServiceLink().writeInt(13, 0, 0x0500, ind); id = application().getServiceLink().readInt(13, 0, 0x0500); if (!id.equals(ind)){ System.out.println(String.format("bus_snapshot_id: %d != %d",ind,id)); } else { Integer ts,f0; ts = application().getServiceLink().readInt(13, 0, 0x0501); f0 = application().getServiceLink().readInt(13, 0, 0x0502); Long hash = ((long)ts<<32) | f0; if (!hashList.containsKey(hash)){ SnapShot snap = snapshotFromDevice(ind); if (snap != null){ Integer find = snapshotToFile(snap); if (find != -1){ hashList.put(snap.getHashCode(), find); } else { application().message("Snapshot konnte nicht gespeichert werden!"); } }; }; }; if (ind.equals(ind_newest)) break; } catch (ServiceLinkRequestFailedException failed){ failed.printStackTrace(); }; ind++; if (ind > snapshotSize){ ind = 0; } } while (!ind.equals(ind_oldest)); } catch (Exception e){ e.printStackTrace(); } application().message(String.format("SnapShotManager: %d bekannte Snapshots nach FullSync", hashList.size())); } private synchronized void doSync(){ Integer ind_oldest,ind_newest,ind; int n,c; try { ind_newest = application().getServiceLink().readInt(13, 0, 0x0581); if (ind_newest == lastNewest) return; ind = lastNewest; c = ind_newest - lastNewest; if (c < 0) c+=snapshotSize; n = 0; if (c == 0){ return; } do { TaskletManager.instance().setProgress(String.format("%d / %d", n,c)); ind ++; ind &= 0x1FF; n++; SnapShot snap = snapshotFromDevice(ind); if (snap != null){ Integer ind_file = snapshotToFile(snap); hashList.put(snap.getHashCode(), ind_file); } } while (!ind.equals(ind_newest)); lastNewest = ind_newest; application().message(String.format("%d neue Snapshots", n)); } catch (ServiceLinkRequestFailedException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } catch (ServiceLinkException e) { e.printStackTrace(); } } public synchronized SnapShot loadSnapShot(int ind){ byte[] bytes = new byte[256]; try { file.seek(ind * 256); file.read(bytes); return new SnapShot(bytes); } catch (IOException e) { e.printStackTrace(); } return null; } public synchronized Integer size(){ try { return ((int)(file.length())/256); } catch (IOException e) { e.printStackTrace(); } return 0; } private synchronized Integer snapshotToFile(SnapShot snap){ Long find; try { find = file.length()/256; file.seek(find * 256); file.write(snap.toBytes()); return find.intValue(); } catch (IOException e) { e.printStackTrace(); return -1; } } private SnapShot snapshotFromDevice(Integer ind){ SnapShot ss = new SnapShot(); Integer id; try { application().getServiceLink().writeInt(13, 0, 0x0500, ind); id = application().getServiceLink().readInt(13, 0, 0x0500); if (!id.equals(ind)){ System.out.println(String.format("bus_snapshot_id: %d != %d",ind,id)); return null; }; ss.setTimestamp( application().getServiceLink().readInt(13, 0, 0x0501)); ss.setField0( application().getServiceLink().readInt(13, 0, 0x0502)); ss.setInputmask( application().getServiceLink().readInt(13, 0, 0x0503)); ss.setOutputmask( application().getServiceLink().readInt(13, 0, 0x0504)); ss.setPullupmask( application().getServiceLink().readInt(13, 0, 0x0505)); ss.setInvertmask( application().getServiceLink().readInt(13, 0, 0x0506)); ss.setTriggermask( application().getServiceLink().readInt(13, 0, 0x0507)); for (int i=0;i<32;i++){ ss.setValue(i, application().getServiceLink().readInt(13, 0, 0x0510 + i)); } for (int i=0;i<8;i++){ ss.setAnalog(i, application().getServiceLink().readInt(13, 0, 0x0508 + i)); } } catch (Exception e){ e.printStackTrace(); return null; } System.out.print(String.format("Snapshot from Device: %s\n", ss.toString())); return ss; } }