Introduction

PragmaTouch team is currently working on a new e-learning project. Below you can see a conceptual system diagram.

Users who access the Management UI inside the ASP.NET MVC 3 application are the content producers and they will access the system from standard web browsers to produce the content. Users who will consume the content (depicted at the bottom of the diagram) will access the system through our official mobile applications and other 3rd party applications. Our official applications and other client apps read/write data to the system through our Web API JSON.

We evaluated some options like OAuth, OAuth2 and simple API key authentication during the development process. All of the standard methods we have evaluated were too standard to implement or not secure enough. So we decided to go for our own simple but yet fairly secure API authentication mechanism.

API Authentication Ticket Request

On the server side authentication ticket requests are handled by an authentication controller which simply checks if "Request Validation Parameters" sent by the client are valid. If validation parameters are valid authentication controller generates a ticket and sends the ticket as JSON data to the client. Here is the authentication controller code

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Web.Security;
using Newtonsoft.Json;
using System.Globalization;

namespace PragmaTouch.WebApp
{
    public class AuthTicketController : Controller
    {
	    private readonly IAuthRequestValidator _authRequestValidator = null;
		public AuthController(IAuthRequestValidator authRequestValidator )
		{
			_authRequestValidator = authRequestValidator;
		}
		
        public ActionResult Index(string p1, string p2)
        {
          if (!_authRequestValidator.IsAuthRequestValid(p1,p2))
          {
            var authData = new AuthData { Ticket = String.Empty , Success = false, Error = "Invalid validation parameters"};
            return Json(authData, JsonRequestBehavior.AllowGet);
          }
          var ticket = new AuthTicket 
          { 
            ApiKey = "apikey_comes_here",
            P1 = p1,
            P2 = p2 
          };
          ticket.SetDefaultExpiresOn();

          JsonNetResult result = new JsonNetResult();
          result.Formatting = Formatting.Indented;
          result.Data = ticket.CreateEncryptedAuthData();
          return result;
        }

        public ActionResult ServerDateTime()
        {
          JsonNetResult result = new JsonNetResult();
          result.Formatting = Formatting.Indented;
          result.Data = new { dateTime = DateTime.Now };
          return result;
        }
    }
}

 

  • IAuthRequestValidator instance is injected by Ninject.MVC
  • Upon successfull validation AuthTicket is generated including the validation parameters and an empty ApiKey value. ApiKey value is a shared secret both by the server and client. Server does not put the Api Key value into the AuthTicket intentionally because the server will expect the client to populate the key to AuthTicket on subsequent API calls
  • Server sets a default expiration for the ticket.  
  • AuthTicket is encrypted by the server and the result is served to the client as AuthData JSON object.

API Request

 

The client application adds the authentication ticket (serialized as JSON) into the Authorization header of every API request. On the server side we implemented an ApiAuthorizeFilter attribute which intercepts the requests to the secured API actions and validates the authentication ticket included in the Authorization header of the request. Here is the code for the ApiAuthorizeFilter attribute

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using Newtonsoft.Json;

namespace PragmaTouch.WebApp
{
  public class ApiAuthorizeAttribute:AuthorizeAttribute
  {
    protected override bool AuthorizeCore(HttpContextBase httpContext)
    {
      var authorizationHeader = httpContext.Request.Headers["Authorization"];
      if (String.IsNullOrWhiteSpace(authorizationHeader))
        return false;

      try
      {
        AuthData authData = JsonConvert.DeserializeObject(authorizationHeader);
        AuthTicket authTicket = JsonConvert.DeserializeObject(authData.Ticket.Decrypt());
        DateTime expiresOn = DateTime.Now.AddDays(1);
        
        if (ConfigHelper.CheckForExpiredAuthTicket)
          expiresOn = AuthTicket.ParseExpiresOn(authTicket.ExpiresOn);
        
        return authTicket.ApiKey == ConfigHelper.ApiKey && expiresOn > DateTime.Now;
      }
      catch
      {
        return false;
      }
    }

    protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext)
    {
      var result = new JsonNetResult();
      result.Formatting = Newtonsoft.Json.Formatting.Indented;
      result.Data = new AuthData{Success = false, Error = "Authorization required"};
      filterContext.Result = result; 
    }
  }
}

 

  • ApAuthorizeAttribute simply checks if the authentication ticket has a valid Api Key value and if authentication ticket has expired (to minimaze chance of reply attacks)
  • Expiration control is optional and can be turned on/off with a value specified in the web.config file of the ASP.NET MVC 3 application
  • The same crypto algorithm and crypto keys are used on both sides (the server and client)

 

Refreshing the Authentication Ticket

Clients can refresh the authentication ticket using two alternatives

  1. Simply request for a new authentication ticket
  2. Call the ServerDateTime action in the AuthTicketController to find out the current server datetime then add some extra time to the ExpiresOn value of the authentication ticket if ticket has expired.

Sample Client Code

