Хуудсууд

2012-09-13

Java annotations example

I've done some small-scale presenting about annotations in Java based on a simple use case in my company. I thought I would post it here for a greater audience.

Annotations in Java is a very powerful enhancement that can save a lot of time for developers and programmers. Basically, it enables programmers to avoid creating bunch of configurations based on XML, database records, etc. Instead they can annotate certain classes or fields to achieve different configurations. That is how now we don't declare our servlets in web.xml with its class and URL pattern; instead we annotate them by typing @WebServlet in the Java file.

OK, the use case: Let's assume that we are developing a tax processing program. We have an entity class called Citizen.java which looks something like following:


Let's also assume that our program shall be a pretty generic one where we can define our processing formulas. Let's say we define formulas and set its variables to Citizen class' fields. Say we have if (A < (new Date()).getTime()) { B; } else { 0-B/2; }.

Obviously, some of the fields are irrelevant for formula designing. So, we define an annotation and annotate those fields which are relevant.


and
We have also defined an attribute called name for the annotation so that it can be more readable.

Finally, what and why are doing it is that we are building drop-down menus for setting variables in each formula we define. We are not able to fetch those fields annotated with @Calculated to fill those drop-down menus.

The ways to using these kind of functionality are left for your imaginations.

Of course, using reflections in run-time may make your program run slower. However, you can always cache the annotated fields list in your favorite embedded key-value store database.

2012-08-07

Embedded key-store store database wrapping-up

In my last post, I have mentioned about what a key-value store database and little about Sleepycat. While Sleepycat is great, it needs some configuration before actually using it. For this reason, I have written an wrapper which stores only unicode-based strings as key and value. The code is given in the following Gist. The usage example has been given in the comment.

2012-06-30

Embedded, persistent key-store

One often needs an embedded, persistent, key-store database solution if he/she is developing a software which relies on configurations made upon deployment. I was that one yesterday, so I looked up on the Internet for a solution. The solution was, with no convincing reason, Berkeley DB Java Edition, Sleepy Cat to be specific.

So here is the code chunk that did the trick! For a developer of modern languages like Python, it seemed like a lot of work for simple tasks. However, if you wrap it with your own code it can be helpful in many ways.


2012-01-09

The Friendship of the Music: A review for Genghis Blues


The world as we know is full of inspirations, surprises and other amazing things with all its diversity. This diversity is its people who vary from the highlanders in the Andes, to the arctic Eskimos, from city dwellers of enormous metropolitan areas to Tuareg people in the Saharan desert. The greatest inspiration that is maybe music, a common thing that all different cultures in the world share. The inspiration for Paul Pena, a renowned jazz musician from the United States, was a practice of music from the nomadic people in the Central Asian Altai mountains. Called khoomei locally, this is a style of throat-singing in which the performer produces multiple tones simultaneously making a unique melody. As interesting as how it sounds is the journey and friendship formed when Paul Pena wanted to know better about what he heard on radio.

Khoomei, otherwise called overtone singing, is practiced by the nomadic people in Mongolia, Chinese Inner Mongolia and Russian Siberian republics like Tuva and Khakassia. It’s believed that khoomei was originated from nomadic herdsmen trying to emulate sounds of mountains, rivers, sand and wild animals. Mongolian nomads have a very different lifestyle which have great impact on khoomei. Mongolian plateau consists of steppes and Gobi desert that last thousands of kilometers where one may not find people for days. Altai ranges have steep mountains raising over the clouds. Herding domestic animals in the arid steppes and hunting games in enormous mountains can last days and sometimes months without seeing home. In such geography and condition, wilderness can be friend of people. Culturally tied to Mongolia, Tuva is a republic in Russian Federation. Tuva was an independent country in the first half of the 20-th century [1]. Afterwards it was incorporated into Russia. The people in Tuva share  lots of cultural elements with Mongolians.

Paul Pena, an American jazz singer accidentally catches khoomei on the radio, when he was surprised by what he was hearing. Excited, he goes to a local music store to look up what he has just listened where he finds out about khoomei performed by Tuvan artists. He wants to go further and make some studies. Apparently he gets along with an organization called Friends of Tuva which is a friendly community that gathers information about Tuva. Friends of Tuva was formed by Nobel laureate physicist Richard Feynman and friends [2]. After performing khoomei unofficially in a Tuvan event in America, Paul Pena was invited to Tuva by Kongar-Ool Ondar who is a throat-singing master in Tuva. After informing with letters, just after the USSR was split, the group of friends travel to Tuva in a very long trip. They get there to be welcomed very friendly by the Tuvan people and meet Kongar-Ool Ondar. The group get along very nicely with local people thus establishing friendships with the people. Furthermore, having learnt khoomei before going to Tuva, Paul Pena wins Tuvan national throat-singing competition called Kargyrgaa [3]. Paul Pena and Kongar-Ool Ondar perform famous jazz music and Tuvan music together with big smiles on both of their faces. The friendship was there to grow and last rest of the following years.

The world is a big... big place. There are thousands of different ethnic groups and hundreds of different cultures which can not be easily percieved by each other. But inspirations are always there to be found by some medium. In “Genghis Blues”, the music was the medium and it connected different cultures to create friendships among them.  It can be best summarized by Paul Pena in his letter which states, “Kongar-Ool and I have been working in the hope of promoting better understanding between people of different nationalities, races, beliefs, languages, and cultural and economic systems. I believe that in this work there can be found evidence that such understanding and cooperation can be realized.” [3]

References
  1. World at War timelines. http://www.schudak.de/timelines/tannutuva1911-1944.html retrieved Jan 03, 2012
  2. Friends of Tuva website. Frequently asked questions: http://www.fotuva.org/faq/part_1.html retrieved Jan 03, 2012
  3. A personal letter by Paul Pena in 1994. http://www.fotuva.org/gb/paul.html retrieved Jan 03, 2012

