wtorek, grudnia 18, 2012

Tuning GFS2

echo 2048 > /sys/kernel/config/dlm/cluster/lkbtbl_size
echo 2048 > /sys/kernel/config/dlm/cluster/rsbtbl_size
echo 2048 > /sys/kernel/config/dlm/cluster/dirtbl_size

czwartek, grudnia 13, 2012

BW parallel processing

Long lasting activities are put into spawned processes. Spawned processes share responses via Wait/Notify BW mechanism. Schema for response is a choice of all results/errors from all called activities. First wait can get response from any spawned process, the same if for subsequent Wait calls.

How to make compensations for this kind of process? Subprocess after failed notify should revert its actions, main process does necessery waiting and responds to client with success or error, when from first wait we get fatal error which should break other subprocess call, we do not wait for other calls - they will be reverted.

poniedziałek, grudnia 10, 2012

__caret_closure_caret_ i __caret_userClosure_caret_

Wywołania adapterowe Tibco BW zawierają pola __caret_closure_caret_ i __caret_userClosure_caret_. Pola te z założenia są generyczne i przeznaczone do adapterów każdego typu, ale mogą przenosić informacje sterujące adaptera konkretnego typu. W Tibco Designerze te elementy widoczne są bez ściśle określonego typu XSD. W przypadku adaptera SAP R/3 w większości przypadków nie należy się klauzurkami przejmować, póki nie zawierają parametrów kontrolujących wywołania RFC. Element __caret_closure_caret_ powinien być rzutowany i przepisywany jako binary/base64, zaś __caret_userClosure_caret_ powinien mieć koercję do AESchemas/ae/SAPAdapter40/classes/RFCCLOSURE.

Wykrywanie kodowania znaków w requescie HTTP

String acceptCharset = request.getHeader(ACCEPT_CHARSET);
Charset charset = getBestCharset(acceptCharset!=null ? acceptCharset :
 getCharsetFromContentType(request.getHeader(CONTENT_TYPE), content));
  
    private static Charset getBestCharset(String acceptCharset) {
        if (acceptCharset==null)
            return CharsetUtil.UTF_8;
        StringTokenizer st = new StringTokenizer(acceptCharset, ",");
        while (st.hasMoreTokens()) {
            try {
                return Charset.forName(st.nextToken().trim());
            }
            catch (Exception exc) {};
        }
        return CharsetUtil.UTF_8;
    }
 
    private static String getCharsetFromContentType(String ct, ChannelBuffer data) {
        ct = ct!=null ? ct.toLowerCase() : "";
        int charsetPos = ct.indexOf("charset=");
        if (charsetPos!=-1) {
            for (int i=charsetPos+8; i < ct.length(); i++) {
                if (!Character.isLetterOrDigit(ct.charAt(i))) {
                    return ct.substring(charsetPos+8, i);
                }
            }
        }
        if (data!=null) {
            int win1250_score = 0;
            int iso8859_2_score = 0;
            for (int i=0; i < data.readableBytes(); i++) {
                int b = (data.getByte(i) & 0xff);
                if (b == '%') {
                    if (i+2 < data.readableBytes()) {
                        try {
                            b = Integer.rotateLeft(getHex(data.getByte(i+1)), 4) + getHex(data.getByte(i+2));                           
                        }
                        catch (Exception parseExc) {}
                    }
                }
                for (int k=0; k < WIN1250.length; k++) {
                    if (b == WIN1250[k])
                        win1250_score++;
                    else if (b == ISO_8859_2[k])
                        iso8859_2_score++;
                }
            }
            System.out.println(win1250_score+"/"+iso8859_2_score);
            if (win1250_score > 0 && win1250_score >= iso8859_2_score)
                return "windows-1250";
            if (iso8859_2_score > 0 && iso8859_2_score >= win1250_score)
                return "iso-8859-2";
        }
        return null;
    }
 
    private final static int getHex(byte b) {
        int c = b & 0xff;
        if (c >= '0' && c <= '9')
            return c-'0';
        if (c >= 'a' && c <= 'f')
            return 10+c-'a';
        if (c >= 'A' && c <= 'F')
            return 10+c-'A';
        throw new RuntimeException("Char "+c+" is not valid hex");
    }
 
    /* ąśźĄŚŹ */
    private final static int WIN1250[] = { 185,156,159,165,140,143 };
    private final static int ISO_8859_2[] = { 177,182,188,161,166,172 };

piątek, grudnia 07, 2012