public class SampleApiClient
{	
	public class ServerDateTime
    {
      public string dateTime { get; set; }
    }

    private AuthData _authTicket = null;
	private bool ApiAuthenticate(stirng p1, string p2)
	{
		_authTicket = null;
		try
		{
		string apiUrl = "http://localhost/AuthTicket";
		WebClient wc = new WebClient();

		string authDataJson = wc.DownloadString(String.Format("{0}?p1={1}&p2={2}", apiUrl, p1, p2));

		_authTicket = JsonConvert.DeserializeObject(authDataJson);
		if (!_authTicket.Success)
		{
		  return false;
		}

		var authTicket = JsonConvert.DeserializeObject(_authTicket.Ticket.Decrypt());
		authTicket.ApiKey = ConfigHelper.ApiKey;
		_authTicket.Ticket = JsonConvert.SerializeObject(authTicket).Encrypt();
		return true;
		}
		catch (Exception ex)
		{
			// Do some error reporting
			throw ex;
		}
	}
	
	public bool GetServerDateTime(out DateTime dateTime)
    {
      dateTime = DateTime.MinValue;
      string apiUrl = "http://localhost/Api/AuthTicket/ServerDateTime";
      if (String.IsNullOrWhiteSpace(apiUrl))
        return false;
 
      WebClient wc = new WebClient();
      string jsonResult = wc.DownloadString(apiUrl);
      ServerDateTime result = JsonConvert.DeserializeObject(jsonResult);
      dateTime = AuthTicket.ParseExpiresOn(result.dateTime);
      return true;
    }
	
	public void ApiExpireAuthTicket()
    {
      if (_authTicket == null || String.IsNullOrWhiteSpace(_authTicket.Ticket))
        return;

      var authTicket = JsonConvert.DeserializeObject(_authTicket.Ticket.Decrypt());
      authTicket.ExpiresOn = String.Empty;
      _authTicket.Ticket = JsonConvert.SerializeObject(authTicket).Encrypt();
    }
	
    public bool RefreshAuthenticationTicket(object sender, EventArgs e)
    {
      if (_authTicket == null || String.IsNullOrWhiteSpace(_authTicket.Ticket))
        return;

      DateTime serverDateTime = DateTime.Now;
      if (!GetServerDateTime(out serverDateTime))
      {
        return false;
      }
      
      var authTicket = JsonConvert.DeserializeObject(_authTicket.Ticket.Decrypt());
      authTicket.ExpiresOn = AuthTicket.CreateExpiresOnString(serverDateTime.AddHours(12));
      _authTicket.Ticket = JsonConvert.SerializeObject(authTicket).Encrypt();
	  return true;
    }
	private string ApiRequest(string apiRequestUrl)
    {
      try
      {  
        MyWebClient wc = new MyWebClient(_authTicket);
        return wc.DownloadString(apiRequestUrl);
        
      }
      catch (Exception ex)
      {
			// Do some error reporting
			throw ex;
      }
    }
	
	
}

Here is the custom WebClient class which is used to add the authentication ticket to the request Authorization header as JSON serialized data.

public class MyWebClient:WebClient
{
	AuthData _ticket = null;
	public MyWebClient():base()
	{

	}

	public MyWebClient(AuthData ticket):this()
	{
	  _ticket = ticket;
	}

	protected override WebRequest GetWebRequest(Uri address)
	{
	  WebRequest request = base.GetWebRequest(address);
	  if (_ticket != null)
		request.Headers.Add("Authorization", JsonConvert.SerializeObject(_ticket));

	  return request;
	}
}

 


I love MonoTouch, but sometimes MonoTouch lets me down very very bad. The latest scenario was simple in theory. The scenario is

  • Create an HttpWebRequest
  • Provide the NTLM credentials of the user to the HttpWebRequest

The helper method below simply creates and returns an HttpWebRequest

 private HttpWebRequest CreateRequest_NTLM(string url, string username, string password, string domain)
 {
    HttpWebRequest result = (HttpWebRequest)WebRequest.Create(url);
    NetworkCredential networkCredential = new NetworkCredential(username, password, domain);
    CredentialCache credentialCache = new CredentialCache();
    credentialCache.Add(new Uri(url), "NTLM", networkCredential);
    result.Credentials = credentialCache;
      

    System.Net.IWebProxy proxy = System.Net.WebRequest.DefaultWebProxy;

    if (proxy != null)
     result.Proxy = proxy;
      
      
    result.Timeout = 30000;
    result.Method = "GET";
    return result;
 }

Here we create the HttpWebRequest and call BeginGetResponse

 private AuthenticateUser(string username, string password, string domain)
 {
	HttpWebRequest request = CreateRequest_NTLM("http://www.protectedweb.com/",username,password,domain);
	request.BeginGetResponse(new AsyncCallback(AuthenticateUserCompleted),request);
 }
 private void AuthenticateUserCompleted(IAsyncResult asyncResult)
 {
	//Upon successfull authentication some business code executes here 
 } 