2011-03-21

Verilog ашиглан цуваа танигч хийсэн минь

Verilog хэрэглээд цуваа танигч хийснийгээ та бүхэнтэй хуваалцья гэж бодлоо. Электрон хэлхээ нь хир зай эзлэх вэ, хэлхээ их халах уу гэх мэт асуудлуудыг бодолцоогүйг анхаарна уу!

Энд цуваа танигчийгаа finite-state machine болон цуваа оролт, паралель гаралттай shift register ашиглан хийсэн юм.

Finite-state machine


`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Module Name:   fsm
// Tool versions: Xilinx ISE 12.1
// Description:
//                Sequence detector using FSM
//
//////////////////////////////////////////////////////////////////////////////////
module fsm(clk, reset, inp, outp);
  input clk;
  input reset;
  input inp;
  output outp;
 
  reg[2:0] state;
  reg outp;
 
  always @(posedge clk) // always trigger on clk
     begin
        if (reset)  // check if reset
           begin
              state <= 3'b000;                outp <= 1'b0;             end          else        // else update outp             begin                if (state == 3'b111 & inp == 1'b0)                   outp <= 1'b1;                else                   outp <= 1'b0;             end          case(state) // state transition          3'b000:             if (inp == 1'b1) state <= 3'b001;             else state <= 3'b000;          3'b001:             if (inp == 1'b0) state <= 3'b010;             else state <= 3'b000;          3'b010:             if (inp == 1'b0) state <= 3'b011;             else state <= 3'b000;          3'b011:             if (inp == 1'b1) state <= 3'b100;             else state <= 3'b000;          3'b100:             if (inp == 1'b0) state <= 3'b101;             else state <= 3'b000;          3'b101:             if (inp == 1'b1) state <= 3'b110;             else state <= 3'b000;          3'b110:             if (inp == 1'b1) state <= 3'b111;             else state <= 3'b000;          3'b111:             state <= 3'b000;          default:             state <= 3'b000;          endcase       end       endmodule 

Хэлхээ нь ийм болж байна:

Shift-register


`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Module Name:   shr
// Tool versions: Xilinx ISE 12.1
// Description: 
//                Sequence detector using shift register
//
//////////////////////////////////////////////////////////////////////////////////
module shr(clk, reset, inp, outp);
   input clk;
   input reset;
   input inp;
   output outp;
   
   reg[7:0] shr;
   reg outp;
   
   always @(posedge clk) // always trigger on clk
      begin
         if (reset)  // check if reset
            begin
               shr <= 8'b00000000;
               outp <= 1'b0;
            end
         else
            begin
               shr <= shr << 1;
               shr[0] <= inp;
               if (shr == 8'b10010110)
                  outp <= 1'b1;
               else
                  outp <= 1'b0;
            end
         
      end

endmodule

За тэгээд 2уланг нь доорх тест модулиар ажиллууллаа даа:


`timescale 1ns / 1ps
////////////////////////////////////////////////////////////////////////////////
// Module Name:   shr_test
// Tool versions: Xilinx ISE 12.1
// Description:
//                Verilog Test Fixture created by ISE for modules:
//                   shr
//
////////////////////////////////////////////////////////////////////////////////

module shr_test;

// Inputs
reg clk;
reg reset;
reg inp;

// Outputs
wire outp;

// Instantiate the Unit Under Test (UUT)
shr uut (
 .clk(clk),
 .reset(reset),
 .inp(inp),
 .outp(outp)
);

always #5 clk = ~clk;

initial begin
 // Initialize
 clk = 1;
 inp = 0;
 reset = 0;

 // reset=1 when clk rises and reset=0
 // in the next rise of clk
 #9 reset = 1;
 #3 reset = 0;

 // Stimulus
 #1 inp = 1;
 #10 inp = 0;
 #10 inp = 0;
 #10 inp = 1;
 #10 inp = 0;
 #10 inp = 1;
 #10 inp = 1;
 #10 inp = 0;
 #30
 $finish;
end
    
endmodule

За тэгсэн чинь доорх симуляцууд гараад ирлээ.

Finite-state machine

Shift register

2011-03-19

Электроник ч сонирхолтой юм аа

Компьютерийн инженер ч гэсэн электроникийг цухасхан сураад байгаадаа олзуурхаад байгаа. Цаана чинь "их бүтээн байгуулалт", "7000 инженер хэрэгтэй байна" гээд яриад байна. R&D (судалгаа) хийж үйлдвэржүүлэлтийг бий болгохын тулд инженерүүд маань өөрсдөө шинийг санаачилж, туршиж үзэх хэрэгтэй байна. Тэгээд орлого олохуйц шинэ бүтээгдэхүүний үйлдвэрлэлт бий болговол 7000 инженерийн нэг та 20 хүний ажлын байр бий болгож улс орноо хөгжүүлэхэд хувь нэмэр оруулж болох юм. Туршиж үзэхийн тулд харин инженер тал бүрийн мэдлэг туршлагатай байх хэрэгтэй гэж бодож байна.

Жишээ нь компьютерийн инженер Bluetooth шиг богино долгионы радио дамжуулах технологи хөгжүүллээ гэхэд радио долгион, тодорхой хэлбэлзэлийн долгион үүсгэх хэлхээ хйих тухай мэдэхгүй байвал нэг тиймэрхүү.

2011-01-09

FUSE - хэрэглэгчийн орон зайн файл систем

Сүүлийн үед үүл, тархай систем гэсэн нэр томьёонуудыг олонтаа сонсох боллоо. Сүлжээ ашиглан зарим файлуудыг өөр тооцоолуур дээр хадгалаж, өөрийн тооцоолуур дээр байгаа мэтээр хандах гэх мэт олон дэвшилтэт арга замууд бие болсон ба ийм технологи дээр суурилсан олон start-up компани бий болсон.

Энэ бичлэгтээ ийм технологи хийхэд маш их тус болдог FUSE (хэрэглэгчийн орон зайн файл систем) дээр жишээ хийж үзсэнээ хуваалцья гэж бодлоо. Юниксжуу үйлдлийн систем дээр байгаа файл системийг хүссэнээрээ харж хэрэглэхэд тус болдог цөмийн модуль юм.

За тэгэхээр нэг ийм жишээ бичье. Та өөрийгөө тагнуулч байна гэж бод. Тагнаж байгаа хүнийхээ гэрт орлоо. Хэрэглэгчийн тодорхой хугацаанд хандсан файлыг эсвэл хамгийн сүүлд хандсан файлыг олохыг хүслээ гэж бодьё. Энэ жишээн дээр бичих програм маань тодорхой хавтасыг хувьсагч болгож өгөөд ажиллуулахад тэр хавтасан дотор байгаа файлуудыг хамгийн сүүлд өөрчлөгдсөн жил, сар, өдөр, цагаар нь ангилладаг програм байх юм.

Жишээ нь, доорх шиг хавтасыг ангилья гэж бодьё:

Дээрх зурган дээр файлын нэрүүдийн өмнөх багана файлын хамгийн сүүлд өөрчлөгдсөн огноо болохыг анхаарна уу!

Тэгвэл програмыг ажиллуулсаны хүчинд доорх байдлаар харж болох юм.

Дээрх зурган дээр бид ангилсан хавтасуудын тусламжтайгаар 2010 оны 05 сарын 10-нь 01 цагт хамгийн сүүлд өөрчлөгдсөн файлыг харж байгаа юм.

За ингээд жишээний мааны код:

modiffs.c


#define FUSE_USE_VERSION 26

static const char * modiffsVersion = "2010.12.24";

#include <sys/types.h>
#include <sys/stat.h>
#include <sys/statvfs.h>
#include <stdio.h>
#include <strings.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include <errno.h>
#include <fcntl.h>
#include <sys/xattr.h>
#include <dirent.h>
#include <unistd.h>
#include <fuse.h>
#include <time.h>

#define STACK_SIZE 250

typedef struct stack_s {
   char * items[STACK_SIZE];
   int size;
} stack;

int stack_exist(stack * s, char * elem) {
   int i = 0;
   for (i=0; i < s->size; i++) {
       if (strcmp(elem, s->items[i]) == 0) {
           return 1;
       }
   }
   return 0;
}

void stack_push(stack * s, char * elem) {
   s->items[s->size++] = elem;
}

int dir_depth(const char * path) {
   int depth = 0;
   char * temp = strchr(path, '/');
   while (temp != NULL) {
       depth++;
       temp = strchr(temp + 1, '/');
   }
   return depth;
}

char * full_path(char * upath, char * d_name) {
   char * ret = (char *) malloc(sizeof(char)*(strlen(upath) + strlen(d_name) + 1));
   strcpy(ret, upath);
   strcat(ret, d_name);
   return ret;
}

// Global to store our read-write path
char * rw_path;

// Translate an modiffs path into it's underlying filesystem path
static char * translate_path(const char * path) {

   char * rPath= malloc(sizeof(char)*(strlen(path)+strlen(rw_path)+1));

   strcpy(rPath, rw_path);
   if (rPath[strlen(rPath)-1]=='/') {
       rPath[strlen(rPath)-1]='\0';
   }
  
   int depth = dir_depth(path);
  
   if (strcmp("/", path) == 0) {
       strcat(rPath, "/");
   } else if (depth < 5) {
       strcat(rPath, "/");
   } else {
       int i = 0;
       char * temp = strchr(path, '/');
       while (i < (depth-1)) {
           i++;
           temp = strchr(temp + 1, '/');
       }
       strcat(rPath, "/");
       strcat(rPath, temp);
   }
  
   return rPath;
}

/*
* level:
* 0: year
* 1: month
* 2: day
* 3: hour
*/
char * last_attr(const char * path, int level) {   
   int depth = 0;
   char * cont = (char *) malloc(sizeof(char)*strlen(path));
   strcpy(cont, path);
   char * temp = strtok(cont, "/");
   while (depth < level && temp != NULL) {
       depth++;
       temp = strtok(NULL, "/");
   }
   return temp;
}

/******************************
*
* Callbacks for FUSE
*
******************************/

static int modiffs_getattr(const char * path, struct stat * stbuf) {
  
   int res = 0;
   int depth = dir_depth(path);
   memset(stbuf, 0, sizeof(struct stat));
  
   if (strcmp(path, "/") == 0) {
       stbuf->st_mode = S_IFDIR | 0755;
       stbuf->st_nlink = 1;
       stbuf->st_ctime = time(NULL);
       stbuf->st_atime = time(NULL);
       stbuf->st_mtime = time(NULL);
       stbuf->st_size = 4096;
   } else if (depth < 5) {       
       stbuf->st_mode = S_IFDIR | 0444;
       stbuf->st_nlink = 1;
       stbuf->st_ctime = time(NULL);
       stbuf->st_atime = time(NULL);
       stbuf->st_mtime = time(NULL);
       stbuf->st_size = 4096;
   } else {       
       char * upath = translate_path(path);
       res = lstat(upath, stbuf);
       free(upath);
       if(res == -1) {
           return -errno;
       }
   }

   return res;
}

static int modiffs_readlink(const char *path, char *buf, size_t size)
{
   int res;
   char * upath = translate_path(path);

   res = readlink(upath, buf, size - 1);
   free(upath);
   if(res == -1) {
       return -errno;
   }
   buf[res] = '\0';
   return 0;
}

static int modiffs_readdir(const char *path, void *buf, fuse_fill_dir_t filler, off_t offset, struct fuse_file_info *fi) {
  
   DIR * dp;
   struct dirent * de;
   int res;
  
   struct tm *ts;
  
   (void) offset;
   (void) fi;
  
   int depth;
  
   char * upath = translate_path(path);
  
   dp = opendir(upath);
  
   if(dp == NULL) {
       res = -errno;
       return res;
   }
  
   filler(buf, ".", NULL, 0);
   filler(buf, "..", NULL, 0);
  
   if (strcmp("/", path) == 0) {       
       stack years;
       years.size = 0;
       while((de = readdir(dp)) != NULL) {       
           struct stat st_modif;
           memset(&st_modif, 0, sizeof(st_modif));
           char * year = (char *) malloc(sizeof(char) * 5);           
           stat(full_path(upath, de->d_name), &st_modif);
           ts = localtime(&(st_modif.st_mtime));
           strftime(year, 255, "%Y", ts);
           if (stack_exist(&years, year) == 0) {
               stack_push(&years, year);
               filler(buf, year, NULL, 0);
           }
       }
   } else {
       depth = dir_depth(path);
       if (depth == 1) {
           stack months;
           months.size = 0;
           while((de = readdir(dp)) != NULL) {       
               struct stat st_modif;
               memset(&st_modif, 0, sizeof(st_modif));
               char * year = (char *) malloc(sizeof(char)*5);
               char * month = (char *) malloc(sizeof(char)*3);
               stat(full_path(upath, de->d_name), &st_modif);
               ts = localtime(&(st_modif.st_mtime));
               strftime(year, 255, "%Y", ts);
               strftime(month, 255, "%m", ts);
               if (strcmp(last_attr(path,0), year) == 0) {
                   if (stack_exist(&months, month) == 0) {
                       filler(buf, month, NULL, 0);
                       stack_push(&months, month);
                   }
               }
           }
       } else if (depth == 2) {
           stack days;
           days.size = 0;
           while((de = readdir(dp)) != NULL) {       
               struct stat st_modif;
               memset(&st_modif, 0, sizeof(st_modif));
               char * year = (char *) malloc(sizeof(char)*5);
               char * month = (char *) malloc(sizeof(char)*3);
               char * day = (char *) malloc(sizeof(char)*3);
               stat(full_path(upath, de->d_name), &st_modif);
               ts = localtime(&(st_modif.st_mtime));
               strftime(year, 255, "%Y", ts);
               strftime(month, 255, "%m", ts);
               strftime(day, 255, "%d", ts);
              
               if (strcmp(last_attr(path,0), year) == 0 &&
                   strcmp(last_attr(path,1), month) == 0) {
                   if (stack_exist(&days, day) == 0) {
                       stack_push(&days, day);
                       filler(buf, day, NULL, 0);
                   }
               }                           
           }
       } else if (depth == 3) {
           stack hours;
           hours.size = 0;
           while((de = readdir(dp)) != NULL) {       
               struct stat st_modif;
               memset(&st_modif, 0, sizeof(st_modif));
               char * year = (char *) malloc(sizeof(char)*5);
               char * month = (char *) malloc(sizeof(char)*3);
               char * day = (char *) malloc(sizeof(char)*3);
               char * hour = (char *) malloc(sizeof(char)*3);
               stat(full_path(upath, de->d_name), &st_modif);
               ts = localtime(&(st_modif.st_mtime));
               strftime(year, 255, "%Y", ts);
               strftime(month, 255, "%m", ts);
               strftime(day, 255, "%d", ts);
               strftime(hour, 255, "%H", ts);
              
               if (strcmp(last_attr(path,0), year) == 0 &&
                   strcmp(last_attr(path,1), month) == 0 &&
                   strcmp(last_attr(path,2), day) == 0) {
                   if (stack_exist(&hours, hour) == 0) {
                       stack_push(&hours, hour);
                       filler(buf, hour, NULL, 0);
                   }
               }                           
           }
       } else {
           while((de = readdir(dp)) != NULL) {
               if (strcmp(".", de->d_name) == 0 || strcmp("..", de->d_name) == 0) {
                   continue;
               }             
              
               struct stat st_modif;
               memset(&st_modif, 0, sizeof(st_modif));
               char * year = (char *) malloc(sizeof(char)*5);
               char * month = (char *) malloc(sizeof(char)*3);
               char * day = (char *) malloc(sizeof(char)*3);
               char * hour = (char *) malloc(sizeof(char)*3);
               stat(full_path(upath, de->d_name), &st_modif);
               ts = localtime(&(st_modif.st_mtime));
               strftime(year, 255, "%Y", ts);
               strftime(month, 255, "%m", ts);
               strftime(day, 255, "%d", ts);
               strftime(hour, 255, "%H", ts);
              
               if (strcmp(last_attr(path,0), year) == 0 &&
                   strcmp(last_attr(path,1), month) == 0 &&
                   strcmp(last_attr(path,2), day) == 0 &&
                   strcmp(last_attr(path,3), hour) == 0) {
                  
                   struct stat st;
                   memset(&st, 0, sizeof(st));
                   st.st_ino = de->d_ino;
                   st.st_mode = de->d_type << 12;

                   if (filler(buf, de->d_name, &st, 0)) {
                       break;
                   }
               }
           }
       }
   }
  
   free(upath);
   closedir(dp);
  
   return 0;
}

static int modiffs_mknod(const char *path, mode_t mode, dev_t rdev)
{
   (void)path;
   (void)mode;
   (void)rdev;
   return -EROFS;
}

static int modiffs_mkdir(const char *path, mode_t mode)
{
   (void)path;
   (void)mode;
   return -EROFS;
}

static int modiffs_unlink(const char *path)
{
   (void)path;
   return -EROFS;
}

static int modiffs_rmdir(const char *path)
{
   (void)path;
   return -EROFS;
}

static int modiffs_symlink(const char *from, const char *to)
{
   (void)from;
   (void)to;
   return -EROFS;
}

static int modiffs_rename(const char *from, const char *to)
{
   (void)from;
   (void)to;
   return -EROFS;
}

static int modiffs_link(const char *from, const char *to)
{
   (void)from;
   (void)to;
   return -EROFS;
}

static int modiffs_chmod(const char *path, mode_t mode)
{
   (void)path;
   (void)mode;
   return -EROFS;

}

static int modiffs_chown(const char *path, uid_t uid, gid_t gid)
{
   (void)path;
   (void)uid;
   (void)gid;
   return -EROFS;
}

static int modiffs_truncate(const char *path, off_t size)
{
   (void)path;
   (void)size;
   return -EROFS;
}

static int modiffs_utime(const char *path, struct utimbuf *buf)
{
   (void)path;
   (void)buf;
   return -EROFS;
}

static int modiffs_open(const char *path, struct fuse_file_info *finfo)
{
   int res;
  
   int flags = finfo->flags;

   if ((flags & O_WRONLY) || (flags & O_RDWR) || (flags & O_CREAT) || (flags & O_EXCL) || (flags & O_TRUNC) || (flags & O_APPEND)) {
       return -EROFS;
   }
  
   char * upath = translate_path(path);

   res = open(upath, flags);

   free(upath);
   if(res == -1) {
       return -errno;
   }
   close(res);
  
   return 0;
}

static int modiffs_read(const char *path, char *buf, size_t size, off_t offset, struct fuse_file_info *finfo)
{
   int fd;
   int res;
   (void)finfo;

   char * upath = translate_path(path);
   fd = open(upath, O_RDONLY);
   free(upath);
   if(fd == -1) {
       res = -errno;
       return res;
   }
   res = pread(fd, buf, size, offset);

   if(res == -1) {
       res = -errno;
   }
   close(fd);
   return 0;
  
}

static int modiffs_write(const char *path, const char *buf, size_t size, off_t offset, struct fuse_file_info *finfo)
{
   (void)path;
   (void)buf;
   (void)size;
   (void)offset;
   (void)finfo;
   return -EROFS;
}

static int modiffs_statfs(const char *path, struct statvfs *st_buf)
{
   int res;
   char * upath = translate_path(path);
   res = statvfs(upath, st_buf);
   free(upath);
   if (res == -1) {
       return -errno;
   }
   return 0;
}

static int modiffs_release(const char *path, struct fuse_file_info *finfo)
{
   (void) path;
   (void) finfo;
   return 0;
}

static int modiffs_fsync(const char *path, int crap, struct fuse_file_info *finfo)
{
   (void) path;
   (void) crap;
   (void) finfo;
   return 0;
}

static int modiffs_access(const char *path, int mode)
{
   int res;
   char *upath = translate_path(path);

   /* Don't pretend that we allow writing
    * Chris AtLee <chris@atlee.ca>
    */
   if (mode & W_OK)
       return -EROFS;

   res = access(upath, mode);
   free(upath);
   if (res == -1) {
       return -errno;
   }
   return res;
}

struct fuse_operations modiffs_oper = {
   .getattr     = modiffs_getattr,
   .readlink    = modiffs_readlink,
   .readdir     = modiffs_readdir,
   .mknod       = modiffs_mknod,
   .mkdir       = modiffs_mkdir,
   .symlink     = modiffs_symlink,
   .unlink      = modiffs_unlink,
   .rmdir       = modiffs_rmdir,
   .rename      = modiffs_rename,
   .link        = modiffs_link,
   .chmod       = modiffs_chmod,
   .chown       = modiffs_chown,
   .truncate    = modiffs_truncate,
   .utime       = modiffs_utime,
   .open        = modiffs_open,
   .read        = modiffs_read,
   .write       = modiffs_write,
   .statfs      = modiffs_statfs,
   .release     = modiffs_release,
   .fsync       = modiffs_fsync,
   .access      = modiffs_access
};
enum {
   KEY_HELP,
   KEY_VERSION,
};

static void usage(const char* progname)
{
   fprintf(stdout,
           "usage: %s readwritepath mountpoint [options]\n"
           "\n"
           "   Mounts readwritepath as a read-only mount at mountpoint\n"
           "\n"
           "general options:\n"
           "   -o opt,[opt...]     mount options\n"
           "   -h  --help          print help\n"
           "   -V  --version       print version\n"
           "\n", progname);
}

static int modiffs_parse_opt(void *data, const char *arg, int key,
                         struct fuse_args *outargs)
{
   (void) data;

   switch (key)
   {
   case FUSE_OPT_KEY_NONOPT:
       if (rw_path == 0)
       {
           rw_path = strdup(arg);
           return 0;
       }
       else
       {
           return 1;
       }
   case FUSE_OPT_KEY_OPT:
       return 1;
   case KEY_HELP:
       usage(outargs->argv[0]);
       exit(0);
   case KEY_VERSION:
       fprintf(stdout, "ROFS version %s\n", modiffsVersion);
       exit(0);
   default:
       fprintf(stderr, "see `%s -h' for usage\n", outargs->argv[0]);
       exit(1);
   }
   return 1;
}

