30 Nisan 2019 Salı

GoF - Prototype Örüntüsü

Giriş
Yarı bitmiş nesnenin clone'lanması içindir. Şeklen şöyle



Flyweight ile İlişkisi
Prototype yeni nesnelerin yarı bitmiş bir nesneden kopyalanarak yaratılması içindir. Örneğin bir oyundan EnemyPrototype ile bir çok düşman nesnesi yaratılabilir. Flyweight ise hazır nesnelerin paylaşılması içindir.

Tomcat

Giriş
Tomcat tam bir J2EE Application Server değil. J2EE standardındaki herşeyi gerçekleştirmiyor. Açıklaması şöyle. JSP ölü bir teknoloji olduğuna göre ben sadece Servlet Container olarak düşünüyorum.
The Apache Tomcat® software is an open source implementation of the Java Servlet, JavaServer Pages, Java Expression Language and Java WebSocket technologies.
Zip Olarak Kurulum
Tomcat Zip Olarak Kurulum yazısına taşıdım.

Service Olarak Kurulum
Tomcat Servis Olarak Kurulum yazısına taşıdım.

Docker Olarak Kurulum
war dosyaları "/usr/local/tomcat/webapps/" dizinine kopyalanır

Örnek
Şöyle yaparız
FROM tomcat:9.0.64-jre11    (the chosen DockerHub image)
ADD target/provman.war /usr/local/tomcat/webapps/ 
                            (The relative location of your WAR file)
EXPOSE 8080     (The port that the Docker container will listen to) 
Çalıştırmak için şöyle yaparız
docker build -t provman .      (don’t forget the dot!)
docker run -p 80:8080 provman  
Örnek
Şöyle yaparız
From tomcat
COPY ./target/hello-world.war /usr/local/tomcat/webapps

Locale
-Duser.language=en -Duser.country=US ile Tomcat Türkçe bir makinede Amerikan locale ile çalıştırılır. Bu bazen Java'nın toUpperCase() metodu ile çıkarttığı problemi aşmamıza yardımcı olur.

URL Yolu
Tomcat http isteklerini yüklü olan war'ların URL'lerinin en uzunundan başlayarak bulmaya çalışır.
İki tane war yüklü olsun.
İlki ROOT.war, context = /
İkincisi ise api#v1.war, context = /api/v1/
olsun

Şu istek farklı bir yere GET http://<hostname>/api/someMethod
Şu istek farklı bir yere GET http://<hostname>/api/v1/someMethod
gider.

Context.xml
TOMCAT_HOME\conf\context.xml dosyasıdır.

JNDI - DataSource
Açıklaması şöyle
NOTE - The default data source support in Tomcat is based on the DBCP connection pool from the Commons project. However, it is possible to use any other connection pool that implements javax.sql.DataSource, by writing your own custom resource factory, as described below.
JNDI ayarı şöyle yapılır.
<?xml version="1.0" encoding="UTF-8"?>
<Context antiJARLocking="true" path="/eatST">
<Resource 
    name="jdbc/test"
    auth="Container" 
    type="javax.sql.DataSource"
    maxActive="100" 
    maxIdle="30" 
    maxWait="10000" 
    username="root"
    password="123" 
    driverClassName="com.mysql.jdbc.Driver"
    url="jdbc:mysql://localhost:3306/test?
         useUnicode=true&amp;characterEncoding=UTF8"
    factory="org.apache.tomcat.jdbc.pool.DataSourceFactory"
 />
 </Context>