Below is the WireShark capture output when the code is run on .NET Framework on a windows machine

Below is the WireShark capture output when the code is run iOS simulator on Mac OSX

As you can see HttpWebRequest of MonoTouch just hangs after the first 303 response of the server and our AuthenticateUserCompleted method is never called.


Posted in: MonoTouch  Tags:
aliozgur posted on February 2, 2012 17:07

Recently we have reorginzed our Jira and implemented a User Request project to get the user requests in a single Jira project with all components in place. With this implementation user requests are assigned to our team managers then they decide how these requests will be mapped to internal projects. We also implemented a custom workflow and at some point (User Test) the user request is assigned to the reporter (our users). When our users complete the tesing and indicate success or failure the request is assigned back to the team managers. This implementation is working pretty well. Our users no longer create issues in our internal projects and the team managers can control the workload and schedule of their teams. With this implementation we can also give to the point reports to the management. In future we plan to be able to dedicate a virtual budget for each department our users work for so that we can calculate a virtual cost and time spent reports for each department.

This implementation has one downside so far; when a user request is created team managers, most of the time, create one or more issues in internal projects. Team managers copy the user entered summary and description while creating issues in our internal projects which are then linked to user requests. When we started this project we were just cloning the user requests and then we were moving the cloned user request to our internal projects. But this usage was braking the continuity of the user request issue numbers. For example; when the original user request with key value of UR-1 is cloned  the cloned user request will have the key value of UR-2. When we move UR-2 to our internal project Jira will not reclaim UR-2 for the next user request instead the next user request will have UR-3 as the key value.

We felt uncomfortable with the discontinued issue numbers so we decided not to use clone/move method and just decided to manually copy user entered summary and description to the issues created in our internal projects. Manual copy/paste is tedious and prone to errors so I cecked out the web to see if Jira has some built in plugin which will allow us to Clone/Copy an issue from one project to another project. Unfortunately I found out that Jira does not have this feature or any plugin to perform this task easily.

The next step was to discover if we could implement this plugin ourselves. The book titled "Jira Development Cookbook" by Jobin Kuruvilla from Packt helped me to grasp the details of Jira plugin development. We will develop our own Issue Copy plugin for Jira, when we have some spare time from daily tasks.

I will share the source code of the plugin from my blog once it is completed, so stay tuned and take a look at "Jira Development Cookbook" by Jobin Kuruvilla from Packt if you are interested in Jira development.


Posted in: General Development  Tags:

Oh well... It seems that we are making the same old mistake again. It is hard to articulate my feelings about the trending tablet business. It feels like we are traversing the same path again. To be more clear I guess we again do what we did in the past when the PC business was in its early days. 

History

I'm relatively young and unexperienced character in this software business but as far as I remember from my readings about the evolution of the PC age once hardware vendors used to create their proprietary OSes running only on their hardware and some software companies were making contracts with rest of the hardware vendors for deploying OSes on their platforms. As time went by PC market changed characteristics and more consumers began to purchase PCs. Increase in demand forced hardware vendors to standardize the hardware specs so that they can build cost effective PCs. Then proprietary OSes were replaced by generic OSes like Windows and Linux distros. And today as a consumer when you buy a PC, laptop or netbook you know that you can install Windows or other Linux distributions on your hardware; you believe that it is your right and freedom to use any OS on your hardware.  You should have already noted this scenario is in action right now for the tablet business.

Future

I hope within 5 to 10 years period tablet hardware vendors like Samsung, HTC, Nokia, Sony and otheers will realize the similarity I've tried to articulate above and decide to produce standardized tablet hardware so that we can install either Android or Windows 8 or even better have dual boot option on our tablets. 

Exceptions

  • Apple will not follow this trend as it was the case with PCs
  • Motorola (well actually Google) will probably not follow the trend as well

Early Adopters

As of today Microsoft seems to be on right path since Microsoft has no Windows Phone or Windows Tablet hardware unit. But if rumors about the Nokia acquisition comes true Microsoft will jump in the Exceptions wagon with Apple and Motorola

Lets wait and see...


Posted in: Mobile  Tags:

Son günlerin gündemde tutunamayan konusu Fatih Projesi ciddi vaadleri olan ve ülkemizin geleceğini yakından ilgilendiren bir proje. Bu proje kapsamında yapılması planlanan çalışmalar şu 5 ana başlık altında toplanmış

  1. Donanım ve Yazılım Altyapısının İyileştirilmesi 
  2. e-İçeriğin Sağlanması ve Yönetilmesi
  3. Öğretim programlarında Etkin BT Kullanımı
  4. Derslerde BT Kullanımı İçin Öğretmenlere Hizmetiçi Eğitim
  5. Ağ Altyapısı ve Geniş Bant İnternet Kullanımı ile Bilinçli ve Güvenli BT Kullanımının Sağlanması
