Friday, 7 September 2018

Program to demonstrate using O_DIRECT option in file operations and writev() call

Program

/* Below program showcases the use of O_DIRECT file option. Also, demonstrates writev() use */

#include <iostream>
#include <fcntl.h>    /* For O_RDWR */
#include <unistd.h>   /* For open(), creat() */
#include <string.h>   /* For strlen() */
#include <malloc.h>   /* For memalign() */
#include <sys/uio.h>  /* For struct iovec */
#include <stdint.h>   /* For datatypes */

#define O_DIRECT_ENABLE 1
using namespace std;

int main(int argc, char *argv[])
{
        if (argc != 3) {
            cout << "run: ./<prog_binary_name> <input_file_name> <outputFileName>"<<endl;
            return 0;
        }

        int fd_out, fd_in, ret;
#if O_DIRECT_ENABLE
        fd_out = open(argv[2], O_CREAT | O_WRONLY | O_TRUNC | O_APPEND | O_DIRECT, S_IRWXG | S_IRWXU);
        fd_in = open(argv[1], O_RDONLY | O_DIRECT);
#else
        fd_out = open(argv[2], O_CREAT | O_WRONLY | O_TRUNC | O_APPEND, S_IRWXG | S_IRWXU);
        fd_in = open(argv[1], O_RDONLY);
#endif
        if(!fd_out || !fd_in) {
            cout << "Unable to open one of the given files"<<endl;
            return 0;
        }
        char file_data1[4096];
        char *file_data2 = (char*)memalign(4096, 4096);

        /* Below vector declaration won't compile since aligned_allocator defined in xilinx lib.
        vector<uint8_t, aligned_allocator<uint8_t>>  file_data3(4096);
        read(fd_in, file_data3, 4096);
        int file_data3_len = strlen(file_data2);
        */

        read(fd_in, file_data1, 4096); /* not work with O_DIRECT option, it returns 0 bytes */
        int file_data1_len = strlen(file_data1);

        /* works with O_DIRECT since memalign is used for creating the buffer */
        read(fd_in, file_data2, 4096);
        int file_data2_len = strlen(file_data2);

        cout<<"read_4k_nonMemAlign, read_4k_memAlign: "<<file_data1_len<<", "<<file_data2_len<<endl;

        char *data = (char*)malloc(sizeof(char)* 4096);
        strcpy(data, "salkfalksfjslfnsdlfksdklfnsldkfslkdfskldfjskldngslkdgjsdngslkdgskldglksdglksdglsdglsdgklsdfgdfkg");
        int data_len =  strlen(data);

        char *data2 = (char*)memalign(4096, 4096);
        strcpy(data2, "12345678912345678912345678912345678912345678912345678912345678912345678912345678912345678912345");
        int data2_len =  strlen(data2);

        ret = write(fd_out, data, data_len); /* fails with -1 if O_DIRECT enabled */
        cout<<"data(malloc) write ret: "<<ret<<endl;

        ret = write(fd_out, data2, 4096); /* write() works with O_DIRECT since data buffer is memaligned and given size is 4096 also aligned */
        cout<<"data2(memalign) write ret: "<<ret<<endl;

        ret = lseek(fd_out, data_len, SEEK_SET);
        cout<<"seek ret1: "<<ret<<endl;
        ret = write(fd_out, file_data2, 4096); /* write() works with O_DIRECT since buf is memaligned */
        cout<<"write_ret2: "<<ret<<endl;

        ret = lseek(fd_out, 0, SEEK_CUR);
        cout<<"seek ret2: "<<ret<<endl;

        struct iovec    iov[4];
        iov[0].iov_base = (char *) file_data2;
        iov[0].iov_len  = 4096;
        iov[1].iov_base = (char *) data2;
        iov[1].iov_len  = 4096;//data2_len;
        iov[2].iov_base = (char *) file_data1;
        iov[2].iov_len  = file_data1_len;
        iov[3].iov_base = (char *) data;
        iov[3].iov_len  = data_len;

        int total_len = iov[0].iov_len + iov[1].iov_len + iov[2].iov_len + iov[3].iov_len;
        cout<<"total_len: "<<total_len<<" {"<<data_len<<", "<<data2_len<<", "<<file_data1_len<<", "<<file_data2_len<<"}"<<endl;

/*        ret = writev(fd_out, &iov[0], 4); */
        ret = writev(fd_out, &iov[0], 2);
        cout<<"writev ret: "<<ret<<endl; /*writev() works fine when O_DIRECT flag removed in file open option. */
        ret = lseek(fd_out, 4096+data2_len, SEEK_SET);
        cout<<"seek ret: "<<ret<<endl;
        ret = write(fd_out, data, 4096); /* write() works with O_DIRECT since buf is memaligned */
        cout<<"ret: "<<ret<<endl;
        close(fd_out);
        close(fd_in);
        return 0;
}

