15 Kasım 2014 Cumartesi

Supervisor Yazılım

Giriş
Yönetici yazılım (Supervisor) bileşenlerin durumlarını sorgulayarak, hayatta olup olmadıklarına bakarak tüm sistemin state'ini belirler. Eğer state değişmişse tüm bileşenlere duyurarak, herkesin yeni state'e uygun şekilde davranmasını ister. Yani Supervisor bir sistemin state değiştirmesi görevini yerine getiren yazılımdır.

UML
Sistemin state'leri arasındaki geçişleri görsel olarak çizmek için UML'deki State Diagram uygun olabilir.

Önce sistemin ne zaman state değiştireceğini gösteren bir şekil çizilir. Bu şekil geçiş koşullarını (transition criteria) gösterir. Belli şartlar sağlanırsa geçiş gerçekleşir. Örneğin bir cihazın hata vermesi, bir bileşenin heartbeat göndermeyi kesmesi (liveness'ın kaybedilmesi gibi)

Örnek sistem state'leri

State::Unknown --->
State::Operational<--->State::Degraded
                               |--->State::Failure

Design Pattern
Yönetici yazılımı geliştirirken de "State Pattern" tasarım örüntüsü kullanılabilir.

Periyodik Mesajlar Varsa Window Yöntemi
Örnek
Her saniye çalışan bir timer ve elimizde son 5 saniyelik veri olsun 
- En son 3 saniyede 3 mesaj almışsa sistem Operational State içindedir
- Eğer daha az mesaj almışsa bu sefer pencereyi biraz daha büyütür ve son 5 saniyeye bakar.
  Eğer 2 veya daha fazla mesaj almışsa sistem Degraded State'tedir. 
  Eğer 2'den de az mesaj almışsa sistem Not Operational State'tedir.

Örnek
Her saniye çalışan bir timer ve elimizde son 5 saniyelik veri olsun
- Eğer 5 saniye içinde 3 tane ardışık veri almışsa Operation State içindedir. Ardışık veri kontrolü için bu kod kullanılabilir. Şöyle yaparız
public boolean hasConsecutiveNumbers(List<Integer> list, int reqiredConsecutives) {

  boolean result = false;     
  int consecutives = 1;

  for (int i = 1; i < list.size(); i++) {
    // Going through each number here
    if (list.get(i) - list.get(i-1) == 1) {
      consecutives++; // Numbers were consecutive
      if (consecutives == reqiredConsecutives) {
        result = true;
        break;
      }
    } else {
      consecutives = 1;
    }
  }
  return result;
}

14 Kasım 2014 Cuma

C# Enumerable sınıfı

Giriş
Enumerable sınıfı IEnumerable<T> arayüzünü gerçekleştirir. Sınıfın arayüzden gelmeyen kendine özgü bazı metodları da vardır.

Empty metodu
Normalde şöyle bir kod olması beklenir.
public static IEnumerable<TResult> Empty<TResult>()
{
    yield break;
}

13 Kasım 2014 Perşembe

C++ ve Exception

Not : Bu konu ile ilgili olarak Linux Sinyalleri başlıklı yazıya göz atabilirsiniz.

Exception Bilgileri
C++ İle Exception yazısına taşıdım.

Uygulamadan Çıkma Bilgileri

std::terminate()
Bir exception atıldıktan sonra eğer onu yakalayan bir catch() ifadesi yoksa C++ tarafından std::terminate() fonksiyonu çağırılır. Bu fonksiyon da direkt std::abort() fonksiyonunu çağırır . std::abort isminden de belli olduğu gibi SGABRT sinyalinin gönderilmesine sebep olur ve uygulama kapanırken çağırmak üzere atadığı atexit() vs. gibi fonksiyonları işletemeden, yani temizlik yapamadan kapanır. Eğer işletim sisteminde gerekli ayarlar yapılmışsa bir core dosyası oluşturulur.

std::abort()
std::abort yazısına taşıdım.

std::set_terminate()
std::set_terminate yazısına taşıdım.

std::exit()
Aşağıdaki şekli buradan aldım ve std::exit()'in nasıl çalıştığını gösteriyor. Şeklin sadece ortasındaki exit function yazan kısmına bakarsak exit handler'ların çağırıldığı ve standart I/O cleanup yapıldığını görmek mümkün. std::exit() metodunun tek kötü tarafı stack üzerinde yaratılmış olan değişkenlere ait destructor'ların çağırılmaması, yani "Destructors of variables with automatic storage durations are not called." cümlesine dikkat etmek lazım.


Aşağıdaki atexit metodunun kodu var.
int atexit (void (* __func) (void) ) {
  if (atexitCurEntries >= atexitMaxEntries){
     return ERROR;
  }
  pAtexitTable [ atexitCurEntries ].__func = __func;
  atexitCurEntries++;
  return OK;
}
std::_Exit
Bu metod fork() ile başlatılan child process'leri bitirmek için kullanılır. Böylecek atexit() ile kaydedilen metodlar çalıştırılmaz. _Exit() bir C metodudur. _exit() ise POSIX çağrısıdır.

std::quick_exit()
Eğer static desctructorları çağırmak istemiyorsak ancak I/O streamler boşaltılsın istiyorsak std::quick_exit() metodunu da kullanmak faydalı olabilir.

std::atexit()
std::atexit yazısına taşıdım.

8 Kasım 2014 Cumartesi

Java Locale Sınıfı

Locale Nedir?
Uygulamalar farklı ülkelerin standartlarına göre çalışmak için, o ülkenin gösterim için kullandığı formatlama bilgisini kullanırlar. Bu formatlama bilgisini saklayan sınıfa Locale denilir.

Örneğin her ülkenin tarih, para, zaman için belirlediği ayraçlar bulunur. Nesnelerin toString() veya benzeri bir metodları çağrıldığında, otomatik olarak seçili locale'i kullanarak string oluşturmaları beklenir.

Örneğin DecimalFormat sınıfı atanmış locale'i kullanır.


JVM ve Locale
Türkçe çalıştırmak için aşağıdaki gibi yapılabilir.
java -Duser.country = TR -Duser.language = tr

Locale Sınıfı
Locale ile ilgili  herşey bu sınıf içinde.

Constructor metodu
Örnek:
Locale locale = new Locale("pt", "BR");
Bazı ülkelerin Locale nesneleri hazır geliyor. (France,Canada,China, US)
Locale.FRENCH
Locale.US
displayCountry metodu

locale.getDisplayCountry() ile ülke ismi alınır.

getAllAvailableLocales metodu

Örnek
for (Locale locale : Locale.getAvailableLocales()) {..}

7 Kasım 2014 Cuma

Task Parallel Library Data Flow

Task Parallel Library Data Flow (TPDL) Actor tabanlı bir çatı.

Actor Nedir?
Actor çatısı block ve pipeline kavramları üzerine inşa edilir. Actor tek thread'i ve bir kuyruğu olan bileşendir.

Actor şöyle tanımlanıyor.
"An actor is a completely isolated component that runs in its own thread. An actor doesn't have more than one thread and there's no concurrency to worry about as there's no shared state between actors. Each actor has its own copy of the data that it needs. Multiple actors can be composed together in a system and can talk to each other by passing messages between them."

TPDL kapsamında Actor yerine Block kelimesi kullanılıyor. Her block'un bir "buffer" ve bir de "task" bileşeni vardır.

Blocklar Birbilerine Nasıl Eklenir
Blokları birbirlerine eklemek için LinkTo metodu kullanılır.

Blocklar Nasıl Sonlandırılır
Block'ların Complete() metodunun çağırılması gerekir. Bir Block'un Comlete() metodu çağırılınca, bağlı olduğu diğer Block'ların da Complete() metodu tetiklenir.

Data Source Nedir?
Data Source TPDL ile kurulan bloklar için girdi üretir. InputBlock data source'tan veri okur ve pipeline'a sokar.

BufferBlock, BroadcastBlock gibi sınıflar veri üretirler.

ActionBlock
Her eklenen veri için bir action çağırır




5 Kasım 2014 Çarşamba

Bloom Filter - Probabilistic Data Structure - Nesne Var Diyorsa Yanılma İhtimali (False Positive) Bulunur

Giriş
Bloom Filter'ı şimdiye kadar hiçbir programda kullanmadım. Ama ilginç bir konu olduğunu düşündüğüm için not almak istedim.

Bloom vs Cuckoo Filter
Bloom Filtre silmeyi desteklemez. Silme isteniyorsa Cuckoo Filter kullanılmalı.

Bloom Filter Nedir?
Çok fazla sayıda nesneyi - örneğin 10 milyon tane - bir set/dictionary/map içinde bellekte tutmak istersek ve amacımız sadece nesnenin  veri yapısı içinde olmadığını bilmek ise bloom filter kullanılır. Açıklaması şöyle
When you ask a Bloom filter if it remembers a specific item, it will answer either “probably yes” or “definitely no.” If it says “probably yes” there’s a slight chance that it could be wrong. But if it says “definitely no” it’s totally confident about the answer.
Nasıl Çalışır
Bir tane büyük bit array yaratılır. Eklenmek istenen nesne N farklı hash'ten geçirilir. Her hash sonucunda array içindeki bir bit atanır. Nesne var mı kontrolü yapılmak istenirse tekrar N tane hash çalıştırılır. 
- Eğer bitlerden bir tanesi bile 0 ise nesne yoktur. 
- Tüm bitlerin 1 olması nesnenin var olduğu anlamına gelmez. False positive bir sonuç gelmiş olabilir.

Bazı Kullanım Örnekleri
1. Google Chrome
 Açıklaması şöyle
Whenever you try to access a URL, Google Chrome first checks with a local Bloom filter in your browser. This filter is filled with a list of hashed malicious URLs. If the Bloom filter returns “probably yes,” Chrome reaches out to Google’s servers for further verification. If the Bloom filter says “definitely no,” Chrome doesn’t bother with the server check, saving you time and preserving server resources.
2. Apache Cassandra and HBase
 Açıklaması şöyle
Instead of doing a slow disk read every time they need to check if specific data exists, these databases use a Bloom filter for a quick first check. The Bloom filter has a smaller memory footprint, which makes this operation much faster. If the Bloom filter returns “probably yes,” the system may perform a disk read to confirm. But if the filter says “definitely no,” the system avoids the disk read, saving a lot of time.
Yanlış Kullanım Örneği
Sosyal ağlarda A ve C kişileri eğer ortak B arkadaşları varsa, arkadaş olabiliyorlar. A ve C'nin ortak arkadaşları var mı diye kontrol etmek için bloom filter kullanılamaz. Çünkü bloom filter var derse bile yanılma ihtimali bulunur,  yani false positive  dönebilir.

Gerçekleştirim Örnekleri
Örnek
Şöyle yaparız
import java.util.BitSet;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;

public class BloomFilter {
  private BitSet bitSet;
  private int bitSetSize;
  private int numOfHashFunctions;

  public BloomFilter(int size, int numOfHashFunctions) {
    this.bitSetSize = size;
    this.numOfHashFunctions = numOfHashFunctions;
    this.bitSet = new BitSet(bitSetSize);
  }

  // Add element to Bloom Filter
  public void add(String url) throws NoSuchAlgorithmException {
    for (int i = 0; i < numOfHashFunctions; i++) {
      int hashCode = getHash(url, i);
      bitSet.set(Math.abs(hashCode % bitSetSize));
    }
  }

  // Check if element is present in Bloom Filter
  public boolean mightContain(String url) throws NoSuchAlgorithmException {
    for (int i = 0; i < numOfHashFunctions; i++) {
    int hashCode = getHash(url, i);
    if (!bitSet.get(Math.abs(hashCode % bitSetSize))) {
      return false;
    }
    }
    return true;
  }

  // Computes the i-th hash function for the given URL
  private int getHash(String url, int i) throws NoSuchAlgorithmException {
     MessageDigest md5 = MessageDigest.getInstance("MD5");
     md5.update(ByteBuffer.allocate(4).order(ByteOrder.LITTLE_ENDIAN).putInt(i).array());
     md5.update(url.getBytes());
     byte[] digest = md5.digest();
     int hash = ByteBuffer.wrap(digest).getInt();
     return hash;
  }
}
Kullanmak için şöyle yaparız
public static void main(String[] args) throws NoSuchAlgorithmException {
  BloomFilter bloomFilter = new BloomFilter(1000000, 3);

  // Add some URLs to the Bloom filter
  bloomFilter.add("http://example1.com");
  bloomFilter.add("http://example2.com");

  // Check if URLs are present in the Bloom filter
  System.out.println(bloomFilter.mightContain("http://example1.com")); // Outputs: true
  System.out.println(bloomFilter.mightContain("http://example3.com")); // Outputs: false
}
Guava
BloomFilter Sınıfı yazısına taşıdım


3 Kasım 2014 Pazartesi

Gömülü Proje Örnekleri

Giriş
Gömülü projelerde kullanılan bazı tasarımları aşağıda not aldım. Bu tasarımların en önemli özellikleri dinamin bellek kullanmamaları.

Unique_Ptr
Gömülü projelerde std::unique_ptr kullanamıyoruz. Bu yüzden kendi sınıfımızı yazmak gerekiyor. Aşağıda küçük bir örnek var.

Object<---(has)ObjectPtr<-----------(has)ObjectPtrList
                            |
                            |
                ObjectPoolTable
                            |
                            |
                    ObjectPool

ObjectPtr::Assign ()
ObjectPtr::Release () metodları Object nesnesini ait olduğu ObjectPool'a geri verir. ObjectPool array, list, set, tree gibi herhangi bir veriyapısı üzerine kurulu olabilir.


Parser
Konuyu Gömülü Proje Örnekleri - Parser başlıklı yazıya taşıdım.

Transmission
Konuyu Gömülü Proje Örnekleri - TransmissionQueue başlıklı yazıya taşıdım.

Reception
Aşağıda zarflanan mesajları açarak internal yapılara çeviren bir tasarım var.
Formatlı mesaj işlemede en önemli adımlardan bir tanesi gelen mesajın hangi mesaj olduğunun belirlenmesi. İşlenecek mesajlar genellikle bir enum ile sıralanırlar. Verinin bir veya daha fazla alanı okunarak, bir tablo vasıtasıyla mesajın kimliği belirlenir.

Mesajlar gerekirse bir Accumalator içinde biriktiriliyor ve daha sonra IMessage dizisi şeklinde kullanılıyorlar.