Bu maddelerin hepsi Türkiye'de verilen eğitimin kalitesini farklı açılardan arttıracaktır ancak benim değinmek istediğim konular özellikle 1. madde kapsamında yapılması planlanan çalışmaları kapsamaktadır.Donanım ve Yazılım Altyapısının İyileştirilmesi başlığını ayrıntılı bir şekilde incelediğimizde dersliklerin dizüstü bilgisayarlarla donatılmasının amaçlandığını görüyoruz. Basında çıkan haberlerden takip ettiğimiz kadarıyla Milli Eğitim bakanlığı ve hükümet dizüstü bilgisayarlardan çok tablet bilgisayarlara odaklanmış durumda. Bu çerçevede dersliklerin (aslında öğrencilerin) tablet bilgisayarlar ile donatılması çalışmasında hükümet'in özellikle Apple ve Google ile temaslarda bulunduğunu ayrıca yerli bilgisayar üreticileri nezdinde de temasların ve çalışmaların yapıldığını biliyoruz. Bu çalışmaların ve temasların hepsi bu tür bir girişim öncesi karar verme aşamasında önemli ve değerli faaliyetler. Ancak benim kişisel fikrim eğitim'e yönelik tablet bilgisayar donanımının ve bu donanım üzerinde çalışacak işletim sisteminin tasarım ve geliştirmesinin TÜBİTAK çatısı altında kurulacak ekipler ve kamuya ait bir üretici firma tarafından geliştirilmesinin zorunlu olduğu yönünde. Bu çalışmanın tamamen yerli kaynaklar kullanılarak yapılabileceğine inanmama neden olan bazı gerçekleri aşağıdaki gibi özetleyebilirim

Hemen hemen tüm tablet üreticileri kullandıkları donanım parçalarını Çin'de anlaşmalı şirketlere ürettirmektedir. Ancak bu üreticiler kullanacakları donanım'ın tasarımını kendileri yapmakta veya tasarım şirketlerine yaptırmaktadırlar. Bana göre bizim ülkemizde bu donanım bileşenlerini tasarlayabilecek insan kaynağı mevcuttur. Hükümet bu projenin bir başarı hikayesi olmasını istiyorsa derhal bu donanımın tasarımını yapabilecek kişileri tespit etmeli ve gerekirse yurt dışında Apple, Google, Motorola, HTC, Samsung, Sony gibi ciddi üreticilerde çalışmakta olan mühendisleri TÜBİTAK bünyesinde bu çalışmaya katılmaları için ikna etme çalışmalarına başlamalıdır.

Türkiye TÜBİTAK çatısı altında bence çok başarılı bir işletim sistemi olan Pardus'u geliştirmeyi başarmıştır. Çok önemli bir başarı hikayesi olan ve başarılarını sürdüren Pardus yapılanmasına benzer bir yapılanma kendi tablet işletim sistemimiz için de hızla devreye alınmalıdır. Hatta kendi tablet işletim sistemimizi Pardus'un kapsamını genişleterek geliştirmeliyiz. Günümüzün en başarılı mobil işletim sistemlerinden biri olan Android'in çekirdeği ile Pardus'un çekirdeğinin Linux olduğunu göz önüne alırsak bunu başarmak için Amerika'yı yeniden keşfetmemize gerek kalmayacaktır. Diğer yandan bu çalışmada açık kaynak kodlu olan Android kodunu inceleyip gerekli düzenlemeler ve yenilemeleri de rahatlıkla yapabiliriz. Örneğin Android'in Java temelli ve Dalvik kullanan yapısına benzer C# temelli ve Mono bileşenlerini kullanan bir işletim sistemi geliştirebiliriz.

Tasarımı TÜBİTAK tarafından yapılan donanım'ın montajının yapılması, donanım bileşenlerinin üretimin Çin'de yaptırılması, servis desteğinin organizasyonunun sağlanması gibi konularda faaliyet gösterecek %100 devlete ait bir kamu şirketi kurulmalı. Türkiye gibi bilmem kaç haneli büyüme rakamlarını yakalamış ve bilmem kaç miliyar dolar ihracat hedefi olan bir ülkenin bu tür bir kamu şirketi'nin finansmanını sürdürülebilir bir yapıda sağlayabileceği açıktır. (Bu şirket'in özelleştirilmesinin önüne yasal engellerin daha kurulma aşamasında konulması da bence kesinlikle gereklidir)

Uygulama mağzası ve milli eğitim bakanlığının dijital eğitim materyallerine erişime imkan sağlayan içerik mağzası gibi hizmetler sadece yerli yazılım firmalarına ihale edilebilir. Bu şekilde tablet işletim sistemlerinin kalbi sayılan uygulamaların ve içeriğin yönetimi merkezi bir yapı ile daha kolay sağlanabilir.

Geliştirilen tablet donanımı ve işletim sistemi ticari uygulama ve içeriğe kapalı olmalı sadece eğitim amaçlı ücretsiz içeriğe odaklanmalıdır. Böylece donanım ve işletim sistemi üzerinde ticari bir baskı unsuru oluşması veya oluşturulması engellenebilir.