Kradzież kodu: T-Mobile obwinia Software Mind

Szanowny Panie,
Bardzo dziękujemy za zawrócenie uwagi PTC na problem związany z produktem dostarczanym przez jednego z naszych dostawców, firmę Software Mind SA, z siedzibą przy ul. Bociana 22A w Krakowie (dalej "Software Mind").
Jako firma ceniąca sobie etyczne działania w biznesie, dzięki Pana informacjom rozpoczęliśmy wewnętrzny proces wyjaśnień z dostawcą.

Chcielibyśmy jednocześnie zaznaczyć, że jakiekolwiek dalsze kwestie, związane z wykorzystaniem przez firmę Software Mind Pańskiej własności intelektualnej powinien Pan kierować bezpośrednio do rzeczonej firmy.

Pozdrawiam,
Piotr Chmiel

Kierownik, Dział Zarządzania Zgodnością
Polska Telefonia Cyfrowa S.A.

czwartek, grudnia 06, 2012

Tibco BW FlowLimit


FlowLimit jest zaimplementowany w taki sposób, że po jego przekroczeniu wyłączany jest starter (onStop) aż do momentu, kiedy zwolnią się wszystkie wątki obsługujące proces startera. Jeśli FlowLimit wynosi 20 a podłączonych jest 30 klientów, którzy ciągle wywołują jednowątkowo usługę SOAP over HTTP, to 10 klientów będzie obserwowało długi czas połączenia, odmowę połączenia (connection refused) lub błąd HTTP 503 Service Unavailable. Czekanie na zwolnienie wszystkich wątków wykonawczych jak i różne zachowania przy odrzucaniu żądania (w dodatku bez jakiegokolwiek śladu w logach BW!) budzą zastrzeżenia. Proces obsługi żądania powinien sprawdzać stan nasycenia puli wykonawczej i jeśli nie jest ona pełna pozwalać na stworzenie eventu BW i w rezultacie wykonanie procesu. Jeśli kolejka oczekujących żądań jest zbyt długa i nie maleje, to wykraczający poza limit komunikat powinien być szybko odrzucany. Oryginalna implementacja Tibco tak ładnie się nie zachowuje, wyraźnie widoczna jest czkawka. Całe szczęście własny Java Event Starter pozwala na stworzenie własnych bardziej deterministycznych lekkich usług, w których dbamy o opóźnienia, przepustowość i niezawodność.

poniedziałek, grudnia 03, 2012

Denial of Service attack against Tibco EMS

In a loop with every iteration create 50 000 producers on one session and then close it. On session close server will be deleting information about session from metadb and this activity will slow down whole server causing massive timeouts. It will be impossible to access services hosted on EMS.

sobota, grudnia 01, 2012

HornetQAIO64.dll

Sportowałem na szybko libhornetqaio64.so pod 64-bitowe Windows. Binarka jest dla serwera 2.2.14. Przy odrobinie konsekwencji da się zmapować API jeden do jednego. Asynchroniczne operacje I/O dają serwerowi JMS HornetQ duży wzrost wydajności na Linuksie.

poniedziałek, listopada 26, 2012

NVidia driver registry config


Skoda Rapid

Najmniejszy sedan Skody ma 4,48m. Skoda Octavia ma 4,57m a Volkswagen Jetta 4,64m. Bagażnik jest spory, ale przez to tylna szyba jest płaska, co powoduje słabą widoczność do tyłu. Bardzo przyzwoita jakość materiałów.





sobota, listopada 24, 2012

ICC antiblue color profiles

Workaround na niebiesko-zielone ekrany LCD.

piątek, listopada 23, 2012

Z książki 'Modele i zastosowania systemów czasu rzeczywistego'








czwartek, listopada 22, 2012

Przykłady na schemacie Oracle HR