catalina.properties dosyasındaki değerleri kullanarak şöyle yaparız.
<Resource name="${tomcat.dbpool.ups.quartz.resourcename}" auth="Container"
  type="javax.sql.DataSource" driverClassName="oracle.jdbc.OracleDriver"
  url="${tomcat.dbpool.ups.quartz.connectionurl}"
  username="${tomcat.dbpool.ups.quartz.username}"
  password="${tomcat.dbpool.ups.quartz.password}"
  maxTotal="${tomcat.dbpool.ups.quartz.maxTotal}"
  maxIdle="${tomcat.dbpool.ups.quartz.maxIdle}"
  minIdle="${tomcat.dbpool.ups.quartz.minIdle}"
  maxWaitMillis="${tomcat.dbpool.ups.quartz.maxWaitMillis}"
  validationQueryTimeout="${tomcat.dbpool.ups.quartz.validationQueryTimeout}"
  testWhileIdle="true"
  removeAbandonedOnMaintenance="true"
  timeBetweenEvictionRunsMillis="..."
  minEvictableIdleTimeMillis="..."
 />
maxIdle bağlantılar boşa çıksa bile kaç tane açık tutulacağını belirtir. 2 olarak belirtmek için şöyle yaparız. maxActive en fazla kaç bağlantı açılacağını belirtir.
<Resource
   name=XXXXX
   type=xxxxx
   username=xxxxx
   password=xxxxxx
   driverClassName=xxxxx
   maxIdle=2
   url=xxxxx
   maxActive=10
/>

Realm Nedir?
Kullanıcıları yetkilendiren sisteme verilen isim.

JDBCRealm
Kullanıcıyı, veritabanındaki bir tabloya bakarak yetkilendirir.
<Realm localDataSource="true" debug="99"
    className="org.apache.catalina.realm.JDBCRealm" connectionName="user"
    connectionPassword="password" connectionURL="jdbc:mysql://localhost:3306/ ccc"
    digest="md5" driverName="com.mysql.jdbc.Driver" roleNameCol="role_name"
    userCredCol="password" userNameCol="email_id"
    userRoleTable="users_list" userTable="user_list_view" />
Combined Realm
Combined Realm istemciyi bir veya daha fazla datasource ile authenticate edebilir.

Session
Persistent session yani tomcat tekrar başlatılınca session'ları hatırlasın istemezsek, session'ların kaydedildiği dizini boş tanımlarız. Şöyle yaparız.
<!-- Uncomment this to disable session persistence across Tomcat restarts -->

<Manager pathname="" />
Eğer session bilgisini Redis üzerinde saklamak istersek şöyle yaparız.
<Manager className="org.redisson.tomcat.RedissonSessionManager"

   configPath="${catalina.base}/redisson.conf" readMode="MEMORY" updateMode="DEFAULT"/>

Server.xml
Tomcat Server.xml yazısına taşıdım.

Remote Debug
Eclipse ile uzaktaki bir Tomcat üzerindeki uygulamayı debug etmek için eclipse debug remote web application başlıklı yazıya bakılabilir.

startup.bat dosyası ayarları
Sunucu Tomcat.exe kullanılarak başlatılmaz. startup.bat ile başlatılır.
startup.bat dosyası catalina.bat dosyasını çağırıyor.

CATALINA_OPTS
startup.bat dosyası içinde CATALINA_OPTS değişkeni tanımlanarak çeşitli JVM ayarları yapmak mümkün. Örnek :
export CATALINA_OPTS=-Xms16m -Xmx256m;
catalina.bat dosyası ayarları
JAVA_OPTS
Örnek:
set JAVA_OPTS="-Djava.library.path=/usr/tomcat/shared/lib"
Bir diğer örnekte ise gelen HTTP isteklerini loglamak mümkün.
export JAVA_OPTS="$JAVA_OPTS -Dcom.sun.xml.ws.transport.http.client.HttpTransportPipe.dump=true"

CATALINA_HOME\lib
Eğer ClassNotFoundException exception alınırsa gerekli olan jar dosyalarını bu dizine kopyalamak mümkün. Ancak bu dizin tomcat üzerine çalışan tüm uygulamalar tarafından ortak kullanıldığından, jar dosyaları arasında sürüm farkından dolayı sorun da çıkarabilir.

Tomcat'in ilk kurulumunda bazı jar dosyaları bu dizinden geliyor. Örneğin servlet 3.0 api'si servlet-api.jar dosyasında mevcut.




Yazılım Mimarisi - Service Oriented Architecture (SOA)