Milli Eğitim bakanlığı Fatih Projesi kapsamındaki tüm okullara hizmet verebilecek bir data center kurarak okullara LMS gibi hizmetleri ortak bir kaynaktan merkezi olarak sunabilir.

TÜBİTAK çatısı altında üniversitelerin de iş birliği ile Türkiye kendi LMS'ini (Learning Management System) geliştirip işletebilir

Teknolojiyi tüketirken çok yakından takip eden fakat özellikle devlet'in vatandaşlarına sunmakla yükümlü olduğu hizmetlerin sağlanmasında teknoloji yokmuş gibi davranan bir ülke olarak yukarıda belirttiğim hayalin gerçekleşmesi zor görünebilir. Fakat Fatih Projesi belirlenen takvimde uygulamaya geçirilebilirse belki de dünyada bu çapta dijital eğitime geçen ilk ülke olabiliriz. Bence ülke olarak bu fırsatı iyi değerlendirimeli ve özellikle %100 yerli kaynaklarla bu projenin hayata geçirilmesi için yapabileceklerimizi küçümsememeliyiz. 

NOT: Hindisatan teknoloji'nin eğitimde daha etkin kullanılması için çalışmalarına uzun süredir devam ediyor ve Aakash isimli devlet destekli tabletin geliştirmesinin bitmek üzere olduğu duyuruldu.  


Posted in: Mobile , Moodle  Tags:

Düşük bellek koşulları altında OOM sonlandırıcı devreye girer ve zaman içinde gelişen bir dizi heuristic yöntem kullanarak bir işlem (process) seçer ve sonlandırır. Bu başka bir işlemin seçilip sonlandırılmasını istemiş kullanıcılar için oldukça can sıkıcı olabilir. Ayrıca sonlandırılan bu işlem, sistem açısında da önemli bir işlem de olabilir. Yanlış işlemlerin zamansız sonlandırılmasının önüne geçmek adına, pek çok geliştirici OOM işlem sonlandırma faaliyetleri üzerinde daha fazla kontrolleri olması gerektiği kanısındadır.

Neden OOM sonlandırıcı?

Ana dağıtımların çekirdekleri (kernels) /proc/sys/vm/overcommit_memory varsayılan değerini 0 olarak belirler, bu şu anlama geliyor, çalışan işlemler sistemde o anda kullanıma hazır bulunan boş bellekten fazlasını talep edebilirler. Bunun yapılması tahsis edilen belleğin hemen kullanılmıyor olmasına ve işlemlerin ayırdıkları belleğin tamamını yaşamları boyunca kullanmıyor olmalarına dayanmaktadır. "Overcommit" olmadan sistem bir kısmını israf ederek de olsa hafızasını tam olarak kullanamazdı. OOM riskleri pahasına "Overcommit" yöntemi ile sistem belleğini daha verimli bir şekilde kullanır. Belek savurganı programlar sistemin tüm belleğini tüketerek durmasına neden olabilir. Kullanıcı işlemleri için tek bir bellek sayfasının ayrılamadığı belleğin bu kadar düşük olduğu durumlar, OOM sonlandırıcının devreye girmesine ve sistemin geri kalanının yararı için kurbanlık kuzuyu belirlemesine yol açar.

Kullanıcılar ve sistem yöneticileri genellikle OOM işlem sonlandırıcının davranışını kontrol etmenin yollarını istemişlerdir. Sistemdeki önemli işlemlerin sonlandırılmasını engellemek ve sonlandırılacak işlemlerin sırasının belirlenmesi kontrolünü kolaylaştırmak için /proc/<pid>/oom_adj ucu sunulmuştur. oom_adj geçerli değerleri -17 ile +15 arasındadır. Değer ne kadar büyükse OOM sonlandırıcının seçiminde o kadar öncelikli olur. Değer -17 ise OOM sonlandırıcı sürecinde ele alınmaz.

Kimler Elverişsiz?

Bellek tükenmesi durumlarında bir işlemin sonlandırılacak işlem olarak seçilmesi elverişsizlik skoruna (oom_score) bağlıdır. Elverişsizlik skoru kabaca işlemin tükettiği bellek miktarı çalıştığı canlı kaldığı süre ve oom_adj değerine bağlı olarak ne kadar çok bellek tüketti isen o kadar çok ne kadar süredir çalışıyorsan o denli az elverişsiz olacak şekilde sistem tarafından belirlenerek /proc/<pid>/oom_score a yansıtır.

