Android fragmentáció, mennyire probléma ez valójában? - Android portal

tanulj meg fejleszteni. Nem a platform alkalmatlan, hanem te.

A tesztelések során az derült ki, hogy bár különböző készülékeken és verziókon jöttek elő a problémák, mégsem a fragmentáció volt a gond, hanem klasszikus szoftverfejlesztési hibák. Ezek pedig nyilván nem jöttek elő pl. az 1GB RAM-al bíró Galaxy S II és hasonló erőműveken. Tanultak a hibáikból, jobb kódot készítettek és jobb fejlesztők lettek. Arról nem beszélve, hogy a leckét is megtanulták: nem a fragmentáció, hanem a programozói tudás hiánya a probléma.

A legnagyobb probléma pedig végig az volt, hogy egyszerűen nem ismerték a platformot és nem szenteltek neki elegendő időt.

>

Android fragmentáció, mennyire probléma ez valójában?

Common Pitfalls of jQuery - Peter Olson

  1. Excessive jQuery Calls

Instead of

$("#example").text("Hello, world!");
$("#example").css("color", "red");

user

var $example = $("#example");
$example.text("Hello, world!");
$example.css("color", "red");

  1. Missing parts of selectors

  2. Repetitive Selectors

  3. Unused Shortcuts

Common Pitfalls of jQuery

Lean from the Trenches: Managing Large-Scale Projects with Kanban - Henrik Kniberg

Nagyszerű könyv. Lean elvek. Agile fejlesztés. És nem az elmélet, hanem az, hogyan ténylegesen megvalósították egy állami projekten a svéd rendőrségnél.

Többszörösen is aktuális számomra, mert én is közszférában létező projekten dolgozom. Az ottani tapasztalatok és problémákat én is látom a saját szervezetemben. És ha ezek a módszerek ott beváltak, akkor itt az EU más intézményeiben is működnie kell.

Gyakorlatilag semmi elmélet. Csak a véres valóság.

Gazdagok összeesküvése - Kiyosaki

"Bezzeg én megmondtam" oktatókönyv.

A gazdagok  összeesküvése boritó

Bezzeg: Gazdag papa próféciáiban igen hosszan kifejtett egy jövőképet, amit már gazdag apja vezetett fel. Azt a jövőképet, ami a "Monopoly-pénz" bevezetése hozott magával. Az egésznek van egy "bezzeg én megmondtam" stílusa.

Oktató:

  • Cashflow négyszög
  • AB háromszög
  • monetáris rendszer
  • Bankok pénztermelési folyamata
  • Fundamentális vs. technikai kereskedők a tőzsdén
  • Gazdaságtörténet.

Egyik rész sem mondott újat. Egyszerűen a 2008-as gazdasági válság tükrében sokkal reálisabbnak látszanak az építőkövek.

3 szabály:

  1. tanuld meg irányítani a kézpénzáramlásodat
  2. készülj mindig rossz időkre és csak jó időket fogsz látni.
  3. Nyomtass saját pénzt.

Az idő rövid története - Stephen Hawkins

Vad kicsapongásom a mindennapi olvasnivalók között.

Az idő rövid története

Tetszett, hiszen érthető és logikus megismerhettem a legmagasabb fizikai modelleket és elméleteket.

De bevallom, hogy még nem olvastam el és nem is biztos, hogy el fogom valaha is. Egyszerűen azért, mert nagyon nagy részét már ismertem korábbról. Még az egyetemen tanultam amolyan szabadon választható tantárgyak keretei között. Szinte egy az egyben ugyan az.

Persze lehet, hogy a kedvetlenségbe a töménység is beleszólt. Luxemburgból Budapestre menet olvastam el és egy teljes napig bizony nem köt le a téma.

Tudásháló - James Burke

Hogyan kapcsolódik a német bombázás, egy éhes kacsa és az adrenalin felfedezése? Egy vegetáriánus nő és a mesterséges lélegeztetés? A Morse-jel és egy művészeti akadémia és a pszichoszomatikus szó eredete. Vesekő az égetett mész és a skót whisky? És a Gőzmozdony?

Érdekesnek érdekes. A felfedezések között bizony voltak kapcsolatok. Gyakran olyanok, amire nem is gondoltál volna. De azért nem egy egységes mű. Úgy csapong, ahogy a kapcsolatok jönnek. Ez nem baj, hiszen ez a világ. A gond az, hogy emiatt nem is fogod sajnálni ha leteszed vagy félbehagyod és fél év múlva folytatod.