Program Output

$g++ odirect_writev_prog.cpp -o odirect_writev_prog
$ ./odirect_writev_prog input.txt output_fd.txt
read_4k_nonMemAlign, read_4k_memAlign: 0, 4096
data(malloc) write ret: -1
data2(memalign) write ret: 4096
seek ret1: 96
write_ret2: -1
seek ret2: 96
total_len: 8288 {96, 95, 0, 4096}
writev ret: -1
seek ret: 4191
ret: -1

Tuesday, 31 October 2017

Generate Binary Numbers using Queue data structure

Generate Binary Numbers using Queue data structure

Problem Statement (from geeksforgeeks):

Given a number n, Write a program that generates and prints all binary numbers with decimal values from 1 to n.
Input:
The first line of input contains an integer T denoting the number of test cases.
The first line of each test case is N.

Output:
Print all binary numbers with decimal values from 1 to n in a single line.

Constraints:
1 ≤ T ≤ 100
1 ≤ N ≤ 500

Example:
Input
2
2
5
Output
1 10
1 10 11 100 101

Solution:

/* Generating Binary Numbers of given input using Queue Data structure.
 * Implemented in C language.
 * Used Circular Queue as part of the implementation
 */

#include<stdio.h>
#include<stdlib.h>
#include<string.h>

struct queue{
    int cap;
    int front, rear;
    int size;
    char array[1000][10];
};

struct queue* createQueue(int n){
    struct queue *q = (struct queue*)malloc(sizeof(struct queue));
    
    q->cap = n;
    q->front = -1;
    q->rear = n - 1;
    q->size = 0;
    return q;
}

int isQueueEmpty(struct queue *q){
    return q->size == 0;
}

int isQueueFull(struct queue *q){
    return q->size == q->cap;
}

void enQueue(struct queue *q, char *ch){
    if (isQueueFull(q))
        return;
    q->rear = (q->rear + 1) % q->cap;
    strcpy (q->array[q->rear], ch);
    q->size += 1;
}

char* deQueue(struct queue *q){
    if (isQueueEmpty(q))
        return NULL;
    q->front = (q->front + 1) % q->cap;
    q->size -= 1;
    return q->array[q->front];
    
}

void printQueue(struct queue *q){
    printf("Queue elements...\n");
    for (int i = 0; i < q->front; i++)
        printf("ele: %s\n", q->array[i]);
}
void toBinary(int n) {
    struct queue *q = createQueue(n);
    
    enQueue(q, "1");
    
    for (int i = 1; i <= n; i++) {
        char d1[10], d2[10];
        strcpy(d1, deQueue(q));
        printf("%s ", d1);
        strcpy(d2, d1);
        strcat(d1, "0");
        strcat(d2, "1");
        enQueue(q, d1);
        enQueue(q, d2);
    }
    printf("\n");
    free(q);
}

int main()
{
    // Note that size of arr[] is considered 100 according to
    // the constraints mentioned in problem statement.
    int arr[100], t, n;
 
    // Input the number of test cases you want to run
    scanf("%d", &t); 
 
    // One by one run for all input test cases
    while (t--)
    {
        // Input the size of the array
        scanf("%d", &n);
        toBinary(n);
    }
    return 0;
}

Friday, 2 September 2016

Python Learning - Notes


I have prepared this document during my Python course from sololearn.com

You might also like

Related Posts Plugin for WordPress, Blogger...