Sistemin swapoff() çağrısında (bu çağrı ile bir takas dosyası sistemden kaldırılır) yer alan herhangi bir şanssız işlem sonlandırılmak üzere seçilecek ilk işlem olur. Geriye kalan işlemlerin ilk bellek boyutları orijinal elverişsizlik skoru haline gelir. Eğer aynı belleği paylaşmıyorlarsa kendilerine bağlı alt işlemlerin (child process) kullandıkları bellek miktarının yarısı ana işlemin (parent process) elverişsizlik skoruna toplanır. Böylece salkımlı (forking) işlemler sonlandırılmaya birincil aday olurlar. Fazla bellek tüketen bir alt işlemi bulunan ana işlem sonlandırıcı tarafından alt işlem parçasına göre daha az tercih edilir olacaktır. Son olarak önemli işlemlerin korunması adına aşağıdaki kurallar uygulanır :

  • - işlemin "nice" değeri 0 dan büyükse skoru 2 ile çarpılır.
  • - superuser veya donanıma doğrudan erişen ( CAP_ SYS_ADMIN ,CAP_SYS_RESOURCE veya CAP_SYS_RAWIO ) bir görev ise skoru 4 e bölünür. Donanıma doğrudan erişen bir superuser görevin skoru 16 ya bölünerek bu kümülatif olarak yapılır.
  • - Bir "cpuset" inde bir oom durumu oluşur ve işaretli görev o sete ait değilse skoru 8 e bölünür.
  • - Son olarak ortaya çıkan skor değeri 2 üzeri oom_adj değeri ile çarpılır.


Böylece en yüksek elverişsizlik skoruna sahip görev (task) seçilerek bağlı alt (child) işlemleri sonlandırılır. Eğer görevin bağlı alt işlemleri yoksa oluşan bir oom durumunda kendisi de sonlandırılabilir.

OOM-Killer politikalarının kullanıcı alanına taşınması

oom_score zamanla değişen dinamik bir değer olduğundan sistem yönetimi için gereken farklı ve dinamik politikalar için yeterince esnek değildir. Bir oom durumunda hangi sürecin sonlandırılacağının belirlenmesi oldukça zordur. Sistem yönetimi yaratılan ve sonlanan her işlemin skorunu ayarlamak zorundadır,bu sürekli yeni işlemlerin başladığı ve sonlandığı bir sistemde oldukça zordur. Oom-killer politikalarının kolay uygulanabilmesi için Evgeniy Polyakov isme dayanan bir çözüm önermiştir. Onun yaması (patch) sonlandırılacak ilk işlem ismi /proc/sys/vm/oom_victim içinde bulunanlardan biri olacaktır. İsim tabanlı çözümün sınırlamaları :

  • görev adı güvenilir bir işaretçi değildir.
  • hiyerarşi olasılığına rağmen bu yaklaşım ile bir seferde sadece bir isim belirlenebilmektedir.
  • isimleri aynı olmasına karşın farklı "binary" lerin olabilmesi.
  • oom_victim de belirtilen sürecin bulunamaması durumunda bir sonrakine geçilmesi ile pek çok tarama gerektirmektedir.


Alan Cox bu çözümü beğenmiyor ve "container" ların bu sorunun çözümü için en uygun yol olduğunu öneriyordu. Bu öneriye karşılık olarak, Nikanth Karthikesan'ın katkısı olan "oom-killer controller" ı bellek yetersizliği durumlarında bir sıra işlemin sonlandırılabilmesi kontrolünü sağlıyordu. Bu yama (patch) ile oom.priority sahasına sahip bir oom kontrol grubu (cgroup) sunuldu ve sonlandırılacak işlem en yüksek oom.priority değerine sahip işlemlerin arasından seçildi.

 

Gömülü (Embedded) Sistemlerde Düşük BellekYönetimi

Oom-killer çok düşük bellek koşulları oluşana değin devreye girmiyor ve geç kalıyordu, Android geliştiricileri düşük bellek durumlarında daha büyük ölçüde kontrole ve boş bellek tükenmeden devreye girecek bir çözüme ihtiyaç duydular. Böylece birden fazla düşük bellek eşiği bulunan "lowmemory" sürücüsü (driver) ortaya çıktı. Bir düşük bellek durumunda ilk alt eşiğe ulaşıldığında arka plan (background) işlemler sorundan haberdar edildi. Bu işlemler sonlanmadılar bunun yerine durumlarını (state) kaydettiler. Bu durum görevler arasında geçişlerde bir miktar gecikmeye neden olur, çünkü uygulamanın aktive olduğunda durumunu (state) geri yüklemesi gerekir. Düşük bellek baskısı arttıkça "lowmemory" sonlandırıcı durumları kaydedilmiş arka plan uygulamalarını daha sonra ön plandaki uygulamaları sonlandırır.

Android telefonunuzu "root" ladıysanız bu düşük alt bellek eşik (minfree) değerlerini değiştirebilir bu sayede belirttiğiniz eşik değeri ile daha erken yada geç "lowmemory" sonlandırıcının devreye girmesini sağlayabilirsiniz. Android market de "root" lanan cihazlarda bu değerleri değiştirmenize imkan tanıyan çeşitli uygulamalar mevcut , benim kullanıp memnun kaldığım uygulama

Auto Memory Manager
market://search?q=pname:com.lim.android.automemman

Afiyet bal şeker olsun.