Tudásháló

Stop Motivating People - They Hate It - Herding Cats

  • Stop Motivating People They Hate It
  • Motivation comes from internal forces.
  • In the business world I don't want to work with anyone who needs motivation. It's a waste of time, annoys the person and annoys me as to why I need to motivate someone I pay good money to do their job.

Stop Motivating People - They Hate It

Showing Up On Time - Herding Cats

There is a notion - a wrong notion - that the critical path is the path through the network of activities with zero slack. If you have a zero slack network, you're late before you start.

All IMPORTANT items in your project need protection. That protect is called schedule margin.

In the scheduling world, NEVER have the important work on the critial path without schedule margin.

Don't Use Slack Time for Anything Other Than Deliverables Protection

So In The End

  • No schedule margin - you're late
  • Never put important stuff on the critical path with schedule margin
  • Plan all work, never leave anything left over to do when you have free time
  • It's the off critical path items that will kill your project when they get on the critical path because you weren't watching them. Watch everything, all the time.
  • Use Monte Carlo - all project numbers are random numbers. Knowing the Probability Distribution Function is the start, then knowing the drivers - things that push other things - and their PDF's provide decision points about keeping things off the path.

Showing Up On Time

Hogyan lehet egy vállalat világszínvonalú rövid idő alatt? - ITÉlet

  • Az átalakítás tapasztalatait, illetve a mozgatórugóit szeretném most megosztani.
  • Technológia helyett emberek, folyamatok és tudás
  • az IT hatékonysága, mérete és a felhasználók elégedettsége nem technológiai kérdés.
  • A rosszul működő IT osztályból világszínvonalút faragni 5 év alatt az óriási lépés. Sőt, sok-sok óriási lépés. Az átalakítás radikális volt, sok konfliktussal járt. Sok jó munkatárs elment a cégtől, másokat kirúgtak.
  • Lépésről lépésre
  • A világszínvonal eléréséhez nagy utat kellett megtenni, de nem lehetett mindent egyszerre megváltoztatni. Egyszerre csak mindig egy dolog változott, de az jelentősen.
  • Felülről lefelé
  • vasszigorral, diktatórikus módszerekkel felülről vezérelték.
  • A radikális változások egyértelműen egy új felsővezető érkezéséhez köthetők.
  • Ötletek helyett másolás
  • a cég egyszerűen fogta a legjobb gyakorlatokat, az adott sztenderdet és lemásolta.
  • az átalakítások miatt sok volt a konfliktus.
  • Erős költségcsökkentés
  • Legyünk pragmatikusak: az IT szervezet hatékonyabbá tétele azt is jelenti, hogy kevesebb ember fog olcsóbban az eddigieknél jobb szolgáltatást nyújtani.
  • A változással járó lépésekre ez a 3 fázis volt jellemző:
    1. Directing: Az új módszer bevezetése eldöntött tény, azt felülről vezérelve végrehajtják, részvétel kötelező, beleszólás minimális. Az ellenállást erővel letörik.
    2. Supporting: Elindul az új módszer. A munkatársak megkapnak hozzá minden segítséget (oktatás, dokumentáció, felsővezetői segítség). Ha valakinek gondja van, akkor támogatást kap hogy jól tudja csinálni.
    3. Delegating: A módszert mindenki ismeri és működik. A munkatársak hatalmat kapnak, javaslatokat tehetnek, javíthatnak a folyamaton, jöhetnek az ötletek.
  • Közös alap a közös cél