Giriş
Açıklaması şöyle. Yani ilk mimaride SOAP kullanılması öngörülmüş.
In 2005, Dr. Peter Rodgers addressed micro web services during a presentation at a Web Services Edge conference, where the first generation of micro web services was based on service-oriented architecture (SOA). SOA is a "self-contained" software module that performs as a task, and this allows the service to communicate based on SOAP (Simple Object Access Protocol). The main SOAP idea is, "Do the simplest thing possible."
Bu mimarideki amaç şirketteki ortak yapılan şeyleri bir servis yapısına dönüştürmek. Açıklaması şöyle.
When the concept of a Service Oriented Architecture was launched, the idea was that if you build a service that provides a common function, it would be a waste to keep it from others in the organization. The underlying premise is that writing software is expensive, and multiple implementations allow for different interpretations of what actual services should be provided. By making your services available to the entire organisation you get a single source of truth, and nobody needs to re-invent the wheel. As such, SOA is more about responsibilities and where they lie in the organization, rather than things like application size and the technologies used.
Şeklen şöyle


SOA Manifesto
Açıklaması şöyle
Business value over technical strategy
Strategic goals over project-specific benefits
Intrinsic interoperability over custom integration
Shared services over specific-purpose implementations
Flexibility over optimization
Evolutionary refinement over pursuit of initial perfection
Servis Nedir?
Açıklaması şöyle
Applying service-orientation results in units of software partitioned into discrete, autonomous, and network-accessible units, each designed to solve an individual concern. These units qualify as services
Service Layer
Açıklaması şöyle
In service-oriented architecture (SOA), the service layer is the third layer in a five-abstraction-layer model. The model consists of 

1. Object layer, 
2. Component layer, 
3. Service layer, 
4. Process layer and 
5. Enterprise layer.

The service layer can be considered as a bridge between the higher and lower layers, and is characterized by a number of services that are carrying out individual business functions. 
Ara Katman Yazılımı
SOA sayesinde middleware (ara katman yazılımı) da önem kazandı. Açıklaması şöyle.
That said, “doing” SOA has become synonymous with the use of communication protocols like SOAP (the Simple Object Access Protocol) over HTTP, tools like an Enterprise Service Bus, and messages encoded in XML, all of which has little to do with organizational structure, and everything with technology. Looking further along those lines, you could say that Service Oriented Architectures led to the popularization of “Middleware” as a separate layer, and products targeting it became powerful platforms for application integration. It also helped cement the importance of “Enterprise” standards, most notably centralized data dictionaries and Enterprise Architecture.
Problemler
Her zamanki gibi servisin biraz daha farklı çalışan sürümü istendiği zaman sıkıntı çıkıyor. Açıklaması şöyle
With application development you will soon be confronted with the need for change; either the “customers” want a slightly different service interface, or you yourself want to incorporate new functionality and lessons learned. This causes friction, because you can no longer consider the service interface as fully your own, and unexpected (from the viewpoint of the users) changes may break other applications. You are left with basically two alternatives: create different versions of the interface, or coordinate releases over the boundaries of applications or even departments.

24 Nisan 2019 Çarşamba

Split Brain Scenario

Giriş
Master ve Slave düğümler arasında ağ (network) problemi olması. Açıklaması şöyle.
This is a classical problem in any distributed system where each node thinks the other nodes are down, while in reality, only the network communication between the nodes is broken. This scenario is more commonly known as a split-brain scenario, and if not handled properly, can lead to more than one node claiming to be a master ... which, in turn, leads to data inconsistencies and corruption.
Yıllar önce buna benzer bir problemle karşılaşmıştım ve o zaman bir problemin ismini bilmediğim için düzgün araştırma da yapamamıştım. Problemin ismini öğrenince not almak istedim.