Kaynaklar

Posted in:   Tags:
aliozgur posted on August 10, 2011 12:36

We have been using Jira at our office for 5-6 years or so. During this time I was a member of the development team and was just an end user of Jira. After the recent change in my position I'm expected to use Jira as a management tool. Default installation of Jira comes with some defaults which will definitely help you but if you want to effectively manage your team and the job you have to fine tune your Jira setup.

Jira 4 Essentials by Patrick Li (Packt Publishing)  is a must read book if you need to fine tune and customize your Jira installation to meet your very own needs. The book walks through each customizable bit of Jira and with the Help Desk Project section at the end of each chapter customizations are applied to a practical sample implementation. I highly recommend team managers and Jira admins to read Jira 4 Essentials. 

JIRA 4 Essentials


Posted in: General Development  Tags:
aliozgur posted on August 9, 2011 10:13

Competition in the wild is really stressful and as a result people make hard to believe mistakes, especially when they are #2 not #1, such as claiming that the only real iOS app is theirs but not the one developed by the competitors. This kind of approach is technically wrong and has some ethical problems. Pricing, differentiation, offering more functionality, advertising your product, special offers, sponsorships, using social media and all other regular tools can be used in competition but blaming the competitors with sentences like "Do not get cheated by fake apps!!" (oh no!!! too many exclamations, this must be important) is not ethical.

Sentences like "My app is the only real iOS app" just reflects your technical inability and ignorance. Let me tell you the truth; the end user is not interested in what is real or fake (fake=browser  according to you). The end user just wants to get the advertised functionality. 

Anyway. Let me explain you,this is really simple, what makes an app a real iOS app

  1. Being approved by Apple and being available on the Apple AppStore
  2. Being able to run on iOS (iPhone, iPad and iPod Touch), which means your app executes real iOS machine code
  3. Following the iOS User Interface Design Guidelines
  4. Being able to use the official iOS APIs and Frameworks such as DocumentInteractionController found in UIKit Framework    

See? This is really simple just 4 rules not much or less. Including irrelevant app specific features and wrong performance indicators in a comparison table can make your conclusion seem convincing. But trust me users do not care much about these tables and conclusions especially if it is very clear that you have benefits from this comparisions.

NOTE-1: Browser apps are also real apps since they meet all the 4 criterias I mentioned

NOTE-2: mTouch and mTouch+ are not browser apps but they do have generic browser views to support displaying of unsupported Moodle content/mod/activity

NOTE-3: I'm aware of that the release of moodlEZ caused some uncontrolled stress on you. Take it easy and keep improving your apps and business


Posted in: Mobile , Moodle , MoodleTouch , MTouch  Tags:

Yesterday Yalla Apps contacted with me and asked for an interview. The interview  was conducted to get more insight on the WP7 developer community and thier opinions about different platforms.

Below are my answers to the questions of Yalla Apps

Yalla Apps: Are you a Developer or Designer or both? What is your experience level?

Ali Özgür : I'm a software developer. I currently work for Istanbul Bilgi University, one of the largest privately held university in Turkey, as the Platforms and Services Team Manager. I got BS degree in Computer Engineering from Istanbul Technical University and also hold an MBA degree from Istanbul Bilgi University. I'm developing software for more than 10 years. I've spend most of this time developing on Microsoft platforms with Microsoft developer tools. I've started my software development career working on Motorola MCU software. I've developed software with C++, Delphi, C# and ASP.NET MVC during my 10 year career. I worked on military, education, media, document management, OCR, workflow, Windows CE and mobile projects. I've contributed to some open source projects and in the mean time I maintain my own open source project PragmaSQL.

 

Yalla Apps: What gets you started on developing for a certain platform? What are all platforms you develop for?

Ali Özgür : Ecosystem of the platform is very important in my opinion. By ecosystem I mean developer tools, platform APIs and SDKs, programming model of the platform, the quality of the hardware running the platform, market share, general profile of the platform users, nice looking appstore There are also some technical parameters I take into consideration. For example providing a unified programming model to developers for different form factors, having strong DRM (Digital Rights Management) to allow just licensed software are some of the technical parameters. 

I'm developing software for Windows platform as part of my regular job with Microsoft .NET and other Microsoft technologies. Under PragmaTouch (my side project) we develop primarily for Apple iOS. Weare also evaluating Android and WP7 and have some demo apps. Personally I've also developed for Windows CE couple of years ago.

 

Yalla Apps: Would you consider developing for WP7? What you think is missing in WP7 development platform – what is better in others?

Ali Özgür: We are not just considering actually we are actively evaluating WP7 by writing some little demo apps. I think WP7 has a great development platform. First of all you build software for WP7 with the greatest development IDE in the market, in my opinion, which is Visual Studio. You develop with C#, which is the master piece of primarily Anders Hejlsberg and all other great guys at Microsoft. I really love C# as a programming language and when combined with Visual Studio you have the bare minimums to produce a quality software.  WP7 has an emulator not a simulator, the difference is somehow technical but important. As a developer in my opinion others have nothing better than the WP7 development platform. But as a platform for example copy/paste and hardware is better in iOS,

 