static struct fuse_opt modiffs_opts[] = {
   FUSE_OPT_KEY("-h",          KEY_HELP),
   FUSE_OPT_KEY("--help",      KEY_HELP),
   FUSE_OPT_KEY("-V",          KEY_VERSION),
   FUSE_OPT_KEY("--version",   KEY_VERSION),
   FUSE_OPT_END
};

int main(int argc, char *argv[])
{
   struct fuse_args args = FUSE_ARGS_INIT(argc, argv);
   int res;

   res = fuse_opt_parse(&args, &rw_path, modiffs_opts, modiffs_parse_opt);
   if (res != 0)
   {
       fprintf(stderr, "Invalid arguments\n");
       fprintf(stderr, "see `%s -h' for usage\n", argv[0]);
       exit(1);
   }
   if (rw_path == 0)
   {
       fprintf(stderr, "Missing readwritepath\n");
       fprintf(stderr, "see `%s -h' for usage\n", argv[0]);
       exit(1);
   }

   fuse_main(args.argc, args.argv, &modiffs_oper, NULL);

   return 0;
}

Дээрх кодыг Убунту дээр ирдэг fuse-rofs багцын эх код дээр өөрчлөлт хийж бий болгосоныг анхаарна уу!

Эмхэтгэж ажиллуулахын тулд:

test.sh

gcc -o modiffs -Wall -ansi -W -std=c99 -g -ggdb -D_GNU_SOURCE -D_FILE_OFFSET_BITS=64 -lfuse modiffs.c fusermount -u /home/dagvadorj/Desktop/u sudo umount /home/dagvadorj/Desktop/u ./modiffs /home/dagvadorj/Desktop/untitled /home/dagvadorj/Desktop/u

2010-12-08

BX, Стамбулд

2 жилийн өмнө BX-ийг Стамбулд ирэхэд хийсэн анимэшн. Сая харсан чинь гоё санагдаад хуваалцлаа.
video

2010-11-12

Монгол хүний хийсэн програмын хэл

Яаая, хүний анхаарал татах гээд лаг гарчиг тавьцан.

2 сарын өмнөөс нэг хэлмэрчилдэг програмын хэл хийж эхэлсэн юмаа. Одоо альфа хувилбараа толилуулмаар байна. Дуусах яагаачгүй байгаа болохоор "0.81" хувилбар гэж нэрлэе.

Энэ хаягаас татаж авч болно. http://www.box.net/shared/sqp3d08p9e

Татаж авсны дараа задлаад root хэрэглэгчээр орсны дараа доорх коммандуудыг ажиллуулна.

# make
# litelang example.lite
example.lite болон түүн дотроос дуудагдаж байгаа factorial.lite програм нь доорх агуулгатай.

example.lite

print("Тавтай морил!")

include("factorial.lite")

a=7
b=4
print("a=",a,", b=",b)
print("a+b=", a+b)
print("a/b=", a/b)
print("a%b=", a%b)
print("a!=",factorial(a))
print(8,"!=",factorial(8))

gcd = func(x,y)
  while y > 0
    z = y
    y = x%y
    x = z
  end
  return(x)
end

print("15,12 хоёр тооны хамгийн их ерөнхий хуваагч бол: ",gcd(15,12))

print("Таны нэр: ")
a = input()
print("Сайн уу, ", a)

print("
litelang програмын хэл нь одоогийн байдлаар
альфа шатандаа байна.
")

factorial.lite

print("
Энэ файлд факториал функцийн тодорхойлолт бий.
")

factorial = func(n)
    value = 1
    while n>0
       value *= n
       n -= 1
    end
    return(value)
end

2010-10-01

General purpose linked list, stack and queue for C

Programmers refer to use modern programming languages like Java, Python or Ruby for their uses, because of their powerful built-in functions and flexibility. However, sooner or later, a programmer will have to face their old fella C someday.

For me, I had to use C when I decided to write an interpreter for a programming language I am developing. Of course, C lack of a bunch of stuff, which other modern languages have like hash table, and indexing of a list with a negative index (Python can do list[-2]), etc. But the first things I needed were stack, queue and linked list. We always write these ourselves when programming in C.

Here, I wrote a code for a linked list which can be used as stack and queue and supports negative indexing. Followings are the codes hosted on Google Code:

http://code.google.com/p/litelang/source/browse/trunk/litelang/slist.h (Includes description for methods)

http://code.google.com/p/litelang/source/browse/trunk/litelang/slist.c

Peace!

2010-05-12

Image Processing буюу Зураг Боловсруулалт

Номын санд явж байсан манай сургуулийн нэг Камбуж залуу нэг даалгавар хараадхаа гэхээр нь очоод харсан сонирхолтой санагдаад хийж үзлээ.

ppm төрлийн зургийн файл нь ASCII форматаар илэрхийлэгддэг юм байна.

Жишээ нь доорх шиг ppm форматтай зургийг текст эдитор дээр нээвэл хажуудахь шиг харагдана.

Файлыг эндээс татаж авч болно.

ASCII кодыг тайлбарлавал:
P3 # форматын төрөл
150 150 # зургийн өргөн, урт
255 # хэрэглэгдсэн максимум өнгө
176 # эхний цэгийн RGB кодын Red
158 # эхний цэгийн RGB кодын Green
158 # эхний цэгийн RGB кодын Blue
172 # хоёр дахь цэгийн RGB кодын Red
152 # хоёр дахь цэгийн RGB кодын Green
153 # хоёр дахь цэгийн RGB кодын Blue

3 дахь мөрөөс хойш 150x150x3 мөр байна. Учир нь 3 тоо нэг цэгийн өнгийг илэрхийлж байна.

Тэгээд код бичиж үзлээ, энгийн мөртлөө их таалагдлаа. Програмыг ажиллуулахад доорх дөрвөн зураг ppm форматаар үүсэх юм.

Хүний арьсны өнгийг аватарын арьсны өнгөтэй төстэй болгодог болохоор ингэж нэрлэлээ :) Зургийн RGB кодны улаан, цэнхэр хоёр утгыг нь солиход гарна Зургийн нэгатив Зургийн хэмжээг 2 дахин багасгасан байдал Толинд харсан байдал

За ингээд эцэст нь кодоо хавсаргая:


#include 

#include 



int main() {

        FILE * input;
        FILE * avatar;

        FILE * negative;

        FILE * small;
        FILE * mirror;

        int i, m;

        int width, height, max;

        char fname[20];
        

        printf("Enter the name of the file: ");

        scanf("%20s", &fname);
        

        input = fopen(fname, "r");
        avatar = fopen("avatar.ppm", "w");

        negative = fopen("negative.ppm", "w");

        small = fopen("small.ppm", "w");
        mirror = fopen("mirror.ppm", "w");

        
        if (input == NULL) {

           printf("ERROR: The file can not be found!\n");

           return -1;

        }
        

        fscanf(input, "P3\n%d %d\n%d", &width, &height, &max);
        fprintf(avatar, "P3\n%d %d\n%d\n", width, height, max);

        fprintf(negative, "P3\n%d %d\n%d\n", width, height, max);

        fprintf(small, "P3\n%d %d\n%d\n", width/2, height/2, max);
        fprintf(mirror, "P3\n%d %d\n%d\n", width, height, max);

        
        int dim = width*height;

        int temp[dim][3];

        
        for (i=0;i < dim;i++) {

            fscanf(input, "%d %d %d ", &temp[i][0], &temp[i][1], &temp[i][2]);

            fprintf(avatar, "%d %d %d ", 

                temp[i][2], 

                temp[i][1], 

                temp[i][0]);
            fprintf(negative, "%d %d %d ", 

                max-temp[i][0], 

                max-temp[i][1], 

                max-temp[i][2]);

            if ((i/width)%2==0) {

                if (i%2==0)

                   fprintf(small, "%d %d %d ", 

                       temp[i][0], 

                       temp[i][1], 

                       temp[i][2]);

            }

        }
    
        for (i=0;i < dim;i++) {
        m = (i/width)*width+width-i%width-1;
        fprintf(mirror, "%d %d %d ", temp[m][0], temp[m][1], temp[m][2]);
        }
        

        fclose(input);
        fclose(avatar);

        fclose(negative);

        fclose(small);
        fclose(mirror);

        return 0;

}

Дажгүй цэгцтэй код боллоо. Зураг том бол RAM-д их зай эзлэх нь дээ. :(

2010-05-08

Confession of an Invader

Nearly 1.5 thousand light years from home and we finally made it. 2060 AD, a united space expedition called Confederation of Space Missions discovered a new planet with life on it. After leaving the Earth which has ultimately limited resource and overpopulation, the team finally made to one of 50 moons of NZ53-04 planet in the NZ-53 solar system, which was first located in the 2010s. This moon, relatively younger than our Earth, has enormous amount of aqua and a very dynamic life-form.

This was supposed to be the home, new hope for the mankind. About 2.3 times bigger than the Earth, physically the planet is formed by highlands and deep valleys. The planet has magnificent amount of dissipate, the planet is almost all covered with deep cloud, the highlands are similar to shallow rain forests and streams on it are fed by the clouds. What are in the deep valleys and what is happening out there is mystery. Earlier expeditions reported deathly fauna – giant lizard-like creatures and scary jungle. People called these deep valleys “death” valleys.

We called the planet Renzhou, Chinese for “Man's dominion”, though its indigenous intellectual creatures are the Mangi. Mangis, koala-sized creatures, have tribal societies like earlier plains people. They lived in the planet's highlands. Although, they seemed frightened when the research teams first came, they became friendly shortly.

The cloud making an layer underneath the planet's atmosphere made people hard to breathe, since the pressure was too high. It was a major obstacle for forming colonies alongside the planet since everyone with wear special costume and people would only live in facilities. It was impossible because the first immigration package from the Earth would include some 4 billion people and livestock. Scientists came out with a solution. The solution was to use microwave and chemicals to reduce the amount of the cloud. They were successful. The cloud did became less.

Understanding that the planet's weather condition was changing as a result of humans actions, the mangis were unpleasant with the situation. Clashes of different sizes took place in the highlands. Approved by the United Nations, army regiments and raged volunteers started war against the mangis. As a result the mangis were relocated to the death valleys.

We established colonies on the highlands. New Australland, Ningpo, Nova Occitan, Fukian, Formosa, and Gulliver were among the first ones. Minor mutations were observed among people. This phenomenon first was thought to be fine. It was later proved that the thick cloudy structure covering the planet was making the life on Renzhou immune to the toxic substances coming from NZ-53 and NZ-53-04.

The cloud was unrecoverable since the forests both in the highlands and the deep valleys are decreased 80% in size and the water supply has decreased 65%. 44 years ago, man was first coming to Renzhou, and today we are leaving the planet with our spaceships. I am one of the few people who were lucky enough to be on one of the ships. About 3.4 billion people are left on the planet for definite death. We, on the ships, are all infected with the toxins. It is most probably that we all be died as well.

Evolution, “the stronger beats the weaker”, cruelty, Darwin's law, war, violence, … Unfortunately, it seems that they will always exist alongside with human.

2010-05-01

Downloading your e-mail on a server to process

You know all the great features of craigslist and Facebook, that use anonymous, standalone e-mail for forwarding request to an ad owner or replying to a message via e-mail.

Well, I will show you how to do something like these.

Scenario: An chronological script will download new e-mails, then a Python script will process on these e-mails.

For downloading e-mails, I used getmail4. The best tutorial for it can be found here.

For my case, /home/manchurian/.getmail/getmailrc looks like this:

[retriever]
type = SimplePOP3Retriever
server = [my_mail_server]
username = [my_mail]
password = [my_mail_password]

[destination]
type = Mboxrd
path = /home/manchurian/inbox

Make the mail downloading automatic using crontab -e:

* * * * * getmail -n
-n is for retrieving new mails only.

Now it is time to process the downloaded mails anyway you want:

import mailbox
mails = mailbox.mbox("/home/manchurian/inbox")

mails.lock()

try:
   for m in mailbox:
      if m['from'] == 'abc@abc.org':
         print m['subject']
finally:
   mails.unlock()

Cheers,

Backing up MySQL database

Losing data on your business application's database would be a real disaster. Here's a way simple script to back up your MySQL database.

Scenario

We have a remote Debian server with the database, and an Ubuntu server (Intel Xeon) in our office right beneath my table. :)

We wanted to have our database backed up daily. So here we go:

1-st step. Save SQL script of the database in the remote server.


#!/bin/bash
export d=$(date +'%Y-%m-%d')
mkdir -p /root/backup/$d
mysqldump --add-drop-table --allow-keywords -q -a -c -u root -p[password_for_mysql_root] [databasename] > /root/backup/$d/[databasename].sql

Save it as /root/mysqlbackup.sh

2-nd step. Automize it with crontab -e to run daily at 05:30.

30 05 * * * /root/mysqlbackup.sh

3-rd step. Fetch the SQL from the local server and save.

#!/bin/bash
export d=$(date +'%Y-%m-%d')
mkdir -p /root/backup/$d
pscp -sftp -l root -pw [password_for_remote_server_root] root@[server_ip]:/root/backup/$d/[databasename].sql /root/backup/$d
exit 0

2010-03-22

Berkeley RISC I

RISC төрлийн архитектуртай Berkeley RISC I ассемблэр дээр код бичиж үзлээ.


N EQU 10
DIZI EQU $500

 ORG $500
 DCINT 7
 DCINT -98
 DCINT 5
 DCINT 678
 DCINT -832
 DCINT 4567
 DCINT -789
 DCINT 409
 DCINT -372
 DCINT 65


 ORG $600
START:
 ADD R0,N,R17  
 XOR R16,R16,R16  
 SLL R17,2,R17  
back: 
 LDL (R16)DIZI,R2  
 CALL deltaD(R0),R3 
 NOP
 STL (R16)DIZI,R2  
 ADD R16,4,R16  
 NOP
 SUB R16,R17,R18  
 NOP
 JMP BMI,back(R0) 
 NOP
 NOP

 ORG $700
deltaD: 
 SLL R2,1,R21  
 JMP BMI,neg(R0)  
 NOP
 NOP
 
 SLL R2,2,R2  
 RET (R0)R3
 NOP

neg: 
 SUB R0,R2,R2  
 NOP 
 RET (R0)R3
 NOP


2010-03-07

Моторолла 68000

Эхэн үеийн Макуудад ажилладаг байсан Моторолла 68000 процессерийн ассемблэр хэл дээр програм бичлээ. 16 бит, тэмдэгтгүй тоог анхны тоо эсэхийг шалгадаг програм; яарч хийсэн учир илүү хурдан ажиллууладаг, цөөхөн регистр ашигладаг болгож амжсангүй.
     ORG $0500
num   DC.W  83

     ORG $0600
res   DS.B   1


     ORG  $1000
start MOVEA.L      #$4000,SP

     MOVE.B       #2, (res)
     PEA       num         
     JSR        chkpri     
     MOVE.B   D7, res

     MOVEA.L    #$4000,SP

     MOVE.B #9, D0
     TRAP #15

     ORG  $2000
chkpri MOVE.W  6(A7),A1
     MOVE.W  #2,D3
     MOVE.W  (A1),D4
back  MOVE.L  D4,D2
     DIVU.W  D3,D2
     ADD.W  #1,D3
     CMP.W  D4,D3
     BEQ  pri
     SWAP  D2
     CMPI.W  #0,D2
     BNE  back
     MOVEQ  #0,D7
     RTS
pri   MOVEQ  #1,D7
     RTS


     END  START
chkpri рутиныг ашиглаад массиваас анхны тоонуудыг ялгаж өөр массивт хуулдаг програм:
   ORG $0502
from   DC.W 87,92,7,84,65,32,11,83,103,287
N    DC.W  10

   ORG $0602 
to   DS.W N
  

     
       
   ORG     $1000
 
start   MOVEA.L     #$4000,SP
  
  
   LEA  from,A2 
   LEA  to,A3 
   MOVE.W  N,D5   
   MULU.W  #2,D5   
        
   MOVE.W  #0,D1   
back1   PEA  0(A2,D1.W)  
   ADDI.W  #2,D1   
   JSR  chkpri   
   CMPI.W  #1,D7   
   BEQ  cpypri
   CMP.W  D1,D5   
   BNE  back1
                       LEA  to,A3 
   MOVE.W  D6,(A3)   
   JMP  out   
   
cpypri          ADDI.W  #1,D6   
   ADD.W  #2,A3   
   MOVE.W  D4,(A3)   
   JMP  back1

out

2010-02-17

Linux сервер дээр SVN суулгах

SVN (Subversion) бол багаараа хамтарч төсөл гүйцэтгэхэд тун хэрэгтэй зүйл. Энд тохируулах үйл явцыг бичлээ. Хэрвээ та Debian юмуу Ubuntu хэрэглэж байгаа бол энд хэрэгтэй Apache HTTPd, Subversion зэргийг суулгах нүд эрмэхийн төдий амар зүйл тул суулгах хэсгийг алгасья. Доорх үйл явцад SVN-рүү HTTP протокол ашиглаж холбогдохоор бодож хийе:
# mkdir /subversion
# chown www-data:www-data /subversion
# su www-data
$ svnadmin create /subversion
$ exit
# htpasswd -c /subversion/htpasswd dagvadorj
# htpasswd /subversion/htpasswd oyunjargal
Дараа нь /etc/apache2/httpd.conf файлд дараах мөрүүдийг оруулна:
 <location /svn>
   DAV svn
   SVNPath /subversion
   AuthType Basic
   AuthName "Dagvadorj Subversion Repository"
   AuthUserFile /subversion/htpasswd
   Require valid-user
 </location>