Çözüm
3 tane farklı çözüm var. Açıklaması şöyle
1. Third-party actor (or witness) — an independent application outside of the cluster that can check the availability of all the nodes. Several types of applications can be used for this purpose: load-balancer, Zookeeper, or some other dedicated cluster software. And there are a variety of scenarios of how exactly this application protects the cluster from the split-brain problem. It can check the availability of nodes with heartbeats or register the nodes inside the application, allowing only one primary node to be registered.
2. Consensus — the decision about the current leader is based on the nodes’ vote. To promote one of the replicas to be the primary one, it should get a majority of votes, or quorum[3]. This approach is used in MongoDB replica sets. Another example is Hazelcast, which uses the quorum approach for write operations to protect itself from split-brain [4]. When an operation can’t be performed on the sufficient number of cluster members, it raises an exception.
3. Generation numbers — there is a generation number available across the cluster, which monotonically increases every time the leader is changed. All the nodes accept only actions performed using the current value of this number. When the old leader is disconnected from other nodes, it will keep the old generation number and won’t be able to apply changes anymore.
Split Brain ve Distributed Lock
Açıklaması şöyle.
But in general, when we are talking about locks, it is better to have only one node in charge of a particular lock in order to prevent the split-brain issue. 

17 Nisan 2019 Çarşamba

ffplay Komutu

-i seçeneği
Şöyle yaparız
ffplay -f lavfi -i testsrc=s=3x3,geq=r='...':g='...':b='...'

12 Nisan 2019 Cuma

IEEE 754 - Nan - Matematiksel Olarak Hesaplanamayan Bir Durumda Ortaya Çıkar

Giriş
NaN maksimum exponent ve sıfır olmayan bir mantissa olarak temsil edilir.

Örnek
Şöyledir. Exponent 11 bit tamamı 1. Mantissa'nın da başındaki bit 1.
 1 1111111 1111 1000 00000000 00000000 00000000 00000000 00000000 00000000
 ||             ||                                                       |
 |<-   Exp     -><-                     Mantissa                        ->
  Sign
NaN Hangi Durumlarda Ortaya Çıkar
Nan Belirsiz ve Tanımsız olarak tabir edilen durumlarda ortaya çıkar. Açıklaması şöyle
NaN is a concept defined in IEEE 754 standard for floating-point arithmetic, not being a number is not the same as negative infinity or positive infinity, NaN is used for arithmetic values that cannot be represented, not because they are too small or too large but simply because they don't exist.

1. Belirsiz Durumu- Indeterminate
Belirsiz (0.0 / 0.0) , (sonsuz / sonsuz) gibi işlem sonucu çıkar. Belirsizi bulmak kolay. a / b = c denklemini a = b x c şeklinde de yazabilirim.

0 = 0 x c denkleminde c herhangi bir sayı olabilir. Bu yüzden belirsizdir.
sonsuz = sonsuz x c denkleminde c herhangi bir sayı olabilir. Bu yüzden belirsizdir.

2. Tanımsız Durumu - Undefined
Tanımsız (x / 0.0) gibi bir işlem sonucu çıkar.
Örnek
a = 0.0 x c şeklinde bir denklem yazarsam a'nın her zaman 0 olduğunu bilirim. Ancak a 0'dan farklıdır diye bir varsayımla başlarsam kendimle çelişirim. Bu yüzden işlem tanımsızdır.
Örnek
Bir diğer tanımsız ise şöyle
Math.sqrt(-2.0)
Örnek
Bir diğer tanımsız şöyle
1/0 = ∞ //too large     
log (0) = -∞ //too small
sqrt (-1) = NaN //is not a number, can't be calculated
Nan ve Infinity Arasındaki Fark Nedir
Açıklaması şöyle. Yani sonuç tanımsız ise Nan, overflow var ise Infinity döndürülmeye çalışılır.
A NaN is returned (under IEEE 754) in order to continue a computation when a truly undefined (intermediate) result has been obtained. An infinity is returned in order to continue a computation after an overflow has occurred.
Örnek
Elimizde şöyle bir kod olsun. Negatif sonsuzun kare kökü tanımsızdır Nan döner. Negatif Sonsuzun üssü aslında yine sonsuzdur ve Nan değil Infinity döner.
Math.sqrt(Double.NEGATIVE_INFINITY); // NaN
Math.pow(Double.NEGATIVE_INFINITY, 0.5); // Infinity
Genel Kural
Genel kural olarak şunu söyleyebiliriz. Bir aritmetik işlemin sağ veya sol tarafında NaN varsa, sonuç NaN çıkar.

Aritmetik İşlem
Yukarıdaki kurak gereği toplama, çıkarma, bölme ve çarpma işlemleri hep NaN verir.
float qNaN = std::numeric_limits<float>::quiet_NaN();
float result = qNaN - qNaN; //nan verir
Karşılaştırma
Örnek
NaN sayısı bir başka NaN sayısı ile ==, <, > işlemine göre karşılaştırılamaz.
double a = Double.NaN;
double b = Double.NaN;
System.out.println(a == b); // false
System.out.println(a < b); //  false
System.out.println(a > b); //  false
Visual Studio ile debug ederken NaN iki şekilde görülebilir. İlki -1.#IND000000000000 (indetermined belirsiz) diğeri ise -1.#INF000000000000 (undefined tanımsız)  sabitleridir.

Örnek
C++ standardında bir hata var. std::min() ve std::max() hatalı sonuç veriyor. Elimizde şöyle bir kod olsun.
#include <iostream>
#include <cmath>
#include <algorithm>

int main(int, char**)
{
  double one = 1.0, zero = 0.0, nan = std::nan("");

  cout << "std::min(1.0, NaN) : " << std::min(one, nan) << endl;
  cout << "std::min(NaN, 1.0) : " << std::min(nan, one) << endl;

  cout << "std::min_element(1.0, 0.0, NaN) : " << std::min({one, zero, nan}) << endl;
  cout << "std::min_element(NaN, 1.0, 0.0) : " << std::min({nan, one, zero}) << endl;

  cout << "std::min(0.0, -0.0) : " << std::min(zero, -zero) << endl;
  cout << "std::min(-0.0, 0.0) : " << std::min(-zero, zero) << endl;
}
Çıktı olarak şunu alırız
$ g++ --std=c++17 ./test.cpp
$ ./a.out
std::min(1.0, NaN) : 1
std::min(NaN, 1.0) : nan
std::min_element(1.0, 0.0, NaN) : 0
std::min_element(NaN, 1.0, 0.0) : nan
std::min(0.0, -0.0) : 0
std::min(-0.0, 0.0) : -0

1. Programlama Dillerinde NaN
C++
std::isnan kulllanılır.

Java
Geçersiz bir sayıyı temsil etmek için Float.NaN ve Double.NaN kullanılır

C#
Java ile aynıdır.

2. NaN Kontrolü
Bir sayının NaN olup olmadığı şöyle kontrol edilebilir. Maksimum exponent için 0X7FF yani 11 bit kullanılıyor. Geriye kalan 53 bit 0XFF ile alınıyor. Eğer Exponent 0X7FF ve mantissa sıfırdan büyükse sayımız 0X7FF0000000000000'ten büyüktür.
public unsafe static bool IsNaN(double d)
{
  return (*(UInt64*)(&d) & 0x7FFFFFFFFFFFFFFFL) > 0x7FF0000000000000L;
}
veya şöyle yapılabilir. Aşağıdaki kod exponent ve mantissa'yı daha net gösteriyor.
inline constexpr bool
isnan(const std::uint32_t bits) noexcept
{
  constexpr std::uint32_t exponent = UINT32_C(0x7f800000);
  constexpr std::uint32_t mantissa = UINT32_C(0x007fffff);
  return ((bits & exponent) == exponent) && ((bits & mantissa) != 0);
}

inline constexpr bool
isnan(const std::uint64_t bits) noexcept
{
  constexpr std::uint64_t exponent = UINT64_C(0x7ff0000000000000);
  constexpr std::uint64_t mantissa = UINT64_C(0x000fffffffffffff);
  return ((bits & exponent) == exponent) && ((bits & mantissa) != 0);
}