Hogyan kell egy új menedzsert beilleszteni? - ITÉlet

  • Az új kolléga beillesztése és betanítása nagyon is pénzbe vágó kérdés.
  • Hogyan kellene ezt jól csinálni?
  • Mint minden munkakörben, itt is fontos, hogy tiszta és világos célja legyen az új menedzser felvételének. Sajnos ez nem így szokott lenni.
  • Csakis akkor vegyünk fel valakit, ha nagyon pontosan el tudjuk magyarázni egy 5 éves gyereknek is, mi lesz az illető dolga.
  • A tiszta és világos cél alapján a jelölttel tisztázni az elvárásokat, és ennek alárendelni a kiválasztást (pont mint akármilyen más pozíciónál).
  • Mint minden más munkakörben, a menedzser esetén is fontos, hogy az első pár hónapot betanulással töltse. Egy fejlesztőt se engednek oda azonnal a kódhoz, tehát a menedzser nyakába sem szabad azonnal felelősséget tolni.
  • első hónapban a menedzser egyébként sem csinál mást, csak ismerkedik, figyel és jegyzetel. A legjobb, legdrágább, legtapasztaltabb menedzserek is.
  • a menedzser betanulási ideje az átlagosnál hosszabb. Fél év után lesz 80%, és 12 hónap kell a 100% eléréséhez. Ez a munkakörből adódik.
  • A beillesztésen nagyon sokat segít vagy ront, hogy milyen segítséget kap a menedzser.
  • Ahhoz, hogy egy menedzser teljes értékű legyen, az alábbi ismeretekre van szüksége:
    • Az összes embert megismerni, akivel valaha is kapcsolatba kerülhet
    • Az összes fontos emberrel személyesen találkozni
    • Az összes folyamatról dokumentációt és oktatást kapni
    • Az összes szoftverről amit használni kell (teleconf eszköz, dokumentumtár, csoportmunka eszköz, könyvelési rendszer, reporting rendszer, stb) oktatást és dokumentációt kapni
    • Teljes és átfogó képet kapni az elvégzendő munka szakmai oldaláról
  • Az a legjobb, ha létezik egy betanulási terv,
  • A menedzser beillesztésének fontos lépése az, amikor a menedzser és főnöke tisztázza a szokásokat és a közös munka alapjait.
  • Ugyanennyire fontos dolog, hogy az új menedzsert ellenőrizni kell.
  • Új menedzser esetén fontos az önbizalom felépítése. Ami azért érdekes, mert akkor lesz önbizalma ha nem hibázik, márpedig ő új ember aki még nem ismeri a dörgést

Speed Hashing - Coding horror

Az abszolút minimum amit tudni kell a hash függvényekről, digitális aláírásról és jelszavakról.

If you are a user:

Make sure all your passwords are 12 characters or more, ideally a lot more. I recommend adopting pass phrases, which are not only a lot easier to remember than passwords (if not type) but also ridiculously secure against brute forcing purely due to their length.

If you are a developer:

Use bcrypt or PBKDF2 exclusively to hash anything you need to be secure. These new hashes were specifically designed to be difficult to implement on GPUs. Do not use any other form of hash. Almost every other popular hashing scheme is vulnerable to brute forcing by arrays of commodity GPUs, which only get faster and more parallel and easier to program for every year.

Speed Hashing

Pollozó megoldás

Pollozó megoldás

Igazából pollozó megoldást nem kell nagyon programkóddal igazolni, mert alapvetően újgyakorlatnak kell lennie:

  1. Könyvtár rekurzív bejárása és megjegyzése
  2. várakozni egy kicsit
  3. Könyvtár rekurzív bejárása és megjegyzése.
  4. Összehasonlítani a 1. és 3. pont eredményeit
  5. Különbség kiértékelése alapján lehet továbblépni

Előnye, hogy

  • nem kell operációs rendszer támogatás
  • kis adaptációval akár egy távoli FTP rendszer monitorozását is meg lehet oldani
  • Oprendszer támogatott megoldásokkal ellentétben távoli könyvtárakon is megbízhatóan működik
  • Komplex fájlrendszerbeni változásokat könnyebb lekövetni

Hátránya:

  • a már korábban említett folyamatos könyvtárbejárás
  • sok idő, ha a fájlrendszer lassú
  • nagy könyvtárszerkezetnél a bejárás nagyon rendszerterhelő

Ami viszont érdekesnek találtam az a jpoller. Főleg azért érdekes, mert olyan rémületes ábrája van, hogy még átnézni sem volt kedvem, nem hogy megérteni :)

JPoller class diagram

Java 7 NIO notification

Java 7 NIO notification

Igazából ide nincs milyen példát felhozni, hiszen csaknem ugyan az, mint a JPathwatch. Szinte csak az importokat kell lecserélni.

Jellemzője:

  • java 7. Még friss és sokáig tipikusan a üzleti alkalmazásoknál nem fognak gyorsan váltani.
  • alapból nem kezeli a rekurzív könyvtár vizsgálatot.
  • a többi kb a JPathwatch-nál leírtak.

Rekurzív könyvtárvizsgálat

Ugyan alapbül nem támogatja, de azért természetesen megoldható. A WatchDir.java példában következő módon:

    /**
     * Register the given directory with the WatchService
     */
    private void register(Path dir) throws IOException {
        WatchKey key = dir.register(watcher, ENTRY_CREATE, ENTRY_DELETE, ENTRY_MODIFY);
        if (trace) {
            Path prev = keys.get(key);
            if (prev == null) {
                System.out.format("register: %s\n", dir);
            } else {
                if (!dir.equals(prev)) {
                    System.out.format("update: %s -> %s\n", prev, dir);
                }
            }
        }
        keys.put(key, dir);
    }

/**
 * Register the given directory, and all its sub-directories, with the
 * WatchService.
 */
private void registerAll(final Path start) throws IOException {
    // register directory and sub-directories
    Files.walkFileTree(start, new SimpleFileVisitor<Path>() {
        @Override
        public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs)
            throws IOException
        {
            register(dir);
            return FileVisitResult.CONTINUE;
        }
    });
}

További kapcsolódó linkek:

JPathwatch

JPathwatch

Példaprogram a következő:

public class JPathwatchSample {

public static void main(String[] args) throws Exception { WatchService watchService = FileSystems.getDefault().newWatchService(); Path watchedPath = Paths.get("c:/temp"); WatchEvent.Kind[] eventsToWatch = new WatchEvent.Kind[] { StandardWatchEventKind.ENTRY_CREATE, StandardWatchEventKind.ENTRY_DELETE, StandardWatchEventKind.ENTRY_MODIFY, StandardWatchEventKind.OVERFLOW, ExtendedWatchEventKind.ENTRY_RENAME_FROM, ExtendedWatchEventKind.ENTRY_RENAME_TO, }; WatchKey key = null; try { key = watchedPath.register(watchService, eventsToWatch, ExtendedWatchEventModifier.FILE_TREE); } catch (UnsupportedOperationException uox) { System.err.println("file watching not supported!"); } catch (IOException iox) { System.err.println("I/O errors"); }

for (;;) {
  // take() will block until a file has been created/deleted
  WatchKey signalledKey;
  try {
    signalledKey = watchService.take();
  }
  catch (InterruptedException ix) {
    continue;
  }
  catch (ClosedWatchServiceException cwse) {
    System.out.println("watch service closed, terminating.");
    break;
  }

  // get list of events from key
  List<WatchEvent<?>> list = signalledKey.pollEvents();

  // VERY IMPORTANT! call reset() AFTER pollEvents() to allow the
  // key to be reported again by the watch service
  signalledKey.reset();

  System.out.println("--------------------------------");
  // we'll simply print what has happened; real applications
  // will do something more sensible here
  for (WatchEvent e : list) {
    String message = "";
    if (e.kind() == StandardWatchEventKind.ENTRY_CREATE) {
      Path context = (Path) e.context();
      message = context.toString() + " created";
    }
    else if (e.kind() == StandardWatchEventKind.ENTRY_DELETE) {
      Path context = (Path) e.context();
      message = context.toString() + " deleted";
    }
    else if (e.kind() == StandardWatchEventKind.ENTRY_MODIFY) {
      Path context = (Path) e.context();
      message = context.toString() + " modified";
    }
    else if (e.kind() == ExtendedWatchEventKind.ENTRY_RENAME_FROM) {
      Path context = (Path) e.context();
      message = context.toString() + " renamed from";
    }
    else if (e.kind() == ExtendedWatchEventKind.ENTRY_RENAME_TO) {
      Path context = (Path) e.context();
      message = context.toString() + " renamed to";
    }
    else if (e.kind() == StandardWatchEventKind.OVERFLOW) {
      message = "OVERFLOW: more changes happened than we could retreive";
    }
    System.out.println(message);
  }
}

} }

Jellemzői:

  • java 5
  • java 7 api kompatibilis, ami jó. Könnyen át lehet állni java7-re
  • java 7 api kompatibilis, ami rosz. Nem szép az API. pl:
    • StandardWatchEventKinds: Milyen elbaszott egy név
    • ENTRY_CREATE: Minden esemény ENTRY-vel kezdődik. De mivel egy konstans család tagjai teljesen felesleges. Persze a CREATE, MODIFY, stb szavak könnyen ütközhetnek más API-val, de akkor miért pont az ENTRY-vel prefixelt. Prefix sem kell, ha nem az elbaszott StandardWatchEventKinds osztályba tartozik.
    • Kicsit kibővíti a java7-es API-t. Maguk a kibővítések jók (például a rekurzív figyelés). De emiatt lesz teljesen kompatibilis.
  • rekurzívan is tud figyelni könyvtárszerkezetet
  • szinkron API.
  • szálat blokkolva (take()) és nem blokkolva (poll()) is használható.
  • egy take() hívásra egyszerre több eventet is kapunk, amiből lehet következtetni a végrehajtandó műveletre.
  • Könyvtár létrehozás:
    • dir created
  • könyvtár törlése:
    • dir deleted
  • file létrehozása
    • file.txt created
  • file módosítása
    • file.txt modified
  • file átnevezése
    • file.txt renamed from
    • file2.txt renamed to
  • file törlés
    • file2.txt deleted
  • kicsi file másolása a figyelt könvtárba
    • stylesheet.css created
    • stylesheet.css modified
    • stylesheet.css modified
  • nagy file másolása
    • alcatraz.101.hdtv-lol.avi created
    • alcatraz.101.hdtv-lol.avi modified
    • újjabb event handling ciklus
    • alcatraz.101.hdtv-lol.avi modified
  • alkönyvtár létrehozás
    • dir\subdiir created
    • dir modified
  • alkönyvtárban file ltrehozás
    • dir\subdiir\subfile.txt created
    • dir\subdiir modified
  • alkönyvtárban file módosulás
    • dir\subdiir\subfile.txt modified

File másolás kezelésére itt készítő tanácsa (FAQ):

Can I use jpathwatch to find out when a program finished writing to a file?

This is a bit tricky, but doable. First of all the problem is that most operating systems do not provide events for that, all they report is if a file has been created, modified or deleted in a directory, which is what jpathwatch passes back to your application code.

So effectively, you can find out when a program writes to a file, but you can’t find out when it’s done with it.

What I recommend in this case is to use heuristics: Assume that a process is done writing to a file when the file isn’t modified for a while (say, ten seconds or so).

Assume you watch a directory on an FTP server, and you want to pick up files after they have finished uploading to that directory.

In a loop, you poll() on the WatchService for events on that directory. For each file that is created or modified (ENTRY_CREATE/ENTRY_MODIFY), you store the time of the last event on that file. Maintain a sorted list of these times; the oldest file in the list is the one that is going to expire first. Remove files that have expired from your sorted list (calculate if their last event time plus the timeout is less than the current time) and flag them as ‘done’.

For the now oldest file in your list that hasn’t expired yet, calculate the time until it will expire, and call poll() with that duration. If you have no more files in your list, call take() instead of poll() to wait for new files to appear.

Az én kis problémámra a következő implementációt hoztam össze.

Másodjára implementálva a megoldást kiderül, hogy a JNotify esetén mely kódrészleteket tudom újra felhasználni. A JNotify-ban megismert BatchExecutor nagyon jól ki lehet emelni. A szemafor váltogatást interfész mögé teszem és már egy csomó mindent nem kell újra megírnom.

public interface IWorkerSemafor {
  public void working();
  public void notWorking();
}

class BatchExecutor implements Runnable { private final IWorkerSemafor semafor;

BatchExecutor(IWorkerSemafor semafor) { this.semafor = semafor; }

@Override public void run() { this.semafor.working(); try { Thread.sleep(1 * 1000); // 1 sec } catch (InterruptedException e) { return; } finally { this.semafor.notWorking(); } try { System.out.println("executing command... "+new Date()); Runtime.getRuntime().exec("cmd /c build.bat "); } catch (IOException e) { e.printStackTrace(); } } }

És a következő egyszerű kódot írtam, hogy meghajthassam a funkcionalitást:

public class JPathwatchSample2 {

public static void main(String[] args) throws Exception { Thread watcherT = new Thread(watcher); watcherT.start(); System.out.println("JPathwatch: Press CTR+C to stop"); for (;;) { Thread.sleep(1000); } }

static volatile boolean workerRunning = false;

static Runnable watcher = new BackgroundWatcher();

static class BackgroundWatcher implements Runnable, IWorkerSemafor { public void run() { WatchService watchService = FileSystems.getDefault().newWatchService(); Path watchedPath = Paths.get("c:/temp"); setup(watchService, watchedPath); for (;;) { WatchKey signalledKey; try { signalledKey = watchService.take(); } catch (InterruptedException ix) { continue; } catch (ClosedWatchServiceException cwse) { System.out.println("watch service closed, pls exit"); break; } List<WatchEvent<?>> list = signalledKey.pollEvents(); signalledKey.reset(); if (workerRunning) { continue; } if (null == list || 0 == list.size()) { continue; } Thread worker = new Thread(new BatchExecutor(this)); worker.start(); } } private void setup(WatchService watchService, Path watchedPath) { WatchEvent.Kind<?>[] eventsToWatch = new WatchEvent.Kind[] { StandardWatchEventKind.ENTRY_CREATE, StandardWatchEventKind.ENTRY_DELETE, StandardWatchEventKind.ENTRY_MODIFY, StandardWatchEventKind.OVERFLOW, ExtendedWatchEventKind.ENTRY_RENAME_FROM, ExtendedWatchEventKind.ENTRY_RENAME_TO, }; WatchKey key = null; try { key = watchedPath.register(watchService, eventsToWatch, ExtendedWatchEventModifier.FILE_TREE); } catch (UnsupportedOperationException uox) { uox.printStackTrace(); } catch (IOException iox) { iox.printStackTrace(); } } @Override public void working() { workerRunning = true; } @Override public void notWorking() { workerRunning = false; } }; }

JNotify

JNotify

Nativ megoldás. Az operációs rendszer értesít a változásokról.

A websiton található sample minimális átirat.

public class JNotifySample {

public static void main(String args[]) throws Exception { // path to watch String path ="c:/TEMP";

// watch mask, specify events you care about,
// or JNotify.FILE_ANY for all events.
int mask = JNotify.FILE_CREATED |
    JNotify.FILE_DELETED |
    JNotify.FILE_MODIFIED |
    JNotify.FILE_RENAMED;

// watch subtree?
boolean watchSubtree = true;

// add actual watch
int watchID = JNotify.addWatch(path, mask, watchSubtree, new Listener());

// sleep a little, the application will exit if you
// don't (watching is asynchronous), depending on your
// application, this may not be required
Thread.sleep(1000000);

// to remove watch the watch
boolean res = JNotify.removeWatch(watchID);
if (!res) {
  // invalid watch ID specified.
}

}

static class Listener implements JNotifyListener { public void fileRenamed(int wd, String rootPath, String oldName, String newName) { print("renamed " + rootPath + " : " + oldName + " -> " + newName); }

public void fileModified(int wd, String rootPath, String name) {
  print("modified " + rootPath + " : " + name);
}

public void fileDeleted(int wd, String rootPath, String name) {
  print("deleted " + rootPath + " : " + name);
}

public void fileCreated(int wd, String rootPath, String name) {
  print("created " + rootPath + " : " + name);
}

void print(String msg) {
  System.err.println(msg);
}

} }

Működésének jellemzői:

  • Aszinkron értesítés folyik. Semmi ráhatásunk nincs, hogy mikor kapjuk az értesítést.
  • Könyvtár létrehozás:
    • created c:/TEMP : notify\dir az új könyvtár létrehozása
    • modified c:/TEMP : notify szülő könyvtár módosulása(!)
  • könyvtár törlése:
    • deleted c:/TEMP : notify\dir
    • modified c:/TEMP : notify
  • file létrehozása
    • created c:/TEMP : notify\file.txt
    • modified c:/TEMP : notify
  • file módosítása
    • modified c:/TEMP : notify\file.txt
  • file átnevezése
    • renamed c:/TEMP : notify\file.txt -> notify\file2.txt
    • modified c:/TEMP : notify
    • modified c:/TEMP : notify\file2.txt
    • modified c:/TEMP : notify\file2.txt
  • file törlés
    • deleted c:/TEMP : notify\file2.txt
    • modified c:/TEMP : notify
  • file másolása a figyelt könvtárba
    • created c:/TEMP : notify\alcatraz.101.hdtv-lol.avi
    • modified c:/TEMP : notify
    • modified c:/TEMP : notify\alcatraz.101.hdtv-lol.avi
    • modified c:/TEMP : notify\alcatraz.101.hdtv-lol.avi
  • külső librarikat kell futtató környezetnek adni a -Djava.library.path= jvm argumentummal
  • alap file műveletekre komplex értesítés érkezik, ami jó
  • alap file műveletekre komplex értesítés érkezik, ami rossz
  • java 5
  • rekurzívan tud könyvtárakat figyelni

Elég körülményes egy buildelő rendszert ráépíteni, mert a file módosításon kívül igen komplex értesítéseket kapunk. Amire lehet egy kicsit építeni az az, hogy bármi is történik vagy a file vagy egy könyvtár módosul. A gond az, hogy többször is. Ha több fájlról van szó, akkor meg állományonként, ami igen nagy.

Igen részletesen lehet az fájlrendszer értesítéseit elkapni, de pont emiatt nagyon nehéz egy olyan egyszerű funkcionalitást is ráépíteni mint az én kis dokumentum fordításom.

A probléma megoldása lehet az, hogy ha értesülünk az eseményről:

  1. lekapcsolódunk az eseményekről egy kicsit, elvégre már az első esemény is elegendő.
  2. Várunk egy kicsit, hogy a folyamatban lévő műveletek be tudjanak fejeződni.
  3. Visszaállunk figyelésre. A végrehajtandó tevékenység lehet, hogy annyi ideig tart, hogy közben teljesen valid másik file esemény megtörténte is.
  4. Végrehajtjuk amit akarunk.

A triggerelt esemény végrehajtásának hosszától függően a 3. és 4. esemény fel is cserélhető.

Konkrétan:

Csupaszítsuk le egy kicsit az alapprogramot:

public class JNotifySample2 {
  public static void main(String args[]) throws Exception {
    String path = "c:/TEMP/notify";
    int mask = JNotify.FILE_CREATED |
        JNotify.FILE_DELETED |
        JNotify.FILE_MODIFIED |
        JNotify.FILE_RENAMED;
    boolean watchSubtree = false;
    JNotify.addWatch(path, mask, watchSubtree, new JNotifyExecutorListener());
    System.out.println("Press CTR+C to stop...");
    for (; true;) {
      Thread.sleep(10000);
    }
  }
}

És a listenert is készítsük el:

package public class JNotifyExecutorListener extends JNotifyAdapter {
  volatile boolean executing = false;
  static void  p(String s){
    System.out.println(s);
  }
  @Override
  public void fileModified(int wd, String rootPath, String name) {
    p("modification is notified");
    if(!name.endsWith(".txt")){
      return;
    }
    p("executing something? "+executing);
    if (!executing) {
      p("start the BatchExecutor thread");
      Thread t = new Thread(new BatchExecutor());
      t.start();
    }
    p("modification handler method end");
  }

class BatchExecutor implements Runnable { @Override public void run() { p("setting to execution..."); // Indicating that it make no sense to executing = true; p("executing something (BatchExecutor)? "+executing); try { p("sleep a bit..."); Thread.sleep(1 * 1000); // 1 sec } catch (InterruptedException e) { p(e.toString()); return; } finally { p("setting back flag"); // ready to catch the next event executing = false; } p("executing something (BatchExecutor 2)? "+executing);

  try {
    p("Start command line...");
    Runtime.getRuntime().exec("cmd /c Path_to/build.bat ");
  }
  catch (IOException e) {
    e.printStackTrace();
  }
  p("command is ready");
}

} }

Java directory watcher

Miért java-val kezdem?

Egyrészt ebben van a legnagyobb tapasztalatom. Másrészt ha ez megvan, akkor megvan minden olyan nyelvben is, amit kedvelek (Ruby/JRuby, Scala) egy jó kis wrapper API-val.

Kell itt refactorálni?

Scala By Example - Martin Odersky

Nagyszerű kiegészítés a Scala for Impatient-hez.

Scala by example

Free book

Scala for the Impatient - Cay Horstmann

Scala for the impatient

Az ami a Programming in Scala könyv nem. Rövid gyors. Ugyan nem teljesen részletekbe menő, de napi szinten használható hátteret ad és útmutatást ahhoz, hogyan keresd elő a részleteket.

Persze nem teljes. De kezdésnek már tökéletesen elegendő. Sokkal hamarabb kedvet kapsz hozzá, mint mondjuk a 800 oldalnyi referencia könyv olvasása során.

Tartalom átvétel