select sys.dbms_xmlgen.getxml('select e.first_name || '' '' || e.last_name as full_name, d.manager_id as manager_id, d.department_name, l.city, cursor(select em.first_name || '' '' || em.last_name as full_name, j.job_title from hr.employees em, hr.jobs j where em.manager_id = d.manager_id and em.job_id = j.job_id) as employee from hr.departments d, hr.employees e, hr.locations l where d.location_id = l.location_id and (l.city like ''' || ? ||  ''') and e.employee_id = d.manager_id') as xml from dual

środa, listopada 21, 2012

Zamiennik solarisowego /etc/project w Linuksie

mkdir /cgroup
mount -t tmpfs cg /cgroup
mkdir /cgroup/cg-tibo-apps
mount -t cgroup cg-tibco-apps -o cpuset,cpu,memory,blkio /cgroup/cg-tibo-apps
mkdir /cgroup/cg-tibo-apps/bw-channel-crm
echo 0 > /cgroup/cg-tibo-apps/bw-channel-crm/cpuset.cpus
echo 0 > /cgroup/cg-tibo-apps/bw-channel-crm/cpuset.mems
echo 2000 > /cgroup/cg-tibo-apps/bw-channel-crm/cpu.shares
echo `ps -ef | grep bwengine | grep bw-channel-crm | grep -v grep | awk '{print $2}' > /cgroup/cg-tibo-apps/bw-channel-crm/tasks

HornetQ 2.2.14 AIO 3x szybszy od Tibco EMS 6.3


1 milion komunikatów z bieżącą datą w body jest wysyłanych przez 22 procesy BW na jedną persystentną kolejkę JMS. HornetQ radzi sobie w 607 sekund, EMS w 1941 sekund. Klient to Windows 7, serwer to CentOS 5.8 - oba 64-bitowe, współdzielony storage to NFS. HornetQ jest tańszy i szybszy, nie ma błędów w obsłudze XA, nie ma limitu pamięciowego na ilość komunikatów w kolejce, po restarcie wznawia pracę od razu.

poniedziałek, listopada 19, 2012

Wieszający się out-of-box klient HornetQ


Domyślnie serwer blokuje klienta przed takim wysyłaniem wiadomości, które spowodowałoby przekroczenie limitu zasobów na serwerze - 10MB RAM per kolejka. Należy zmienić to konfiguracji dodając opcje page. Do diagnostyki produktów typu black box doskonale nadaje się Your Kit Java Profiler.

piątek, listopada 16, 2012

EMS server unresponsive

EMS preallocates linear datastore range chunks per sender. Too many concurrent producers (> 10 000) causes a lot of random I/O writes and as a result whole EMS server becomes unresponsive. Limit number of producers and consumers or buy fast SSD storage.

Although EMS messages are swapped to disk their headers and internal indices are kept in memory, so for every 1M messages you need 1GB RAM.

środa, listopada 14, 2012

Prosty test na XA

import java.io.FileOutputStream;
import java.io.PrintStream;
import java.util.Scanner;

import javax.jms.MessageConsumer;
import javax.jms.MessageProducer;
import javax.jms.TextMessage;
import javax.jms.XAConnection;
import javax.jms.XASession;
import javax.transaction.Transaction;
import javax.transaction.TransactionManager;
import javax.transaction.xa.XAResource;

import com.tibco.tibjms.TibjmsXAConnectionFactory;


public class Test {
 
 private static boolean canRun = true;
 private final static void runTest() throws Exception {
  final com.tibco.tibjms.TibjmsXAConnectionFactory xacf = 
   new  TibjmsXAConnectionFactory();
  xacf.setConnAttemptCount(60);
  xacf.setConnAttemptDelay(100);
  xacf.setConnAttemptTimeout(1000);
  xacf.setReconnAttemptCount(60);
  xacf.setReconnAttemptDelay(100);
  xacf.setReconnAttemptTimeout(1000);
  xacf.setServerUrl("tcp://node1:7222,tcp://node2:8222");
  Thread[] threads = new Thread[20];
  FileOutputStream fos = new FileOutputStream("C://xa.log");
  final PrintStream ps = new PrintStream(fos);
  for (int i=0; i < threads.length; i++) {
    threads[i] = new Thread() {
      public void run() {
        while (canRun) {
         XAConnection xaconn1 = null;
         XAConnection xaconn2 = null;
         TransactionManager tm = null;
         XAResource xares1 = null;
         XAResource xares2 = null;
         try {
          xaconn1 = xacf.createXAConnection();
          xaconn2 = xacf.createXAConnection();
          tm = com.arjuna.ats.jta
           .TransactionManager.transactionManager();
          tm.setTransactionTimeout(30);
          xaconn1.start();
          xaconn2.start();
          XASession sess1 = xaconn1.createXASession();
          XASession sess2 = xaconn1.createXASession();
          xares1 = ( sess1.getXAResource() ); 
          xares2 = ( sess2.getXAResource() );
          MessageConsumer bw1cons = 
           sess1.createConsumer(sess1.createQueue("test.bw1"));
          MessageConsumer fw1cons =
           sess1.createConsumer(sess1.createQueue("test.fw1"));
          MessageProducer bw1prod = 
           sess1.createProducer(sess1.createQueue("test.bw1"));
          MessageProducer fw1prod = 
           sess1.createProducer(sess1.createQueue("test.fw1"));
          tm.begin();
          tm.getTransaction().enlistResource(xares1);
          tm.getTransaction().enlistResource(xares2);
          ///
          TextMessage m = (TextMessage) bw1cons.receive(1000);
          if (m!=null)
           fw1prod.send(m);
          m = (TextMessage) fw1cons.receive(1000);
          if (m!=null)
           bw1prod.send(m);
          ///
          tm.getTransaction().delistResource(xares1,
           XAResource.TMSUCCESS);
          tm.getTransaction().delistResource(xares2,
           XAResource.TMSUCCESS);
          tm.commit(); 
         }
         catch (Exception e) {
          e.printStackTrace(ps);
          ps.flush();
          Transaction tr = null;
          try {
           tr = tm.getTransaction();
          }
          catch (Exception ex) {
           ex.printStackTrace(ps);
           ps.flush();
          }
          if (tr!=null) {
           try {
            tr.rollback();
           }
           catch (Exception ex) {
            ex.printStackTrace(ps);
            ps.flush();
           }
           try {
            tr.delistResource(xares1, XAResource.TMFAIL);
           }
           catch (Exception ex) {
            ex.printStackTrace(ps);
            ps.flush();
           }
           try {
            tr.delistResource(xares2, XAResource.TMFAIL);
           }
           catch (Exception ex) {
            ex.printStackTrace(ps);
            ps.flush();
           }
          }
         }
         finally {
          try {
           xaconn1.close();
          }
          catch (Exception ex) {
           ex.printStackTrace();
          }
          try {
           xaconn2.close();
          }
          catch (Exception ex) {
           ex.printStackTrace();
          }
         }
        }
       }
      };
    }
    for (Thread t : threads)
     t.start();
 }

public static void main(String[] args) throws Exception {
  System.out.println("Press q to stop.");
  runTest();
  Scanner sc = new Scanner(System.in);
  if (sc.nextLine().contains("q"))
    canRun = false;
  sc.close();
 }
}

Reklama Plus - OBA MA

piątek, listopada 09, 2012

Usługa ESB na wielu transportach


Świat idzie do przodu i ESB powinno wystawiać tę samą usługę jako SOAP over HTTP i SOAP over JMS, a od jakiegoś czasu oczekiwany jest REST+JSON. W Tibco do pierwszych dwóch można wykorzystać kontrolkę serwis, a do REST+JSON wystawić HTTP Receivera tłumaczącego wejście za pomocą biblioteki Staxon do XML-a i podać obiekt XML do tej samej implementacji serwisu.

czwartek, listopada 08, 2012

Kradnąc kod źródłowy zmieniaj nazwy zmiennych, stałych i metod

Błyskotliwy przykład kradzieży przez Software Mind wytwarzającego oprogramowanie dla operatora sieci komórkowej: pracownicy odszyfowali pliki class, zdekompilowali bajtkod Javy i przekleili bez zmian nazw zmiennych, metod, stałych. Przypadek naruszenia praw autorskich w Polsce można normalnie zgłosić do prokuratury, jest to procesowane z urzędu.

TDI to ponad 4000 linii wyspecjalizowanego kodu, 70 plików o rozmiarze około 150KB wytworzonych przez 3 lata o pracochłonności około 100 dniówek pracy dewelopera. Powstało pod wpływem prac rozwojowych dla Generali dotyczących wdrożenia Service Mix-a, kiedy okazało się, że interfejs JBI pozwala na podłączenie kodu audytującego przetwarzane komunikaty. Tibco BW posiada analogiczne listenery i takich używa TDI.

Update: Operator całą winą obarcza dostawcę, który nie poinformował, że odebrany produkt zawiera wady prawne i informuje, że w przypadku roszczeń względem operatora, zostaną zgłoszone przez niego roszczenia względem dostawcy.

środa, listopada 07, 2012

Architekt

Ilu architektów potrzebnych jest do EAI?
  • architekt od wypracowanych technologicznych standardów i bibliotek kodu (adaptuje technologie, tworzy frameworki, szablony, przykłady)
  • architekt od procesów wytwarzania oprogramowania (definiuje kroki związane z analizą, dewelopmentem, testowaniem, wdrażaniem, usuwaniem błędów)
  • architekt od standardów wytwarzania oprogramowania (definiuje przyjęte wzorce projektowe, techniki, zasady kodowania, używania API)
  • architekt od infrastruktury (sprzęt, sieć, storage, systemy operacyjne, wysoka dostępność)

środa, października 31, 2012

TDI4BW

TDI integrates with Tibco BW Engine and sees all executed processes and all data. It gathers basic runtime process statistics, can gather selected data flowing through processes (using XPath selectors called markers) and can gather detailed performance information per activity.
TDI can be integrated with Tibco BW in two ways:
  • TRA mode - modification of .tra file (independent from deployment, any deployed BW component can have TDI enabled; may be performed by IT Operations to analyze problems in production environment or to build BAM solution)
  • OnStartup mode - addition of OnStartup process (must be put into EAR file and deployed with whole project, usually used for analyzing single project during Friendly User Test/Trial Run)

Configuration can be done via params_table.

================================================================================
 Parameter           | Description               
================================================================================
 EXTRACT_NUMBERS^      values: *true,false;    Data extracted from XPath markers 
   is normalized: duplicates are removed, string and numbers representing the
   same values can be converted to numbers; extraction is greedy: q123456789
   will be converted to number 123456789
   
 TDI_CONFIG_FILE      value: path to config.env file with configuration props
   File is read at startup. TDI will also check for config.env file inside
   its jar file.
 
 TSI_ADDRESS          value: URL to Tibco Service Improvement endpoint receiving
   data from TDI, it can be URL in schema  host:port to use default HSQL db,
   it can be Oracle JDBC connection string 'jdbc:oracle:thin:HR/HR@host:1521:XE'
   or Cassandra URL 'cassandra:host:9160' or 'void' (no data upload).
   
 PROFILER^             values:yes,*no;   Flag to enable or disable profiler. 
   Profiler gathers statistics in the form: activityName -> execution time / 
   evaluation time + timestamp of start
   
 LOGGER^               values:yes,*no;    Flag to enabling logging of data from
   WriteToLog and Log4J activities; Data will be put the same way as from marker
   
 IGNORE_ERROR_TEXT^    value:*TDI_IGNORE_ERROR;   TDI sees all errors, both
   handled with error transition and unhandled. Some 'Generate Error' activities
   may be used in logging libraries/projlibs and so they should be ignored. This
   is exact text match - value can be in activity name, XML elements names or
   inside nodes' data.
   
 STALLED_JOB_TIME    value:*300000;  When job runs longer than given time
   it will be marked and reported as hung/stalled.
   
 WORK_INTERVAL       value:*10000;     Time interval between iterative event
   delivery to endpoint gathering data.
   
 PING_TIME           value:*60000;    Time interval between iterative ping event
   delivery to endpoint gathering data. Ping means that Tibco BW component is
   alive.
   
 MARKERS^             value: follow schema MARKER_$Name:$Value, where $Name can
   be string for non-indexed marker and number 1-4 for indexed marker. $Value
   is simple XPath expresion for selecting XML nodes, in which values devops
   are interested to. Example: MARKER_1://orders/orderId. When data matches
   marker expression the exact node value is stored as a marker value and
   also whole message is store in separate object.
 
 SKIP_MK_MESSAGE^     value:true,*false;   Skip gathering whole messages when
   one of its elements matches marker.
   
 CONN_POOL_LIFETIME   value:0-86400000;    Cache connection for given time.
   Zero means that connection pooling is disabled and connection is created
   for every event delivery.
   
-------------------------------------------------------------------------------
   Parameters marked ^ are reloaded in runtime during ping,
   others are loaded once at startup.

   
================================================================================
 File               | Description
================================================================================   
 tdi.jar/auto.cfg     URL for endpoint storing data, see parameter TSI_ADDRESS
 
 tdi.jar/config.env   File for storing configuration

 tdi.jar/bootstrap.sql for initial Oracle database configuration for TDI,
  put ojdbc5.tdi in the same path as tdi.jar
 
 tdi.jar/licence.txt  Licence checked on startup, TDI is free for non-production
   usage

środa, października 17, 2012

Zoo












I know kung-fu. Stay away.


I took online training.

 

Bezwypadkowy. Drugie auto w rodzinie. Jeździła kobieta niepaląca.



Dzieci wesoło wybiegły ze szkoły. Zapaliły papierosy.


Dwójka ze sternikiem


Wrocław







Kotek