Yalla Apps: Do you think WP7 will play a significant role in mobile OS?

Ali Özgür : Yes, I definitely think that WP7 will play a significant role in mobile. Especially the recent Microsoft-Nokia agreement and the success of the partnership will be very important in determining the place of WP7 in mobile market. Nokia is the biggest mobile manufacturer by quantity and has high market shares in developing countries where demand for new technology is increasing every year. Xbox customers will also play important role during this process since Microsoft has great customer base on this platform.

 

Yalla Apps: Do you consider learning new technologies for mobile – which ones?

Ali Özgür : Yes, I consider learning new technologies for mobile. HTML5 is the number one in my personal list.


 


Posted in: .NET Development , IPhone , Mobile  Tags:

Here is a stackoverflow question which describes the issue very well

I have some code that needs to run after the a UIWebView finishes loading a document. For that I've set the UIWebView's delegate to my controller, and implemented the webViewDidFinishLoading method.

This gets called multiple times, depending on the type of page to load. I'm not sure if it's because of ajax requests, requests for images, or maybe even iframes.

Is there a way to tell that the main request has finished, meaning the HTML is completely loaded?

Or perhaps delay my code from firing until all of those events are done firing?

Some people say that "UIWebView must die". Yes I actually agree with them. UIWebView loads slower than Safari, it is hard to use and it does not expose some core methods. For example you can not get source of the loaded HTML page or the document title with a regular method call. But it has its strenghts like the stringByEvaluatingJavaScriptFromString (MonoTouch equivalent is EvaluateJavascript) method. With this method you can perform some of the missing core functions.

The idea to solve the mentioned problem goes on like this

 

  1. Inject javascript to the loaded (or still loading) document
  2. With the enjected javascript check the document ready state
  3. If document is already loaded inject  a hidden input indicating the document is loaded
  4. If document is not loaded yet inject another javascrip which simply binds an anonymous function to window.onload so that we can inject the hidden document loaded indicator input when window.onload is called
  5. As the last step each time didFinishLoading is called/fired try to find the injected document loaded indicator input element by evaluating another javascript
  6. If document loaded indicator input element is in place we can be sure that the whole document is loaded and we can continue with the execution
Here is the injected javascript script code mentiond through steps 1-4
 
if(document.readyState == 'complete')
{
	var element = document.createElement('input'); 
	element.setAttribute('type','hidden'); 
	element.setAttribute('id','moodlez_documentloaded'); 
	document.body.appendChild(element);
}
else
{
  var script = document.createElement('script');
  script.type = 'text/javascript';
  script.setAttribute('id','moodlez_windowload');
  script.text = "window.onload = function(){var element = document.createElement('input'); element.setAttribute('type','hidden'); element.setAttribute('id','moodlez_documentloaded'); document.body.appendChild(element);}";
  document.body.appendChild(script);
}

In the above JavaScript code the if(document.readyState == 'complete') block is needed so that we can handle the case when didFinishLoading fires only one time because the HTML page does not contain any frames and other stuff causing multiple  calls to didFinishLoading.

Here is the MonoTouch (C#) code which implements the steps mentioned above

 

public void LoadCompleted ()
{
	// Your code here......
	
	// check if the hidden document loaded indicator input is present
	jsResult = this.WebView.EvaluateJavascript ("document.getElementById('moodlez_windowload').toString();");
	
	// hidden element is not present so evaluate the javascript which has the potential to add the element
	if (String.IsNullOrWhiteSpace (jsResult)) 
	{
		string eval = "if(document.readyState == 'complete'){" + Helper.LoadCompleteJs + "}else{" + "var script = document.createElement('script');" + " script.type = 'text/javascript';" + " script.setAttribute('id','moodlez_windowload');" + " script.text = \"window.onload = function(){" + Helper.LoadCompleteJs + "}\";" + " document.body.appendChild(script);" + "}";				
		this.WebView.EvaluateJavascript (eval);
	}
	
	
	// Lets check again if the hidden document loaded indicator input is present
	jsResult = this.WebView.EvaluateJavascript ("document.getElementById('moodlez_documentloaded').toString();");
	
        // document loaded indicator input is not present so this means document did not complete loading	
	if (string.IsNullOrWhiteSpace (jsResult)) 
		return;
			
	// Your code here, which you want to be executed after document loading si really completed
			
}

Note: Helper.LoadCompleteJs static variable holds the following javascript code string which in turn is loaded from a resource file on application startup

 

var element = document.createElement('input'); 
element.setAttribute('type','hidden'); 
element.setAttribute('id','moodlez_documentloaded'); 
document.body.appendChild(element);

This method can be used from Objective-C, just translate the code of LoadComplete method to Objective-C and you are ready to go.

 


Posted in: MonoTouch  Tags: